43 lines
2.6 KiB
TypeScript
43 lines
2.6 KiB
TypeScript
import assert from "node:assert/strict";
|
|||
|
|
import { limitedBody, synthesize, wikipediaClient } from "../src/network.js";
|
||
|
|
const signal = new AbortController().signal;
|
||
|
|
let calls: { url: string; init?: RequestInit }[] = [];
|
||
|
|
const mock = (async (url: URL | RequestInfo, init?: RequestInit) => {
|
||
|
|
calls.push({ url: String(url), init });
|
||
|
|
if (String(url).includes("list=search")) return Response.json({ query: { search: [{ title: "北京" }] } });
|
||
|
|
return Response.json({ query: { pages: [{ title: "北京", extract: "北京是中国的首都。" }] } });
|
||
|
|
}) as typeof fetch;
|
||
|
|
const wiki = wikipediaClient(mock);
|
||
|
|
assert.deepEqual(await wiki.search("北京", signal), [{ title: "北京", description: "Chinese Wikipedia" }]);
|
||
|
|
const page = await wiki.read("北京", signal);
|
||
|
|
assert.equal(page.text, "北京是中国的首都。");
|
||
|
|
assert(page.attribution.includes("CC BY-SA"));
|
||
|
|
assert(page.url.startsWith("https://zh.wikipedia.org/wiki/"));
|
||
|
|
const count = calls.length;
|
||
|
|
await wiki.read("北京", signal);
|
||
|
|
assert.equal(calls.length, count, "Repeated loads use the bounded cache");
|
||
|
|
assert((calls[0].init?.headers as Record<string, string>)["user-agent"].includes("QuixosReading"));
|
||
|
|
assert(new URL(calls[0].url).searchParams.has("maxlag"));
|
||
|
|
await assert.rejects(() => wiki.read("a|b", signal), /Invalid/);
|
||
|
|
await assert.rejects(() => limitedBody(new Response("x".repeat(50)), 10), /too large/);
|
||
|
|
await assert.rejects(
|
||
|
|
() => limitedBody(new Response("", { status: 429, headers: { "retry-after": "10" } }), 10),
|
||
|
|
/Retry after 10/,
|
||
|
|
);
|
||
|
|
let speechRequest: RequestInit | undefined;
|
||
|
|
const speech = (async (url: URL | RequestInfo, init?: RequestInit) => {
|
||
|
|
assert(String(url).startsWith("https://api.elevenlabs.io/v1/text-to-speech/voice/stream"));
|
||
|
|
speechRequest = init;
|
||
|
|
return new Response(new Uint8Array([1, 2, 3]), { headers: { "content-type": "audio/mpeg" } });
|
||
|
|
}) as typeof fetch;
|
||
|
|
assert.deepEqual(await synthesize("你好", "fixture-private-key", "voice", signal, speech), new Uint8Array([1, 2, 3]));
|
||
|
|
assert.equal((speechRequest?.headers as Record<string, string>)["xi-api-key"], "fixture-private-key");
|
||
|
|
assert.equal(JSON.parse(speechRequest?.body as string).model_id, "eleven_multilingual_v2");
|
||
|
|
await assert.rejects(() => synthesize("你好", "", "voice", signal, speech), /API key/);
|
||
|
|
await assert.rejects(() => synthesize("中".repeat(1201), "key", "voice", signal, speech), /1,200/);
|
||
|
|
await assert.rejects(
|
||
|
|
() => synthesize("你好", "key", "voice", signal, (async () => new Response("", { status: 401 })) as typeof fetch),
|
||
|
|
/did not accept/,
|
||
|
|
);
|
||
|
|
console.log("PASS Wikipedia bounds, identification, attribution, cache and speech headers/errors");
|