chore: excluir TESTS.md del repositorio
This commit is contained in:
1
frontend/.gitignore
vendored
1
frontend/.gitignore
vendored
@@ -6,3 +6,4 @@ dist
|
||||
*.log
|
||||
.svelte-kit
|
||||
vite.config.ts.timestamp-*
|
||||
TESTS.md
|
||||
|
||||
@@ -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 |
|
||||
Reference in New Issue
Block a user