78 lines
4.1 KiB
TypeScript
78 lines
4.1 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
import { after, describe, it } from "node:test";
|
|
import { DICTATION_LANGUAGES, deepgramListenUrl, isDictationLanguage } from "../src/core/dictation.ts";
|
|
import { sanitizeUserSettings } from "../src/core/settings.ts";
|
|
import { resolveSettings } from "../src/core/settings-resolution.ts";
|
|
import { parseDictationSettingsBody } from "../src/server/settings-body.ts";
|
|
|
|
describe("Nova-3 dictation language contract", () => {
|
|
it("offers monolingual languages/locales and a distinct multilingual mode", () => {
|
|
assert.equal(DICTATION_LANGUAGES[0]?.code, "multi");
|
|
assert.equal(new Set(DICTATION_LANGUAGES.map((item) => item.code)).size, DICTATION_LANGUAGES.length);
|
|
for (const code of ["en", "pl", "en-GB", "pt-BR", "zh-Hant", "ar-EG", "multi"]) {
|
|
assert.ok(isDictationLanguage(code), code);
|
|
}
|
|
// Xhosa and Zulu are documented for multi, not monolingual Nova-3.
|
|
for (const code of ["xh", "zu", "en-CA", "auto", "xx", "pl&model=other", null, 3]) {
|
|
assert.equal(isDictationLanguage(code), false, String(code));
|
|
}
|
|
const labels = DICTATION_LANGUAGES.slice(1).map((item) => item.label);
|
|
assert.deepEqual(labels, [...labels].sort((a, b) => a.localeCompare(b, "en")));
|
|
});
|
|
|
|
it("only language varies in the streaming URL; all tuned parameters survive", () => {
|
|
for (const language of ["en", "pl", "multi", "en-GB"] as const) {
|
|
const url = new URL(deepgramListenUrl(language));
|
|
assert.equal(url.origin + url.pathname, "wss://api.deepgram.com/v1/listen");
|
|
assert.deepEqual(Object.fromEntries(url.searchParams), {
|
|
model: "nova-3", encoding: "linear16", sample_rate: "16000", channels: "1",
|
|
smart_format: "true", punctuate: "true", endpointing: "300", language,
|
|
});
|
|
}
|
|
});
|
|
|
|
it("old records default to English and explicit preferences resolve without a migration", () => {
|
|
assert.equal(resolveSettings(null).dictation.language, "en");
|
|
assert.equal(resolveSettings({ version: 1 }).dictation.language, "en");
|
|
for (const language of ["pl", "multi", "en-GB"] as const) {
|
|
const record = sanitizeUserSettings({ version: 1, dictation: { language } });
|
|
assert.equal(record?.version, 1);
|
|
assert.equal(resolveSettings(record).dictation.language, language);
|
|
}
|
|
});
|
|
|
|
it("rejects invalid API values and drops invalid stored preferences", () => {
|
|
assert.deepEqual(parseDictationSettingsBody({}), { ok: true, settings: {} });
|
|
assert.deepEqual(parseDictationSettingsBody({ language: "multi" }), { ok: true, settings: { language: "multi" } });
|
|
for (const value of [null, [], "pl", { language: "xx" }, { language: null }, { language: 3 }]) {
|
|
assert.equal(parseDictationSettingsBody(value).ok, false);
|
|
}
|
|
for (const dictation of [null, [], "pl", { language: "xx" }, { language: 3 }]) {
|
|
const record = sanitizeUserSettings({ version: 1, dictation, general: { autoUpdate: false } });
|
|
assert.equal(resolveSettings(record).dictation.language, "en");
|
|
assert.equal(record?.general?.autoUpdate, false);
|
|
}
|
|
});
|
|
});
|
|
|
|
const testData = mkdtempSync(path.join(tmpdir(), "lh-dictation-settings-"));
|
|
process.env.LH_DATA_DIR = testData;
|
|
after(() => { rmSync(testData, { recursive: true, force: true }); });
|
|
const { readSettings, writeSettings } = await import("../src/store/settings.ts");
|
|
|
|
it("the section route persists language independently and rejects unsupported values without writing", async () => {
|
|
const { PUT } = await import("../app/api/settings/[section]/route.ts");
|
|
writeSettings({ version: 1, general: { autoUpdate: false } });
|
|
const put = (language: string) => PUT(new Request("http://localhost/api/settings/dictation", {
|
|
method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ language }),
|
|
}), { params: Promise.resolve({ section: "dictation" }) });
|
|
assert.equal((await put("pl")).status, 200);
|
|
const saved = { version: 1, dictation: { language: "pl" }, general: { autoUpdate: false } };
|
|
assert.deepEqual(readSettings(), saved);
|
|
assert.equal((await put("unsupported")).status, 400);
|
|
assert.deepEqual(readSettings(), saved);
|
|
});
|