81 lines
3.3 KiB
TypeScript
81 lines
3.3 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
||
|
||
const homeH1 = (page: import("@playwright/test").Page) => page.getByRole("heading", { level: 1 });
|
||
|
||
const loginHeading = (page: import("@playwright/test").Page) =>
|
||
page.getByRole("heading", { name: "登录" });
|
||
|
||
test.describe("浏览器前进 / 后退触发页面更新", () => {
|
||
test("软导航后 goBack / goForward 换页", async ({ page }) => {
|
||
await page.goto("/zh-CN");
|
||
await expect(homeH1(page)).toContainText("私有影音库");
|
||
|
||
await page.getByRole("link", { name: "登录 / 注册" }).first().click();
|
||
await expect(page).toHaveURL(/\/zh-CN\/auth\/login/);
|
||
await expect(loginHeading(page)).toBeVisible();
|
||
|
||
await page.goBack();
|
||
await expect(page).toHaveURL(/\/zh-CN$/);
|
||
await expect(homeH1(page)).toContainText("私有影音库");
|
||
|
||
await page.goForward();
|
||
await expect(page).toHaveURL(/\/zh-CN\/auth\/login/);
|
||
await expect(loginHeading(page)).toBeVisible();
|
||
});
|
||
|
||
test("history.state 被抹成 null 后仍能后退换页", async ({ page }) => {
|
||
await page.goto("/zh-CN");
|
||
await expect(homeH1(page)).toContainText("私有影音库");
|
||
|
||
// 复现旧 bug:replaceState(null) 让 ClientRouter onPopState 直接 return
|
||
await page.evaluate(() => {
|
||
window.history.replaceState(null, "", window.location.href);
|
||
});
|
||
|
||
await page.locator('a[href="/zh-CN/auth/login"]').first().click();
|
||
await expect(page).toHaveURL(/\/zh-CN\/auth\/login/);
|
||
|
||
await page.goBack();
|
||
await expect(page).toHaveURL(/\/zh-CN$/);
|
||
await expect(homeH1(page)).toContainText("私有影音库");
|
||
});
|
||
|
||
test("setQueryParams 式 replaceState 后跨页后退仍换页", async ({ page }) => {
|
||
await page.goto("/zh-CN/auth/login");
|
||
await expect(loginHeading(page)).toBeVisible();
|
||
|
||
await page.evaluate(() => {
|
||
const url = new URL(window.location.href);
|
||
url.searchParams.set("next", "/zh-CN/library");
|
||
window.history.replaceState(window.history.state, "", url.toString());
|
||
});
|
||
await expect(page).toHaveURL(/next=/);
|
||
|
||
await page.locator('a[href="/zh-CN"]').first().click();
|
||
await expect(page).toHaveURL(/\/zh-CN$/);
|
||
await expect(homeH1(page)).toContainText("私有影音库");
|
||
|
||
await page.goBack();
|
||
await expect(page).toHaveURL(/\/zh-CN\/auth\/login/);
|
||
await expect(loginHeading(page)).toBeVisible();
|
||
});
|
||
|
||
test("绕过守卫写入 null state 后,popstate 兜底仍换页", async ({ page }) => {
|
||
await page.goto("/zh-CN");
|
||
await expect(homeH1(page)).toContainText("私有影音库");
|
||
|
||
// 用原生 replaceState 直接抹掉 state,验证 popstate 兜底(非补丁路径)
|
||
await page.evaluate(() => {
|
||
const proto = History.prototype as History;
|
||
proto.replaceState.call(window.history, null, "", window.location.href);
|
||
});
|
||
|
||
await page.locator('a[href="/zh-CN/auth/login"]').first().click();
|
||
await expect(page).toHaveURL(/\/zh-CN\/auth\/login/);
|
||
|
||
await page.goBack();
|
||
await expect(page).toHaveURL(/\/zh-CN$/);
|
||
await expect(homeH1(page)).toContainText("私有影音库");
|
||
});
|
||
});
|