transcribe.test.mjs
88 lines 2.8 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 1 day ago
1 /**
2 * Transcription helper: validation, size limit, OpenAI response handling (fetch mocked).
3 */
4 import { describe, it, beforeEach, afterEach } from 'node:test';
5 import assert from 'node:assert';
6 import fs from 'fs';
7 import os from 'os';
8 import path from 'path';
9 import { fileURLToPath } from 'url';
10 import { transcribe, WHISPER_MAX_FILE_BYTES } from '../lib/transcribe.mjs';
11
12 const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
14 describe('transcribe()', () => {
15 let tmpDir;
16 let origFetch;
17 let origKey;
18
19 beforeEach(() => {
20 tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'kn-tr-'));
21 origFetch = globalThis.fetch;
22 origKey = process.env.OPENAI_API_KEY;
23 process.env.OPENAI_API_KEY = 'sk-test-mock-key';
24 });
25
26 afterEach(() => {
27 globalThis.fetch = origFetch;
28 if (origKey === undefined) delete process.env.OPENAI_API_KEY;
29 else process.env.OPENAI_API_KEY = origKey;
30 try {
31 fs.rmSync(tmpDir, { recursive: true, force: true });
32 } catch (_) {}
33 });
34
35 it('throws when file is missing', async () => {
36 const p = path.join(tmpDir, 'nope.mp3');
37 await assert.rejects(() => transcribe(p), /File not found/);
38 });
39
40 it('throws on unsupported extension', async () => {
41 const p = path.join(tmpDir, 'x.flac');
42 fs.writeFileSync(p, Buffer.from('x'));
43 await assert.rejects(() => transcribe(p), /Unsupported format/);
44 });
45
46 it('throws when file exceeds WHISPER_MAX_FILE_BYTES', async () => {
47 const p = path.join(tmpDir, 'huge.wav');
48 const fd = fs.openSync(p, 'w');
49 try {
50 fs.ftruncateSync(fd, WHISPER_MAX_FILE_BYTES + 1);
51 } finally {
52 fs.closeSync(fd);
53 }
54 await assert.rejects(() => transcribe(p, { transcodeOversized: false }), /25MB/);
55 });
56
57 it('throws when OPENAI_API_KEY is unset', async () => {
58 delete process.env.OPENAI_API_KEY;
59 const p = path.join(tmpDir, 'a.mp3');
60 fs.writeFileSync(p, Buffer.from([0, 0, 0]));
61 await assert.rejects(() => transcribe(p), /OPENAI_API_KEY/);
62 });
63
64 it('returns trimmed text from API JSON', async () => {
65 const p = path.join(tmpDir, 'a.mp3');
66 fs.writeFileSync(p, Buffer.from([0xff, 0xfb, 0x90, 0x00]));
67
68 globalThis.fetch = async (url, init) => {
69 assert.match(String(url), /audio\/transcriptions/);
70 assert.ok(init && init.headers && init.headers.Authorization);
71 return new Response(JSON.stringify({ text: ' hello world ' }), { status: 200 });
72 };
73
74 const out = await transcribe(p);
75 assert.strictEqual(out.text, 'hello world');
76 assert.strictEqual(out.transcoded, undefined);
77 });
78
79 it('propagates API errors', async () => {
80 const p = path.join(tmpDir, 'b.m4a');
81 fs.writeFileSync(p, Buffer.from([0, 1, 2]));
82
83 globalThis.fetch = async () =>
84 new Response('rate limited', { status: 429, statusText: 'Too Many Requests' });
85
86 await assert.rejects(() => transcribe(p), /429/);
87 });
88 });
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 1 day ago