Built for people who think better out loud.
1import { describe, expect, it, vi } from "vitest";
2
3import { transcribeWithBackend } from "./transcriptionClient";
4
5describe("transcribeWithBackend", () => {
6 it("returns the transcription payload on success", async () => {
7 const fetchMock = vi.fn().mockResolvedValue(
8 new Response(JSON.stringify({ text: "hello", language: "en" }), {
9 status: 200,
10 headers: { "content-type": "application/json" },
11 }),
12 );
13 vi.stubGlobal("fetch", fetchMock);
14
15 const blob = new Blob(["audio"], { type: "audio/webm" });
16 const payload = await transcribeWithBackend({
17 endpointUrl: "http://localhost:3001/api/transcribe",
18 blob,
19 });
20
21 expect(payload.text).toBe("hello");
22 expect(payload.language).toBe("en");
23 expect(fetchMock).toHaveBeenCalledOnce();
24 });
25
26 it("throws with backend error message when request fails", async () => {
27 const fetchMock = vi.fn().mockResolvedValue(
28 new Response(JSON.stringify({ error: { message: "nope" } }), {
29 status: 400,
30 headers: { "content-type": "application/json" },
31 }),
32 );
33 vi.stubGlobal("fetch", fetchMock);
34
35 const blob = new Blob(["audio"], { type: "audio/webm" });
36
37 await expect(
38 transcribeWithBackend({
39 endpointUrl: "http://localhost:3001/api/transcribe",
40 blob,
41 }),
42 ).rejects.toThrow("nope");
43 });
44
45 it("throws when response is missing a text field", async () => {
46 const fetchMock = vi.fn().mockResolvedValue(
47 new Response(JSON.stringify({ language: "en" }), {
48 status: 200,
49 headers: { "content-type": "application/json" },
50 }),
51 );
52 vi.stubGlobal("fetch", fetchMock);
53
54 const blob = new Blob(["audio"], { type: "audio/webm" });
55
56 await expect(
57 transcribeWithBackend({
58 endpointUrl: "http://localhost:3001/api/transcribe",
59 blob,
60 }),
61 ).rejects.toThrow("Backend did not return a transcription.");
62 });
63});