import { calculatePrice, type PriceRule } from '../src/pricing/pricing.policy'; import { pricingSchema } from '../src/pricing/pricing.schema'; const rule: PriceRule = { taxMode: 'EXCLUSIVE', merchandiseTaxBps: 1800, shippingFee: '50.00', shippingTaxBps: 1800, freeShippingMinimum: null, }; describe('configurable pricing calculations', () => { it('calculates exclusive merchandise tax and shipping tax exactly', () => { expect(calculatePrice('100.00', rule)).toEqual({ merchandiseTax: '18.00', shippingNet: '50.00', shippingTax: '9.00', taxTotal: '27.00', payableTotal: '177.00', }); }); it('extracts inclusive tax without adding it twice and handles odd basis points', () => { expect( calculatePrice('118.00', { ...rule, taxMode: 'INCLUSIVE' }), ).toMatchObject({ merchandiseTax: '18.00', payableTotal: '177.00' }); expect( calculatePrice('100.01', { ...rule, taxMode: 'INCLUSIVE', merchandiseTaxBps: 1, }), ).toMatchObject({ merchandiseTax: '0.01' }); }); it('applies free shipping at the discounted merchandise threshold and rounds small values', () => { const free = { ...rule, freeShippingMinimum: '100.00' }; expect(calculatePrice('100.00', free)).toMatchObject({ shippingNet: '0.00', shippingTax: '0.00', payableTotal: '118.00', }); expect(calculatePrice('99.99', free).shippingNet).toBe('50.00'); expect( calculatePrice('0.01', { ...rule, merchandiseTaxBps: 5000, shippingFee: '0.00', }).merchandiseTax, ).toBe('0.01'); expect( calculatePrice('0', { ...free, freeShippingMinimum: '0.00' }) .payableTotal, ).toBe('0.00'); }); it('requires explicit bounded rules and rejects active or unknown fields on creation', () => { const input = { ...rule, name: 'Test policy', currency: 'INR', countryCode: 'in', }; expect(pricingSchema.parse(input)).toMatchObject({ countryCode: 'IN', region: '', }); for (const change of [ { merchandiseTaxBps: -1 }, { shippingTaxBps: 10001 }, { shippingFee: '-1.00' }, { active: true }, { countryCode: 'IND' }, { currency: 'XXX' }, ]) expect(pricingSchema.safeParse({ ...input, ...change }).success).toBe( false, ); }); });