refactor: improve test structure for Bun compatibility
- Update all test files to use named mock variables instead of inline mocks - Clear mock history in beforeEach instead of using mock.restore() - Add default mock implementations stored at module level - Document that tests should not use --randomize flag due to mock.module() limitations - All 89 unit tests pass consistently without randomization
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Acceptance Test: Account Creation, Login, and Deletion (UI-based)
|
||||
*
|
||||
* This test demonstrates the full workflow using the UI:
|
||||
* 1. Create a test account via registration
|
||||
* 2. Log in using the authentication UI
|
||||
* 3. Delete the test account
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { prisma } from '@/lib/prisma';
|
||||
|
||||
// Generate unique test account credentials
|
||||
function getTestCredentials() {
|
||||
const timestamp = Date.now();
|
||||
return {
|
||||
email: `test-${timestamp}@example.com`,
|
||||
password: 'TestPassword123!',
|
||||
name: `Test User ${timestamp}`
|
||||
};
|
||||
}
|
||||
|
||||
test.describe.serial('Account Lifecycle Acceptance Test', () => {
|
||||
let testEmail: string;
|
||||
let testPassword: string;
|
||||
let testName: string;
|
||||
|
||||
test.beforeAll(async () => {
|
||||
const credentials = getTestCredentials();
|
||||
testEmail = credentials.email;
|
||||
testPassword = credentials.password;
|
||||
testName = credentials.name;
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
// Clean up: delete test user if they still exist
|
||||
try {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { email: testEmail }
|
||||
});
|
||||
if (user) {
|
||||
await prisma.user.delete({ where: { id: user.id } });
|
||||
console.log(`Cleaned up test user: ${testEmail}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Cleanup error:', error);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Test 1: Create test account via registration
|
||||
* Uses the unauthenticated project (no storage state)
|
||||
*/
|
||||
test('1. Create test account via registration', async ({ page }) => {
|
||||
// Navigate to registration page
|
||||
await page.goto('/auth/register');
|
||||
|
||||
// Wait for JavaScript to be ready
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Wait for the form to be visible and the submit button to be enabled
|
||||
await page.waitForSelector('form');
|
||||
await page.waitForSelector('button[type="submit"]:not([disabled])');
|
||||
|
||||
// Fill in registration form
|
||||
await page.fill('input[name="name"]', testName);
|
||||
await page.fill('input[name="email"]', testEmail);
|
||||
await page.fill('input[name="password"]', testPassword);
|
||||
|
||||
// Submit the form
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Wait for redirect to player profile (regular users are redirected to their profile)
|
||||
await page.waitForURL(/\/players\/\d+\/profile/, { timeout: 10000 });
|
||||
|
||||
// Wait a moment for the user to be saved to database
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Verify user was created in database
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { email: testEmail }
|
||||
});
|
||||
expect(user).not.toBeNull();
|
||||
expect(user?.email).toBe(testEmail);
|
||||
expect(user?.role).toBe('player');
|
||||
});
|
||||
|
||||
/**
|
||||
* Test 2: Log in with test account
|
||||
* Uses the unauthenticated project (no storage state)
|
||||
*/
|
||||
test('2. Log in with test account', async ({ page }) => {
|
||||
// Navigate to login page
|
||||
await page.goto('/auth/login');
|
||||
|
||||
// Fill in login form
|
||||
await page.fill('input[name="email"]', testEmail);
|
||||
await page.fill('input[name="password"]', testPassword);
|
||||
|
||||
// Submit the form
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Wait for redirect to admin or player profile
|
||||
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
|
||||
|
||||
// Reload to ensure session is loaded from cookies
|
||||
await page.reload();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Wait for logout button to appear
|
||||
await page.waitForSelector('text=Sign out', { timeout: 10000 });
|
||||
|
||||
// Check for user's email or name in the navigation
|
||||
const userEmail = await page.locator(`text=${testEmail}`).count();
|
||||
const userName = await page.locator(`text=${testName}`).count();
|
||||
const logoutButton = await page.locator('text=Sign out').count();
|
||||
|
||||
// At least one of these should be present if logged in
|
||||
expect(userEmail + userName + logoutButton).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
/**
|
||||
* Test 3: Delete test account
|
||||
* Uses the authenticated project (admin)
|
||||
*/
|
||||
test('3. Delete test account', async () => {
|
||||
// For now, we'll delete via direct database access
|
||||
// In a real scenario, this would be done via an admin API endpoint
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { email: testEmail }
|
||||
});
|
||||
|
||||
if (user) {
|
||||
await prisma.user.delete({ where: { id: user.id } });
|
||||
console.log(`Test user deleted: ${testEmail}`);
|
||||
}
|
||||
|
||||
// Verify user was deleted
|
||||
const deletedUser = await prisma.user.findUnique({
|
||||
where: { email: testEmail }
|
||||
});
|
||||
expect(deletedUser).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user