mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 06:51:12 -05:00
feat: Implement Playwright testing setup
This commit is contained in:
134
tests/e2e/auth/login.spec.ts
Normal file
134
tests/e2e/auth/login.spec.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Login E2E Tests
|
||||
*
|
||||
* Tests authentication flow, session persistence, and error handling.
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { LoginPage } from '../../helpers/page-objects/LoginPage';
|
||||
import { getTestUserCredentials, logout } from '../../fixtures/auth';
|
||||
|
||||
// These tests run without pre-authenticated state
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test.describe('Login Flow', () => {
|
||||
let loginPage: LoginPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
loginPage = new LoginPage(page);
|
||||
await loginPage.goto();
|
||||
});
|
||||
|
||||
test('should login successfully with valid credentials', async ({ page }) => {
|
||||
const { email, password } = getTestUserCredentials('user');
|
||||
|
||||
await loginPage.login(email, password);
|
||||
await loginPage.expectLoginSuccess();
|
||||
|
||||
// Verify we're redirected to homepage
|
||||
await expect(page).toHaveURL('/');
|
||||
});
|
||||
|
||||
test('should show error with invalid password', async ({ page }) => {
|
||||
const { email } = getTestUserCredentials('user');
|
||||
|
||||
await loginPage.login(email, 'wrongpassword123');
|
||||
await loginPage.expectLoginError();
|
||||
|
||||
// Verify we're still on auth page
|
||||
await expect(page).toHaveURL(/\/auth/);
|
||||
});
|
||||
|
||||
test('should show error with non-existent email', async ({ page }) => {
|
||||
await loginPage.login('nonexistent@example.com', 'password123');
|
||||
await loginPage.expectLoginError();
|
||||
});
|
||||
|
||||
test('should persist session after page refresh', async ({ page }) => {
|
||||
const { email, password } = getTestUserCredentials('user');
|
||||
|
||||
// Login
|
||||
await loginPage.login(email, password);
|
||||
await loginPage.expectLoginSuccess();
|
||||
|
||||
// Reload page
|
||||
await page.reload();
|
||||
|
||||
// Should still be logged in (not redirected to /auth)
|
||||
await expect(page).not.toHaveURL(/\/auth/);
|
||||
});
|
||||
|
||||
test('should clear session on logout', async ({ page }) => {
|
||||
const { email, password } = getTestUserCredentials('user');
|
||||
|
||||
// Login
|
||||
await loginPage.login(email, password);
|
||||
await loginPage.expectLoginSuccess();
|
||||
|
||||
// Logout
|
||||
await page.click('button:has-text("Logout")').or(page.click('[data-testid="logout"]'));
|
||||
|
||||
// Should be redirected to auth or homepage
|
||||
// And trying to access protected route should redirect to auth
|
||||
await page.goto('/moderation/queue');
|
||||
await expect(page).toHaveURL(/\/auth/);
|
||||
});
|
||||
|
||||
test('should validate email format', async ({ page }) => {
|
||||
await loginPage.login('invalid-email', 'password123');
|
||||
|
||||
// Should show validation error
|
||||
await expect(page.getByText(/invalid.*email/i)).toBeVisible();
|
||||
});
|
||||
|
||||
test('should require password', async ({ page }) => {
|
||||
const { email } = getTestUserCredentials('user');
|
||||
|
||||
await page.fill('input[type="email"]', email);
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Should show validation error
|
||||
await expect(page.getByText(/password.*required/i)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Role-Based Access', () => {
|
||||
test('moderator can access moderation queue', async ({ browser }) => {
|
||||
const context = await browser.newContext({ storageState: '.auth/moderator.json' });
|
||||
const page = await context.newPage();
|
||||
|
||||
await page.goto('/moderation/queue');
|
||||
|
||||
// Should not be redirected
|
||||
await expect(page).toHaveURL(/\/moderation\/queue/);
|
||||
|
||||
// Page should load successfully
|
||||
await expect(page.getByText(/moderation.*queue/i)).toBeVisible();
|
||||
|
||||
await context.close();
|
||||
});
|
||||
|
||||
test('regular user cannot access moderation queue', async ({ browser }) => {
|
||||
const context = await browser.newContext({ storageState: '.auth/user.json' });
|
||||
const page = await context.newPage();
|
||||
|
||||
await page.goto('/moderation/queue');
|
||||
|
||||
// Should be redirected or see access denied
|
||||
await expect(page.getByText(/access denied/i).or(page.getByText(/not authorized/i))).toBeVisible();
|
||||
|
||||
await context.close();
|
||||
});
|
||||
|
||||
test('admin can access admin panel', async ({ browser }) => {
|
||||
const context = await browser.newContext({ storageState: '.auth/admin.json' });
|
||||
const page = await context.newPage();
|
||||
|
||||
await page.goto('/admin/users');
|
||||
|
||||
// Should not be redirected
|
||||
await expect(page).toHaveURL(/\/admin/);
|
||||
|
||||
await context.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user