Files
blackcanyontickets/reactrebuild0825/tests/theme.spec.ts
dzinesco aa81eb5adb feat: add advanced analytics and territory management system
- Add comprehensive analytics components with export functionality
- Implement territory management with manager performance tracking
- Add seatmap components for venue layout management
- Create customer management features with modal interface
- Add advanced hooks for dashboard flags and territory data
- Implement seat selection and venue management utilities
- Add type definitions for ticketing and seatmap systems

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-26 09:25:10 -06:00

320 lines
10 KiB
TypeScript

import path from 'path';
import { test, expect } from '@playwright/test';
import type { Page } from '@playwright/test';
const DEMO_ACCOUNTS = {
admin: { email: 'admin@example.com', password: 'demo123' },
};
async function takeScreenshot(page: Page, name: string) {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const fileName = `theme_${name}_${timestamp}.png`;
await page.screenshot({
path: path.join('screenshots', fileName),
fullPage: true
});
return fileName;
}
async function loginAsAdmin(page: Page) {
await page.goto('/login');
await page.fill('[data-testid="email-input"]', DEMO_ACCOUNTS.admin.email);
await page.fill('[data-testid="password-input"]', DEMO_ACCOUNTS.admin.password);
await page.click('[data-testid="login-button"]');
await expect(page).toHaveURL('/dashboard', { timeout: 10000 });
}
async function getThemeFromLocalStorage(page: Page) {
return await page.evaluate(() => localStorage.getItem('bct_theme'));
}
async function getDocumentTheme(page: Page) {
return await page.evaluate(() => document.documentElement.classList.contains('dark'));
}
test.describe('Theme Switching', () => {
test.beforeEach(async ({ page }) => {
// Clear theme storage
await page.evaluate(() => {
localStorage.removeItem('bct_theme');
localStorage.removeItem('bct_auth_user');
localStorage.removeItem('bct_auth_remember');
});
});
test('should start with default light theme', async ({ page }) => {
await page.goto('/');
// Should start with light theme
const isDark = await getDocumentTheme(page);
expect(isDark).toBe(false);
await takeScreenshot(page, 'default-light-theme');
// Check theme toggle button shows correct state
await expect(page.locator('[data-testid="theme-toggle"]')).toBeVisible();
});
test('should switch from light to dark theme', async ({ page }) => {
await loginAsAdmin(page);
// Verify starting in light theme
let isDark = await getDocumentTheme(page);
expect(isDark).toBe(false);
await takeScreenshot(page, 'before-dark-switch');
// Click theme toggle
await page.click('[data-testid="theme-toggle"]');
// Should switch to dark theme
isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
// Verify theme is saved to localStorage
const savedTheme = await getThemeFromLocalStorage(page);
expect(savedTheme).toBe('dark');
await takeScreenshot(page, 'after-dark-switch');
// Check visual elements have dark theme classes
await expect(page.locator('body')).toHaveClass(/dark/);
});
test('should switch from dark to light theme', async ({ page }) => {
// Set dark theme initially
await page.evaluate(() => {
localStorage.setItem('bct_theme', 'dark');
document.documentElement.classList.add('dark');
});
await loginAsAdmin(page);
// Verify starting in dark theme
let isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
await takeScreenshot(page, 'before-light-switch');
// Click theme toggle
await page.click('[data-testid="theme-toggle"]');
// Should switch to light theme
isDark = await getDocumentTheme(page);
expect(isDark).toBe(false);
// Verify theme is saved to localStorage
const savedTheme = await getThemeFromLocalStorage(page);
expect(savedTheme).toBe('light');
await takeScreenshot(page, 'after-light-switch');
});
test('should persist theme across page refreshes', async ({ page }) => {
await loginAsAdmin(page);
// Switch to dark theme
await page.click('[data-testid="theme-toggle"]');
let isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
// Refresh the page
await page.reload();
// Theme should persist
isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
const savedTheme = await getThemeFromLocalStorage(page);
expect(savedTheme).toBe('dark');
await takeScreenshot(page, 'dark-theme-after-refresh');
});
test('should persist theme across navigation', async ({ page }) => {
await loginAsAdmin(page);
// Switch to dark theme
await page.click('[data-testid="theme-toggle"]');
await takeScreenshot(page, 'dark-theme-dashboard');
// Navigate to events page
await page.click('[data-testid="nav-events"]');
await expect(page).toHaveURL('/events');
// Theme should persist
const isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
await takeScreenshot(page, 'dark-theme-events-page');
// Navigate back to dashboard
await page.click('[data-testid="nav-dashboard"]');
await expect(page).toHaveURL('/dashboard');
// Theme should still persist
const stillDark = await getDocumentTheme(page);
expect(stillDark).toBe(true);
await takeScreenshot(page, 'dark-theme-dashboard-return');
});
test('should apply theme to all components', async ({ page }) => {
await loginAsAdmin(page);
// Take screenshot in light theme
await takeScreenshot(page, 'components-light-theme');
// Switch to dark theme
await page.click('[data-testid="theme-toggle"]');
// Check that key components have theme applied
await expect(page.locator('[data-testid="sidebar"]')).toHaveClass(/dark/);
await expect(page.locator('[data-testid="header"]')).toHaveClass(/dark/);
await expect(page.locator('[data-testid="main-content"]')).toHaveClass(/dark/);
await takeScreenshot(page, 'components-dark-theme');
});
test('should handle system theme preference', async ({ page }) => {
// Mock system preference for dark theme
await page.emulateMedia({ colorScheme: 'dark' });
await page.goto('/');
// Should respect system preference
await takeScreenshot(page, 'system-dark-preference');
// Mock system preference for light theme
await page.emulateMedia({ colorScheme: 'light' });
await page.reload();
await takeScreenshot(page, 'system-light-preference');
});
test('should show theme toggle with correct icon', async ({ page }) => {
await loginAsAdmin(page);
// In light theme, should show moon icon (to switch to dark)
let isDark = await getDocumentTheme(page);
expect(isDark).toBe(false);
await expect(page.locator('[data-testid="theme-toggle"] [data-testid="moon-icon"]')).toBeVisible();
await takeScreenshot(page, 'theme-toggle-light-mode');
// Switch to dark theme
await page.click('[data-testid="theme-toggle"]');
// In dark theme, should show sun icon (to switch to light)
isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
await expect(page.locator('[data-testid="theme-toggle"] [data-testid="sun-icon"]')).toBeVisible();
await takeScreenshot(page, 'theme-toggle-dark-mode');
});
test('should handle theme toggle keyboard interaction', async ({ page }) => {
await loginAsAdmin(page);
// Focus the theme toggle button
await page.focus('[data-testid="theme-toggle"]');
// Press Enter to toggle theme
await page.keyboard.press('Enter');
// Should switch to dark theme
const isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
await takeScreenshot(page, 'keyboard-theme-toggle');
// Press Space to toggle back
await page.keyboard.press('Space');
// Should switch back to light theme
const isLight = await getDocumentTheme(page);
expect(isLight).toBe(false);
});
test('should maintain proper contrast ratios in both themes', async ({ page }) => {
await loginAsAdmin(page);
// Test light theme contrast
await takeScreenshot(page, 'contrast-light-theme');
// Check text is readable against background
const lightTextColor = await page.locator('h1').evaluate((el) =>
getComputedStyle(el).color
);
const lightBgColor = await page.locator('body').evaluate((el) =>
getComputedStyle(el).backgroundColor
);
console.log('Light theme - Text:', lightTextColor, 'Background:', lightBgColor);
// Switch to dark theme
await page.click('[data-testid="theme-toggle"]');
await takeScreenshot(page, 'contrast-dark-theme');
// Check text is readable against background
const darkTextColor = await page.locator('h1').evaluate((el) =>
getComputedStyle(el).color
);
const darkBgColor = await page.locator('body').evaluate((el) =>
getComputedStyle(el).backgroundColor
);
console.log('Dark theme - Text:', darkTextColor, 'Background:', darkBgColor);
});
test('should handle rapid theme switching', async ({ page }) => {
await loginAsAdmin(page);
// Rapidly toggle theme multiple times
for (let i = 0; i < 5; i++) {
await page.click('[data-testid="theme-toggle"]');
await page.waitForTimeout(100); // Small delay to see the transition
}
// Should end up in dark theme (odd number of clicks)
const isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
await takeScreenshot(page, 'rapid-theme-switching-end');
// Theme should be saved correctly
const savedTheme = await getThemeFromLocalStorage(page);
expect(savedTheme).toBe('dark');
});
test('should handle theme on login page', async ({ page }) => {
await page.goto('/login');
// Theme toggle should be available on login page
await expect(page.locator('[data-testid="theme-toggle"]')).toBeVisible();
await takeScreenshot(page, 'login-page-light-theme');
// Switch to dark theme
await page.click('[data-testid="theme-toggle"]');
const isDark = await getDocumentTheme(page);
expect(isDark).toBe(true);
await takeScreenshot(page, 'login-page-dark-theme');
// Login should maintain theme
await page.fill('[data-testid="email-input"]', DEMO_ACCOUNTS.admin.email);
await page.fill('[data-testid="password-input"]', DEMO_ACCOUNTS.admin.password);
await page.click('[data-testid="login-button"]');
await expect(page).toHaveURL('/dashboard', { timeout: 10000 });
// Theme should persist after login
const stillDark = await getDocumentTheme(page);
expect(stillDark).toBe(true);
await takeScreenshot(page, 'dashboard-after-login-dark-theme');
});
});