/* * **설비는 자리에도 구역에도 설 수 있다.** * * ── 실물 (2026-09-06) ─────────────────────────────────────────────────────── * `EQ-CAM-SHOWER-01`(에어샤워)이 `LINE-CAM` 이라는 **구역**에 딸려 있다. 라인 전체에 붙는 설비는 * 자리 하나를 고를 수 없고, 그것이 정상이다. * * 그런데 인제스트가 그 참조를 **「끊어졌다」고 경고**했다. 자리 목록에서만 찾았기 때문이다. * * ``` * unresolved-reference * equipment.homeLocation points at something that is not in this twin (EQ-CAM-SHOWER-01→LINE-CAM) * ``` * * 계약이 그 갈림을 위해 `homeLocationKind = 'location' | 'area'` 를 두었는데 **아무도 안 채우고 * 있었다** — 선언만 있고 읽는 쪽도 쓰는 쪽도 0곳이었다. * * 짐작하지 않는다. 마스터가 이미 `role` 로 자리와 구역을 가르고 있으므로 그것을 읽는다. */ import { test } from 'node:test' import assert from 'node:assert/strict' import { masterToTwin } from '../server/service/reference/reference-master.ts' const master = (): any => ({ source: 'm', system: 'mes', siteName: 'S', space: { spaceId: 'm-site', width: 100, depth: 60, unit: 'm' }, locations: [ { id: 'ST-1', role: 'location', type: 'weld-station', capacity: 1 }, { id: 'LINE-CAM', role: 'area', type: 'line' } ], equipment: [ { id: 'EQ-WELD-1', kind: 'welder', homeLocationId: 'ST-1' }, { id: 'EQ-CAM-SHOWER-01', kind: 'air-shower', homeLocationId: 'LINE-CAM' } ] }) const eq = (model: any, id: string) => model.equipment.find((e: any) => e.id === id) test('★ 구역에 선 설비는 homeLocationKind 로 그것을 말한다', () => { const { model } = masterToTwin(master()) const shower = eq(model, 'EQ-CAM-SHOWER-01') assert.equal(shower.homeLocation, 'LINE-CAM') assert.equal(shower.homeLocationKind, 'area', '구역인 것을 안 말하면 읽는 쪽이 자리로 읽는다') }) test('★ 자리에 선 설비는 그 칸을 안 만든다 — 계약의 기본값이 location 이다', () => { /* * 없는 칸을 만들면 화면이 그것을 그리고, 「자리」라는 당연한 말이 모든 줄에 붙는다. * `homeOf()` 가 없을 때 `'location'` 을 내는 것이 그래서다. */ const { model } = masterToTwin(master()) const welder = eq(model, 'EQ-WELD-1') assert.equal(welder.homeLocation, 'ST-1') assert.equal('homeLocationKind' in welder, false) }) test("★ role 이 'both' 면 자리다 — 구역으로 만들지 않는다", () => { /* * `both` 는 그 줄이 자리 목록에도 구역 목록에도 들어간다는 뜻이다. 설비가 그것을 가리키면 * **자리 쪽이 이긴다** — 자리는 설비가 실제로 서는 지점이고, 구역은 그것을 담는 넓이다. */ const m = master() m.locations = [{ id: 'CELL-1', role: 'both', type: 'cell', capacity: 1 }] m.equipment = [{ id: 'EQ-1', kind: 'welder', homeLocationId: 'CELL-1' }] const { model } = masterToTwin(m) assert.equal('homeLocationKind' in eq(model, 'EQ-1'), false) }) test('기준 자리가 없는 설비는 그 칸도 없다', () => { const m = master() m.equipment = [{ id: 'EQ-FREE', kind: 'agv' }] const { model } = masterToTwin(m) assert.equal('homeLocationKind' in eq(model, 'EQ-FREE'), false) }) test('★ 이 테스트가 실제로 무언가를 잰다 — 견준 것이 0이면 빨강', () => { const { model } = masterToTwin(master()) assert.equal(model.equipment.length, 2, '설비를 하나도 안 읽었다') assert.notEqual( eq(model, 'EQ-CAM-SHOWER-01').homeLocationKind, eq(model, 'EQ-WELD-1').homeLocationKind, '구역에 선 설비와 자리에 선 설비가 같아졌다' ) })