134 lines
5.0 KiB
JavaScript
134 lines
5.0 KiB
JavaScript
import {
|
|
ORDER_STATUS_GROUPS,
|
|
ORDER_STATUS_LABELS,
|
|
ORDER_STATUS_ORDER,
|
|
statusesInGroup,
|
|
groupForBookingStatus,
|
|
isInGroup,
|
|
} from '@/lib/orderStatusGroups';
|
|
|
|
/**
|
|
* The Orders page's tab taxonomy. What these tests protect is that every raw
|
|
* backend booking enum lands in exactly one operator-facing tab, that an
|
|
* unmapped enum stays visible rather than vanishing from the totals, and that
|
|
* this taxonomy stays deliberately DIFFERENT from the Deliveries one (the file
|
|
* header calls the split explicit product direction that was reverted once).
|
|
*/
|
|
describe('orderStatusGroups', () => {
|
|
describe('shape of the taxonomy', () => {
|
|
it('should expose a label for every group key', () => {
|
|
Object.keys(ORDER_STATUS_GROUPS).forEach((group) => {
|
|
expect(ORDER_STATUS_LABELS[group]).toEqual(expect.any(String));
|
|
expect(ORDER_STATUS_LABELS[group]).not.toBe('');
|
|
});
|
|
});
|
|
|
|
it('should order the tabs to match the lifecycle and cover every group', () => {
|
|
expect(ORDER_STATUS_ORDER).toEqual(['pending', 'assigned', 'active', 'delivered', 'cancelled']);
|
|
expect([...ORDER_STATUS_ORDER].sort()).toEqual(Object.keys(ORDER_STATUS_GROUPS).sort());
|
|
});
|
|
|
|
it('should never assign the same raw status to two groups', () => {
|
|
const seen = new Map();
|
|
Object.entries(ORDER_STATUS_GROUPS).forEach(([group, raws]) => {
|
|
raws.forEach((raw) => {
|
|
expect(seen.has(raw)).toBe(false);
|
|
seen.set(raw, group);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should keep every raw status lowercase so lookups cannot miss on case', () => {
|
|
Object.values(ORDER_STATUS_GROUPS)
|
|
.flat()
|
|
.forEach((raw) => expect(raw).toBe(raw.toLowerCase()));
|
|
});
|
|
});
|
|
|
|
describe('groupForBookingStatus', () => {
|
|
it.each([
|
|
['pending_pickup', 'pending'],
|
|
['unassigned', 'pending'],
|
|
['miler_assigned', 'assigned'],
|
|
['converted_to_consignment', 'assigned'],
|
|
['pickup_scheduled', 'assigned'],
|
|
['out_for_delivery', 'active'],
|
|
['delivered', 'delivered'],
|
|
['cancelled', 'cancelled'],
|
|
['rejected', 'cancelled'],
|
|
])('should map raw booking status %s to the %s tab', (raw, group) => {
|
|
expect(groupForBookingStatus(raw)).toBe(group);
|
|
});
|
|
|
|
it('should keep Miler_Assigned on the Assigned tab — assigning is an operator action here', () => {
|
|
// Deliberately NOT the Deliveries taxonomy, where miler_assigned is still
|
|
// 'pending' until the rider themselves accepts.
|
|
expect(groupForBookingStatus('Miler_Assigned')).toBe('assigned');
|
|
});
|
|
|
|
it('should be case-insensitive about the backend enum casing', () => {
|
|
expect(groupForBookingStatus('OUT_FOR_DELIVERY')).toBe('active');
|
|
expect(groupForBookingStatus('Pending_Pickup')).toBe('pending');
|
|
});
|
|
|
|
it('should return the lowercased raw value for an enum it has never seen', () => {
|
|
// An unmapped status must stay visible in a breakdown, not vanish.
|
|
expect(groupForBookingStatus('Inwarded_At_Hub')).toBe('inwarded_at_hub');
|
|
expect(groupForBookingStatus('brand_new_backend_state')).toBe('brand_new_backend_state');
|
|
});
|
|
|
|
it.each([
|
|
[null, 'pending'],
|
|
[undefined, 'pending'],
|
|
['', 'pending'],
|
|
])('should treat a blank status (%p) as pending rather than crashing', (raw, expected) => {
|
|
expect(groupForBookingStatus(raw)).toBe(expected);
|
|
});
|
|
|
|
it('should not throw on a non-string status', () => {
|
|
expect(() => groupForBookingStatus(42)).not.toThrow();
|
|
expect(groupForBookingStatus(42)).toBe('42');
|
|
});
|
|
});
|
|
|
|
describe('statusesInGroup', () => {
|
|
it('should return the raw enums backing a known group', () => {
|
|
expect(statusesInGroup('delivered')).toEqual(['delivered', 'completed', 'success']);
|
|
});
|
|
|
|
it('should return an empty array for an unknown group instead of undefined', () => {
|
|
// Callers spread/`.includes()` this directly — undefined would throw.
|
|
expect(statusesInGroup('nope')).toEqual([]);
|
|
expect(statusesInGroup(undefined)).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('isInGroup', () => {
|
|
it('should confirm membership case-insensitively', () => {
|
|
expect(isInGroup('Out_For_Delivery', 'active')).toBe(true);
|
|
expect(isInGroup('delivered', 'active')).toBe(false);
|
|
});
|
|
|
|
it('should return false for an unknown group rather than throwing', () => {
|
|
expect(isInGroup('delivered', 'not_a_group')).toBe(false);
|
|
});
|
|
|
|
it('should treat a null status as not in any non-pending group', () => {
|
|
expect(isInGroup(null, 'delivered')).toBe(false);
|
|
// '' is an explicit member of the pending group.
|
|
expect(isInGroup(null, 'pending')).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('coverage of the tab set', () => {
|
|
it('should place every raw status into a group whose label is rendered', () => {
|
|
Object.values(ORDER_STATUS_GROUPS)
|
|
.flat()
|
|
.forEach((raw) => {
|
|
const group = groupForBookingStatus(raw);
|
|
expect(ORDER_STATUS_ORDER).toContain(group);
|
|
});
|
|
});
|
|
});
|
|
});
|