You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
2.6 KiB
TypeScript

/**
* E2E test: Registration flow.
*
* Validates the full magic-link registration process:
* 1. Call the registration API directly (bypasses Turnstile DOM issues)
* 2. Insert a known magic link token into the DB
* 3. Navigate to the verify URL
* 4. Assert redirect to home with user email visible
*
* NOTE: The Cloudflare Turnstile script causes continuous DOM mutations that
* prevent Playwright from interacting with elements on the login/register
* pages. The backend runs in test mode where Turnstile verification is
* bypassed, so we call the API directly with a dummy token.
*/
import { test, expect } from '@playwright/test';
import { createHash } from 'node:crypto';
import { createDbClient } from '../helpers/auth';
test.describe('Registration flow', () => {
test('should register a new user and verify via magic link', async ({
page,
request,
}) => {
test.setTimeout(60_000);
const uniqueEmail = `e2e-reg-${Date.now()}@test.local`;
// Step 1: Register via the API directly.
// The backend is in test mode (TURNSTILE_SECRET_KEY = "test-turnstile-secret-always-pass")
// so any turnstile_token value is accepted.
const registerResp = await request.post('/api/v1/auth/register', {
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
data: {
email: uniqueEmail,
display_name: 'E2E Test User',
turnstile_token: 'mock-token',
},
});
expect(registerResp.ok()).toBe(true);
// Step 2: Insert a known magic token in the DB for verification
const knownRawToken = `e2e-reg-token-${Date.now()}`;
const knownTokenHash = createHash('sha256')
.update(knownRawToken)
.digest('hex');
const expiresAt = new Date(Date.now() + 15 * 60 * 1000).toISOString();
const client = createDbClient();
await client.connect();
try {
await client.query(
`INSERT INTO magic_tokens (email, token_hash, expires_at, used)
VALUES ($1, $2, $3, false)`,
[uniqueEmail.toLowerCase(), knownTokenHash, expiresAt],
);
} finally {
await client.end();
}
// Step 3: Navigate to the GET verify endpoint with the raw token.
// This endpoint verifies the token, creates a session, sets the cookie,
// and redirects to APP_URL.
await page.goto(`/api/v1/auth/verify?token=${knownRawToken}`, { waitUntil: 'domcontentloaded' });
// The verify endpoint redirects to the app URL. Wait for the home page.
await page.waitForURL('**/', { timeout: 15_000 });
// Step 4: Assert the user email is visible in the navbar
await expect(page.getByText(uniqueEmail)).toBeVisible({ timeout: 15_000 });
});
});