fe6bb3290e
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>
80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import { generateToken, verify, getLogin, getTrusted } from '../auth';
|
|
|
|
const VALID_SECRET = 'test-secret-min-32-chars-aaaaaaa!';
|
|
|
|
beforeEach(() => {
|
|
process.env.JWT_SECRET = VALID_SECRET;
|
|
});
|
|
|
|
afterEach(() => {
|
|
delete process.env.JWT_SECRET;
|
|
});
|
|
|
|
describe('generateToken', () => {
|
|
test('vrátí token pro platný login', () => {
|
|
const token = generateToken('alice');
|
|
expect(typeof token).toBe('string');
|
|
expect(token.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
test('vyhodí chybu bez JWT_SECRET', () => {
|
|
delete process.env.JWT_SECRET;
|
|
expect(() => generateToken('alice')).toThrow('JWT_SECRET');
|
|
});
|
|
|
|
test('vyhodí chybu pro příliš krátký JWT_SECRET', () => {
|
|
process.env.JWT_SECRET = 'short';
|
|
expect(() => generateToken('alice')).toThrow('32');
|
|
});
|
|
|
|
test('vyhodí chybu pro prázdný login', () => {
|
|
expect(() => generateToken('')).toThrow('login');
|
|
expect(() => generateToken(' ')).toThrow('login');
|
|
});
|
|
|
|
test('vyhodí chybu pro chybějící login', () => {
|
|
expect(() => generateToken(undefined)).toThrow('login');
|
|
});
|
|
});
|
|
|
|
describe('verify', () => {
|
|
test('vrátí true pro platný token', () => {
|
|
const token = generateToken('alice');
|
|
expect(verify(token)).toBe(true);
|
|
});
|
|
|
|
test('vrátí false pro podvrženou signaturu', () => {
|
|
const token = generateToken('alice');
|
|
const tampered = token.slice(0, -5) + 'XXXXX';
|
|
expect(verify(tampered)).toBe(false);
|
|
});
|
|
|
|
test('vrátí false pro token podepsaný jiným secret', () => {
|
|
process.env.JWT_SECRET = 'other-secret-min-32-chars-bbbbb!';
|
|
const tokenOther = generateToken('alice');
|
|
process.env.JWT_SECRET = VALID_SECRET;
|
|
expect(verify(tokenOther)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('getLogin / getTrusted', () => {
|
|
test('round-trip: getLogin vrátí správný login', () => {
|
|
const token = generateToken('bob');
|
|
expect(getLogin(token)).toBe('bob');
|
|
});
|
|
|
|
test('trusted=false je výchozí hodnota', () => {
|
|
const token = generateToken('alice');
|
|
expect(getTrusted(token)).toBe(false);
|
|
});
|
|
|
|
test('trusted=true je zachováno', () => {
|
|
const token = generateToken('alice', true);
|
|
expect(getTrusted(token)).toBe(true);
|
|
});
|
|
|
|
test('getLogin vyhodí chybu pro chybějící token', () => {
|
|
expect(() => getLogin(undefined)).toThrow('token');
|
|
});
|
|
});
|