refactor(e2e): organize fixtures by feature
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
import { apiEnvelope } from "../data/common";
|
||||
import { emailLoginResponse, guestLoginResponse, refreshedEmailLoginResponse, refreshedGuestLoginResponse } from "../data/auth";
|
||||
|
||||
export interface AuthMockState {
|
||||
chatSendTokenRefreshFlow: boolean;
|
||||
isChatSendTokenExpired: () => boolean;
|
||||
}
|
||||
|
||||
export async function registerAuthMocks(page: Page, state: AuthMockState) {
|
||||
await page.route("**/api/auth/guest", async (route) => {
|
||||
const response = state.chatSendTokenRefreshFlow && state.isChatSendTokenExpired() ? refreshedGuestLoginResponse : guestLoginResponse;
|
||||
await route.fulfill({ json: apiEnvelope(response) });
|
||||
});
|
||||
await page.route("**/api/auth/login", async (route) => {
|
||||
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) });
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
import { apiEnvelope } from "../data/common";
|
||||
import { chatSendResponse, createChatSendResponse, createPaidImageHistoryResponse, createWeeklyLimitChatSendResponse, emptyChatHistoryResponse, insufficientCreditsUnlockImageResponse, insufficientCreditsUnlockVoiceResponse, paidImageChatSendResponse, paidImageUnlockHistoryResponse, paidVoiceHistoryResponse } from "../data/chat";
|
||||
|
||||
export interface ChatMockOptions {
|
||||
chatLimitTriggerAt?: number;
|
||||
chatSendTokenRefreshFlow: boolean;
|
||||
paidImageFlow: boolean;
|
||||
paidImageInsufficientCreditsFlow: boolean;
|
||||
paidVoiceInsufficientCreditsFlow: boolean;
|
||||
}
|
||||
|
||||
export interface ChatMockState {
|
||||
hasExpiredChatSend: boolean;
|
||||
paidImageRequested: boolean;
|
||||
paidImageUnlocked: boolean;
|
||||
}
|
||||
|
||||
export async function registerChatMocks(page: Page, options: ChatMockOptions, state: ChatMockState) {
|
||||
let sendCount = 0;
|
||||
|
||||
await page.route("**/api/chat/history**", async (route) => {
|
||||
const response = options.paidVoiceInsufficientCreditsFlow
|
||||
? paidVoiceHistoryResponse
|
||||
: options.paidImageInsufficientCreditsFlow
|
||||
? createPaidImageHistoryResponse(false)
|
||||
: options.paidImageFlow && state.paidImageRequested
|
||||
? createPaidImageHistoryResponse(state.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 (options.chatSendTokenRefreshFlow && !state.hasExpiredChatSend) {
|
||||
state.hasExpiredChatSend = true;
|
||||
await route.fulfill({ status: 401, json: { message: "expired" } });
|
||||
return;
|
||||
}
|
||||
const response = options.paidImageFlow && message.includes("给我发图片")
|
||||
? paidImageChatSendResponse
|
||||
: options.chatLimitTriggerAt != null && sendCount >= options.chatLimitTriggerAt
|
||||
? createWeeklyLimitChatSendResponse(sendCount, options.chatLimitTriggerAt)
|
||||
: options.chatLimitTriggerAt != null
|
||||
? createChatSendResponse(sendCount)
|
||||
: chatSendResponse;
|
||||
if (options.paidImageFlow && message.includes("给我发图片")) {
|
||||
state.paidImageRequested = true;
|
||||
state.paidImageUnlocked = false;
|
||||
}
|
||||
await route.fulfill({ json: apiEnvelope(response) });
|
||||
});
|
||||
|
||||
await page.route("**/api/chat/unlock-history", async (route) => {
|
||||
if (options.paidImageFlow && state.paidImageRequested) state.paidImageUnlocked = true;
|
||||
const response = options.paidImageFlow && state.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 = options.paidVoiceInsufficientCreditsFlow
|
||||
? insufficientCreditsUnlockVoiceResponse
|
||||
: options.paidImageInsufficientCreditsFlow || options.paidImageFlow && state.paidImageRequested && !state.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) });
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
import { apiEnvelope } from "../data/common";
|
||||
import { createPaymentOrderResponse, paidPaymentOrderStatusResponse, paymentPlansResponse, tipPaymentPlansResponse, vipStatusResponse } from "../data/payment";
|
||||
|
||||
export async function registerPaymentMocks(page: Page) {
|
||||
await page.route("**/api/payment/plans**", async (route) => route.fulfill({ json: apiEnvelope(paymentPlansResponse) }));
|
||||
await page.route("**/api/payment/tip-plans**", async (route) => route.fulfill({ json: apiEnvelope(tipPaymentPlansResponse) }));
|
||||
await page.route("**/api/payment/create-order", async (route) => route.fulfill({ json: apiEnvelope(createPaymentOrderResponse) }));
|
||||
await page.route("**/api/payment/order-status**", async (route) => route.fulfill({ json: apiEnvelope(paidPaymentOrderStatusResponse) }));
|
||||
await page.route("**/api/payment/vip-status", async (route) => route.fulfill({ json: apiEnvelope(vipStatusResponse) }));
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
|
||||
import { apiEnvelope } from "../data/common";
|
||||
import { e2eEmailUser } from "../data/auth";
|
||||
import { userEntitlementsResponse } from "../data/user";
|
||||
|
||||
export async function registerUserMocks(page: Page) {
|
||||
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) });
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user