diff --git a/tests/fixtures/test-01.note.md b/tests/fixtures/test-01.note.md new file mode 100644 index 0000000..c41837e --- /dev/null +++ b/tests/fixtures/test-01.note.md @@ -0,0 +1,11 @@ +--- +voice-id: "20260927-111503-0000" +voice-status: "inserted" +voice-device: "test-device" +voice-audio: "[[voice/source/20260927-111503-0000.m4a]]" +voice-mime: "audio/mp4" +voice-attempts: 0 +--- +![[voice/source/20260927-111503-0000.m4a]] + +Это тестовая запись для проверки распознавания речи с помощью модели WHISPER, для сравнения между двух конкретных моделей. diff --git a/tests/golden.test.ts b/tests/golden.test.ts new file mode 100644 index 0000000..07ce4c7 --- /dev/null +++ b/tests/golden.test.ts @@ -0,0 +1,56 @@ +import { existsSync, readdirSync, readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; +import { saveCapture } from '../src/core/capture'; +import { QueueRunner } from '../src/core/queue'; +import { MemoryNotes, MemoryRecordings, ScriptedTranscriber, TestEnv } from './fakes'; + +const FIXTURES = fileURLToPath(new URL('./fixtures/', import.meta.url)); +const MIME: Record = { m4a: 'audio/mp4', webm: 'audio/webm', ogg: 'audio/ogg' }; +const cases = readdirSync(FIXTURES) + .filter((f) => f.endsWith('.note.md')) + .map((f) => f.slice(0, -'.note.md'.length)); + +function audioFor(name: string): { file: string; mime: string } { + for (const ext of Object.keys(MIME)) { + const file = `${FIXTURES}${name}.${ext}`; + if (existsSync(file)) return { file, mime: MIME[ext] }; + } + throw new Error(`нет аудиофикстуры tests/fixtures/${name}.m4a (или .webm/.ogg) для эталона ${name}.note.md`); +} + +function toArrayBuffer(buf: Buffer): ArrayBuffer { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer; +} + +describe('golden', () => { + it('has at least one case', () => { + expect(cases.length).toBeGreaterThan(0); + }); + + for (const name of cases) { + it(name, async () => { + const { file, mime } = audioFor(name); + const audio = toArrayBuffer(readFileSync(file)); + const transcript = readFileSync(`${FIXTURES}${name}.txt`, 'utf8'); + const expected = readFileSync(`${FIXTURES}${name}.note.md`, 'utf8'); + + const env = new TestEnv(); + const notes = new MemoryNotes(); + const recordings = new MemoryRecordings(); + const transcriber = new ScriptedTranscriber([{ ok: true, text: transcript }]); + + const path = await saveCapture( + { recordings, notes, env }, + { chunks: [audio], mime, startedAt: env.now(), endedAt: new Date(env.now().getTime() + 47_000), interrupted: false }, + ); + await new QueueRunner({ recordings, notes, transcriber, env }).tick(); + + expect(path).toBe('voice/inbox/2026-09-27 14-15-03.md'); + expect(transcriber.calls).toHaveLength(1); + expect(transcriber.calls[0].mime).toBe(mime); + expect(Buffer.from(transcriber.calls[0].audio).equals(Buffer.from(audio))).toBe(true); + expect(notes.files.get(path!)).toBe(expected); + }); + } +});