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,106 @@
|
||||
import { isTextSoupName, capitalize, sanitizeText, parseAllergens } from '../restaurants';
|
||||
|
||||
describe('isTextSoupName', () => {
|
||||
test('rozpozná "polévka"', () => {
|
||||
expect(isTextSoupName('Polévka dne')).toBe(true);
|
||||
});
|
||||
|
||||
test('rozpozná "česnečka"', () => {
|
||||
expect(isTextSoupName('Česnečka s krutony')).toBe(true);
|
||||
});
|
||||
|
||||
test('rozpozná "vývar"', () => {
|
||||
expect(isTextSoupName('Hovězí vývar s nudlemi')).toBe(true);
|
||||
});
|
||||
|
||||
test('rozpozná "slepičí s " (parciální shoda pro slepičí vývar)', () => {
|
||||
expect(isTextSoupName('Slepičí s nudlemi')).toBe(true);
|
||||
});
|
||||
|
||||
test('neklasifikuje hlavní jídlo jako polévku', () => {
|
||||
expect(isTextSoupName('Svíčková na smetaně s knedlíky')).toBe(false);
|
||||
});
|
||||
|
||||
test('neklasifikuje prázdný řetězec', () => {
|
||||
expect(isTextSoupName('')).toBe(false);
|
||||
});
|
||||
|
||||
test('není case-sensitive', () => {
|
||||
expect(isTextSoupName('POLÉVKA DNEŠKA')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('capitalize', () => {
|
||||
test('zformátuje první písmeno na velké', () => {
|
||||
expect(capitalize('svíčková')).toBe('Svíčková');
|
||||
});
|
||||
|
||||
test('nechá velká písmena beze změny', () => {
|
||||
expect(capitalize('ABC')).toBe('ABC');
|
||||
});
|
||||
|
||||
test('prázdný řetězec zůstane prázdný', () => {
|
||||
expect(capitalize('')).toBe('');
|
||||
});
|
||||
|
||||
test('jednoznakový řetězec', () => {
|
||||
expect(capitalize('a')).toBe('A');
|
||||
});
|
||||
});
|
||||
|
||||
describe('sanitizeText', () => {
|
||||
test('odstraní tabulátor (první výskyt)', () => {
|
||||
// replace('\t', '') odstraní tab bez přidání mezery
|
||||
expect(sanitizeText('\tKnedlíky')).toBe('Knedlíky');
|
||||
});
|
||||
|
||||
test('nahradí první " , " za ", "', () => {
|
||||
// replace(' , ', ', ') nahrazuje pouze první výskyt
|
||||
expect(sanitizeText('Knedlíky , zelí')).toBe('Knedlíky, zelí');
|
||||
});
|
||||
|
||||
test('ořízne okrajové mezery', () => {
|
||||
expect(sanitizeText(' Jídlo ')).toBe('Jídlo');
|
||||
});
|
||||
|
||||
test('kombinace: tab + mezera okolo čárky', () => {
|
||||
expect(sanitizeText('\tKnedlíky , zelí ')).toBe('Knedlíky, zelí');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseAllergens', () => {
|
||||
test('extrahuje alergeny na konci řetězce', () => {
|
||||
const result = parseAllergens('Svíčková 1,3,7');
|
||||
expect(result.cleanName).toBe('Svíčková');
|
||||
expect(result.allergens).toEqual([1, 3, 7]);
|
||||
});
|
||||
|
||||
test('toleruje mezery okolo čárek v alergenech', () => {
|
||||
const result = parseAllergens('Řízek 1, 3, 7');
|
||||
expect(result.allergens).toEqual([1, 3, 7]);
|
||||
});
|
||||
|
||||
test('vrátí prázdná pole pro jídlo bez alergenů', () => {
|
||||
const result = parseAllergens('Ovocný salát');
|
||||
expect(result.cleanName).toBe('Ovocný salát');
|
||||
expect(result.allergens).toEqual([]);
|
||||
});
|
||||
|
||||
test('nesplete se s číslem uprostřed názvu', () => {
|
||||
const result = parseAllergens('Jídlo č. 5 bez alergenů');
|
||||
expect(result.cleanName).toBe('Jídlo č. 5 bez alergenů');
|
||||
expect(result.allergens).toEqual([]);
|
||||
});
|
||||
|
||||
test('single alergen', () => {
|
||||
const result = parseAllergens('Houby 7');
|
||||
expect(result.cleanName).toBe('Houby');
|
||||
expect(result.allergens).toEqual([7]);
|
||||
});
|
||||
|
||||
test('prázdný řetězec vrátí prázdné výsledky', () => {
|
||||
const result = parseAllergens('');
|
||||
expect(result.cleanName).toBe('');
|
||||
expect(result.allergens).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user