import { describe, it, expect } from 'vitest'; import { packEmptiesOntoWagons, wagonsNeeded, type EmptyLoadPick } from './emptyContainerLoad.util'; const pick = (id: string, containerSize: '20' | '40'): EmptyLoadPick => ({ id, containerSize }); describe('emptyContainerLoad.util', () => { it('gives each 40ft its own wagon', () => { const { assignments, unplaced } = packEmptiesOntoWagons( [pick('a', '40'), pick('b', '40')], [1, 2, 3], ); expect(unplaced).toEqual([]); expect(assignments.map((a) => a.wagonSequenceNo)).toEqual([1, 2]); }); it('pairs 20ft two to a wagon, last odd one alone', () => { const { assignments } = packEmptiesOntoWagons( [pick('a', '20'), pick('b', '20'), pick('c', '20')], [4, 5], ); expect(assignments.map((a) => [a.id, a.wagonSequenceNo])).toEqual([ ['a', 4], ['b', 4], ['c', 5], ]); }); it('never mixes a 40ft and a 20ft on one wagon', () => { const { assignments } = packEmptiesOntoWagons( [pick('a', '20'), pick('b', '40'), pick('c', '20')], [1, 2], ); const bySizeOnWagon = new Map(); for (const a of assignments) { bySizeOnWagon.set(a.wagonSequenceNo, [ ...(bySizeOnWagon.get(a.wagonSequenceNo) ?? []), a.containerSize, ]); } for (const sizes of bySizeOnWagon.values()) { expect(sizes.includes('40') ? sizes.length : 0).toBeLessThan(2); expect(sizes.length).toBeLessThanOrEqual(2); } }); it('reports picks that ran out of wagons instead of dropping them', () => { const { assignments, unplaced } = packEmptiesOntoWagons( [pick('a', '40'), pick('b', '40'), pick('c', '20'), pick('d', '20')], [7], ); expect(assignments).toHaveLength(1); expect(unplaced.map((p) => p.id)).toEqual(['b', 'c', 'd']); }); it('counts wagons needed', () => { expect(wagonsNeeded([])).toBe(0); expect(wagonsNeeded([pick('a', '40'), pick('b', '20'), pick('c', '20')])).toBe(2); expect(wagonsNeeded([pick('a', '20')])).toBe(1); }); });