Adding migrations and lot of work. Starting work on the demo scope

This commit is contained in:
2026-08-22 14:53:23 +02:00
parent 1893bf23af
commit 94ccbfd1b9
29 changed files with 1280 additions and 122 deletions
+47
View File
@@ -0,0 +1,47 @@
import { describe, expect, it } from 'vitest'
import type { CaseState, DocumentExhibit, NoteExhibit } from '../src/types.js'
import { filterLevelVisibility, mergePlayerStateForPersistence } from './levelVisibility.js'
const placed = { x: 10, y: 20, width: 174, height: 145, rotation: 0, zIndex: 1, hidden: false }
const open: DocumentExhibit = { id: 'open', type: 'document', title: 'Open', body: [], regions: [], fileType: 'image', metadata: {}, ...placed }
const gated: DocumentExhibit = { id: 'gated', type: 'document', title: 'Gated', body: [], regions: [], fileType: 'image', metadata: {}, requiredFlags: ['tip.received'], ...placed }
const note: NoteExhibit = { id: 'note', type: 'note', title: 'Note', content: '', ...placed }
const state: CaseState = {
id: 'demo', title: 'Demo', subtitle: '', exhibits: [open, gated, note], viewport: { x: 0, y: 0, zoom: 1 },
relations: [{ id: 'source', type: 'source', fromExhibitId: note.id, toExhibitId: gated.id, sortOrder: 0 }],
connections: [{ id: 'thread', fromExhibitId: open.id, toExhibitId: gated.id }],
views: [], brief: { body: '', concepts: [] }, revision: 0,
}
describe('level flag visibility', () => {
it('hides gated documents and every edge touching them', () => {
const visible = filterLevelVisibility(state, [], [], false)
expect(visible.exhibits.map(item => item.id)).toEqual(['open', 'note'])
expect(visible.relations).toEqual([])
expect(visible.connections).toEqual([])
expect(visible.newlyVisibleDocumentIds).toEqual(['open'])
})
it('reveals earned documents once without leaking their gate definition', () => {
const visible = filterLevelVisibility(state, ['tip.received'], ['open'], false)
expect(visible.exhibits.map(item => item.id)).toEqual(['open', 'gated', 'note'])
expect((visible.exhibits[1] as DocumentExhibit).requiredFlags).toBeUndefined()
expect(visible.newlyVisibleDocumentIds).toEqual(['gated'])
})
it('returns all documents and requirements to author mode', () => {
const authored = filterLevelVisibility(state, [], [], true)
expect((authored.exhibits[1] as DocumentExhibit).requiredFlags).toEqual(['tip.received'])
expect(authored.newlyVisibleDocumentIds).toEqual([])
})
it('preserves unrevealed documents and their edges during a play-mode save', () => {
const visible = filterLevelVisibility(state, [], ['open'], false)
const submitted = { ...visible, exhibits: visible.exhibits.map(item => item.id === 'open' ? { ...item, x: 99 } : item) }
const merged = mergePlayerStateForPersistence(state, visible, submitted)
expect(merged.exhibits.find(item => item.id === 'open')?.x).toBe(99)
expect(merged.exhibits.find(item => item.id === 'gated')).toMatchObject({ requiredFlags: ['tip.received'] })
expect(merged.relations).toHaveLength(1)
expect(merged.connections).toHaveLength(1)
})
})