sessionStore.test.ts
3,625 bytes
| 1 | import { mkdtemp, rm } from 'node:fs/promises' |
|---|---|
| 2 | import { tmpdir } from 'node:os' |
| 3 | import path from 'node:path' |
| 4 | import { afterEach, beforeEach, describe, expect, it } from 'vitest' |
| 5 | import { initialCoverage } from '../../shared/types' |
| 6 | import { SessionStore } from './sessionStore' |
| 7 | |
| 8 | describe('SessionStore', () => { |
| 9 | let baseDir: string |
| 10 | let store: SessionStore |
| 11 | |
| 12 | beforeEach(async () => { |
| 13 | baseDir = await mkdtemp(path.join(tmpdir(), 'voicetask-store-')) |
| 14 | store = new SessionStore(baseDir) |
| 15 | }) |
| 16 | |
| 17 | afterEach(async () => { |
| 18 | await rm(baseDir, { recursive: true, force: true }) |
| 19 | }) |
| 20 | |
| 21 | it('creates a session and reloads it with matching data', async () => { |
| 22 | const created = await store.createSession('my project', '/tmp/target') |
| 23 | expect(created.name).toBe('my project') |
| 24 | expect(created.targetDir).toBe('/tmp/target') |
| 25 | expect(created.status).toBe('interviewing') |
| 26 | expect(created.coverage).toEqual(initialCoverage()) |
| 27 | |
| 28 | const reloaded = await store.getSession(created.id) |
| 29 | expect(reloaded).toEqual(created) |
| 30 | }) |
| 31 | |
| 32 | it('returns null for an unknown session id', async () => { |
| 33 | expect(await store.getSession('does-not-exist')).toBeNull() |
| 34 | }) |
| 35 | |
| 36 | it('assigns sequential segment ids S1..Sn', async () => { |
| 37 | const session = await store.createSession('proj', '/tmp/target') |
| 38 | const first = await store.appendSegment(session.id, 'user', 'hello') |
| 39 | expect(first.segment.id).toBe('S1') |
| 40 | const second = await store.appendSegment(session.id, 'interviewer', 'what next?') |
| 41 | expect(second.segment.id).toBe('S2') |
| 42 | const third = await store.appendSegment(session.id, 'user', 'more') |
| 43 | expect(third.segment.id).toBe('S3') |
| 44 | |
| 45 | const reloaded = await store.getSession(session.id) |
| 46 | expect(reloaded?.segments.map((s) => s.id)).toEqual(['S1', 'S2', 'S3']) |
| 47 | expect(reloaded?.segments.map((s) => s.text)).toEqual(['hello', 'what next?', 'more']) |
| 48 | }) |
| 49 | |
| 50 | it('updates coverage, summary, and status', async () => { |
| 51 | const session = await store.createSession('proj', '/tmp/target') |
| 52 | const coverage = { ...initialCoverage(), goal: 'clear' as const } |
| 53 | const updated = await store.updateTurn(session.id, { |
| 54 | coverage, |
| 55 | summary: 'a running summary', |
| 56 | status: 'done', |
| 57 | }) |
| 58 | expect(updated.coverage).toEqual(coverage) |
| 59 | expect(updated.summary).toBe('a running summary') |
| 60 | expect(updated.status).toBe('done') |
| 61 | }) |
| 62 | |
| 63 | it('lists sessions as summaries, newest first', async () => { |
| 64 | const a = await store.createSession('alpha', '/tmp/a') |
| 65 | const b = await store.createSession('beta', '/tmp/b') |
| 66 | await store.updateTurn(b.id, { status: 'done' }) |
| 67 | |
| 68 | const list = await store.listSessions() |
| 69 | expect(list).toHaveLength(2) |
| 70 | expect(list).toEqual( |
| 71 | expect.arrayContaining([ |
| 72 | { id: a.id, name: 'alpha', status: 'interviewing', createdAt: a.createdAt }, |
| 73 | { id: b.id, name: 'beta', status: 'done', createdAt: b.createdAt }, |
| 74 | ]), |
| 75 | ) |
| 76 | const sorted = [...list].sort((x, y) => y.createdAt.localeCompare(x.createdAt)) |
| 77 | expect(list).toEqual(sorted) |
| 78 | }) |
| 79 | |
| 80 | it('deletes a session and reports missing ones', async () => { |
| 81 | const session = await store.createSession('gone soon', '/tmp/g') |
| 82 | expect(await store.deleteSession(session.id)).toBe(true) |
| 83 | expect(await store.getSession(session.id)).toBeNull() |
| 84 | expect(await store.listSessions()).toEqual([]) |
| 85 | expect(await store.deleteSession(session.id)).toBe(false) |
| 86 | }) |
| 87 | |
| 88 | it('lists no sessions when the base directory does not exist yet', async () => { |
| 89 | const emptyStore = new SessionStore(path.join(baseDir, 'nonexistent')) |
| 90 | expect(await emptyStore.listSessions()).toEqual([]) |
| 91 | }) |
| 92 | }) |
| 93 | |