65 lines
2.6 KiB
JavaScript
65 lines
2.6 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import {
|
|
announcePassingHelper,
|
|
announceRaceStartedHelper,
|
|
getSessionAnnouncementText,
|
|
selectSpeechVoice,
|
|
} from "../src/runtime_services.js";
|
|
|
|
test("speech voice selection prefers an explicit voice and then the current language", () => {
|
|
const voices = [
|
|
{ name: "English", lang: "en-US", voiceURI: "voice-en", localService: true },
|
|
{ name: "Swedish", lang: "sv-SE", voiceURI: "voice-sv", localService: true },
|
|
];
|
|
|
|
assert.equal(selectSpeechVoice(voices, "voice-en", "sv-SE")?.voiceURI, "voice-en");
|
|
assert.equal(selectSpeechVoice(voices, "", "sv-SE")?.voiceURI, "voice-sv");
|
|
assert.equal(selectSpeechVoice(voices, "missing", "de-DE"), null);
|
|
});
|
|
|
|
test("session announcements distinguish practice from racing", () => {
|
|
const t = (key) => key;
|
|
assert.equal(getSessionAnnouncementText({ type: "open_practice" }, "start", { t }), "timing.practice_started_voice");
|
|
assert.equal(getSessionAnnouncementText({ type: "practice" }, "finish", { t }), "timing.practice_finished_voice");
|
|
assert.equal(getSessionAnnouncementText({ type: "final" }, "start", { t }), "timing.race_started_voice");
|
|
assert.equal(getSessionAnnouncementText({ type: "heat" }, "finish", { t }), "timing.race_finished_voice");
|
|
});
|
|
|
|
test("passing announcement uses the driver's spoken name and beeps while speech is busy", () => {
|
|
const calls = [];
|
|
announcePassingHelper(
|
|
{ displayName: "Anders", speechName: "Ann-ders" },
|
|
{
|
|
state: { settings: { audioEnabled: true, passingSoundMode: "name" } },
|
|
t: () => "Unknown",
|
|
speakText: (value, options) => { calls.push([value, options]); return false; },
|
|
playPassingBeep: () => calls.push(["beep"]),
|
|
}
|
|
);
|
|
|
|
assert.deepEqual(calls, [["Ann-ders", { interrupt: false }], ["beep"]]);
|
|
});
|
|
|
|
test("race start creates an overlay event and plays enabled start cues", async () => {
|
|
const calls = [];
|
|
announceRaceStartedHelper(
|
|
{ id: "session_1", name: "A Final", type: "final" },
|
|
{
|
|
state: { settings: { audioEnabled: true, startSoundEnabled: true, finishVoiceEnabled: true } },
|
|
t: (key) => key,
|
|
pushOverlayEvent: (type, label, options) => calls.push([type, label, options]),
|
|
playStartCue: () => calls.push(["tone"]),
|
|
speakText: (value, options) => calls.push(["speech", value, options]),
|
|
}
|
|
);
|
|
|
|
assert.deepEqual(calls, [
|
|
["start", "A Final • timing.start", { silentCue: true }],
|
|
["tone"],
|
|
]);
|
|
await new Promise((resolve) => setTimeout(resolve, 700));
|
|
assert.deepEqual(calls[2], ["speech", "timing.race_started_voice", { interrupt: true }]);
|
|
});
|