import { describe, it, expect } from 'vitest'; import { createCurr } from '@/glob/lib/curr_engine.ts'; import { createLing, p } from '@/ling/lib/engine.ts'; import type { CurrDefinition } from '../lib/curr_types.ts'; // ============================================================================= // FIXTURES // ============================================================================= const ling = createLing({ common: { ok: { es: 'Aceptar', en: 'OK' } } } as const, 'es'); const definitions: Record = { EUR: { symbol : '€', code : 'EUR', name : p({ es: { one: 'euro', other: 'euros' }, en: { one: 'euro', other: 'euros' } }), conversionValue: 1, }, USD: { symbol : '$', code : 'USD', name : p({ es: { one: 'dólar', other: 'dólares' }, en: { one: 'dollar', other: 'dollars' } }), conversionValue: 1.08, }, MXN: { symbol : '$', code : 'MXN', name : p({ es: { one: 'peso mexicano', other: 'pesos mexicanos' }, en: { one: 'Mexican peso', other: 'Mexican pesos' } }), conversionValue: 18.5, }, GBP: { symbol : '£', code : 'GBP', name : p({ es: { one: 'libra esterlina', other: 'libras esterlinas' }, en: { one: 'pound sterling', other: 'pounds sterling' } }), conversionValue: 0.85, }, JPY: { symbol : '¥', code : 'JPY', name : p({ es: { one: 'yen', other: 'yenes' }, en: { one: 'yen', other: 'yen' } }), conversionValue: null, // sin conversión disponible }, }; // ============================================================================= // CURR — Formato y conversión de moneda // ============================================================================= describe('createCurr', () => { describe('selectedCurrency', () => { it('usa la primera moneda definida por defecto', () => { const curr = createCurr(definitions, ling, {}, 'es'); expect(curr.getCurrency()).toBe('EUR'); }); it('acepta selectedCurrency en la configuración', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'MXN' }, 'es'); expect(curr.getCurrency()).toBe('MXN'); }); it('setCurrency cambia la moneda activa', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); curr.setCurrency('USD'); expect(curr.getCurrency()).toBe('USD'); }); it('setCurrency acepta minúsculas', () => { const curr = createCurr(definitions, ling, {}, 'es'); curr.setCurrency('gbp'); expect(curr.getCurrency()).toBe('GBP'); }); }); describe('f() — display symbol (por defecto)', () => { it('formatea con símbolo en es', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.f(99.5)).toBe('99,50 €'); }); it('formatea con símbolo en en', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'en'); expect(curr.f(99.5)).toBe('99.50 €'); }); it('usa selectedCurrency activa', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); curr.setCurrency('GBP'); expect(curr.f(99.5)).toBe('99,50 £'); }); }); describe('f() — display code', () => { it('formatea con código ISO', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.f(99.5, 'code')).toBe('99,50 EUR'); }); }); describe('f() — display name (pluralización)', () => { it('singular en es', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.f(1, 'name')).toBe('1,00 euro'); }); it('plural en es', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.f(99.5, 'name')).toBe('99,50 euros'); }); it('singular en en', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'en'); expect(curr.f(1, 'name')).toBe('1.00 euro'); }); it('plural MXN en es', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'MXN' }, 'es'); expect(curr.f(2, 'name')).toBe('2,00 pesos mexicanos'); }); }); describe('f() — locale reactivo via función', () => { it('responde a cambios de locale sin recrear el módulo', () => { let locale = 'es'; const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, () => locale); expect(curr.f(99.5)).toContain(',50 €'); locale = 'en'; expect(curr.f(99.5)).toContain('.50 €'); }); }); describe('f() — moneda no registrada', () => { it('fallback al código ISO si la moneda no está definida', () => { const curr = createCurr(definitions, ling, {}, 'es'); curr.setCurrency('XXX'); expect(curr.f(99.5)).toBe('99,50 XXX'); }); }); describe('convert()', () => { it('convierte EUR a USD', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.convert(100, 'EUR', 'USD')).toBeCloseTo(108, 1); }); it('convierte EUR a MXN', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.convert(100, 'EUR', 'MXN')).toBeCloseTo(1850, 0); }); it('misma moneda devuelve el mismo valor', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.convert(100, 'EUR', 'EUR')).toBe(100); }); it('devuelve null si conversionValue es null', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.convert(100, 'EUR', 'JPY')).toBeNull(); }); it('conversionValue como función dinámica', () => { let rate = 1.08; const defs = { EUR: { ...definitions.EUR }, USD: { ...definitions.USD, conversionValue: () => rate }, }; const curr = createCurr(defs, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.convert(100, 'EUR', 'USD')).toBeCloseTo(108, 1); rate = 1.20; expect(curr.convert(100, 'EUR', 'USD')).toBeCloseTo(120, 1); }); }); describe('convertTo()', () => { it('convierte desde selectedCurrency a otra moneda', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); expect(curr.convertTo(100, 'USD')).toBeCloseTo(108, 1); }); it('respeta la moneda activa cambiada con setCurrency', () => { const curr = createCurr(definitions, ling, { selectedCurrency: 'EUR' }, 'es'); curr.setCurrency('USD'); expect(curr.convertTo(108, 'EUR')).toBeCloseTo(100, 1); }); }); describe('get()', () => { it('devuelve la definición de una moneda registrada', () => { const curr = createCurr(definitions, ling, {}, 'es'); expect(curr.get('EUR')?.symbol).toBe('€'); }); it('devuelve undefined para moneda no registrada', () => { const curr = createCurr(definitions, ling, {}, 'es'); expect(curr.get('XXX')).toBeUndefined(); }); it('acepta minúsculas', () => { const curr = createCurr(definitions, ling, {}, 'es'); expect(curr.get('eur')).toBeDefined(); }); }); });