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>
138 lines
5.5 KiB
TypeScript
138 lines
5.5 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Email Verification Flow', () => {
|
|
test('should complete signup and email verification', async ({ page, context }) => {
|
|
// Generate unique email for this test
|
|
const timestamp = Date.now();
|
|
const testEmail = `test${timestamp}@example.com`;
|
|
const testUsername = `testuser${timestamp}`;
|
|
const testPassword = 'TestPassword123!';
|
|
const businessName = `TestBiz${timestamp}`;
|
|
const subdomain = `testbiz${timestamp}`;
|
|
|
|
console.log('\n=== Starting Email Verification Test ===');
|
|
console.log(`Email: ${testEmail}`);
|
|
console.log(`Subdomain: ${subdomain}`);
|
|
|
|
// Step 1: Navigate to signup page on ROOT domain
|
|
console.log('\n1. Navigating to signup page...');
|
|
await page.goto('http://lvh.me:5173/signup');
|
|
|
|
// Wait for page to load
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Step 2: Fill out signup form - Step 1: Account Info
|
|
console.log('2. Filling out account info...');
|
|
await page.getByPlaceholder(/email/i).fill(testEmail);
|
|
await page.getByPlaceholder(/^username/i).fill(testUsername);
|
|
await page.getByPlaceholder(/^password/i).first().fill(testPassword);
|
|
await page.getByPlaceholder(/confirm password/i).fill(testPassword);
|
|
|
|
// Click Next
|
|
await page.getByRole('button', { name: /next/i }).click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Step 3: Fill business info
|
|
console.log('3. Filling out business info...');
|
|
await page.getByPlaceholder(/business name/i).fill(businessName);
|
|
await page.getByPlaceholder(/subdomain/i).fill(subdomain);
|
|
|
|
// Click Next
|
|
await page.getByRole('button', { name: /next/i }).click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Step 4: Select Free plan
|
|
console.log('4. Selecting Free plan...');
|
|
const freeButton = page.locator('button:has-text("Free")').first();
|
|
await freeButton.click();
|
|
|
|
// Click Create Account
|
|
await page.getByRole('button', { name: /create account/i }).click();
|
|
|
|
// Wait for redirect to verification page on business subdomain
|
|
console.log('5. Waiting for redirect to email verification page...');
|
|
await page.waitForURL(`http://${subdomain}.lvh.me:5173/email-verification-required`, {
|
|
timeout: 15000
|
|
});
|
|
|
|
console.log('✓ Signup completed, on email verification page');
|
|
|
|
// Step 5: Verify we're on the email verification required page
|
|
await expect(page.getByText(/email verification required/i)).toBeVisible();
|
|
await expect(page.getByText(testEmail)).toBeVisible();
|
|
|
|
console.log('✓ Email verification page showing correctly');
|
|
|
|
// Step 6: Click resend verification email
|
|
console.log('6. Clicking resend verification email...');
|
|
await page.getByRole('button', { name: /resend verification email/i }).click();
|
|
|
|
// Wait for success message
|
|
await expect(page.getByText(/verification email sent|email sent/i)).toBeVisible({
|
|
timeout: 10000
|
|
});
|
|
|
|
console.log('✓ Verification email resent successfully');
|
|
|
|
// Step 7: Extract token from database
|
|
console.log('7. Extracting verification token from database...');
|
|
|
|
// Use docker exec to get the token
|
|
const { execSync } = require('child_process');
|
|
const tokenQuery = `SELECT email_verification_token FROM users_user WHERE email = '${testEmail}'`;
|
|
const tokenResult = execSync(
|
|
`docker compose exec -T db psql -U postgres -d smoothschedule -t -c "${tokenQuery}"`,
|
|
{ cwd: '/home/poduck/Desktop/smoothschedule', encoding: 'utf-8' }
|
|
);
|
|
|
|
const token = tokenResult.trim();
|
|
console.log(`Token extracted: ${token.substring(0, 20)}...`);
|
|
|
|
// Step 8: Open verification link in new context (simulating clicking email link)
|
|
console.log('8. Opening verification link (simulating email click)...');
|
|
const verificationUrl = `http://${subdomain}.lvh.me:5173/verify-email?token=${token}`;
|
|
console.log(`URL: ${verificationUrl}`);
|
|
|
|
// Open in new page to simulate clicking link from email
|
|
const verifyPage = await context.newPage();
|
|
await verifyPage.goto(verificationUrl);
|
|
await verifyPage.waitForLoadState('networkidle');
|
|
|
|
// Step 9: Verify we're on the verify-email page
|
|
console.log('9. Checking verification page loaded...');
|
|
const currentUrl = verifyPage.url();
|
|
console.log(`Current URL: ${currentUrl}`);
|
|
|
|
// Check that we're on the verify-email page
|
|
expect(currentUrl).toContain('/verify-email');
|
|
expect(currentUrl).toContain(token);
|
|
|
|
// Step 10: Click the "Confirm Verification" button
|
|
console.log('10. Clicking Confirm Verification button...');
|
|
await expect(verifyPage.getByRole('button', { name: /confirm verification/i })).toBeVisible({
|
|
timeout: 5000
|
|
});
|
|
await verifyPage.getByRole('button', { name: /confirm verification/i }).click();
|
|
|
|
// Wait for success message
|
|
await expect(verifyPage.getByText(/email verified|verified/i)).toBeVisible({
|
|
timeout: 10000
|
|
});
|
|
|
|
console.log('✓ Email verified successfully!');
|
|
|
|
// Verify in database that email is now verified
|
|
const verifiedQuery = `SELECT email_verified FROM users_user WHERE email = '${testEmail}'`;
|
|
const verifiedResult = execSync(
|
|
`docker compose exec -T db psql -U postgres -d smoothschedule -t -c "${verifiedQuery}"`,
|
|
{ cwd: '/home/poduck/Desktop/smoothschedule', encoding: 'utf-8' }
|
|
);
|
|
|
|
const isVerified = verifiedResult.trim() === 't';
|
|
expect(isVerified).toBeTruthy();
|
|
|
|
console.log('✓ Database confirms email is verified');
|
|
console.log('\n=== Test Completed Successfully ===\n');
|
|
});
|
|
});
|