import { test as base, type APIRequestContext } from '@playwright/test'; /** Shape returned by POST /auth/register and POST /auth/login */ export interface TokenPair { accessToken: string; refreshToken: string; } /** Generates a unique test user payload for each test run. */ export function createTestUser(suffix = Date.now()) { return { phone: `09${String(suffix).slice(-8).padStart(8, '0')}`, password: 'Test@1234!', fullName: `Test User ${suffix}`, email: `testuser${suffix}@goodgo.test`, }; } /** Registers a new user via the API and returns the token pair. */ export async function registerUser( request: APIRequestContext, user = createTestUser(), ): Promise }> { const res = await request.post('/auth/register', { data: user }); if (!res.ok()) { const body = await res.text(); throw new Error(`Register failed (${res.status()}): ${body}`); } const tokens: TokenPair = await res.json(); return { ...tokens, user }; } /** Logs in an existing user and returns the token pair. */ export async function loginUser( request: APIRequestContext, phone: string, password: string, ): Promise { const res = await request.post('/auth/login', { data: { phone, password }, }); if (!res.ok()) { const body = await res.text(); throw new Error(`Login failed (${res.status()}): ${body}`); } return res.json(); } /** * Extended test fixture that provides a pre-authenticated API context. * * Usage: * import { test } from '../fixtures/auth.fixture'; * test('my test', async ({ authedRequest, testTokens }) => { ... }); */ export const test = base.extend<{ testUser: ReturnType; testTokens: TokenPair; authedRequest: APIRequestContext; }>({ testUser: async ({}, use) => { await use(createTestUser()); }, testTokens: async ({ request, testUser }, use) => { const { accessToken, refreshToken } = await registerUser(request, testUser); await use({ accessToken, refreshToken }); }, authedRequest: async ({ playwright, testTokens, baseURL }, use) => { const ctx = await playwright.request.newContext({ baseURL, extraHTTPHeaders: { Authorization: `Bearer ${testTokens.accessToken}`, }, }); await use(ctx); await ctx.dispose(); }, }); export { expect } from '@playwright/test';