refactor(e2e): organize fixtures by feature
This commit is contained in:
+20
-199
@@ -1,31 +1,11 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
import {
|
||||
apiEnvelope,
|
||||
chatSendResponse,
|
||||
createPaymentOrderResponse,
|
||||
createChatSendResponse,
|
||||
createPaidImageHistoryResponse,
|
||||
createWeeklyLimitChatSendResponse,
|
||||
e2eEmailUser,
|
||||
emptyChatHistoryResponse,
|
||||
emailLoginResponse,
|
||||
guestLoginResponse,
|
||||
insufficientCreditsUnlockImageResponse,
|
||||
insufficientCreditsUnlockVoiceResponse,
|
||||
paidImageChatSendResponse,
|
||||
paidImageUnlockHistoryResponse,
|
||||
paidVoiceHistoryResponse,
|
||||
paidPaymentOrderStatusResponse,
|
||||
paymentPlansResponse,
|
||||
tipPaymentPlansResponse,
|
||||
refreshedEmailLoginResponse,
|
||||
refreshedGuestLoginResponse,
|
||||
userEntitlementsResponse,
|
||||
vipStatusResponse,
|
||||
} from "./test-data";
|
||||
import { registerAuthMocks } from "./api/auth";
|
||||
import { registerChatMocks } from "./api/chat";
|
||||
import { registerPaymentMocks } from "./api/payment";
|
||||
import { registerUserMocks } from "./api/user";
|
||||
|
||||
interface MockCoreApisOptions {
|
||||
export interface MockCoreApisOptions {
|
||||
chatLimitTriggerAt?: number;
|
||||
chatSendTokenRefreshFlow?: boolean;
|
||||
paidImageFlow?: boolean;
|
||||
@@ -33,180 +13,21 @@ interface MockCoreApisOptions {
|
||||
paidVoiceInsufficientCreditsFlow?: boolean;
|
||||
}
|
||||
|
||||
export async function mockCoreApis(
|
||||
page: Page,
|
||||
options: MockCoreApisOptions = {},
|
||||
): Promise<void> {
|
||||
const {
|
||||
chatLimitTriggerAt,
|
||||
chatSendTokenRefreshFlow = false,
|
||||
paidImageFlow = false,
|
||||
paidImageInsufficientCreditsFlow = false,
|
||||
paidVoiceInsufficientCreditsFlow = false,
|
||||
} = options;
|
||||
let sendCount = 0;
|
||||
let hasExpiredChatSend = false;
|
||||
let paidImageRequested = false;
|
||||
let paidImageUnlocked = false;
|
||||
export async function mockCoreApis(page: Page, options: MockCoreApisOptions = {}) {
|
||||
const chatOptions = {
|
||||
chatLimitTriggerAt: options.chatLimitTriggerAt,
|
||||
chatSendTokenRefreshFlow: options.chatSendTokenRefreshFlow ?? false,
|
||||
paidImageFlow: options.paidImageFlow ?? false,
|
||||
paidImageInsufficientCreditsFlow: options.paidImageInsufficientCreditsFlow ?? false,
|
||||
paidVoiceInsufficientCreditsFlow: options.paidVoiceInsufficientCreditsFlow ?? false,
|
||||
};
|
||||
const chatState = { hasExpiredChatSend: false, paidImageRequested: false, paidImageUnlocked: false };
|
||||
|
||||
await page.route("**/api/auth/guest", async (route) => {
|
||||
const response =
|
||||
chatSendTokenRefreshFlow && hasExpiredChatSend
|
||||
? refreshedGuestLoginResponse
|
||||
: guestLoginResponse;
|
||||
await route.fulfill({ json: apiEnvelope(response) });
|
||||
});
|
||||
|
||||
await page.route("**/api/auth/login", async (route) => {
|
||||
if (paidImageFlow) {
|
||||
paidImageRequested = true;
|
||||
}
|
||||
|
||||
await route.fulfill({ json: apiEnvelope(emailLoginResponse) });
|
||||
});
|
||||
|
||||
await page.route("**/api/auth/refresh", async (route) => {
|
||||
await route.fulfill({ json: apiEnvelope(refreshedEmailLoginResponse) });
|
||||
});
|
||||
|
||||
await page.route("**/api/auth/logout", async (route) => {
|
||||
await route.fulfill({ json: apiEnvelope(null) });
|
||||
});
|
||||
|
||||
await page.route("**/api/user/profile", async (route) => {
|
||||
await route.fulfill({ json: apiEnvelope(e2eEmailUser) });
|
||||
});
|
||||
|
||||
await page.route("**/api/user/entitlements", async (route) => {
|
||||
await route.fulfill({ json: apiEnvelope(userEntitlementsResponse) });
|
||||
});
|
||||
|
||||
await page.route("**/api/chat/history**", async (route) => {
|
||||
const response =
|
||||
paidVoiceInsufficientCreditsFlow
|
||||
? paidVoiceHistoryResponse
|
||||
: paidImageInsufficientCreditsFlow
|
||||
? createPaidImageHistoryResponse(false)
|
||||
: paidImageFlow && paidImageRequested
|
||||
? createPaidImageHistoryResponse(paidImageUnlocked)
|
||||
: emptyChatHistoryResponse;
|
||||
|
||||
await route.fulfill({ json: apiEnvelope(response) });
|
||||
});
|
||||
|
||||
await page.route("**/api/chat/send", async (route) => {
|
||||
sendCount += 1;
|
||||
const requestBody = route.request().postDataJSON() as
|
||||
| { message?: unknown }
|
||||
| undefined;
|
||||
const message =
|
||||
typeof requestBody?.message === "string" ? requestBody.message : "";
|
||||
|
||||
if (chatSendTokenRefreshFlow && !hasExpiredChatSend) {
|
||||
hasExpiredChatSend = true;
|
||||
await route.fulfill({
|
||||
status: 401,
|
||||
json: {
|
||||
message: "expired",
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const response =
|
||||
paidImageFlow && message.includes("给我发图片")
|
||||
? paidImageChatSendResponse
|
||||
: chatLimitTriggerAt != null && sendCount >= chatLimitTriggerAt
|
||||
? createWeeklyLimitChatSendResponse(sendCount, chatLimitTriggerAt)
|
||||
: chatLimitTriggerAt != null
|
||||
? createChatSendResponse(sendCount)
|
||||
: chatSendResponse;
|
||||
|
||||
if (paidImageFlow && message.includes("给我发图片")) {
|
||||
paidImageRequested = true;
|
||||
paidImageUnlocked = false;
|
||||
}
|
||||
|
||||
await route.fulfill({ json: apiEnvelope(response) });
|
||||
});
|
||||
|
||||
await page.route("**/api/chat/unlock-history", async (route) => {
|
||||
if (paidImageFlow && paidImageRequested) {
|
||||
paidImageUnlocked = true;
|
||||
}
|
||||
|
||||
const response =
|
||||
paidImageFlow && paidImageRequested
|
||||
? paidImageUnlockHistoryResponse
|
||||
: {
|
||||
unlocked: true,
|
||||
reason: "no_locked_messages",
|
||||
totalLocked: 0,
|
||||
unlockedCount: 0,
|
||||
privateCount: 0,
|
||||
imageCount: 0,
|
||||
voiceCount: 0,
|
||||
requiredCredits: 0,
|
||||
currentCredits: 0,
|
||||
remainingCredits: 0,
|
||||
shortfallCredits: 0,
|
||||
costsByMessage: {},
|
||||
messageIds: [],
|
||||
};
|
||||
|
||||
await route.fulfill({ json: apiEnvelope(response) });
|
||||
});
|
||||
|
||||
await page.route("**/api/chat/unlock-private", async (route) => {
|
||||
const response =
|
||||
paidVoiceInsufficientCreditsFlow
|
||||
? insufficientCreditsUnlockVoiceResponse
|
||||
: paidImageInsufficientCreditsFlow
|
||||
? insufficientCreditsUnlockImageResponse
|
||||
: paidImageFlow && paidImageRequested && !paidImageUnlocked
|
||||
? insufficientCreditsUnlockImageResponse
|
||||
: {
|
||||
unlocked: true,
|
||||
content: "Unlocked message",
|
||||
reason: "ok",
|
||||
creditBalance: 100,
|
||||
creditsCharged: 0,
|
||||
requiredCredits: 0,
|
||||
shortfallCredits: 0,
|
||||
lockDetail: {
|
||||
locked: false,
|
||||
showContent: true,
|
||||
showUpgrade: false,
|
||||
reason: null,
|
||||
hint: null,
|
||||
detail: null,
|
||||
},
|
||||
};
|
||||
|
||||
await route.fulfill({ json: apiEnvelope(response) });
|
||||
});
|
||||
|
||||
await page.route("**/api/payment/plans**", async (route) => {
|
||||
await route.fulfill({ json: apiEnvelope(paymentPlansResponse) });
|
||||
});
|
||||
|
||||
await page.route("**/api/payment/tip-plans**", async (route) => {
|
||||
await route.fulfill({ json: apiEnvelope(tipPaymentPlansResponse) });
|
||||
});
|
||||
|
||||
await page.route("**/api/payment/create-order", async (route) => {
|
||||
await route.fulfill({ json: apiEnvelope(createPaymentOrderResponse) });
|
||||
});
|
||||
|
||||
await page.route("**/api/payment/order-status**", async (route) => {
|
||||
if (paidImageFlow && paidImageRequested) {
|
||||
paidImageUnlocked = true;
|
||||
}
|
||||
|
||||
await route.fulfill({ json: apiEnvelope(paidPaymentOrderStatusResponse) });
|
||||
});
|
||||
|
||||
await page.route("**/api/payment/vip-status**", async (route) => {
|
||||
await route.fulfill({ json: apiEnvelope(vipStatusResponse) });
|
||||
await registerAuthMocks(page, {
|
||||
chatSendTokenRefreshFlow: chatOptions.chatSendTokenRefreshFlow,
|
||||
isChatSendTokenExpired: () => chatState.hasExpiredChatSend,
|
||||
});
|
||||
await registerUserMocks(page);
|
||||
await registerChatMocks(page, chatOptions, chatState);
|
||||
await registerPaymentMocks(page);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user