/* * ★ 상태 축 고르기 — 리프레시가 통째로여서 무겁던 것. * * 지도는 구독 신호를 받고 상태를 다시 읽는다(신호는 가볍고 리프레시는 250ms 로 합쳐진다 — 설계대로). * 문제는 **읽는 양**이었다: 실 저널로 재 보니 트윈 하나가 최대 710KB, 같은 공간에 셋이면 약 2MB. * 그런데 지도가 쓰는 축은 `locations`·`attentions` 둘뿐이다. * * 여기서 지키는 것: 말하지 않으면 자르지 않는다(기존 호출부 무영향), 오타로 화면이 비지 않는다. */ import { test } from 'node:test' import assert from 'node:assert/strict' import { pickAxes, STATE_AXES } from '../server/engine/state-axes.ts' const STATE = { revision: 12, nowTime: '2026-08-05T00:00:00.000Z', simClockMs: 1000, locations: [{ id: 'dock' }], items: [{ epc: 'a' }, { epc: 'b' }], equipment: [{ id: 'fk-1' }], tasks: [{ id: 't1' }], orders: [{ id: 'o1' }], attentions: [{ id: 'bottleneck:dock' }], acked: ['bottleneck:dock'] } test('고른 축만 남는다 — 지도가 쓰는 둘', () => { const { state, unknown } = pickAxes(STATE, ['locations', 'attentions']) assert.deepEqual(unknown, []) assert.deepEqual(Object.keys(state).sort(), ['attentions', 'locations', 'nowTime', 'revision', 'simClockMs']) assert.equal(state.items, undefined, '쓰지 않는 축은 오지 않는다') }) test('축을 지정하지 않으면 자르지 않는다 — 기존 호출부가 그대로 동작해야 한다', () => { assert.equal(pickAxes(STATE, undefined).state, STATE) assert.equal(pickAxes(STATE, []).state, STATE) assert.equal(pickAxes(STATE, null).state, STATE) }) test('시각과 리비전은 늘 남는다 — 무엇을 언제 받았는지 알아야 한다', () => { const { state } = pickAxes(STATE, ['locations']) assert.equal(state.revision, 12) assert.equal(state.nowTime, STATE.nowTime) }) test('모르는 축은 무시하되 그 사실을 돌려준다 — 오타로 화면이 비지 않게', () => { const { state, unknown } = pickAxes(STATE, ['locations', 'attension']) assert.deepEqual(unknown, ['attension']) assert.ok(state.locations, '아는 축은 그대로 온다') }) test('전부 오타면 자르지 않는다 — 빈 화면보다 통째가 낫다', () => { const { state, unknown } = pickAxes(STATE, ['nope', 'alsonope']) assert.equal(state, STATE) assert.deepEqual(unknown, ['nope', 'alsonope']) }) test('없는 축을 요청해도 키를 만들지 않는다 — 없는 것을 빈 배열로 위장하지 않는다', () => { const { state } = pickAxes({ revision: 1, locations: [] }, ['locations', 'persons']) assert.deepEqual(Object.keys(state).sort(), ['locations', 'revision']) assert.equal('persons' in state, false) }) test('상태가 아니면 그대로 돌려준다', () => { assert.equal(pickAxes(null, ['locations']).state, null) assert.equal(pickAxes(undefined, ['locations']).state, undefined) }) test('축 목록이 상태의 축과 어긋나지 않는다 — 이름이 바뀌면 여기서 걸린다', () => { for (const a of ['locations', 'items', 'equipment', 'attentions', 'acked']) { assert.ok((STATE_AXES as readonly string[]).includes(a), a) } })