diff --git a/frontend/src/App.test.js b/frontend/src/App.test.js new file mode 100644 index 0000000..a0a3116 --- /dev/null +++ b/frontend/src/App.test.js @@ -0,0 +1,136 @@ +/* +CI/CD Workshop +Copyright (C) 2025 OpenBokeron + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { render, screen, waitFor } from '@testing-library/svelte'; +import App from './App.svelte'; + +const mockMenu = { + starters: ['Sopa de cocido', 'Ensalada mixta'], + mains: ['Pescado al vapor', 'Pollo asado'], + garnish: ['Patatas fritas'], + desserts: ['Fruta del tiempo', 'Yogur'], + notes: ['Pan y bebida incluidos'], + menu_price: 5.5, + university_deal: { + old_price: 4.5, + current_price: 5.5, + note: 'Gracias al convenio con la Universidad', + }, + alternative: { title: 'Plato alternativo', items: [], price: 5.0 }, + availability: { last_updated: '12:00' }, + espetos_tip: 'Hoy toca sardinas', +}; + +const mockPrices = { + items: [ + { item: 'cafe', price: 1.2, currency: 'EUR', generated_at: '10:00' }, + { item: 'tostada', price: 2.0, currency: 'EUR', generated_at: '10:00' }, + ], +}; + +const mockHealth = { + status: 'ok', + build: 42, + commit: 'abc1234def5678', + author: 'Test Author', + uptime_seconds: 3600, +}; + +const mockBuilds = { + builds: [ + { + number: 42, + status: 'success', + finished_at: Date.now(), + duration_seconds: 60, + commits: [{ commit: 'abc1234', message: 'Fix bug', author: 'Dev' }], + }, + ], +}; + +function createMockFetch() { + return vi.fn((url) => { + if (url.includes('/menu')) { + return Promise.resolve({ ok: true, json: () => Promise.resolve(mockMenu) }); + } + if (url.includes('/prices')) { + return Promise.resolve({ ok: true, json: () => Promise.resolve(mockPrices) }); + } + if (url.includes('/health')) { + return Promise.resolve({ ok: true, json: () => Promise.resolve(mockHealth) }); + } + if (url.includes('/builds')) { + return Promise.resolve({ ok: true, json: () => Promise.resolve(mockBuilds) }); + } + return Promise.resolve({ ok: false, status: 404 }); + }); +} + +describe('App.svelte', () => { + beforeEach(() => { + vi.stubGlobal('fetch', createMockFetch()); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + }); + + it('renderiza el titulo principal', async () => { + render(App); + + await waitFor(() => { + expect(screen.getByRole('heading', { level: 1 })).toBeInTheDocument(); + }); + }); + + it('muestra las secciones del menu cuando carga', async () => { + render(App); + + await waitFor(() => { + expect(screen.getByText('Primeros')).toBeInTheDocument(); + expect(screen.getByText('Segundos')).toBeInTheDocument(); + expect(screen.getByText('Postres')).toBeInTheDocument(); + }); + }); + + it('muestra el estado de la API como operativa', async () => { + render(App); + + await waitFor(() => { + expect(screen.getByText(/Operativa/)).toBeInTheDocument(); + }); + }); + + it('muestra el numero de build de Jenkins', async () => { + render(App); + + await waitFor(() => { + expect(screen.getByText('#42')).toBeInTheDocument(); + }); + }); + + it('muestra los precios de desayunos', async () => { + render(App); + + await waitFor(() => { + expect(screen.getByText('Cafe')).toBeInTheDocument(); + expect(screen.getByText('Tostada')).toBeInTheDocument(); + }); + }); +});