import { describe, it, expect } from 'vitest'; import { NODE_IDS, INITIAL_NODE_POSITIONS, EDGES, NODE_KIND_MAP, SCORE_NODE_NAME_MAP, } from './canvasLayout'; describe('canvasLayout', () => { it('NODE_IDS — 12개 키, 모두 unique', () => { const ids = Object.values(NODE_IDS); expect(ids).toHaveLength(12); expect(new Set(ids).size).toBe(12); }); it('INITIAL_NODE_POSITIONS — 모든 NODE_IDS에 좌표 존재', () => { for (const id of Object.values(NODE_IDS)) { expect(INITIAL_NODE_POSITIONS[id]).toMatchObject({ x: expect.any(Number), y: expect.any(Number), }); } }); it('EDGES — 18개, source/target이 모두 NODE_IDS 안에 존재', () => { expect(EDGES).toHaveLength(18); const validIds = new Set(Object.values(NODE_IDS)); for (const e of EDGES) { expect(validIds.has(e.source)).toBe(true); expect(validIds.has(e.target)).toBe(true); expect(e.id).toBeTruthy(); } }); it('EDGES — 8개 점수 노드는 모두 gate 입력 + combine 출력을 가짐', () => { const SCORE_IDS = [ NODE_IDS.FOREIGN, NODE_IDS.VOLUME, NODE_IDS.MOMENTUM, NODE_IDS.HIGH52W, NODE_IDS.RS, NODE_IDS.MA, NODE_IDS.VCP, NODE_IDS.AI_NEWS, ]; for (const sid of SCORE_IDS) { const hasGateInput = EDGES.some( (e) => e.source === NODE_IDS.GATE && e.target === sid ); const hasCombineOutput = EDGES.some( (e) => e.source === sid && e.target === NODE_IDS.COMBINE ); expect(hasGateInput).toBe(true); expect(hasCombineOutput).toBe(true); } }); it('NODE_KIND_MAP — 각 노드의 kind ∈ {data,gate,score,combine,result}', () => { const valid = new Set(['data','gate','score','combine','result']); for (const id of Object.values(NODE_IDS)) { expect(valid.has(NODE_KIND_MAP[id])).toBe(true); } }); it('SCORE_NODE_NAME_MAP — 8개 점수 노드 ID → backend node name', () => { expect(Object.keys(SCORE_NODE_NAME_MAP)).toHaveLength(8); expect(SCORE_NODE_NAME_MAP[NODE_IDS.FOREIGN]).toBe('foreign_buy'); expect(SCORE_NODE_NAME_MAP[NODE_IDS.VOLUME]).toBe('volume_surge'); expect(SCORE_NODE_NAME_MAP[NODE_IDS.AI_NEWS]).toBe('ai_news'); }); });