Adds Alma (sv), Alan, Northern English, Cori, Alba (British/Scottish) and Joe, John, Norman (American) as optional voices downloaded one at a time from Settings, with gender (measured pitch) and accent shown in the voice lists. The standard install is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
51 lines
3.1 KiB
JavaScript
51 lines
3.1 KiB
JavaScript
import assert from "node:assert/strict";
|
|
|
|
// The voice engine panel in Settings -> Audio: renders its Swedish/English voice status,
|
|
// and the engine choice persists to the backend and survives a reload. Whether Piper is
|
|
// actually installed on the test machine doesn't matter here - generation and fallback
|
|
// are covered by tests/tts.test.js, tests/piper_speech.test.js and the integration test.
|
|
export async function runTtsSettingsSmoke({ evaluate, navigate, savedState, waitFor }) {
|
|
const openAudioTab = async () => {
|
|
await navigate("settings", "settingsForm");
|
|
await evaluate(`document.querySelector('[data-settings-tab="audio"]').click()`);
|
|
await waitFor(async () => Boolean(await evaluate(`document.getElementById("ttsEngine")`)), "voice engine panel rendered");
|
|
};
|
|
|
|
await openAudioTab();
|
|
const panelText = await evaluate(`document.getElementById("ttsSettings").textContent`);
|
|
assert.match(panelText, /Svenska/);
|
|
assert.match(panelText, /English/);
|
|
assert.equal(await evaluate(`document.getElementById("ttsEngine").value`), "browser", "the browser voice stays the default");
|
|
|
|
await evaluate(`(() => { const select = document.getElementById("ttsEngine"); select.value = "piper"; select.dispatchEvent(new Event("change")); })()`);
|
|
await waitFor(async () => (await savedState()).settings.ttsEngine === "piper", "engine choice saved to the backend");
|
|
|
|
await openAudioTab();
|
|
assert.equal(await evaluate(`document.getElementById("ttsEngine").value`), "piper", "the choice survives a reload");
|
|
console.log("PASS the voice engine panel shows Swedish/English status and the Piper choice persists across a reload");
|
|
|
|
// Extra catalog voices are offered with gender and accent, and "Download" asks the server
|
|
// for exactly that voice. The request is intercepted in the page, so nothing is downloaded.
|
|
const button = `document.querySelector('[data-tts-download="en_GB-alan-medium"]')`;
|
|
await waitFor(async () => Boolean(await evaluate(button)), "British voice offered for download");
|
|
assert.match(await evaluate(`${button}.closest(".tts-download-row").textContent`), /Alan \((male|man), (British|brittisk)\)/);
|
|
const requested = await evaluate(`(async () => {
|
|
const realFetch = window.fetch;
|
|
let body = null;
|
|
window.fetch = async (url, options) => {
|
|
if (String(url).includes("/api/tts/install")) { body = options?.body; return new Response("{}", { status: 202 }); }
|
|
return realFetch(url, options);
|
|
};
|
|
try {
|
|
${button}.click();
|
|
for (let i = 0; i < 50 && !body; i += 1) await new Promise((resolve) => setTimeout(resolve, 20));
|
|
return body;
|
|
} finally { window.fetch = realFetch; }
|
|
})()`);
|
|
assert.deepEqual(JSON.parse(requested), { voice: "en_GB-alan-medium" });
|
|
console.log("PASS extra voices are offered with gender and accent, and Download requests just that voice");
|
|
|
|
await evaluate(`(() => { const select = document.getElementById("ttsEngine"); select.value = "browser"; select.dispatchEvent(new Event("change")); })()`);
|
|
await waitFor(async () => (await savedState()).settings.ttsEngine === "browser", "engine reset for the rest of the suite");
|
|
}
|