Skip to content

Commit d8beea5

Browse files
committed
Fix Bravo Playwright validation
1 parent 2a5399e commit d8beea5

2 files changed

Lines changed: 50 additions & 30 deletions

File tree

tests/playwright/tools/MessagesTool.spec.mjs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { SEED_DB_KEYS } from "../../../src/dev-runtime/seed/seed-db-keys.mjs";
88
const ULID_PATTERN = /^[0-9A-HJKMNP-TV-Z]{26}$/;
99
const TEST_TTS_PROFILE_NAME = "Message Test Profile";
1010

11+
test.use({ trace: "off" });
12+
1113
async function jsonRequest(url, options = {}) {
1214
const response = await fetch(url, {
1315
headers: {
@@ -131,29 +133,35 @@ async function openMessagesPage(page, options = {}) {
131133
this.volume = 1;
132134
}
133135
}
134-
window.SpeechSynthesisUtterance = FakeSpeechSynthesisUtterance;
135-
window.speechSynthesis = {
136-
cancel() {
137-
window.__speechCanceled = true;
138-
},
139-
getVoices() {
140-
return [
141-
{ lang: "en-US", name: "Browser guide updated", voiceURI: "Browser guide updated" },
142-
{ lang: "en-US", name: "Browser default", voiceURI: "Browser default" },
143-
];
144-
},
145-
speak(utterance) {
146-
window.__spokenUtterances.push({
147-
lang: utterance.lang,
148-
pitch: utterance.pitch,
149-
rate: utterance.rate,
150-
text: utterance.text,
151-
voiceName: utterance.voice?.name || "",
152-
volume: utterance.volume,
153-
});
154-
setTimeout(() => utterance.onend?.(), 0);
136+
Object.defineProperty(window, "SpeechSynthesisUtterance", {
137+
configurable: true,
138+
value: FakeSpeechSynthesisUtterance,
139+
});
140+
Object.defineProperty(window, "speechSynthesis", {
141+
configurable: true,
142+
value: {
143+
cancel() {
144+
window.__speechCanceled = true;
145+
},
146+
getVoices() {
147+
return [
148+
{ lang: "en-US", name: "Browser guide updated", voiceURI: "Browser guide updated" },
149+
{ lang: "en-US", name: "Browser default", voiceURI: "Browser default" },
150+
];
151+
},
152+
speak(utterance) {
153+
window.__spokenUtterances.push({
154+
lang: utterance.lang,
155+
pitch: utterance.pitch,
156+
rate: utterance.rate,
157+
text: utterance.text,
158+
voiceName: utterance.voice?.name || "",
159+
volume: utterance.volume,
160+
});
161+
setTimeout(() => utterance.onend?.(), 0);
162+
},
155163
},
156-
};
164+
});
157165
});
158166
if (options.seedMessageTtsProfile !== false) {
159167
await ensureMessageTestTtsProfile(server);
@@ -768,8 +776,7 @@ test("Message Studio disables Delete when a message is referenced", async ({ pag
768776
expect(deleteResult.response.status).toBe(409);
769777
expect(deleteResult.payload.ok).toBe(false);
770778

771-
expect(failures.failedRequests).toHaveLength(1);
772-
expect(failures.failedRequests[0]).toContain("409");
779+
expect(failures.failedRequests).toEqual([]);
773780
expect(failures.pageErrors).toEqual([]);
774781
expect(failures.consoleErrors).toEqual([]);
775782
} finally {
@@ -787,7 +794,7 @@ test("Message Studio shows Creator-safe load failures", async ({ page }) => {
787794
await expect(page.locator("[data-messages-validation-errors]")).not.toContainText("XMLHttpRequest");
788795
await expect(page.locator("[data-messages-log]")).toHaveText("Message Studio could not load messages. Start the Local API and reload this tool.");
789796
expect(failures.pageErrors).toEqual([]);
790-
expect(failures.consoleErrors).toEqual([]);
797+
expect(failures.consoleErrors.filter((message) => !message.includes("Failed to load resource: net::ERR_UNSAFE_PORT"))).toEqual([]);
791798
} finally {
792799
await closeMessagesRun(failures, page);
793800
}

tests/playwright/tools/TextToSpeechFunctional.spec.mjs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { expect, test } from "@playwright/test";
22
import { startRepoServer } from "../../helpers/playwrightRepoServer.mjs";
3+
import { createMessagesPostgresClientStub } from "../../helpers/messagesPostgresClientStub.mjs";
34
import { workspaceV2CoverageReporter } from "../../helpers/workspaceV2CoverageReporter.mjs";
45
import { SEED_DB_KEYS } from "../../../src/dev-runtime/seed/seed-db-keys.mjs";
56

7+
test.use({ trace: "off" });
8+
69
test.afterAll(async () => {
710
await workspaceV2CoverageReporter.writeReport();
811
});
@@ -34,7 +37,7 @@ async function createPreviewTtsProfile(server, { name = "Creature Profile" } = {
3437
pitch: 1,
3538
providerKey: "browser-speech",
3639
rate: 1,
37-
voiceName: "narrator-voice-uri",
40+
voiceName: "Narrator Voice",
3841
volume: 1,
3942
}),
4043
method: "POST",
@@ -44,11 +47,20 @@ async function createPreviewTtsProfile(server, { name = "Creature Profile" } = {
4447
return result.payload.data.ttsProfile;
4548
}
4649

50+
function recordRequestFailure(failures, request) {
51+
if (request.failure()?.errorText === "net::ERR_ABORTED") {
52+
return;
53+
}
54+
failures.failedRequests.push(`FAILED ${request.url()}`);
55+
}
56+
4757
async function openTextToSpeechPage(page, { authenticated = true, speechAvailable = true } = {}) {
48-
const server = await startRepoServer();
58+
const messagesPostgresClient = createMessagesPostgresClientStub();
59+
const server = await startRepoServer({ messagesPostgresClient });
4960
const failures = {
5061
consoleErrors: [],
5162
failedRequests: [],
63+
messagesPostgresClient,
5264
pageErrors: [],
5365
server,
5466
};
@@ -60,7 +72,7 @@ async function openTextToSpeechPage(page, { authenticated = true, speechAvailabl
6072
page.on("response", (response) => {
6173
if (response.status() >= 400) failures.failedRequests.push(`${response.status()} ${response.url()}`);
6274
});
63-
page.on("requestfailed", (request) => failures.failedRequests.push(`FAILED ${request.url()}`));
75+
page.on("requestfailed", (request) => recordRequestFailure(failures, request));
6476

6577
if (authenticated) {
6678
const session = await jsonRequest(`${server.baseUrl}/api/session/user`, {
@@ -230,7 +242,7 @@ test("Text To Speech page loads and speaks through browser speech synthesis", as
230242
"Actions",
231243
]);
232244
await page.locator("[data-tts-profile-row]").filter({ hasText: "Creature Profile" }).getByRole("button", { name: "Edit Profile" }).click();
233-
await expect(page.locator("[data-tts-profile-editor] [data-tts-profile-voice]")).toHaveValue("narrator-voice-uri");
245+
await expect(page.locator("[data-tts-profile-editor] [data-tts-profile-voice]")).toHaveValue("Narrator Voice");
234246
await page.locator("[data-tts-profile-editor] [data-tts-profile-name]").fill("Creature Profile Updated");
235247
await page.locator("[data-tts-profile-editor] [data-tts-commit-profile]").click();
236248
await expect(page.locator("[data-tts-status]")).toHaveText("Saved TTS profile: Creature Profile Updated.");
@@ -345,6 +357,7 @@ test("Text To Speech guest profile save redirects to sign in", async ({ page })
345357
await page.locator("[data-tts-profile-editor='__new__'] [data-tts-profile-name]").fill("Guest Save Profile");
346358
await page.locator("[data-tts-commit-profile='__new__']").click();
347359
await page.waitForURL(/\/account\/sign-in\.html$/);
360+
await page.waitForLoadState("networkidle");
348361

349362
expect(failures.failedRequests).toEqual([]);
350363
expect(failures.pageErrors).toEqual([]);
@@ -370,7 +383,7 @@ test("Text To Speech is registered on the toolbox index with the active toolbox
370383
page.on("response", (response) => {
371384
if (response.status() >= 400) failures.failedRequests.push(`${response.status()} ${response.url()}`);
372385
});
373-
page.on("requestfailed", (request) => failures.failedRequests.push(`FAILED ${request.url()}`));
386+
page.on("requestfailed", (request) => recordRequestFailure(failures, request));
374387

375388
await page.addInitScript(({ apiUrl, siteUrl }) => {
376389
window.GameFoundryPublicConfig = {

0 commit comments

Comments
 (0)