Add barcode scanner integration, identifier lookup, and enhanced field mapping for label creation
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
deriveLookupExpirationDays,
|
||||
mapLookupItemToForm,
|
||||
} from '../../../src/features/labels/identifier-lookup-mapper.js';
|
||||
|
||||
function createForm(overrides = {}) {
|
||||
return {
|
||||
itemId: '',
|
||||
itemUuidB64: '',
|
||||
identifierCode: '',
|
||||
externalSource: '',
|
||||
externalId: '',
|
||||
search: '',
|
||||
name: '',
|
||||
description: '',
|
||||
quantity: '',
|
||||
uom: 'g',
|
||||
stockType: 'binary',
|
||||
level: 'plenty',
|
||||
energy: '',
|
||||
energyUnit: 'kcal (100g/ml)',
|
||||
productionDate: '2026-04-10',
|
||||
expireDays: '',
|
||||
expirationDate: '',
|
||||
locationId: '',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('identifier lookup form mapper', () => {
|
||||
it('overwrites mapped fields with non-empty values and preserves production date', () => {
|
||||
const form = createForm({
|
||||
name: 'Old name',
|
||||
productionDate: '2026-04-10',
|
||||
});
|
||||
const lookupItem = {
|
||||
identifier_code: ' 3830012345678 ',
|
||||
name: 'Yogurt',
|
||||
description: 'Plain yogurt',
|
||||
stock_type: 'measured',
|
||||
level: 'low',
|
||||
quantity_initial: 0,
|
||||
uom_symbol: 'ml',
|
||||
calories: 61,
|
||||
calories_unit: 'kcal',
|
||||
external_source: 'openfoodfacts',
|
||||
external_id: 'off-123',
|
||||
expiration_days: 5,
|
||||
location_initial_uuid_b64: 'loc-freezer',
|
||||
};
|
||||
const locations = [
|
||||
{ id: 44, uuid_b64: 'loc-freezer', name: 'Freezer' },
|
||||
];
|
||||
|
||||
const result = mapLookupItemToForm({
|
||||
form,
|
||||
lookupItem,
|
||||
locations,
|
||||
});
|
||||
|
||||
expect(result.didUpdate).toBe(true);
|
||||
expect(result.form.identifierCode).toBe('3830012345678');
|
||||
expect(result.form.name).toBe('Yogurt');
|
||||
expect(result.form.search).toBe('Yogurt');
|
||||
expect(result.form.description).toBe('Plain yogurt');
|
||||
expect(result.form.stockType).toBe('measured');
|
||||
expect(result.form.level).toBe('low');
|
||||
expect(result.form.quantity).toBe('0');
|
||||
expect(result.form.uom).toBe('ml');
|
||||
expect(result.form.energy).toBe('61');
|
||||
expect(result.form.energyUnit).toBe('kcal');
|
||||
expect(result.form.externalSource).toBe('openfoodfacts');
|
||||
expect(result.form.externalId).toBe('off-123');
|
||||
expect(result.form.productionDate).toBe('2026-04-10');
|
||||
expect(result.form.expireDays).toBe('5');
|
||||
expect(result.form.expirationDate).toBe('2026-04-15');
|
||||
expect(result.form.locationId).toBe('44');
|
||||
expect(result.locationSearch).toBe('Freezer');
|
||||
});
|
||||
|
||||
it('clears mapped fields when lookup values are empty or null', () => {
|
||||
const form = createForm({
|
||||
name: 'Keep me',
|
||||
description: 'Still here',
|
||||
quantity: '2',
|
||||
uom: 'pc',
|
||||
energy: '120',
|
||||
energyUnit: 'kcal',
|
||||
stockType: 'descriptive',
|
||||
level: 'some',
|
||||
search: 'Keep me',
|
||||
identifierCode: '12345678',
|
||||
externalSource: 'cache',
|
||||
externalId: 'xyz',
|
||||
expireDays: '3',
|
||||
expirationDate: '2026-04-13',
|
||||
});
|
||||
const lookupItem = {
|
||||
name: ' ',
|
||||
description: null,
|
||||
quantity_initial: null,
|
||||
uom_symbol: '',
|
||||
calories: null,
|
||||
calories_unit: '',
|
||||
stock_type: '',
|
||||
level: '',
|
||||
identifier_code: '',
|
||||
external_source: null,
|
||||
external_id: ' ',
|
||||
date: 'bad-date',
|
||||
expire_date: '2026-05-20',
|
||||
};
|
||||
|
||||
const result = mapLookupItemToForm({
|
||||
form,
|
||||
lookupItem,
|
||||
locations: [],
|
||||
});
|
||||
|
||||
expect(result.didUpdate).toBe(true);
|
||||
expect(result.form.identifierCode).toBe('');
|
||||
expect(result.form.name).toBe('');
|
||||
expect(result.form.search).toBe('');
|
||||
expect(result.form.description).toBe('');
|
||||
expect(result.form.stockType).toBe('');
|
||||
expect(result.form.level).toBe('');
|
||||
expect(result.form.quantity).toBe('');
|
||||
expect(result.form.uom).toBe('');
|
||||
expect(result.form.energy).toBe('');
|
||||
expect(result.form.energyUnit).toBe('');
|
||||
expect(result.form.externalSource).toBe('');
|
||||
expect(result.form.externalId).toBe('');
|
||||
expect(result.form.expireDays).toBe('');
|
||||
expect(result.form.expirationDate).toBe('');
|
||||
expect(result.form.productionDate).toBe('2026-04-10');
|
||||
});
|
||||
|
||||
it('derives expiration days from date/expire_date when expiration_days is missing', () => {
|
||||
const days = deriveLookupExpirationDays({
|
||||
date: '2026-01-02',
|
||||
expire_date: '2026-01-12',
|
||||
});
|
||||
|
||||
expect(days).toBe(10);
|
||||
});
|
||||
|
||||
it('updates location only when current form location is empty', () => {
|
||||
const lookupItem = {
|
||||
location_initial_uuid_b64: 'loc-fridge',
|
||||
};
|
||||
const locations = [
|
||||
{ id: 5, uuid_b64: 'loc-fridge', name: 'Fridge' },
|
||||
];
|
||||
|
||||
const withExistingLocation = mapLookupItemToForm({
|
||||
form: createForm({ locationId: '8' }),
|
||||
lookupItem,
|
||||
locations,
|
||||
});
|
||||
const withoutLocation = mapLookupItemToForm({
|
||||
form: createForm({ locationId: '' }),
|
||||
lookupItem,
|
||||
locations,
|
||||
});
|
||||
|
||||
expect(withExistingLocation.form.locationId).toBe('8');
|
||||
expect(withExistingLocation.locationSearch).toBeNull();
|
||||
expect(withoutLocation.form.locationId).toBe('5');
|
||||
expect(withoutLocation.locationSearch).toBe('Fridge');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user