Files
h2h-prototype/frontend/tests/admin-panel.spec.ts
2026-01-11 18:50:26 -06:00

829 lines
30 KiB
TypeScript

import { test, expect, Page } from '@playwright/test';
/**
* Admin Panel E2E Tests
*
* Tests for the comprehensive Admin Panel functionality including:
* - Dashboard with stats and settings
* - User Management with search, filter, and actions
* - Events tab with CRUD operations
* - Data Tools for wipe and seed
* - Simulation controls
* - Audit Log viewing and filtering
*
* NOTE: These tests require an admin user to be authenticated.
* If no admin user exists, tests will verify the access control behavior.
*/
// Test configuration
const BASE_URL = 'http://localhost:5173';
const API_URL = 'http://localhost:8000';
// Test users - try admin first, then regular users
const TEST_USERS = [
{ email: 'admin@example.com', password: 'admin123', isAdmin: true },
{ email: 'testadmin@example.com', password: 'admin123', isAdmin: true },
{ email: 'alice@example.com', password: 'password123', isAdmin: false },
];
// Helper function to perform login and return success status
async function loginAsUser(page: Page, email: string, password: string): Promise<boolean> {
try {
await page.goto(`${BASE_URL}/login`, { timeout: 10000 });
await page.waitForLoadState('domcontentloaded', { timeout: 10000 });
// Fill in login form using correct selectors from LoginForm.tsx
const emailInput = page.locator('#email');
const passwordInput = page.locator('#password');
await emailInput.fill(email);
await passwordInput.fill(password);
// Submit the form
const submitButton = page.locator('button[type="submit"]');
await submitButton.click();
// Wait for navigation or error
try {
await page.waitForURL(/^(?!.*\/login).*/, { timeout: 8000 });
return true;
} catch {
// Check for error message
const error = page.locator('.bg-error\\/10');
if (await error.isVisible()) {
return false;
}
return false;
}
} catch (error) {
console.log('Login failed:', error);
return false;
}
}
// Helper to set up authentication via localStorage (mock auth)
// NOTE: Must be called BEFORE navigating to the page
async function setupMockAuth(page: Page): Promise<void> {
// Create mock auth tokens - must use access_token key (not token)
const mockToken = 'mock_admin_token_for_testing';
// Set localStorage before page loads
await page.addInitScript((token) => {
localStorage.setItem('access_token', token);
localStorage.setItem('refresh_token', 'mock_refresh_token');
}, mockToken);
}
// Helper to mock the auth/me endpoint
async function mockAuthMe(page: Page): Promise<void> {
await page.route(`${API_URL}/api/v1/auth/me`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
id: 1,
email: 'admin@example.com',
username: 'admin',
display_name: 'Admin User',
is_admin: true,
}),
});
});
}
// Helper to navigate to admin page
async function navigateToAdmin(page: Page): Promise<void> {
await page.goto(`${BASE_URL}/admin`, { timeout: 15000 });
await page.waitForLoadState('domcontentloaded');
}
// ============================================================================
// Test Suite: Access Control (No Auth Required)
// ============================================================================
test.describe('Admin Panel - Access Control', () => {
test('should redirect to login when not authenticated', async ({ page }) => {
await page.goto(`${BASE_URL}/admin`);
await page.waitForLoadState('networkidle', { timeout: 10000 });
// Should be on login page
await expect(page).toHaveURL(/.*login/);
await expect(page.locator('h2:has-text("Login to your account")')).toBeVisible();
});
test('should show login form with correct fields', async ({ page }) => {
await page.goto(`${BASE_URL}/login`);
await page.waitForLoadState('domcontentloaded');
// Verify login form elements
await expect(page.locator('#email')).toBeVisible();
await expect(page.locator('#password')).toBeVisible();
await expect(page.locator('button[type="submit"]:has-text("Login")')).toBeVisible();
});
test('should show error for invalid credentials', async ({ page }) => {
await page.goto(`${BASE_URL}/login`);
await page.locator('#email').fill('invalid@example.com');
await page.locator('#password').fill('wrongpassword');
await page.locator('button[type="submit"]').click();
// Wait for error message
await expect(page.locator('.bg-error\\/10')).toBeVisible({ timeout: 5000 });
});
});
// ============================================================================
// Test Suite: Admin Panel UI Components (With Mocked Auth)
// ============================================================================
test.describe('Admin Panel - UI Structure (Mocked Auth)', () => {
test.beforeEach(async ({ page }) => {
// Setup mock authentication - localStorage
await setupMockAuth(page);
// Mock auth/me endpoint
await mockAuthMe(page);
// Mock the admin API responses
await page.route(`${API_URL}/api/v1/admin/dashboard`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
total_users: 25,
active_users: 20,
suspended_users: 2,
admin_users: 3,
total_events: 10,
upcoming_events: 5,
live_events: 2,
total_bets: 50,
open_bets: 15,
matched_bets: 20,
total_volume: 5000,
escrow_locked: 1000,
simulation_running: false,
}),
});
});
await page.route(`${API_URL}/api/v1/admin/settings`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
id: 1,
default_house_commission_percent: 2.5,
default_min_bet_amount: 10,
default_max_bet_amount: 1000,
default_min_spread: -20,
default_max_spread: 20,
spread_increment: 0.5,
platform_name: 'H2H',
maintenance_mode: false,
}),
});
});
});
test('should display Admin Panel header', async ({ page }) => {
await navigateToAdmin(page);
await expect(page.locator('h1:has-text("Admin Panel")')).toBeVisible({ timeout: 10000 });
await expect(page.locator('text=Manage the H2H platform')).toBeVisible();
});
test('should display all navigation tabs', async ({ page }) => {
await navigateToAdmin(page);
const expectedTabs = ['Dashboard', 'Users', 'Events', 'Data Tools', 'Simulation', 'Audit Log'];
for (const tabName of expectedTabs) {
await expect(page.locator(`button:has-text("${tabName}")`)).toBeVisible({ timeout: 5000 });
}
});
test('should display dashboard stats', async ({ page }) => {
await navigateToAdmin(page);
await page.waitForLoadState('networkidle', { timeout: 10000 });
// Check stat cards
await expect(page.locator('text=Total Users')).toBeVisible({ timeout: 5000 });
await expect(page.locator('text=Total Events')).toBeVisible();
await expect(page.locator('text=Total Bets')).toBeVisible();
await expect(page.locator('text=Total Volume')).toBeVisible();
});
test('should display Platform Settings when loaded', async ({ page }) => {
await navigateToAdmin(page);
await page.waitForLoadState('networkidle', { timeout: 10000 });
await expect(page.locator('h2:has-text("Platform Settings")')).toBeVisible({ timeout: 5000 });
await expect(page.locator('text=House Commission')).toBeVisible();
});
});
// ============================================================================
// Test Suite: Users Tab (With Mocked Auth)
// ============================================================================
test.describe('Admin Panel - Users Tab (Mocked Auth)', () => {
test.beforeEach(async ({ page }) => {
// Setup mock authentication - localStorage
await setupMockAuth(page);
// Mock auth/me endpoint
await mockAuthMe(page);
// Mock admin API responses
await page.route(`${API_URL}/api/v1/admin/dashboard`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ total_users: 10, simulation_running: false }),
});
});
await page.route(`${API_URL}/api/v1/admin/settings`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 1, default_house_commission_percent: 2.5 }),
});
});
await page.route(`${API_URL}/api/v1/admin/users**`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
users: [
{
id: 1,
email: 'alice@example.com',
username: 'alice',
status: 'active',
is_admin: false,
balance: 1000,
escrow: 0,
wins: 5,
losses: 3,
win_rate: 0.625,
created_at: '2024-01-01T00:00:00Z',
},
{
id: 2,
email: 'bob@example.com',
username: 'bob',
status: 'active',
is_admin: false,
balance: 500,
escrow: 100,
wins: 2,
losses: 4,
win_rate: 0.333,
created_at: '2024-01-02T00:00:00Z',
},
],
total: 2,
page: 1,
page_size: 20,
}),
});
});
await navigateToAdmin(page);
await page.locator('button:has-text("Users")').click();
await page.waitForLoadState('networkidle', { timeout: 10000 });
});
test('should display search input', async ({ page }) => {
await expect(page.locator('input[placeholder*="Search"]')).toBeVisible({ timeout: 5000 });
});
test('should display status filter dropdown', async ({ page }) => {
const statusFilter = page.locator('select').filter({ hasText: /All Status/ });
await expect(statusFilter).toBeVisible();
});
test('should display users table headers', async ({ page }) => {
const headers = ['User', 'Status', 'Balance', 'Stats', 'Joined', 'Actions'];
for (const header of headers) {
await expect(page.locator(`th:has-text("${header}")`)).toBeVisible({ timeout: 5000 });
}
});
test('should display user data in table', async ({ page }) => {
await expect(page.locator('text=alice')).toBeVisible({ timeout: 5000 });
await expect(page.locator('text=bob')).toBeVisible();
});
test('should allow typing in search input', async ({ page }) => {
const searchInput = page.locator('input[placeholder*="Search"]');
await searchInput.fill('test@example.com');
await expect(searchInput).toHaveValue('test@example.com');
});
test('should change status filter', async ({ page }) => {
const statusFilter = page.locator('select').filter({ hasText: /All Status/ });
await statusFilter.selectOption('active');
await expect(statusFilter).toHaveValue('active');
});
});
// ============================================================================
// Test Suite: Events Tab (With Mocked Auth)
// ============================================================================
test.describe('Admin Panel - Events Tab (Mocked Auth)', () => {
test.beforeEach(async ({ page }) => {
// Setup mock authentication - localStorage
await setupMockAuth(page);
// Mock auth/me endpoint
await mockAuthMe(page);
await page.route(`${API_URL}/api/v1/admin/dashboard`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ total_users: 10, simulation_running: false }),
});
});
await page.route(`${API_URL}/api/v1/admin/settings`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 1, default_house_commission_percent: 2.5 }),
});
});
await page.route(`${API_URL}/api/v1/admin/events**`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{
id: 1,
sport: 'football',
home_team: 'Team A',
away_team: 'Team B',
official_spread: -3.5,
game_time: '2024-02-01T19:00:00Z',
venue: 'Stadium',
league: 'NFL',
status: 'upcoming',
},
]),
});
});
await navigateToAdmin(page);
await page.locator('button:has-text("Events")').click();
await page.waitForLoadState('networkidle', { timeout: 10000 });
});
test('should display Create Event button', async ({ page }) => {
await expect(page.locator('button:has-text("Create Event")')).toBeVisible({ timeout: 5000 });
});
test('should display All Events section', async ({ page }) => {
await expect(page.locator('h2:has-text("All Events")')).toBeVisible({ timeout: 5000 });
});
test('should open create event form', async ({ page }) => {
await page.locator('button:has-text("Create Event")').click();
await expect(page.locator('h2:has-text("Create New Event")')).toBeVisible({ timeout: 5000 });
});
test('should display form fields when creating event', async ({ page }) => {
await page.locator('button:has-text("Create Event")').click();
await expect(page.locator('label:has-text("Home Team")')).toBeVisible();
await expect(page.locator('label:has-text("Away Team")')).toBeVisible();
await expect(page.locator('label:has-text("Official Spread")')).toBeVisible();
await expect(page.locator('label:has-text("Game Time")')).toBeVisible();
});
test('should close form when clicking Cancel', async ({ page }) => {
await page.locator('button:has-text("Create Event")').click();
await expect(page.locator('h2:has-text("Create New Event")')).toBeVisible();
await page.locator('button:has-text("Cancel")').first().click();
await expect(page.locator('h2:has-text("Create New Event")')).not.toBeVisible();
});
test('should display event in list', async ({ page }) => {
await expect(page.locator('text=Team A vs Team B')).toBeVisible({ timeout: 5000 });
});
});
// ============================================================================
// Test Suite: Data Tools Tab (With Mocked Auth)
// ============================================================================
test.describe('Admin Panel - Data Tools Tab (Mocked Auth)', () => {
test.beforeEach(async ({ page }) => {
// Setup mock authentication - localStorage
await setupMockAuth(page);
// Mock auth/me endpoint
await mockAuthMe(page);
await page.route(`${API_URL}/api/v1/admin/dashboard`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ total_users: 10, simulation_running: false }),
});
});
await page.route(`${API_URL}/api/v1/admin/settings`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 1, default_house_commission_percent: 2.5 }),
});
});
await page.route(`${API_URL}/api/v1/admin/data/wipe/preview`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
users_count: 10,
spread_bets_count: 25,
events_count: 5,
transactions_count: 50,
can_wipe: true,
cooldown_remaining_seconds: 0,
}),
});
});
await navigateToAdmin(page);
await page.locator('button:has-text("Data Tools")').click();
await page.waitForLoadState('networkidle', { timeout: 10000 });
});
test('should display Data Wiper section', async ({ page }) => {
await expect(page.locator('h2:has-text("Data Wiper")')).toBeVisible({ timeout: 5000 });
});
test('should display Danger Zone warning', async ({ page }) => {
await expect(page.locator('text=Danger Zone')).toBeVisible();
});
test('should display wipe preview counts', async ({ page }) => {
await expect(page.locator('text=Users')).toBeVisible();
await expect(page.locator('text=Spread Bets')).toBeVisible();
await expect(page.locator('text=Events')).toBeVisible();
await expect(page.locator('text=Transactions')).toBeVisible();
});
test('should display Data Seeder section', async ({ page }) => {
await expect(page.locator('h2:has-text("Data Seeder")')).toBeVisible({ timeout: 5000 });
});
test('should display seed configuration inputs', async ({ page }) => {
await expect(page.locator('label:has-text("Number of Users")')).toBeVisible();
await expect(page.locator('label:has-text("Number of Events")')).toBeVisible();
await expect(page.locator('label:has-text("Bets per Event")')).toBeVisible();
await expect(page.locator('label:has-text("Starting Balance")')).toBeVisible();
});
test('should have Wipe Database button', async ({ page }) => {
await expect(page.locator('button:has-text("Wipe Database")')).toBeVisible();
});
test('should have Seed Database button', async ({ page }) => {
await expect(page.locator('button:has-text("Seed Database")')).toBeVisible();
});
test('should open wipe confirmation modal', async ({ page }) => {
await page.locator('button:has-text("Wipe Database")').click();
await expect(page.locator('h3:has-text("Confirm Database Wipe")')).toBeVisible({ timeout: 5000 });
});
test('should require confirmation phrase in wipe modal', async ({ page }) => {
await page.locator('button:has-text("Wipe Database")').click();
await expect(page.locator('input[placeholder="CONFIRM WIPE"]')).toBeVisible();
// Wipe Data button should be disabled
const wipeDataButton = page.locator('button:has-text("Wipe Data")');
await expect(wipeDataButton).toBeDisabled();
});
test('should close wipe modal when clicking Cancel', async ({ page }) => {
await page.locator('button:has-text("Wipe Database")').click();
await expect(page.locator('h3:has-text("Confirm Database Wipe")')).toBeVisible();
await page.locator('.fixed button:has-text("Cancel")').click();
await expect(page.locator('h3:has-text("Confirm Database Wipe")')).not.toBeVisible();
});
});
// ============================================================================
// Test Suite: Simulation Tab (With Mocked Auth)
// ============================================================================
test.describe('Admin Panel - Simulation Tab (Mocked Auth)', () => {
test.beforeEach(async ({ page }) => {
// Setup mock authentication - localStorage
await setupMockAuth(page);
// Mock auth/me endpoint
await mockAuthMe(page);
await page.route(`${API_URL}/api/v1/admin/dashboard`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ total_users: 10, simulation_running: false }),
});
});
await page.route(`${API_URL}/api/v1/admin/settings`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 1, default_house_commission_percent: 2.5 }),
});
});
await page.route(`${API_URL}/api/v1/admin/simulation/status`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
is_running: false,
started_by: null,
started_at: null,
iterations_completed: 0,
last_activity: null,
config: {
delay_seconds: 2.0,
actions_per_iteration: 3,
create_users: true,
create_bets: true,
take_bets: true,
add_comments: true,
cancel_bets: true,
},
}),
});
});
await navigateToAdmin(page);
await page.locator('button:has-text("Simulation")').click();
await page.waitForLoadState('networkidle', { timeout: 10000 });
});
test('should display Activity Simulation header', async ({ page }) => {
await expect(page.locator('h2:has-text("Activity Simulation")')).toBeVisible({ timeout: 5000 });
});
test('should display simulation status badge (Stopped)', async ({ page }) => {
await expect(page.locator('span:has-text("Stopped")')).toBeVisible();
});
test('should display Start Simulation button when stopped', async ({ page }) => {
await expect(page.locator('button:has-text("Start Simulation")')).toBeVisible();
});
test('should display Configure button when stopped', async ({ page }) => {
await expect(page.locator('button:has-text("Configure")')).toBeVisible();
});
test('should show configuration panel when clicking Configure', async ({ page }) => {
await page.locator('button:has-text("Configure")').click();
await expect(page.locator('h3:has-text("Simulation Configuration")')).toBeVisible({ timeout: 5000 });
});
test('should display configuration options', async ({ page }) => {
await page.locator('button:has-text("Configure")').click();
await expect(page.locator('label:has-text("Delay")')).toBeVisible();
await expect(page.locator('label:has-text("Actions per Iteration")')).toBeVisible();
await expect(page.locator('text=Create Users')).toBeVisible();
await expect(page.locator('text=Create Bets')).toBeVisible();
});
});
// ============================================================================
// Test Suite: Audit Log Tab (With Mocked Auth)
// ============================================================================
test.describe('Admin Panel - Audit Log Tab (Mocked Auth)', () => {
test.beforeEach(async ({ page }) => {
// Setup mock authentication - localStorage
await setupMockAuth(page);
// Mock auth/me endpoint
await mockAuthMe(page);
await page.route(`${API_URL}/api/v1/admin/dashboard`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ total_users: 10, simulation_running: false }),
});
});
await page.route(`${API_URL}/api/v1/admin/settings`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 1, default_house_commission_percent: 2.5 }),
});
});
await page.route(`${API_URL}/api/v1/admin/audit-logs**`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
logs: [
{
id: 1,
action: 'DATA_SEED',
description: 'Seeded database with test data',
admin_username: 'admin',
target_type: null,
target_id: null,
details: '{"num_users": 10}',
ip_address: '127.0.0.1',
created_at: '2024-01-15T10:30:00Z',
},
{
id: 2,
action: 'USER_STATUS_CHANGE',
description: 'Changed user status',
admin_username: 'admin',
target_type: 'user',
target_id: 5,
details: '{"old_status": "active", "new_status": "suspended"}',
ip_address: '127.0.0.1',
created_at: '2024-01-14T15:00:00Z',
},
],
total: 2,
page: 1,
page_size: 25,
}),
});
});
await navigateToAdmin(page);
await page.locator('button:has-text("Audit Log")').click();
await page.waitForLoadState('networkidle', { timeout: 10000 });
});
test('should display Audit Log header', async ({ page }) => {
await expect(page.locator('h2:has-text("Audit Log")')).toBeVisible({ timeout: 5000 });
});
test('should display action filter dropdown', async ({ page }) => {
const filterDropdown = page.locator('select').filter({ hasText: /All Actions/ });
await expect(filterDropdown).toBeVisible();
});
test('should display log entries', async ({ page }) => {
await expect(page.locator('text=Seeded database with test data')).toBeVisible({ timeout: 5000 });
});
test('should display log action badges', async ({ page }) => {
await expect(page.locator('text=Data Seed')).toBeVisible();
});
test('should change filter selection', async ({ page }) => {
const filterDropdown = page.locator('select').filter({ hasText: /All Actions/ });
await filterDropdown.selectOption('DATA_WIPE');
await expect(filterDropdown).toHaveValue('DATA_WIPE');
});
});
// ============================================================================
// Test Suite: Tab Navigation (With Mocked Auth)
// ============================================================================
test.describe('Admin Panel - Tab Navigation (Mocked Auth)', () => {
test.beforeEach(async ({ page }) => {
// Setup mock authentication - localStorage
await setupMockAuth(page);
// Mock auth/me endpoint
await mockAuthMe(page);
// Mock all admin API endpoints
await page.route(`${API_URL}/api/v1/admin/**`, async (route) => {
const url = route.request().url();
if (url.includes('dashboard')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ total_users: 10, simulation_running: false }),
});
} else if (url.includes('settings')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 1, default_house_commission_percent: 2.5 }),
});
} else if (url.includes('users')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ users: [], total: 0, page: 1, page_size: 20 }),
});
} else if (url.includes('events')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([]),
});
} else if (url.includes('wipe/preview')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ users_count: 0, spread_bets_count: 0, events_count: 0, transactions_count: 0, can_wipe: true }),
});
} else if (url.includes('simulation/status')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ is_running: false, config: {} }),
});
} else if (url.includes('audit-logs')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ logs: [], total: 0, page: 1, page_size: 25 }),
});
} else {
await route.continue();
}
});
await navigateToAdmin(page);
});
test('should switch between all tabs', async ({ page }) => {
const tabs = [
{ name: 'Users', indicator: 'Search' },
{ name: 'Events', indicator: 'Create Event' },
{ name: 'Data Tools', indicator: 'Data Wiper' },
{ name: 'Simulation', indicator: 'Activity Simulation' },
{ name: 'Audit Log', indicator: 'Audit Log' },
{ name: 'Dashboard', indicator: 'Total Users' },
];
for (const tab of tabs) {
await page.locator(`button:has-text("${tab.name}")`).click();
await page.waitForLoadState('networkidle', { timeout: 5000 });
const indicator = page.locator(`text=${tab.indicator}`).first();
await expect(indicator).toBeVisible({ timeout: 5000 });
}
});
test('should highlight active tab', async ({ page }) => {
// Click Users tab and verify it's highlighted
await page.locator('button:has-text("Users")').click();
const usersTab = page.locator('button:has-text("Users")');
await expect(usersTab).toHaveClass(/text-blue-600|border-blue-600|bg-blue-50/);
});
});
// ============================================================================
// Test Suite: Responsive Behavior
// ============================================================================
test.describe('Admin Panel - Responsive Behavior', () => {
test.beforeEach(async ({ page }) => {
// Setup mock authentication - localStorage
await setupMockAuth(page);
// Mock auth/me endpoint
await mockAuthMe(page);
await page.route(`${API_URL}/api/v1/admin/**`, async (route) => {
const url = route.request().url();
if (url.includes('dashboard')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ total_users: 10, simulation_running: false }),
});
} else if (url.includes('settings')) {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: 1, default_house_commission_percent: 2.5 }),
});
} else {
await route.continue();
}
});
});
test('should render on tablet viewport', async ({ page }) => {
await page.setViewportSize({ width: 768, height: 1024 });
await navigateToAdmin(page);
await expect(page.locator('h1:has-text("Admin Panel")')).toBeVisible({ timeout: 10000 });
});
test('should render on mobile viewport', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
await navigateToAdmin(page);
await expect(page.locator('h1:has-text("Admin Panel")')).toBeVisible({ timeout: 10000 });
});
});