test(e2e): stabilize fixture imports

This commit is contained in:
2026-07-03 14:43:45 +08:00
parent 873a0a8bce
commit e22c5dfb78
9 changed files with 20 additions and 19 deletions
@@ -0,0 +1,114 @@
import { expect, test } from "@playwright/test";
import { mockCoreApis } from "@e2e/fixtures/api-mocks";
import {
clearBrowserState,
completeVipPayment,
dismissChatInterruptions,
enterChatFromSplash,
expectAuthRedirectToVipChatSubscription,
expectVipChatSubscriptionUrl,
submitEmailLogin,
switchToEmailSignIn,
} from "@e2e/fixtures/test-helpers";
const mockedLimitTriggerAt = 5;
const maxManualTestMessages = 51;
test.setTimeout(90_000);
test.beforeEach(async ({ baseURL, context, page }) => {
await clearBrowserState(context, page, baseURL);
await mockCoreApis(page, {
chatLimitTriggerAt: mockedLimitTriggerAt,
});
});
test("guest hits the chat quantity limit and can continue to login and subscription", async ({
page,
}) => {
await enterChatFromSplash(page);
await dismissChatInterruptions(page);
const messageInput = page.getByRole("textbox", { name: "Message" });
const quantityLimitBanner = page
.getByRole("status")
.filter({ hasText: "Insufficient credits" });
let limitTriggeredAt: number | null = null;
let completedSendCount = 0;
await expect(messageInput).toBeVisible({ timeout: 10_000 });
for (let index = 1; index <= maxManualTestMessages; index += 1) {
const message = `limit test ${String(index).padStart(2, "0")}`;
await dismissChatInterruptions(page);
if (completedSendCount > 0) {
const inputStillVisible = await messageInput.isVisible().catch(() => false);
if (!inputStillVisible) {
limitTriggeredAt = completedSendCount;
break;
}
}
if (await isQuantityLimitVisible(quantityLimitBanner)) {
limitTriggeredAt = completedSendCount;
break;
}
await expect(messageInput).toBeVisible();
await messageInput.fill(message);
const sendRequestPromise = page.waitForRequest("**/api/chat/send");
await messageInput.press("Enter");
const sendRequest = await sendRequestPromise;
expect(sendRequest.postDataJSON()).toMatchObject({
message,
});
completedSendCount = index;
if (await isQuantityLimitVisible(quantityLimitBanner)) {
limitTriggeredAt = index;
break;
}
await page.waitForTimeout(1_000);
}
expect(limitTriggeredAt).not.toBeNull();
expect(limitTriggeredAt).toBeLessThanOrEqual(maxManualTestMessages);
expect(limitTriggeredAt).toBe(mockedLimitTriggerAt);
await expect(quantityLimitBanner).toBeVisible();
await expect(messageInput).toHaveCount(0);
const topUpButton = page.getByRole("button", {
name: "Top up credits to continue",
});
await expect(topUpButton).toBeVisible();
await topUpButton.click();
await expect(page).toHaveURL(/\/auth\?redirect=/);
expectAuthRedirectToVipChatSubscription(page);
await switchToEmailSignIn(page);
await submitEmailLogin(page);
await expectVipChatSubscriptionUrl(page);
await completeVipPayment(page);
await expect(page).toHaveURL(/\/chat$/);
await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible();
});
async function isQuantityLimitVisible(
banner: ReturnType<import("@playwright/test").Page["getByTestId"]>,
) {
try {
await banner.waitFor({ state: "visible", timeout: 500 });
return true;
} catch {
return false;
}
}
@@ -0,0 +1,64 @@
import { expect, test, type Request } from "@playwright/test";
import { mockCoreApis } from "@e2e/fixtures/api-mocks";
import {
clearBrowserState,
signInWithEmailAndOpenChat,
} from "@e2e/fixtures/test-helpers";
test.beforeEach(async ({ baseURL, context, page }) => {
await clearBrowserState(context, page, baseURL);
await mockCoreApis(page, {
chatSendTokenRefreshFlow: true,
});
});
test("chat send refreshes an expired token, retries the request, and renders the reply", async ({
page,
}) => {
const chatSendRequests: Request[] = [];
page.on("request", (request) => {
if (new URL(request.url()).pathname === "/api/chat/send") {
chatSendRequests.push(request);
}
});
await signInWithEmailAndOpenChat(page);
const message = "token refresh retry test";
const messageInput = page.getByRole("textbox", { name: "Message" });
await expect(messageInput).toBeVisible({ timeout: 10_000 });
await expect(messageInput).toBeEnabled();
await messageInput.fill(message);
const refreshRequestPromise = page.waitForRequest("**/api/auth/refresh");
const retriedSendResponsePromise = page.waitForResponse(
(response) =>
new URL(response.url()).pathname === "/api/chat/send" &&
response.status() === 200,
);
await messageInput.press("Enter");
const refreshRequest = await refreshRequestPromise;
expect(refreshRequest.method()).toBe("POST");
expect(refreshRequest.headers().authorization).toBeUndefined();
expect(refreshRequest.postDataJSON()).toMatchObject({
refreshToken: "e2e-email-refresh-token",
});
await retriedSendResponsePromise;
await expect.poll(() => chatSendRequests.length).toBe(2);
expect(chatSendRequests[0]?.postDataJSON()).toMatchObject({ message });
expect(chatSendRequests[0]?.headers().authorization).toBe(
"Bearer e2e-email-token",
);
expect(chatSendRequests[1]?.postDataJSON()).toMatchObject({ message });
expect(chatSendRequests[1]?.headers().authorization).toBe(
"Bearer e2e-refreshed-email-token",
);
await expect(page.getByText(message)).toBeVisible();
await expect(page.getByText("Hello from the E2E boyfriend.")).toBeVisible();
});