test(auth): cover PSID external entry login

This commit is contained in:
2026-07-16 11:55:03 +08:00
parent e730799aa5
commit 0b96b5ed95
5 changed files with 87 additions and 1 deletions
+3
View File
@@ -11,6 +11,7 @@ export interface MockCoreApisOptions {
paidImageFlow?: boolean;
paidImageInsufficientCreditsFlow?: boolean;
paidVoiceInsufficientCreditsFlow?: boolean;
psidLoginFlow?: boolean;
}
export async function mockCoreApis(page: Page, options: MockCoreApisOptions = {}) {
@@ -20,12 +21,14 @@ export async function mockCoreApis(page: Page, options: MockCoreApisOptions = {}
paidImageFlow: options.paidImageFlow ?? false,
paidImageInsufficientCreditsFlow: options.paidImageInsufficientCreditsFlow ?? false,
paidVoiceInsufficientCreditsFlow: options.paidVoiceInsufficientCreditsFlow ?? false,
psidLoginFlow: options.psidLoginFlow ?? false,
};
const chatState = { hasExpiredChatSend: false, paidImageRequested: false, paidImageUnlocked: false };
await registerAuthMocks(page, {
chatSendTokenRefreshFlow: chatOptions.chatSendTokenRefreshFlow,
isChatSendTokenExpired: () => chatState.hasExpiredChatSend,
psidLoginFlow: chatOptions.psidLoginFlow,
});
await registerUserMocks(page);
await registerChatMocks(page, chatOptions, chatState);
+11 -1
View File
@@ -1,14 +1,24 @@
import type { Page } from "@playwright/test";
import { apiEnvelope } from "../data/common";
import { emailLoginResponse, guestLoginResponse, refreshedEmailLoginResponse, refreshedGuestLoginResponse } from "../data/auth";
import { emailLoginResponse, guestLoginResponse, psidLoginResponse, refreshedEmailLoginResponse, refreshedGuestLoginResponse } from "../data/auth";
export interface AuthMockState {
chatSendTokenRefreshFlow: boolean;
isChatSendTokenExpired: () => boolean;
psidLoginFlow: boolean;
}
export async function registerAuthMocks(page: Page, state: AuthMockState) {
await page.route("**/api/auth/login/facebook/psid", async (route) => {
if (!state.psidLoginFlow) {
await route.continue();
return;
}
await route.fulfill({ json: apiEnvelope(psidLoginResponse) });
});
await page.route("**/api/auth/guest", async (route) => {
const response = state.chatSendTokenRefreshFlow && state.isChatSendTokenExpired() ? refreshedGuestLoginResponse : guestLoginResponse;
await route.fulfill({ json: apiEnvelope(response) });
+12
View File
@@ -49,3 +49,15 @@ export const refreshedEmailLoginResponse = {
token: "e2e-refreshed-email-token",
refreshToken: "e2e-refreshed-email-refresh-token",
};
export const psidLoginResponse = {
token: "e2e-psid-guest-token",
refreshToken: "",
matchedBy: "psid",
fbAsid: "",
fbPsid: "e2e-facebook-psid",
hasCompleteFacebookIdentity: false,
isGuest: true,
user: e2eUser,
userId: e2eUser.id,
};
@@ -0,0 +1,46 @@
import { expect, test } from "@playwright/test";
import { mockCoreApis } from "@e2e/fixtures/api-mocks";
import { clearBrowserState } from "@e2e/fixtures/test-helpers";
const psid = "e2e-facebook-psid";
test.beforeEach(async ({ baseURL, context, page }) => {
await clearBrowserState(context, page, baseURL);
await mockCoreApis(page, { psidLoginFlow: true });
});
test("user enters from an external PSID link and becomes a guest", async ({
page,
}) => {
const psidLoginRequestPromise = page.waitForRequest(
"**/api/auth/login/facebook/psid",
);
await page.goto(`/external-entry?target=chat&psid=${psid}`);
const psidLoginRequest = await psidLoginRequestPromise;
expect(psidLoginRequest.method()).toBe("POST");
expect(psidLoginRequest.postDataJSON()).toMatchObject({
psid,
bindToGuest: true,
});
expect(psidLoginRequest.postDataJSON().deviceId).toEqual(expect.any(String));
await expect(page).toHaveURL(/\/chat$/);
await expect(page.getByRole("textbox", { name: "Message" })).toBeVisible();
await expect
.poll(() =>
page.evaluate(() => ({
loginProvider: localStorage.getItem("cozsweet:login_provider"),
guestToken: localStorage.getItem("cozsweet:guest_token"),
psid: localStorage.getItem("cozsweet:psid"),
})),
)
.toMatchObject({
loginProvider: "guest",
guestToken: "e2e-psid-guest-token",
psid,
});
});