This commit includes: - Django backend with multi-tenancy (django-tenants) - React + TypeScript frontend with Vite - Platform administration API with role-based access control - Authentication system with token-based auth - Quick login dev tools for testing different user roles - CORS and CSRF configuration for local development - Docker development environment setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
/**
|
|
* Visual Regression Tests
|
|
* Compares implemented components with design specifications
|
|
*/
|
|
|
|
test.describe('Visual Appearance', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Login before each test
|
|
await page.goto('/');
|
|
await page.getByLabel(/username/i).fill('testowner');
|
|
await page.getByLabel(/password/i).fill('testpass123');
|
|
await page.getByRole('button', { name: /login|sign in/i }).click();
|
|
await page.waitForURL(/dashboard|\/$/);
|
|
});
|
|
|
|
test('Dashboard should display key metrics', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Check for metric cards
|
|
const metricCards = page.locator('[class*="metric"], [class*="card"]');
|
|
await expect(metricCards.first()).toBeVisible();
|
|
|
|
// Take screenshot for visual comparison
|
|
await expect(page).toHaveScreenshot('dashboard.png', {
|
|
fullPage: true,
|
|
animations: 'disabled',
|
|
});
|
|
});
|
|
|
|
test('Sidebar navigation should be visible', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Check for sidebar
|
|
const sidebar = page.locator('[class*="sidebar"], nav');
|
|
await expect(sidebar.first()).toBeVisible();
|
|
|
|
// Check for navigation links
|
|
await expect(page.getByRole('link', { name: /dashboard/i })).toBeVisible();
|
|
await expect(page.getByRole('link', { name: /scheduler/i })).toBeVisible();
|
|
await expect(page.getByRole('link', { name: /customers/i })).toBeVisible();
|
|
});
|
|
|
|
test('Top bar should display business name and user info', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Check for top bar elements
|
|
const topBar = page.locator('[class*="topbar"], header').first();
|
|
await expect(topBar).toBeVisible();
|
|
|
|
// Business name or logo should be visible
|
|
await expect(topBar.locator('img, [class*="logo"], h1')).toBeVisible();
|
|
|
|
// User avatar or menu should be visible
|
|
await expect(topBar.locator('[class*="avatar"], [class*="user-menu"]')).toBeVisible();
|
|
});
|
|
|
|
test('Customers page should display customer list', async ({ page }) => {
|
|
await page.goto('/customers');
|
|
|
|
// Check for page heading
|
|
await expect(page.getByRole('heading', { name: /customers/i })).toBeVisible();
|
|
|
|
// Check for customer table or list
|
|
const customerList = page.locator('table, [class*="customer-list"]');
|
|
await expect(customerList.first()).toBeVisible();
|
|
|
|
// Take screenshot
|
|
await expect(page).toHaveScreenshot('customers-page.png', {
|
|
fullPage: true,
|
|
animations: 'disabled',
|
|
});
|
|
});
|
|
|
|
test('Scheduler page should display calendar view', async ({ page }) => {
|
|
await page.goto('/scheduler');
|
|
|
|
// Check for page heading
|
|
await expect(page.getByRole('heading', { name: /scheduler|calendar/i })).toBeVisible();
|
|
|
|
// Check for time slots or calendar grid
|
|
const scheduler = page.locator('[class*="scheduler"], [class*="calendar"]');
|
|
await expect(scheduler.first()).toBeVisible();
|
|
|
|
// Take screenshot
|
|
await expect(page).toHaveScreenshot('scheduler-page.png', {
|
|
fullPage: true,
|
|
animations: 'disabled',
|
|
});
|
|
});
|
|
});
|