import assert from 'node:assert/strict'; import test from 'node:test'; import { HEALTH_ACTIONS, HEALTH_CHANNEL_STEPS, createIdleHealthChannelState, reduceHealthChannel, } from './health-channel-state.mjs'; test('record flow pins metric then waits for value without guessing', () => { let { state } = reduceHealthChannel(createIdleHealthChannelState(), { type: 'select_action', action: HEALTH_ACTIONS.RECORD, }); assert.equal(state.step, HEALTH_CHANNEL_STEPS.AWAIT_METRIC_TYPE); ({ state } = reduceHealthChannel(state, { type: 'pick_metric', metricSet: 'blood_pressure' })); assert.equal(state.step, HEALTH_CHANNEL_STEPS.AWAIT_CONTEXT); ({ state } = reduceHealthChannel(state, { type: 'pick_context', context: 'morning' })); assert.equal(state.step, HEALTH_CHANNEL_STEPS.AWAIT_VALUE); const unexpected = reduceHealthChannel(state, { type: 'unexpected', text: '帮我做个页面' }); assert.equal(unexpected.state.step, HEALTH_CHANNEL_STEPS.AWAIT_VALUE); assert.equal(unexpected.actions[0].type, 'prompt_unexpected'); assert.match(unexpected.actions[0].prompt, /当前正在录入「血压」/); }); test('ambiguous idle input forces action choice instead of guessing', () => { const result = reduceHealthChannel(createIdleHealthChannelState(), { type: 'ambiguous' }); assert.equal(result.state.step, HEALTH_CHANNEL_STEPS.AWAIT_ACTION_CHOICE); const chosen = reduceHealthChannel(result.state, { type: 'choose', choice: 1 }); assert.equal(chosen.state.step, HEALTH_CHANNEL_STEPS.AWAIT_METRIC_TYPE); }); test('photo in await_value always requires confirm before commit', () => { const awaiting = { ...createIdleHealthChannelState(), step: HEALTH_CHANNEL_STEPS.AWAIT_VALUE, metricSet: 'blood_pressure', }; const confirm = reduceHealthChannel(awaiting, { type: 'image', draftId: 'drf-1' }); assert.equal(confirm.state.step, HEALTH_CHANNEL_STEPS.CONFIRM); assert.equal(confirm.actions[0].requireConfirm, true); const committed = reduceHealthChannel(confirm.state, { type: 'commit' }); assert.equal(committed.state.step, HEALTH_CHANNEL_STEPS.COMMITTED); assert.equal(committed.actions[0].type, 'commit_observation'); }); test('exit and timeout leave the health channel', () => { const exited = reduceHealthChannel(createIdleHealthChannelState(), { type: 'exit' }); assert.equal(exited.state.step, HEALTH_CHANNEL_STEPS.EXITED); const timedOut = reduceHealthChannel(createIdleHealthChannelState(), { type: 'timeout' }); assert.equal(timedOut.state.step, HEALTH_CHANNEL_STEPS.EXITED); });