Files
smoothschedule/frontend/tests/e2e/business-owner-login.spec.ts
poduck 373257469b Add scheduler improvements, API endpoints, and month calendar view
Backend:
- Add /api/customers/ endpoint (CustomerViewSet, CustomerSerializer)
- Add /api/services/ endpoint with Service model and migrations
- Add Resource.type field (STAFF, ROOM, EQUIPMENT) with migration
- Fix EventSerializer to return resource_id, customer_id, service_id
- Add date range filtering to EventViewSet (start_date, end_date params)
- Add create_demo_appointments management command
- Set default brand colors in business API

Frontend:
- Add calendar grid view for month mode in OwnerScheduler
- Fix sidebar navigation active link contrast (bg-white/10)
- Add default primaryColor/secondaryColor fallbacks in useBusiness
- Disable WebSocket (backend not implemented) to stop reconnect loop
- Fix Resource.type.toLowerCase() error by adding type to backend

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:09:04 -05:00

98 lines
3.3 KiB
TypeScript

import { test, expect } from '@playwright/test';
test('business owner login flow', async ({ page }) => {
// Enable console logging
page.on('console', msg => {
const type = msg.type();
const text = msg.text();
// Only log errors, warnings, and our custom debug logs
if (type === 'error' || type === 'warning' || text.includes('Failed to')) {
console.log(`BROWSER ${type.toUpperCase()}:`, text);
}
});
// Enable error logging
page.on('pageerror', error => {
console.error('PAGE ERROR:', error.message);
console.error('STACK:', error.stack);
});
// Track network errors
page.on('requestfailed', request => {
console.error('REQUEST FAILED:', request.url(), request.failure()?.errorText);
});
// Go to the login page
console.log('Navigating to login page...');
await page.goto('http://lvh.me:5173/#/login');
// Wait for the page to load
await page.waitForLoadState('networkidle');
// Take screenshot of initial state
await page.screenshot({ path: 'test-results/01-initial-page.png', fullPage: true });
// Check if DevQuickLogin component loaded
const quickLoginVisible = await page.locator('text=Quick Login (Dev Only)').isVisible().catch(() => false);
console.log('Quick Login visible:', quickLoginVisible);
if (quickLoginVisible) {
// Click the Business Owner button
console.log('Clicking Business Owner button...');
await page.click('button:has-text("Business Owner")');
// Wait for navigation or changes
await page.waitForTimeout(2000);
// Take screenshot after clicking
await page.screenshot({ path: 'test-results/02-after-click.png', fullPage: true });
// Check the current URL
const currentUrl = page.url();
console.log('Current URL:', currentUrl);
// Check if #root has content
const rootContent = await page.locator('#root').innerHTML();
console.log('Root content length:', rootContent.length);
console.log('Root content:', rootContent.substring(0, 500));
// Check full page HTML if root is empty
if (rootContent.length === 0) {
const bodyContent = await page.locator('body').innerHTML();
console.log('\nFull body HTML (first 1000 chars):');
console.log(bodyContent.substring(0, 1000));
// Check for script tags
const scripts = await page.locator('script').count();
console.log('\nNumber of script tags:', scripts);
// Evaluate JavaScript in the page context to check for errors
const jsErrors = await page.evaluate(() => {
// Check if React root exists
const root = document.getElementById('root');
return {
rootExists: !!root,
rootHasChildren: root ? root.childNodes.length : 0,
documentReady: document.readyState,
};
});
console.log('\nJS Context:', JSON.stringify(jsErrors, null, 2));
}
// Check for React errors
const hasReactError = await page.locator('text=/error|failed/i').count();
console.log('\nError count on page:', hasReactError);
} else {
console.log('Quick Login component not found. Page content:');
const bodyText = await page.locator('body').textContent();
console.log(bodyText?.substring(0, 1000));
}
// Wait a bit more to see what happens
await page.waitForTimeout(3000);
// Final screenshot
await page.screenshot({ path: 'test-results/03-final-state.png', fullPage: true });
});