mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-20 05:56:53 +00:00
93173b1573
reservation:positions was on the ignored list, while the stop order the same reorder sends was applied, so in other tabs and for other members the bookings sat between the wrong stops until a reload. The event now writes the slots the way the mover's own list did, for the day it names (day_id from REST, dayId from the MCP tool) or as the global slot without one, and caches them offline. A booking handed back by an edit or a reservation:updated event without day slots keeps the ones it had, in the store and in the offline cache. Refs #2631
109 lines
5.0 KiB
TypeScript
109 lines
5.0 KiB
TypeScript
// FE-UTIL-MERGEDORDER-001 to -009: the reorder writes the desktop day plan and the
|
|
// phone's plan timeline both derive from a day's new timeline order.
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
keepDayPositions,
|
|
metadataWithLegPositions,
|
|
moveRow,
|
|
planMergedOrder,
|
|
withTransportPositions,
|
|
} from './mergedOrder';
|
|
|
|
const place = (id: number) => ({ type: 'place', data: { id } });
|
|
const note = (id: number) => ({ type: 'note', data: { id } });
|
|
const transport = (id: number, leg?: number) => ({
|
|
type: 'transport',
|
|
data: { id, __leg: leg == null ? undefined : { index: leg } },
|
|
});
|
|
|
|
describe('planMergedOrder', () => {
|
|
it('FE-UTIL-MERGEDORDER-001: places get sequential slots and what sits between two places shares the gap', () => {
|
|
const plan = planMergedOrder([place(1), note(7), transport(9), place(2), place(3)]);
|
|
expect(plan.assignmentIds).toEqual([1, 2, 3]);
|
|
expect(plan.noteUpdates).toEqual([{ id: 7, sort_order: 1 / 3 }]);
|
|
expect(plan.transportUpdates).toEqual([{ id: 9, day_plan_position: 2 / 3 }]);
|
|
expect(plan.legPosUpdates).toEqual({});
|
|
});
|
|
|
|
it('FE-UTIL-MERGEDORDER-002: rows before the first place sit below zero', () => {
|
|
const plan = planMergedOrder([note(7), place(1)]);
|
|
expect(plan.noteUpdates).toEqual([{ id: 7, sort_order: -0.5 }]);
|
|
expect(plan.assignmentIds).toEqual([1]);
|
|
});
|
|
|
|
it('FE-UTIL-MERGEDORDER-003: the legs of one booking are positioned leg by leg', () => {
|
|
const plan = planMergedOrder([place(1), transport(5, 0), place(2), transport(5, 1)]);
|
|
expect(plan.legPosUpdates).toEqual({ 5: { 0: 0.5, 1: 1.5 } });
|
|
expect(plan.transportUpdates).toEqual([]);
|
|
});
|
|
|
|
it('FE-UTIL-MERGEDORDER-004: a row of any other type takes a slot but writes nothing', () => {
|
|
const plan = planMergedOrder([place(1), { type: 'other', data: { id: 3 } }, note(4), place(2)]);
|
|
expect(plan.noteUpdates).toEqual([{ id: 4, sort_order: 2 / 3 }]);
|
|
expect(plan.transportUpdates).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('withTransportPositions', () => {
|
|
it('FE-UTIL-MERGEDORDER-005: writes the moved bookings for that day and leaves the rest as they were', () => {
|
|
const untouched = { id: 2, day_plan_position: 4, day_positions: { 3: 4 } };
|
|
const moved = { id: 1, day_plan_position: 0, day_positions: { 2: 9 } };
|
|
const fresh = { id: 3 };
|
|
const result = withTransportPositions(
|
|
[moved, untouched, fresh],
|
|
[
|
|
{ id: 1, day_plan_position: 1.5 },
|
|
{ id: 3, day_plan_position: 0.25 },
|
|
],
|
|
7
|
|
);
|
|
expect(result[0]).toEqual({ id: 1, day_plan_position: 1.5, day_positions: { 2: 9, 7: 1.5 } });
|
|
expect(result[1]).toBe(untouched);
|
|
expect(result[2]).toEqual({ id: 3, day_plan_position: 0.25, day_positions: { 7: 0.25 } });
|
|
});
|
|
});
|
|
|
|
describe('metadataWithLegPositions', () => {
|
|
it('FE-UTIL-MERGEDORDER-006: writes each moved leg position for the day, from a string or an object', () => {
|
|
const legs = [{ from: 'FRA', day_positions: { 1: 0.2 } }, { from: 'DXB' }];
|
|
const fromString = metadataWithLegPositions(JSON.stringify({ airline: 'LH', legs }), { 1: 2.5 }, 4);
|
|
expect(fromString).toEqual({
|
|
airline: 'LH',
|
|
legs: [
|
|
{ from: 'FRA', day_positions: { 1: 0.2 } },
|
|
{ from: 'DXB', day_positions: { 4: 2.5 } },
|
|
],
|
|
});
|
|
const fromObject = metadataWithLegPositions({ legs }, { 0: 1.5 }, 4);
|
|
expect(fromObject).toEqual({ legs: [{ from: 'FRA', day_positions: { 1: 0.2, 4: 1.5 } }, { from: 'DXB' }] });
|
|
expect((fromObject?.legs as unknown[])[1]).toBe(legs[1]);
|
|
});
|
|
|
|
it('FE-UTIL-MERGEDORDER-007: metadata without legs, or that cannot be read, has nothing to move', () => {
|
|
expect(metadataWithLegPositions(JSON.stringify({ airline: 'LH' }), { 0: 1 }, 4)).toBeNull();
|
|
expect(metadataWithLegPositions('{not json', { 0: 1 }, 4)).toBeNull();
|
|
expect(metadataWithLegPositions(null, { 0: 1 }, 4)).toBeNull();
|
|
expect(metadataWithLegPositions('', { 0: 1 }, 4)).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('moveRow', () => {
|
|
it('FE-UTIL-MERGEDORDER-008: puts the row in front of the target, behind it with after, at the end without one', () => {
|
|
const rows = ['a', 'b', 'c', 'd'];
|
|
expect(moveRow(rows, 3, (r) => r === 'b', false)).toEqual({ order: ['a', 'd', 'b', 'c'], index: 1 });
|
|
expect(moveRow(rows, 0, (r) => r === 'c', true)).toEqual({ order: ['b', 'c', 'a', 'd'], index: 2 });
|
|
expect(moveRow(rows, 1, () => false, false)).toEqual({ order: ['a', 'c', 'd', 'b'], index: 3 });
|
|
expect(rows).toEqual(['a', 'b', 'c', 'd']);
|
|
});
|
|
});
|
|
|
|
describe('keepDayPositions', () => {
|
|
it('FE-UTIL-MERGEDORDER-009: keeps the day slots of the replaced copy only when the new one has none', () => {
|
|
const prev: { id: number; day_positions?: Record<string, number> | null } = { id: 1, day_positions: { 4: 1.5 } };
|
|
expect(keepDayPositions({ id: 1 }, prev)).toEqual({ id: 1, day_positions: { 4: 1.5 } });
|
|
expect(keepDayPositions({ id: 1, day_positions: null }, prev)).toEqual({ id: 1, day_positions: null });
|
|
expect(keepDayPositions({ id: 1 }, undefined)).toEqual({ id: 1 });
|
|
});
|
|
});
|