test: aggiungi suite completa unit, integration ed e2e
- Unit (12+9): conversion.js (rawToCooked/cookedToRaw, edge case, inversa) e storage.js (save/load, round-trip, default fallback) - Integration (17+12+14): Converter (ricerca, selezione, calcolo, swap, reset), MealPlanner (rendering, add/remove, generateShopping, deduplicazione), ShoppingList (add, toggle, remove, clearAll, contatore) - E2E Playwright (6+6+7+10): navigation, meal-planner, converter, shopping-list - Configurazione: vitest.config.js + playwright.config.js + tests/setup.js - Script: test, test:coverage, test:e2e, test:e2e:ui Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
75
tests/unit/conversion.test.js
Normal file
75
tests/unit/conversion.test.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { rawToCooked, cookedToRaw } from '../../src/utils/conversion.js'
|
||||
|
||||
// DB minimale — isola i test dalle modifiche al JSON reale
|
||||
const db = {
|
||||
'riso basmati': { bollitura: { yield: 3.00 } },
|
||||
'pasta semola': { bollitura: { yield: 1.88 } },
|
||||
'pollo petto': { padella: { yield: 0.75 }, forno: { yield: 0.70 } },
|
||||
'zucchine': { bollitura: { yield: 0.90 }, padella: { yield: 0.82 } },
|
||||
'ceci secchi': { bollitura: { yield: 2.90 } },
|
||||
}
|
||||
|
||||
describe('rawToCooked', () => {
|
||||
it('calcola il peso cotto con fattore > 1 (cereali)', () => {
|
||||
expect(rawToCooked('riso basmati', 'bollitura', 100, db)).toBe(300)
|
||||
})
|
||||
|
||||
it('calcola il peso cotto con fattore non intero', () => {
|
||||
expect(rawToCooked('pasta semola', 'bollitura', 100, db)).toBeCloseTo(188)
|
||||
})
|
||||
|
||||
it('calcola il peso cotto con fattore < 1 (verdure)', () => {
|
||||
expect(rawToCooked('zucchine', 'bollitura', 200, db)).toBeCloseTo(180)
|
||||
})
|
||||
|
||||
it('restituisce 0 per peso 0', () => {
|
||||
expect(rawToCooked('riso basmati', 'bollitura', 0, db)).toBe(0)
|
||||
})
|
||||
|
||||
it('scala linearmente con la quantità', () => {
|
||||
const single = rawToCooked('riso basmati', 'bollitura', 100, db)
|
||||
const double = rawToCooked('riso basmati', 'bollitura', 200, db)
|
||||
expect(double).toBeCloseTo(single * 2)
|
||||
})
|
||||
|
||||
it('usa il metodo di cottura corretto', () => {
|
||||
const padella = rawToCooked('pollo petto', 'padella', 100, db)
|
||||
const forno = rawToCooked('pollo petto', 'forno', 100, db)
|
||||
expect(padella).not.toBe(forno)
|
||||
expect(padella).toBe(75)
|
||||
expect(forno).toBe(70)
|
||||
})
|
||||
|
||||
it('funziona con legumi secchi (fattore molto > 1)', () => {
|
||||
expect(rawToCooked('ceci secchi', 'bollitura', 100, db)).toBeCloseTo(290)
|
||||
})
|
||||
})
|
||||
|
||||
describe('cookedToRaw', () => {
|
||||
it('calcola il peso crudo da un peso cotto', () => {
|
||||
expect(cookedToRaw('riso basmati', 'bollitura', 300, db)).toBeCloseTo(100)
|
||||
})
|
||||
|
||||
it('è l\'inverso esatto di rawToCooked', () => {
|
||||
const rawIn = 150
|
||||
const cooked = rawToCooked('pollo petto', 'padella', rawIn, db)
|
||||
const rawOut = cookedToRaw('pollo petto', 'padella', cooked, db)
|
||||
expect(rawOut).toBeCloseTo(rawIn)
|
||||
})
|
||||
|
||||
it('funziona con verdure (fattore < 1 → crudo > cotto)', () => {
|
||||
const crudo = cookedToRaw('zucchine', 'padella', 82, db)
|
||||
expect(crudo).toBeCloseTo(100)
|
||||
})
|
||||
|
||||
it('restituisce 0 per peso cotto 0', () => {
|
||||
expect(cookedToRaw('riso basmati', 'bollitura', 0, db)).toBe(0)
|
||||
})
|
||||
|
||||
it('scala linearmente', () => {
|
||||
const base = cookedToRaw('riso basmati', 'bollitura', 300, db)
|
||||
const doppio = cookedToRaw('riso basmati', 'bollitura', 600, db)
|
||||
expect(doppio).toBeCloseTo(base * 2)
|
||||
})
|
||||
})
|
||||
59
tests/unit/storage.test.js
Normal file
59
tests/unit/storage.test.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import { save, load } from '../../src/utils/storage.js'
|
||||
|
||||
// localStorage viene svuotato in tests/setup.js — qui garantiamo isolamento locale
|
||||
beforeEach(() => localStorage.clear())
|
||||
|
||||
describe('save', () => {
|
||||
it('serializza un oggetto in JSON', () => {
|
||||
save('test', { a: 1, b: 'due' })
|
||||
expect(localStorage.getItem('test')).toBe('{"a":1,"b":"due"}')
|
||||
})
|
||||
|
||||
it('serializza un array', () => {
|
||||
save('list', [1, 2, 3])
|
||||
expect(localStorage.getItem('list')).toBe('[1,2,3]')
|
||||
})
|
||||
|
||||
it('sovrascrive un valore esistente', () => {
|
||||
save('key', 'primo')
|
||||
save('key', 'secondo')
|
||||
expect(localStorage.getItem('key')).toBe('"secondo"')
|
||||
})
|
||||
|
||||
it('gestisce valori primitivi (numero, stringa, booleano)', () => {
|
||||
save('n', 42)
|
||||
save('s', 'ciao')
|
||||
save('b', false)
|
||||
expect(JSON.parse(localStorage.getItem('n'))).toBe(42)
|
||||
expect(JSON.parse(localStorage.getItem('s'))).toBe('ciao')
|
||||
expect(JSON.parse(localStorage.getItem('b'))).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('load', () => {
|
||||
it('restituisce il valore parsato se la chiave esiste', () => {
|
||||
localStorage.setItem('obj', '{"a":1}')
|
||||
expect(load('obj', null)).toEqual({ a: 1 })
|
||||
})
|
||||
|
||||
it('restituisce il default se la chiave non esiste', () => {
|
||||
expect(load('nonexistent', 'fallback')).toBe('fallback')
|
||||
})
|
||||
|
||||
it('restituisce il default anche per array vuoto come fallback', () => {
|
||||
expect(load('missing', [])).toEqual([])
|
||||
})
|
||||
|
||||
it('round-trip: save → load restituisce il valore originale', () => {
|
||||
const data = [{ id: 1, name: 'pasta', checked: false }]
|
||||
save('shopping', data)
|
||||
expect(load('shopping', [])).toEqual(data)
|
||||
})
|
||||
|
||||
it('round-trip su struttura pasti annidata', () => {
|
||||
const meals = { lunedi: { colazione: ['caffè'], pranzo: [], cena: [] } }
|
||||
save('meals', meals)
|
||||
expect(load('meals', {})).toEqual(meals)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user