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:
139
frontend/tests/e2e/auth-persistence.spec.ts
Normal file
139
frontend/tests/e2e/auth-persistence.spec.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* Authentication Persistence Test
|
||||
*
|
||||
* CRITICAL TEST: Ensures authentication persists across page reloads
|
||||
*
|
||||
* This test verifies that:
|
||||
* 1. Cookies are properly set with domain=.lvh.me
|
||||
* 2. Tokens persist in cookies after page reload
|
||||
* 3. The API client correctly sends tokens with requests
|
||||
* 4. Users remain logged in after refreshing the page
|
||||
*
|
||||
* DO NOT REMOVE OR DISABLE THIS TEST
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Authentication Persistence', () => {
|
||||
test('should maintain authentication after page reload', async ({ page }) => {
|
||||
// Navigate to platform subdomain
|
||||
await page.goto('http://platform.lvh.me:5173/');
|
||||
|
||||
// Should see login page
|
||||
await expect(page.locator('h2')).toContainText('Sign in to your account');
|
||||
|
||||
// Fill in credentials
|
||||
await page.fill('input[name="username"]', 'poduck');
|
||||
await page.fill('input[name="password"]', 'starry12');
|
||||
|
||||
// Click sign in
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Wait for navigation/login to complete
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// Check cookies are set
|
||||
const cookies = await page.context().cookies();
|
||||
console.log('Cookies after login:', cookies);
|
||||
|
||||
const accessToken = cookies.find(c => c.name === 'access_token');
|
||||
const refreshToken = cookies.find(c => c.name === 'refresh_token');
|
||||
|
||||
console.log('Access token:', accessToken);
|
||||
console.log('Refresh token:', refreshToken);
|
||||
|
||||
// Verify tokens exist
|
||||
expect(accessToken).toBeTruthy();
|
||||
expect(refreshToken).toBeTruthy();
|
||||
|
||||
// Should be logged in - check for platform dashboard or user content
|
||||
const currentUrl = page.url();
|
||||
console.log('Current URL after login:', currentUrl);
|
||||
|
||||
// Wait for any dashboard content to appear
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// Take screenshot before reload
|
||||
await page.screenshot({ path: 'tests/e2e/before-reload.png' });
|
||||
|
||||
// Get page content before reload
|
||||
const contentBeforeReload = await page.content();
|
||||
console.log('Page title before reload:', await page.title());
|
||||
|
||||
// Reload the page
|
||||
console.log('Reloading page...');
|
||||
|
||||
// Listen to console logs
|
||||
page.on('console', msg => {
|
||||
console.log('BROWSER CONSOLE:', msg.type(), msg.text());
|
||||
});
|
||||
|
||||
// Listen to network requests
|
||||
page.on('request', request => {
|
||||
if (request.url().includes('/api/auth')) {
|
||||
console.log('REQUEST:', request.method(), request.url());
|
||||
}
|
||||
});
|
||||
|
||||
page.on('response', response => {
|
||||
if (response.url().includes('/api/auth')) {
|
||||
console.log('RESPONSE:', response.status(), response.url());
|
||||
}
|
||||
});
|
||||
|
||||
await page.reload();
|
||||
|
||||
// Wait for page to load
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Check cookies after reload
|
||||
const cookiesAfterReload = await page.context().cookies();
|
||||
console.log('Cookies after reload:', cookiesAfterReload);
|
||||
|
||||
const accessTokenAfterReload = cookiesAfterReload.find(c => c.name === 'access_token');
|
||||
const refreshTokenAfterReload = cookiesAfterReload.find(c => c.name === 'refresh_token');
|
||||
|
||||
console.log('Access token after reload:', accessTokenAfterReload);
|
||||
console.log('Refresh token after reload:', refreshTokenAfterReload);
|
||||
|
||||
// Take screenshot after reload
|
||||
await page.screenshot({ path: 'tests/e2e/after-reload.png' });
|
||||
|
||||
// Get page content after reload
|
||||
console.log('Page title after reload:', await page.title());
|
||||
console.log('Current URL after reload:', page.url());
|
||||
|
||||
// Should still have tokens
|
||||
expect(accessTokenAfterReload, 'Access token should persist after reload').toBeTruthy();
|
||||
expect(refreshTokenAfterReload, 'Refresh token should persist after reload').toBeTruthy();
|
||||
|
||||
// Should NOT see login page
|
||||
const hasLoginForm = await page.locator('input[name="username"]').count();
|
||||
expect(hasLoginForm, 'Should not see login form after reload').toBe(0);
|
||||
});
|
||||
|
||||
test('should inspect cookie storage mechanism', async ({ page }) => {
|
||||
// Navigate to platform subdomain
|
||||
await page.goto('http://platform.lvh.me:5173/');
|
||||
|
||||
// Execute script to test cookie utilities
|
||||
const cookieTest = await page.evaluate(() => {
|
||||
// @ts-ignore
|
||||
const { setCookie, getCookie } = window;
|
||||
|
||||
// Test setting a cookie
|
||||
document.cookie = 'test_cookie=test_value;path=/;domain=.lvh.me;SameSite=Lax';
|
||||
|
||||
// Read back
|
||||
const allCookies = document.cookie;
|
||||
|
||||
return {
|
||||
hostname: window.location.hostname,
|
||||
allCookies,
|
||||
testCookie: document.cookie.split(';').find(c => c.includes('test_cookie'))
|
||||
};
|
||||
});
|
||||
|
||||
console.log('Cookie test results:', cookieTest);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user