Files
Luncher/e2e/tests/login.spec.ts
T
batmanisko fe6bb3290e
ci/woodpecker/push/workflow Pipeline was canceled
ci/woodpecker/pr/workflow Pipeline was canceled
feat: přidání testů – Jest unit testy + Playwright E2E + CI pipeline
Server:
- Jest unit testy (88 testů): auth, utils, restaurants, service, voting, pizza
- in-memory storage mock pro izolaci testů
- oprava race condition při inicializaci Redis (storageReady promise)
- dev route dostupná i pro NODE_ENV=test
- getStatsMock deterministický (nahrazení Math.random)
- exporty interních helperů pro testovatelnost
- /api/health endpoint pro Playwright readiness check
- tsconfig vylučuje test soubory z produkčního buildu

E2E (e2e/):
- Playwright s Firefoxem + Chromiem
- testy: login, menu, výběr jídla, pizza day životní cyklus, QR/nastavení
- trusted-header auth bypass pro testy, video + trace při selhání

CI (Woodpecker):
- pipeline spouštěna na všech větvích a PR (nejen master)
- redis-stack-server service pro E2E – čistý Redis per větev automaticky
- kroky: unit testy, build, E2E testy (parallel kde možné)
- Docker build zůstává pouze pro master

Co-Authored-By: Claude Opus (extra usage) 4.7 <noreply@anthropic.com>
2026-04-29 00:25:22 +02:00

51 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test, expect } from '@playwright/test';
// Tento test záměrně NEPOUŽÍVÁ trusted-header testuje reálný login formulář.
test.use({ extraHTTPHeaders: {} });
test('uživatel se přihlásí formulářem a uvidí obsah aplikace', async ({ page }) => {
// Server běží s HTTP_REMOTE_USER_ENABLED=true, takže POST /api/login vždy vyžaduje
// hlavičku remote-user. Zachytíme požadavky z formuláře (mají tělo s polem login)
// a přidáme hlavičku; požadavek auto-loginu (bez těla) projde bez hlavičky a selže,
// čímž formulář zůstane viditelný.
await page.route('**/api/login', async (route) => {
const body = route.request().postData();
let login: string | undefined;
try { login = body ? JSON.parse(body)?.login : undefined; } catch {}
await route.continue({
headers: login
? { ...route.request().headers(), 'remote-user': login }
: route.request().headers(),
});
});
await page.goto('/');
// Formulář musí být viditelný auto-login selhal (nepřišla hlavička)
const loginInput = page.locator('#login-input');
await expect(loginInput).toBeVisible({ timeout: 10_000 });
// Vyplnění loginu a odeslání Enterem
await loginInput.fill('testuser');
await loginInput.press('Enter');
// Po přihlášení musí zmizet login formulář
await expect(loginInput).not.toBeVisible({ timeout: 10_000 });
// JWT musí být uloženo v localStorage jako 3-dílný token
const token = await page.evaluate(() => localStorage.getItem('token'));
expect(token).toBeTruthy();
expect((token as string).split('.')).toHaveLength(3);
});
test('trusted-header přihlášení proběhne automaticky bez formuláře', async ({ page, context }) => {
// Obnoví trusted header (přepíše prázdný extraHTTPHeaders z test.use výše)
await context.setExtraHTTPHeaders({ 'remote-user': 'e2e-auto-user' });
await page.goto('/');
// Login formulář by se neměl nikdy zobrazit, nebo se ihned schová
await page.waitForLoadState('networkidle');
const loginInput = page.locator('#login-input');
await expect(loginInput).not.toBeVisible({ timeout: 5_000 });
});