88 lines
3.7 KiB
TypeScript
88 lines
3.7 KiB
TypeScript
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 = <T extends Parameters<typeof parseHiboutik>[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);
|
|
}
|
|
});
|
|
});
|