Files
dsh-context/tests/client/modalStore.spec.ts
T
Bowen Liang f106b720ac test: rebuild the suite at source level with 100% per-file coverage gates
The old suite exercised the built lib/ bundle, so v8 remapped almost
nothing (8% src coverage) and every run needed a build first. The new
suite imports src/ directly under two vitest projects (node for
host/shared, jsdom for client), rendering real React 18 trees against
the real dictionaries and ui-primitives, with faithful in-memory
harness faces (cordis inject/effect, locale chain, slots, sessions
provide) instead of plugin mocks.

- 43 fine-grained, stateless, single-module spec files (606 tests)
  forked across workers: ~2.5s wall, no build step
- v8 thresholds at 100/100/100/100 per file over src/**
- host specs drive the real projection definitions (init/apply/view)
  plus one full cordis + SessionStore + SessionProjectionRegistry
  integration; the framework's snapshotJsonValue pins the
  projection-cache precondition on every intermediate fold state
- oxlint's src ruleset now covers tests/** as well
- typecheck covers the tests via tsconfig.tests.json
2026-08-26 00:58:39 +08:00

73 lines
2.5 KiB
TypeScript

// Per-session modal stores (src/client/modalStore.ts): identity, observable
// set semantics, and the deferred token-consume guards. Session ids are
// unique per test so the module-level Maps never leak between cases.
import assert from 'node:assert/strict'
import { describe, test } from 'vitest'
import { modalStoreOf, setPendingConsume, takePendingConsume, type ConsumeGuard } from '../../src/client/modalStore'
describe('modalStoreOf', () => {
test('returns the same store per session id and distinct stores across ids', () => {
assert.equal(modalStoreOf('modal-same-a'), modalStoreOf('modal-same-a'))
assert.notEqual(modalStoreOf('modal-same-a'), modalStoreOf('modal-same-b'))
})
test('starts closed and reports state through getSnapshot', () => {
const store = modalStoreOf('modal-initial')
assert.equal(store.getSnapshot(), false)
})
test('set with the same value does not notify', () => {
const store = modalStoreOf('modal-noop')
let calls = 0
store.subscribe(() => { calls++ })
store.set(false)
assert.equal(calls, 0)
})
test('set with a flipped value notifies once per change', () => {
const store = modalStoreOf('modal-flip')
let calls = 0
store.subscribe(() => { calls++ })
store.set(true)
assert.equal(calls, 1)
assert.equal(store.getSnapshot(), true)
store.set(true)
assert.equal(calls, 1)
store.set(false)
assert.equal(calls, 2)
assert.equal(store.getSnapshot(), false)
})
test('unsubscribe stops notifications', () => {
const store = modalStoreOf('modal-unsub')
let calls = 0
const unsubscribe = store.subscribe(() => { calls++ })
store.set(true)
assert.equal(calls, 1)
unsubscribe()
store.set(false)
assert.equal(calls, 1)
})
})
describe('pending consume guards', () => {
test('take returns the guard once, then undefined', () => {
const guard: ConsumeGuard = { kind: 'bare-token', token: '/context' }
setPendingConsume('consume-once', guard)
assert.equal(takePendingConsume('consume-once'), guard)
assert.equal(takePendingConsume('consume-once'), undefined)
})
test('take on an absent guard returns undefined', () => {
assert.equal(takePendingConsume('consume-absent'), undefined)
})
test('guards are isolated per session', () => {
const guard: ConsumeGuard = { kind: 'span', span: { start: 0, end: 8, draftRev: 1 } }
setPendingConsume('consume-iso-a', guard)
assert.equal(takePendingConsume('consume-iso-b'), undefined)
assert.equal(takePendingConsume('consume-iso-a'), guard)
})
})