From d2f16e65b24952e55f72265b015fa0d6b5e165d6 Mon Sep 17 00:00:00 2001 From: Abdulee Date: Wed, 4 Feb 2026 13:32:39 +0100 Subject: [PATCH] chore: excluir TESTS.md del repositorio --- frontend/.gitignore | 1 + frontend/TESTS.md | 273 -------------------------------------------- 2 files changed, 1 insertion(+), 273 deletions(-) delete mode 100644 frontend/TESTS.md diff --git a/frontend/.gitignore b/frontend/.gitignore index 4346d24..0152d07 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -6,3 +6,4 @@ dist *.log .svelte-kit vite.config.ts.timestamp-* +TESTS.md diff --git a/frontend/TESTS.md b/frontend/TESTS.md deleted file mode 100644 index 8bfabeb..0000000 --- a/frontend/TESTS.md +++ /dev/null @@ -1,273 +0,0 @@ -# Tests del Frontend - Documentación - -Este documento describe los tests implementados para el frontend del taller CI/CD. - -## Estructura de Tests - -``` -frontend/src/ -├── utils/ -│ ├── text.js # Función prettify() -│ └── text.test.js # Tests unitarios -├── services/ -│ ├── api.js # Funciones de API -│ └── api.test.js # Tests con mocking -├── App.svelte # Componente principal -└── App.test.js # Tests de componente -``` - -## Tecnologías Utilizadas - -| Herramienta | Propósito | -|-------------|-----------| -| **Vitest** | Framework de testing (compatible con Vite) | -| **@testing-library/svelte** | Renderizado de componentes Svelte | -| **jsdom** | Simulación del DOM en Node.js | - ---- - -## 1. Tests Unitarios: `text.test.js` - -### Objetivo -Testear funciones puras sin efectos secundarios. La función `prettify()` convierte strings en formato `snake_case` a `Title Case`. - -### Tests Implementados - -| Test | Input | Output Esperado | Concepto | -|------|-------|-----------------|----------| -| Conversión básica | `'hello_world'` | `'Hello World'` | Transformación de texto | -| Múltiples palabras | `'cafe_con_leche'` | `'Cafe Con Leche'` | Manejo de múltiples `_` | -| Sin underscore | `'bocadillo'` | `'Bocadillo'` | Edge case | -| String vacío | `''` | `''` | Boundary testing | -| Mayúsculas | `'TOSTADA_INTEGRAL'` | `'Tostada Integral'` | Normalización | - -### Código Explicado - -```javascript -import { describe, it, expect } from 'vitest'; -import { prettify } from './text'; - -describe('prettify', () => { - it('convierte snake_case a Title Case', () => { - // Dado un string con underscores - const input = 'hello_world'; - - // Cuando llamamos a prettify - const result = prettify(input); - - // Entonces obtenemos Title Case - expect(result).toBe('Hello World'); - }); -}); -``` - -### ¿Por qué este test es ideal para principiantes? - -1. **Sin dependencias externas**: No necesita mocking -2. **Determinístico**: Mismo input = mismo output siempre -3. **Fácil de romper**: Cambiar la función hace fallar el test inmediatamente -4. **Concepto claro**: Input → Función → Output - ---- - -## 2. Tests de API: `api.test.js` - -### Objetivo -Testear funciones que hacen llamadas HTTP sin depender de un servidor real. - -### Concepto Clave: Mocking - -**Mocking** significa "simular" una dependencia externa. En este caso, simulamos `fetch()`: - -```javascript -beforeEach(() => { - // Reemplazamos fetch global con una función simulada - vi.stubGlobal('fetch', vi.fn()); -}); - -afterEach(() => { - // Restauramos el fetch original - vi.unstubAllGlobals(); -}); -``` - -### Tests Implementados - -| Test | Qué Verifica | Concepto de Testing | -|------|--------------|---------------------| -| `getMenu()` éxito | Devuelve datos cuando API OK | Happy path | -| `getMenu()` error | Lanza excepción cuando API falla | Error handling | -| `getPrices()` items | Extrae `.items` del response | Data transformation | -| `getPrices()` vacío | Devuelve `[]` si no hay items | Defensive programming | -| `getCiStatus()` | Llama a `/health` | Contract testing | -| `getBuildHistory()` | Llama a `/builds` | Contract testing | - -### Código Explicado - -```javascript -describe('getMenu', () => { - it('devuelve datos del menu cuando la API responde correctamente', async () => { - // 1. ARRANGE: Preparamos el mock - const mockMenu = { starters: ['Sopa'], mains: ['Pescado'] }; - - fetch.mockResolvedValueOnce({ - ok: true, - json: () => Promise.resolve(mockMenu), - }); - - // 2. ACT: Ejecutamos la función - const result = await getMenu(); - - // 3. ASSERT: Verificamos el resultado - expect(fetch).toHaveBeenCalledWith('/taller/api/menu'); - expect(result).toEqual(mockMenu); - }); -}); -``` - -### ¿Por qué este test es importante para CI/CD? - -- **Independencia**: No necesita backend corriendo -- **Rapidez**: Se ejecuta en milisegundos -- **Fiabilidad**: No falla por problemas de red -- **Contract testing**: Verifica que la API se llama correctamente - ---- - -## 3. Tests de Componente: `App.test.js` - -### Objetivo -Verificar que el componente Svelte renderiza correctamente y muestra la información esperada. - -### Concepto Clave: Testing Library - -`@testing-library/svelte` renderiza componentes y permite buscar elementos como lo haría un usuario: - -```javascript -import { render, screen, waitFor } from '@testing-library/svelte'; -import App from './App.svelte'; - -// Renderiza el componente -render(App); - -// Busca elementos como un usuario -screen.getByText('Menú del día'); -screen.getByRole('heading', { level: 1 }); -``` - -### Tests Implementados - -| Test | Qué Verifica | Selector Usado | -|------|--------------|----------------| -| Título principal | H1 existe | `getByRole('heading', { level: 1 })` | -| Secciones menú | Primeros/Segundos/Postres | `getByText('Primeros')` | -| Estado API | Muestra "Operativa" | `getByText(/Operativa/)` | -| Build number | Muestra "#42" | `getByText('#42')` | -| Precios | Muestra "Cafe", "Tostada" | `getByText('Cafe')` | - -### Código Explicado - -```javascript -describe('App.svelte', () => { - beforeEach(() => { - // Mockeamos fetch para cada endpoint - vi.stubGlobal('fetch', createMockFetch()); - }); - - it('muestra las secciones del menu cuando carga', async () => { - // Renderizamos el componente - render(App); - - // Esperamos a que cargue (es async) - await waitFor(() => { - expect(screen.getByText('Primeros')).toBeInTheDocument(); - expect(screen.getByText('Segundos')).toBeInTheDocument(); - }); - }); -}); -``` - -### ¿Por qué `waitFor`? - -El componente hace llamadas async al montarse. `waitFor` espera hasta que: -1. La condición se cumple, O -2. Pasa el timeout (falla el test) - ---- - -## Ejecutar los Tests - -### Localmente - -```bash -cd frontend -npm install -npm test -``` - -### En modo watch (desarrollo) - -```bash -npm test -- --watch -``` - -### Con coverage - -```bash -npm test -- --coverage -``` - ---- - -## Integración con Jenkins - -Los tests se ejecutan en el pipeline CI (`Jenkinsfile.ci`): - -```groovy -stage('Frontend: check & build') { - steps { - dir('frontend') { - sh ''' - npm install - npm run check - npm test # ← Ejecuta estos tests - npm run build - ''' - } - } -} -``` - -### Flujo en Jenkins - -``` -1. Push/MR → 2. Jenkins detecta → 3. npm test → 4. ¿Pasa? → 5. Build - ↓ NO - Pipeline FALLA - (estudiante corrige) -``` - ---- - -## Cómo Romper los Tests (Ejercicio) - -Para ver Jenkins fallar, prueba: - -| Cambio | Test que Falla | -|--------|----------------| -| Cambiar `prettify()` para no capitalizar | `text.test.js` | -| Cambiar endpoint de `/menu` a `/menus` | `api.test.js` | -| Eliminar sección "Primeros" del HTML | `App.test.js` | - ---- - -## Glosario - -| Término | Definición | -|---------|------------| -| **Unit Test** | Test de una función/módulo aislado | -| **Mock** | Simulación de una dependencia | -| **Assertion** | Verificación de que algo es verdadero | -| **Happy Path** | Escenario donde todo funciona bien | -| **Edge Case** | Escenario límite o inusual | -| **Coverage** | % del código ejecutado por tests |