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>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
// Pizza day testy musí běžet sekvenčně (sdílejí stav mock dne)
|
||||
test.describe.serial('pizza day životní cyklus', () => {
|
||||
|
||||
test.beforeEach(async ({ request }) => {
|
||||
// Vyčistíme data mock dne před každým testem
|
||||
await request.post('/api/dev/clear', { data: { dayIndex: 4 } });
|
||||
});
|
||||
|
||||
test('zobrazí sekci Pizza Day bez aktivního dne', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.waitForLoadState('networkidle');
|
||||
const pizzaSection = page.locator('.pizza-section');
|
||||
await expect(pizzaSection).toBeVisible({ timeout: 10_000 });
|
||||
await expect(pizzaSection.locator('text=není aktuálně založen')).toBeVisible();
|
||||
});
|
||||
|
||||
test('vytvoří, uzamkne a dokončí pizza day', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// --- CREATED ---
|
||||
const createBtn = page.locator('.pizza-section button', { hasText: 'Založit Pizza day' });
|
||||
await expect(createBtn).toBeVisible({ timeout: 10_000 });
|
||||
await createBtn.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await expect(page.locator('.pizza-section')).toContainText('spravován uživatelem', { timeout: 5_000 });
|
||||
|
||||
// Přidáme pizzu přes API (obejde komplex SelectSearch)
|
||||
const token = await page.evaluate(() => localStorage.getItem('token'));
|
||||
const addResp = await page.request.post('/api/pizza/add', {
|
||||
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
|
||||
data: { pizzaIndex: 0, pizzaSizeIndex: 0 },
|
||||
});
|
||||
expect(addResp.ok()).toBeTruthy();
|
||||
|
||||
// Reload – server aktualizoval data přes WebSocket, ale reload je jistější
|
||||
await page.reload();
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// --- LOCK ---
|
||||
const lockBtn = page.locator('.pizza-section button', { hasText: 'Uzamknout' });
|
||||
await expect(lockBtn).toBeEnabled({ timeout: 5_000 });
|
||||
await lockBtn.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await expect(page.locator('.pizza-section')).toContainText('uzamčeny', { timeout: 5_000 });
|
||||
|
||||
// --- ORDERED ---
|
||||
const orderBtn = page.locator('.pizza-section button', { hasText: 'Objednáno' });
|
||||
await expect(orderBtn).toBeEnabled({ timeout: 5_000 });
|
||||
await orderBtn.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await expect(page.locator('.pizza-section')).toContainText('objednány', { timeout: 5_000 });
|
||||
|
||||
// --- DELIVERED ---
|
||||
const deliverBtn = page.locator('.pizza-section button', { hasText: 'Doručeno' });
|
||||
await expect(deliverBtn).toBeVisible({ timeout: 5_000 });
|
||||
// window.confirm dialog − Playwright automaticky potvrdí
|
||||
page.on('dialog', dialog => dialog.accept());
|
||||
await deliverBtn.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await expect(page.locator('.pizza-section')).toContainText('doručeny', { timeout: 5_000 });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user