Adds a Test pronunciation button (forms and list) that plays the passing sound and real announcements with the spoken name through race audio. Fixes the Drivers/Cars search losing focus after one letter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
61 lines
3.5 KiB
JavaScript
61 lines
3.5 KiB
JavaScript
import assert from "node:assert/strict";
|
|
|
|
// Drivers page: the search field keeps focus while a whole name is typed (it used to lose it
|
|
// after the first letter, because every keystroke re-renders the page), and "Test
|
|
// pronunciation" speaks the spoken name - the unsaved one in the form - through race audio.
|
|
export async function runDriversPageSmoke({ evaluate, navigate, savedState, waitFor, base }) {
|
|
const patchState = async (patch) => {
|
|
const current = await savedState();
|
|
Object.assign(current, patch);
|
|
const response = await fetch(base + "/api/state", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(current) });
|
|
assert.equal(response.ok, true);
|
|
};
|
|
const seeded = await savedState();
|
|
await patchState({
|
|
drivers: [...seeded.drivers, { id: "dp_anders", name: "DP Anders", speechName: "Anders the Rocket", transponder: "8550001" }],
|
|
settings: { ...seeded.settings, ttsEngine: "browser", raceAudio: { ...seeded.settings.raceAudio, enabled: true, muted: false, language: "sv", events: {} } },
|
|
});
|
|
|
|
try {
|
|
await navigate("drivers", "driverForm");
|
|
// Type letter by letter, like a person.
|
|
for (const letter of "DP And") {
|
|
const ok = await evaluate(`(() => {
|
|
const input = document.getElementById("driverBrandFilter");
|
|
if (document.activeElement !== input) input.focus();
|
|
input.value += ${JSON.stringify(letter)};
|
|
input.setSelectionRange(input.value.length, input.value.length);
|
|
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
return document.activeElement?.id === "driverBrandFilter";
|
|
})()`);
|
|
assert.equal(ok, true, `focus kept after typing "${letter}"`);
|
|
}
|
|
assert.equal(await evaluate(`document.getElementById("driverBrandFilter").value`), "DP And");
|
|
assert.match(await evaluate(`document.querySelector(".panel table, table")?.innerText || document.body.innerText`), /DP Anders/);
|
|
console.log("PASS the driver search keeps focus so a whole name can be typed");
|
|
|
|
// Capture what the browser voice is asked to say.
|
|
await evaluate(`(() => {
|
|
window.__spoken = [];
|
|
window.speechSynthesis.speak = (utterance) => { window.__spoken.push(utterance.text); setTimeout(() => utterance.onend?.(), 10); };
|
|
})()`);
|
|
await evaluate(`document.querySelector('[data-driver-voice-row="dp_anders"]').click()`);
|
|
await waitFor(async () => (await evaluate(`window.__spoken.join(" | ")`)).includes("Anders the Rocket"), "the saved spoken name is read out");
|
|
|
|
// In the add form: an unsaved nickname is what you hear.
|
|
await evaluate(`(() => {
|
|
window.__spoken = [];
|
|
const form = document.getElementById("driverForm");
|
|
form.elements.name.value = "New Kid";
|
|
form.elements.speechName.value = "Kiddo";
|
|
form.querySelector("[data-driver-voice-test]").click();
|
|
})()`);
|
|
await waitFor(async () => (await evaluate(`window.__spoken.join(" | ")`)).includes("Kiddo"), "the unsaved nickname is read out");
|
|
assert.equal((await savedState()).drivers.some((driver) => driver.name === "New Kid"), false, "testing doesn't save the driver");
|
|
console.log("PASS Test pronunciation reads the spoken name (also an unsaved one) through race audio");
|
|
} finally {
|
|
const current = await savedState();
|
|
await patchState({ drivers: current.drivers.filter((driver) => driver.id !== "dp_anders"), settings: { ...current.settings, raceAudio: seeded.settings.raceAudio, ttsEngine: seeded.settings.ttsEngine } });
|
|
}
|
|
}
|