- Enhanced event creation wizard with multi-step validation - Added advanced QR scanning system with offline support - Implemented comprehensive territory management features - Expanded analytics with export functionality and KPIs - Created complete design token system with theme switching - Added 25+ Playwright test files for comprehensive coverage - Implemented enterprise-grade permission system - Enhanced component library with 80+ React components - Added Firebase integration for deployment - Completed Phase 3 development goals substantially 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
172 lines
6.7 KiB
TypeScript
172 lines
6.7 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Gate Operations Panel', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Login as staff user who has access to gate ops
|
|
await page.goto('/login');
|
|
await page.fill('input[name="email"]', 'staff@example.com');
|
|
await page.fill('input[name="password"]', 'password123');
|
|
await page.click('button[type="submit"]');
|
|
await page.waitForURL('/dashboard');
|
|
});
|
|
|
|
test('should display gate ops panel for authorized users', async ({ page }) => {
|
|
// Navigate to gate ops for a specific event
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Verify page loads and shows main elements
|
|
await expect(page.locator('h1')).toContainText('Gate Operations');
|
|
await expect(page.getByText('Live monitoring dashboard')).toBeVisible();
|
|
|
|
// Verify KPI cards are present
|
|
await expect(page.getByText('Scanned Total')).toBeVisible();
|
|
await expect(page.getByText('Pending Sync')).toBeVisible();
|
|
await expect(page.getByText('Dupes Caught')).toBeVisible();
|
|
|
|
// Verify live scan table is present
|
|
await expect(page.getByText('Live Scan Activity')).toBeVisible();
|
|
await expect(page.locator('table')).toBeVisible();
|
|
await expect(page.getByText('Time')).toBeVisible();
|
|
await expect(page.getByText('Device/Zone')).toBeVisible();
|
|
await expect(page.getByText('Result')).toBeVisible();
|
|
await expect(page.getByText('Latency')).toBeVisible();
|
|
|
|
// Verify scanning control section is present
|
|
await expect(page.getByText('Scanning Control')).toBeVisible();
|
|
});
|
|
|
|
test('should show view-only access for staff users', async ({ page }) => {
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Staff users should see "View Only" badge instead of pause controls
|
|
await expect(page.getByText('View Only - Contact Admin')).toBeVisible();
|
|
|
|
// Should see informational message about admin privileges
|
|
await expect(page.getByText('Only Organization Admins and Super Admins can control scanning operations')).toBeVisible();
|
|
});
|
|
|
|
test('should display real-time data', async ({ page }) => {
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Wait for initial data to load
|
|
await expect(page.locator('table tbody tr')).toHaveCount(1);
|
|
|
|
// Verify KPI numbers are displayed
|
|
const scannedTotal = page.getByTestId('scanned-total') || page.locator('text=tickets today').locator('..').locator('div').first();
|
|
await expect(scannedTotal).toBeVisible();
|
|
|
|
// Verify scan entries have proper structure
|
|
const firstRow = page.locator('table tbody tr').first();
|
|
await expect(firstRow.locator('td')).toHaveCount(5); // Time, Device/Zone, QR, Result, Latency
|
|
});
|
|
|
|
test('should show online/offline status', async ({ page }) => {
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Should show online status badge
|
|
await expect(page.getByText('Online')).toBeVisible();
|
|
});
|
|
|
|
test('should be responsive on mobile', async ({ page }) => {
|
|
// Set mobile viewport
|
|
await page.setViewportSize({ width: 375, height: 667 });
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Verify page is accessible on mobile
|
|
await expect(page.locator('h1')).toBeVisible();
|
|
|
|
// KPI cards should stack vertically on mobile (grid-cols-1)
|
|
const kpiGrid = page.locator('.grid-cols-1');
|
|
await expect(kpiGrid).toBeVisible();
|
|
|
|
// Table should be horizontally scrollable
|
|
await expect(page.locator('.overflow-x-auto')).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('Gate Operations - Admin Controls', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Login as admin user who can control scanning
|
|
await page.goto('/login');
|
|
await page.fill('input[name="email"]', 'admin@example.com');
|
|
await page.fill('input[name="password"]', 'password123');
|
|
await page.click('button[type="submit"]');
|
|
await page.waitForURL('/dashboard');
|
|
});
|
|
|
|
test('should show pause/resume controls for admin users', async ({ page }) => {
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Admin users should see pause scanning button
|
|
const pauseButton = page.getByRole('button', { name: /Pause Scanning|Resume Scanning/ });
|
|
await expect(pauseButton).toBeVisible();
|
|
|
|
// Should not show view-only message
|
|
await expect(page.getByText('View Only - Contact Admin')).not.toBeVisible();
|
|
});
|
|
|
|
test('should toggle scanning state when button is clicked', async ({ page }) => {
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Find the scanning control button
|
|
const controlButton = page.getByRole('button', { name: /Pause Scanning|Resume Scanning/ });
|
|
const initialText = await controlButton.textContent();
|
|
|
|
// Click to toggle
|
|
await controlButton.click();
|
|
|
|
// Verify button text changed
|
|
await expect(controlButton).not.toHaveText(initialText || '');
|
|
|
|
// Should see status change in the description text
|
|
if (initialText?.includes('Pause')) {
|
|
await expect(page.getByText('Scanning is paused - scanners will show pause banner')).toBeVisible();
|
|
} else {
|
|
await expect(page.getByText('Scanners are actively processing tickets')).toBeVisible();
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Gate Operations - Accessibility', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/login');
|
|
await page.fill('input[name="email"]', 'staff@example.com');
|
|
await page.fill('input[name="password"]', 'password123');
|
|
await page.click('button[type="submit"]');
|
|
await page.waitForURL('/dashboard');
|
|
});
|
|
|
|
test('should be keyboard navigable', async ({ page }) => {
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Test keyboard navigation through interactive elements
|
|
await page.keyboard.press('Tab');
|
|
|
|
// Should be able to navigate to table if it has interactive elements
|
|
const focusedElement = page.locator(':focus');
|
|
await expect(focusedElement).toBeVisible();
|
|
});
|
|
|
|
test('should have proper ARIA labels and roles', async ({ page }) => {
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// Table should have proper structure
|
|
await expect(page.locator('table')).toBeVisible();
|
|
await expect(page.locator('thead')).toBeVisible();
|
|
await expect(page.locator('tbody')).toBeVisible();
|
|
|
|
// Headers should be properly associated
|
|
const headers = page.locator('th');
|
|
await expect(headers).toHaveCount(5);
|
|
});
|
|
|
|
test('should have sufficient color contrast', async ({ page }) => {
|
|
await page.goto('/events/event_001/gate-ops');
|
|
|
|
// This would normally use axe-playwright or similar for automated accessibility testing
|
|
// For now, verify key elements are visible
|
|
await expect(page.locator('h1')).toBeVisible();
|
|
await expect(page.getByText('Scanned Total')).toBeVisible();
|
|
await expect(page.locator('table')).toBeVisible();
|
|
});
|
|
}); |