Some checks failed
- Global setup: единый логин всех пользователей перед тестами (без rate limit) - Playwright проекты: testMatch привязка файлов к проектам (убрал 5x дублирование) - LP порт: 3004 → 3050 (реальный порт из ecosystem.config) - Theme тесты: мок API через page.route() (предотвращение 401→logout) - Web UI тесты: защита response?.status() ?? 200 от undefined - getCachedTokens(): чтение токенов из файла вместо loginAs в каждом beforeAll Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
import { request } from '@playwright/test';
|
|
import { writeFileSync } from 'fs';
|
|
import { join } from 'path';
|
|
|
|
const API_URL = process.env.E2E_API_URL || 'http://localhost:3000';
|
|
|
|
const TEST_USERS = {
|
|
trainer: { phone: '+70000000010', password: 'trainer123' },
|
|
coordinator: { phone: '+70000000003', password: 'admin123' },
|
|
manager: { phone: '+70000000003', password: 'admin123' },
|
|
receptionist: { phone: '+70000000004', password: 'admin123' },
|
|
clubAdmin: { phone: '+70000000002', password: 'admin123' },
|
|
superAdmin: { phone: '+70000000001', password: 'admin123' },
|
|
};
|
|
|
|
async function loginWithRetry(
|
|
ctx: Awaited<ReturnType<typeof request.newContext>>,
|
|
phone: string,
|
|
password: string,
|
|
): Promise<{ accessToken: string; refreshToken: string }> {
|
|
for (let attempt = 0; attempt < 8; attempt++) {
|
|
const response = await ctx.post(`${API_URL}/v1/auth/login`, {
|
|
data: { phone, password },
|
|
});
|
|
|
|
if (response.status() === 429) {
|
|
const delay = (attempt + 1) * 12_000;
|
|
await new Promise((r) => setTimeout(r, delay));
|
|
continue;
|
|
}
|
|
|
|
if (!response.ok()) {
|
|
throw new Error(`Login failed for ${phone}: ${response.status()}`);
|
|
}
|
|
|
|
const body = await response.json();
|
|
return { accessToken: body.accessToken, refreshToken: body.refreshToken };
|
|
}
|
|
|
|
throw new Error(`Login rate limited after 8 retries for ${phone}`);
|
|
}
|
|
|
|
export default async function globalSetup() {
|
|
const ctx = await request.newContext();
|
|
|
|
// Login all unique users (coordinator and manager share same credentials)
|
|
const uniqueLogins = [
|
|
{ key: 'superAdmin', ...TEST_USERS.superAdmin },
|
|
{ key: 'clubAdmin', ...TEST_USERS.clubAdmin },
|
|
{ key: 'coordinator', ...TEST_USERS.coordinator },
|
|
{ key: 'receptionist', ...TEST_USERS.receptionist },
|
|
{ key: 'trainer', ...TEST_USERS.trainer },
|
|
];
|
|
|
|
const tokens: Record<string, { accessToken: string; refreshToken: string }> = {};
|
|
|
|
for (const user of uniqueLogins) {
|
|
tokens[user.key] = await loginWithRetry(ctx, user.phone, user.password);
|
|
}
|
|
|
|
// manager shares tokens with coordinator
|
|
tokens.manager = tokens.coordinator;
|
|
|
|
// Save to file for test consumption
|
|
const tokenPath = join(__dirname, '.auth-tokens.json');
|
|
writeFileSync(tokenPath, JSON.stringify(tokens, null, 2));
|
|
|
|
await ctx.dispose();
|
|
}
|