import { parseHiboutik } from './hiboutik.schema'; import { customerAddressHiboutikSchema, fullCustomerHiboutikSchema } from './customer.hiboutik.dto'; import { productHiboutikSchema } from './product.hiboutik.dto'; import { saleHiboutikSchema } from './sale.hiboutik.dto'; import { stockHiboutikSchema } from './stock.hiboutik.dto'; const parse = [0]>(schema: T, data: unknown) => parseHiboutik(schema, data, '/x'); describe('Hiboutik schemas', () => { const product = { product_id: 1, product_model: 'BT21 bottle', product_barcode: '8435497280048', product_brand: 1, product_supplier: 2, product_price: '13.99', product_discount_price: '0.00', product_category: 19, product_display_www: 1, product_arch: 0, products_desc: '', updated_at: '2026-06-28 17:02:55', product_specific_rules: [], }; it('accepts ids, references and flags sent as strings', () => { const parsed = parse(customerAddressHiboutikSchema, { address_id: ' 8 ', customers_id: '43', default: '0' }); expect(parsed.address_id).toBe(8); expect(parsed.customers_id).toBe(43); expect(parsed.default).toBe(0); }); it('turns empty references into 0 and empty text into ""', () => { const parsed = parse(productHiboutikSchema, { ...product, product_brand: '', product_category: null, products_desc: null }); expect(parsed.product_brand).toBe(0); expect(parsed.product_category).toBe(0); expect(parsed.products_desc).toBe(''); }); it('keeps numeric text (zip code) and prices as strings', () => { expect(parse(customerAddressHiboutikSchema, { address_id: 1, zip_code: 75002 }).zip_code).toBe('75002'); expect(parse(productHiboutikSchema, { ...product, product_price: 13.5 }).product_price).toBe('13.5'); }); it('defaults missing lists to [] and strips unknown fields', () => { const parsed = parse(productHiboutikSchema, { ...product, product_specific_rules: '', product_supply_price: '7.49' }); expect(parsed.product_specific_rules).toEqual([]); expect(parsed.product_size_details).toEqual([]); expect(parsed).not.toHaveProperty('product_supply_price'); expect(parse(saleHiboutikSchema, { sale_id: 5, total: '0.00' }).line_items).toEqual([]); }); it('leaves addresses and sales undefined when they are not arrays, so that stored data is kept', () => { const parsed = parse(fullCustomerHiboutikSchema, { customers_id: 1, addresses: '', sales: { error: 'x' } }); expect(parsed.addresses).toBeUndefined(); expect(parsed.sales).toBeUndefined(); }); it('parses stocks sent as decimal strings', () => { expect(parse(stockHiboutikSchema, { product_id: '1', product_size: '0', stock_available: '3.000' })).toEqual({ product_id: 1, product_size: 0, stock_available: 3, }); }); it.each([ ['a missing id', { ...product, product_id: undefined }], ['a zero id', { ...product, product_id: 0 }], ['a non-numeric id', { ...product, product_id: 'abc' }], ['a negative reference', { ...product, product_brand: -1 }], ['an invalid price', { ...product, product_price: 'free' }], ['a list that is not an array', { ...product, product_size_details: { size_id: 1 } }], ])('rejects %s', (_, data) => { expect(() => parse(productHiboutikSchema, data)).toThrow('Unexpected answer from Hiboutik /x'); }); it('names the faulty fields, never their values', () => { expect.assertions(2); try { parse(fullCustomerHiboutikSchema, { customers_id: 'jane@example.com', addresses: [{ address_id: 'Jane Doe' }] }); } catch (error) { expect((error as Error).message).toMatch(/customers_id.*addresses\.0\.address_id/); expect((error as Error).message).not.toMatch(/jane|Doe/i); } }); });