import { describe, it, expect } from 'vitest'; import { applyPreferences, mergeIntoBudgetInputs } from '@/lib/voice/apply'; import type { AbstractedPreferences } from '@/lib/voice/preferences'; import type { BudgetResult } from '@/budget/types'; function prefs(partial: Partial): AbstractedPreferences { return { calidadGlobal: 'media', materialSelections: {}, estructural: false, urgencia: null, presupuestoTarget: null, elementos: [], estiloRender: [], ajustes: [], confianza: 'media', resumen: '', camposFaltantes: [], ...partial, }; } const base: BudgetResult = { partidas: [{ key: 'mano_de_obra', label: 'Mano de obra', importe: 100000 }], subtotal: 100000, factorZona: 1, total: 100000, rango: { min: 85000, max: 115000 }, confianza: 'media', materialesRender: ['suelo cerámico gris'], avisos: [], }; describe('applyPreferences', () => { it('añade elementos y ajustes fijos como partidas y recalcula totales', () => { const r = applyPreferences(base, prefs({ elementos: [{ key: 'isla_cocina', label: 'Isla de cocina', importe: 120000 }], ajustes: [{ label: 'Encimera de piedra natural', tipo: 'fijo', valor: 50000, motivo: 'cuarzo' }], estiloRender: ['estilo nórdico'], })); const byKey = Object.fromEntries(r.partidas.map((p) => [p.key, p.importe])); expect(byKey.isla_cocina).toBe(120000); expect(r.partidas.some((p) => p.label === 'Encimera de piedra natural' && p.importe === 50000)).toBe(true); expect(r.subtotal).toBe(270000); expect(r.total).toBe(270000); expect(r.rango.min).toBe(229500); // round(85000 * 2.7) expect(r.rango.max).toBe(310500); // round(115000 * 2.7) expect(r.materialesRender).toContain('estilo nórdico'); }); it('un ajuste tipo factor se aplica sobre el subtotal original como partida explícita', () => { const r = applyPreferences(base, prefs({ ajustes: [{ label: 'Acabado premium global', tipo: 'factor', valor: 1.1, motivo: 'premium' }], })); expect(r.partidas.some((p) => p.label === 'Acabado premium global' && p.importe === 10000)).toBe(true); expect(r.subtotal).toBe(110000); }); }); describe('mergeIntoBudgetInputs', () => { it('vuelca preferencias y datos del lead en BudgetInputs', () => { const inputs = mergeIntoBudgetInputs( prefs({ calidadGlobal: 'premium', materialSelections: { suelo: 'suelo-p' }, estructural: true }), { tipoReforma: 'cocina', m2Suelo: 16, alturaTecho: null, provincia: 'Madrid' }, ); expect(inputs.calidadGlobal).toBe('premium'); expect(inputs.materialSelections.suelo).toBe('suelo-p'); expect(inputs.estructural).toBe(true); expect(inputs.m2Suelo).toBe(16); expect(inputs.provincia).toBe('Madrid'); }); });