import * as fs from 'fs'; import * as path from 'path'; import axios from 'axios'; import { getMenuSladovnicka, getMenuTechTower, getMenuSenkSerikova, StaleWeekError } from '../restaurants'; jest.mock('axios'); const mockedAxios = axios as jest.Mocked; const fixturesDir = path.join(__dirname, 'fixtures'); const loadFixture = (name: string) => fs.readFileSync(path.join(fixturesDir, name), 'utf-8'); // Pondělí 12.5.2025 const MONDAY = new Date('2025-05-12'); beforeEach(() => { jest.resetAllMocks(); }); describe('Sladovnicka parser', () => { beforeEach(() => { mockedAxios.get = jest.fn().mockResolvedValue({ data: loadFixture('sladovnicka.html') }); }); test('vrátí pole o délce 5 (jeden záznam na každý pracovní den)', async () => { const menu = await getMenuSladovnicka(MONDAY); expect(menu).toHaveLength(5); }); test('pondělní menu obsahuje aspoň jedno jídlo', async () => { const menu = await getMenuSladovnicka(MONDAY); expect(menu[0].length).toBeGreaterThan(0); }); test('první položka pondělního dne je polévka (isSoup=true)', async () => { const menu = await getMenuSladovnicka(MONDAY); expect(menu[0][0].isSoup).toBe(true); }); test('jídla mají name, price a amount', async () => { const menu = await getMenuSladovnicka(MONDAY); const jidlo = menu[0][1]; expect(jidlo.name).toBeTruthy(); expect(jidlo.price).toBeTruthy(); expect(jidlo.amount).toBeTruthy(); }); test('alergeny jsou naparsovány jako čísla', async () => { const menu = await getMenuSladovnicka(MONDAY); const polievka = menu[0][0]; expect(Array.isArray(polievka.allergens)).toBe(true); expect(polievka.allergens!.length).toBeGreaterThan(0); expect(typeof polievka.allergens![0]).toBe('number'); }); }); describe('TechTower parser', () => { beforeEach(() => { mockedAxios.get = jest.fn().mockResolvedValue({ data: loadFixture('techtower.html') }); }); test('vrátí pole o délce 5', async () => { const menu = await getMenuTechTower(MONDAY); expect(menu).toHaveLength(5); }); test('pondělní menu obsahuje polévku a hlavní jídla', async () => { const menu = await getMenuTechTower(MONDAY); expect(menu[0].some(f => f.isSoup)).toBe(true); expect(menu[0].some(f => !f.isSoup)).toBe(true); }); test('TechTower hodí StaleWeekError, pokud datum v hlavičce neodpovídá', async () => { // Fixture obsahuje "12.5.-16.5.2025" – jiný týden = stale const jinaStreda = new Date('2025-04-14'); await expect(getMenuTechTower(jinaStreda)).rejects.toBeInstanceOf(StaleWeekError); }); test('StaleWeekError obsahuje naparsovaná data', async () => { const jinaStreda = new Date('2025-04-14'); try { await getMenuTechTower(jinaStreda); } catch (e) { expect(e).toBeInstanceOf(StaleWeekError); const err = e as StaleWeekError; expect(err.food).toHaveLength(5); } }); }); describe('SenkSerikova parser', () => { beforeEach(() => { // SenkSerikova parsuje arraybuffer – musíme vrátit Buffer, ne string mockedAxios.get = jest.fn().mockResolvedValue({ data: Buffer.from(loadFixture('senkserikova.html')), headers: {} }); }); test('parser provede HTTP request a vrátí pole', async () => { const menu = await getMenuSenkSerikova(MONDAY); expect(mockedAxios.get).toHaveBeenCalledTimes(1); expect(Array.isArray(menu)).toBe(true); }); test('výsledné dny s obsahem mají správnou strukturu (name, price, isSoup)', async () => { const menu = await getMenuSenkSerikova(MONDAY); // Protože MONDAY je v minulosti, parser vrátí placeholdery pro všechny pracovní // dny a .menicka elementy přidá za ně – hledáme aspoň jeden den s reálnými daty const denSJidlem = menu.find(den => den.length > 0 && den[0].name !== 'Pro tento den není uveřejněna nabídka jídel' ); if (denSJidlem) { expect(typeof denSJidlem[0].name).toBe('string'); expect(typeof denSJidlem[0].isSoup).toBe('boolean'); } }); });