Initial commit: SmoothSchedule multi-tenant scheduling platform
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>
This commit is contained in:
80
frontend/tests/e2e/login-flow.spec.ts
Normal file
80
frontend/tests/e2e/login-flow.spec.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Login Flow Test
|
||||
* Tests actual login with poduck credentials
|
||||
*/
|
||||
|
||||
test.describe('Login Flow', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to page first
|
||||
await page.goto('http://lvh.me:5173');
|
||||
|
||||
// Then clear storage
|
||||
await page.context().clearCookies();
|
||||
await page.evaluate(() => {
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
});
|
||||
});
|
||||
|
||||
test('should display login page on initial load', async ({ page }) => {
|
||||
await page.goto('http://lvh.me:5173');
|
||||
|
||||
// Wait for page to load
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Should show login page, not loading screen
|
||||
await expect(page.getByRole('heading', { name: /sign in to your account/i })).toBeVisible({ timeout: 10000 });
|
||||
await expect(page.getByPlaceholder(/username/i)).toBeVisible();
|
||||
await expect(page.getByPlaceholder(/password/i)).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: /sign in/i })).toBeVisible();
|
||||
});
|
||||
|
||||
test('should login with poduck credentials and stay on platform.lvh.me', async ({ page }) => {
|
||||
// Start directly on platform subdomain to allow cookies with domain=.localhost
|
||||
await page.goto('http://platform.lvh.me:5173');
|
||||
|
||||
// Wait for login page
|
||||
await page.waitForLoadState('networkidle');
|
||||
await expect(page.getByRole('heading', { name: /sign in to your account/i })).toBeVisible({ timeout: 10000 });
|
||||
|
||||
// Fill in credentials
|
||||
await page.getByPlaceholder(/username/i).fill('poduck');
|
||||
await page.getByPlaceholder(/password/i).fill('starry12');
|
||||
|
||||
// Click sign in
|
||||
await page.getByRole('button', { name: /sign in/i }).click();
|
||||
|
||||
// Should stay on platform.lvh.me:5173 (no redirect needed for platform users)
|
||||
// Tokens are in cookies with domain=.localhost, accessible across subdomains
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Check that we see the platform dashboard
|
||||
await expect(page.getByRole('heading', { name: /platform dashboard/i })).toBeVisible({ timeout: 10000 });
|
||||
|
||||
// Verify we're still on platform subdomain
|
||||
const url = page.url();
|
||||
console.log('Current URL after login:', url);
|
||||
expect(url).toContain('platform.lvh.me:5173');
|
||||
});
|
||||
|
||||
test('should show error on invalid credentials', async ({ page }) => {
|
||||
await page.goto('http://lvh.me:5173');
|
||||
|
||||
// Wait for login page
|
||||
await page.waitForLoadState('networkidle');
|
||||
await expect(page.getByRole('heading', { name: /sign in to your account/i })).toBeVisible({ timeout: 10000 });
|
||||
|
||||
// Fill in invalid credentials
|
||||
await page.getByPlaceholder(/username/i).fill('invaliduser');
|
||||
await page.getByPlaceholder(/password/i).fill('wrongpass');
|
||||
|
||||
// Click sign in
|
||||
await page.getByRole('button', { name: /sign in/i }).click();
|
||||
|
||||
// Should show error message
|
||||
await expect(page.getByText(/invalid credentials/i)).toBeVisible({ timeout: 5000 });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user