Files
next-tjwater-drainage-frontend/tests/browser/agent-voice-hydration.e2e.ts
T

86 lines
2.9 KiB
TypeScript

import { expect, test } from "playwright/test";
test("speech capability detection preserves the server hydration tree", async ({ page }) => {
const hydrationErrors: string[] = [];
page.on("console", (message) => {
if (message.type() === "error" && /hydration|server rendered html/i.test(message.text())) {
hydrationErrors.push(message.text());
}
});
await page.addInitScript(() => {
Object.defineProperty(window, "SpeechRecognition", {
configurable: true,
value: class SpeechRecognition {}
});
});
await page.goto("/", { waitUntil: "domcontentloaded" });
await expect(page.getByRole("button", { name: "语音输入" })).toBeVisible();
await expect(page.getByRole("button", { name: "权限批准模式" })).toBeVisible();
expect(hydrationErrors).toEqual([]);
});
test("speech recognition failure clears the active animation and explains the error", async ({ page }) => {
await page.addInitScript(() => {
Object.defineProperty(window, "SpeechRecognition", {
configurable: true,
value: class SpeechRecognition {
onerror: ((event: { error: string }) => void) | null = null;
onend: (() => void) | null = null;
start() {
window.setTimeout(() => {
this.onerror?.({ error: "not-allowed" });
this.onend?.();
}, 20);
}
stop() {
this.onend?.();
}
abort() {}
}
});
});
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "语音输入" }).click();
await expect(page.getByRole("button", { name: "语音输入" })).toHaveAttribute("aria-pressed", "false");
await expect(page.locator('[data-slot="voice-input-pulse"]')).toHaveCount(0);
await expect(page.getByText("无法使用麦克风,请在浏览器地址栏允许麦克风权限后重试")).toBeVisible();
});
test("speech recognition writes final transcript into the prompt", async ({ page }) => {
await page.addInitScript(() => {
Object.defineProperty(window, "SpeechRecognition", {
configurable: true,
value: class SpeechRecognition {
onresult: ((event: { resultIndex: number; results: Array<Array<{ transcript: string }> & { isFinal: boolean }> }) => void) | null = null;
onend: (() => void) | null = null;
start() {
window.setTimeout(() => {
const result = Object.assign([{ transcript: "检查城南泵站水位" }], { isFinal: true });
this.onresult?.({ resultIndex: 0, results: [result] });
}, 20);
}
stop() {
this.onend?.();
}
abort() {}
}
});
});
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: "语音输入" }).click();
await expect(page.getByPlaceholder("输入调度问题,Agent 将通过后端会话流式响应")).toHaveValue("检查城南泵站水位");
});