import test from 'node:test'; import assert from 'node:assert/strict'; import { buildDeliveryTimelineModel, buildVehicleTimelineModel, refreshPlan, refreshServerPlan, } from '../static/app/models.mjs'; import { colorForVehicle, routeStyleForVehicle, } from '../static/app/ui/overview.mjs'; function basePlan() { return { name: 'Test City', routingMode: 'straight_line', deliveries: [ { id: 0, label: 'A', kind: 'business', lat: 43.7696, lng: 11.2558, demand: 3, minStartTime: 8 * 3600, maxEndTime: 12 * 3600, serviceDuration: 10 * 60, }, { id: 1, label: 'B', kind: 'residential', lat: 43.7710, lng: 11.2620, demand: 2, minStartTime: 9 * 3600, maxEndTime: 18 * 3600, serviceDuration: 5 * 60, }, ], vehicles: [ { id: 0, name: 'Alpha', capacity: 10, homeLat: 43.7696, homeLng: 11.2558, departureTime: 6 * 3600, deliveryOrder: [0, 1], }, ], viewState: {}, }; } test('refreshPlan builds preview assignments and scores', () => { const plan = refreshPlan(basePlan()); assert.equal(plan.viewState.preview.vehicles.length, 1); assert.equal(plan.viewState.preview.deliveries[0].assignedVehicleName, 'Alpha'); assert.equal(plan.viewState.preview.unassignedDeliveryIds.length, 0); }); test('refreshServerPlan preserves authoritative backend preview', () => { const plan = basePlan(); plan.viewState.preview = { hardScore: -99, softScore: -12345, unassignedDeliveryIds: [1], vehicles: [], deliveries: [], }; const refreshed = refreshServerPlan(plan); assert.equal(refreshed.viewState.preview.hardScore, -99); assert.equal(refreshed.viewState.preview.softScore, -12345); assert.deepEqual(refreshed.viewState.preview.unassignedDeliveryIds, [1]); }); test('refreshPlan recomputes draft preview from straight-line estimates', () => { const plan = basePlan(); plan.viewState.preview = { hardScore: -99, softScore: -12345, unassignedDeliveryIds: [1], vehicles: [], deliveries: [], }; const refreshed = refreshPlan(plan); assert.equal(Math.abs(refreshed.viewState.preview.hardScore), 0); assert.notEqual(refreshed.viewState.preview.softScore, -12345); assert.equal(refreshed.viewState.preview.vehicles.length, 1); assert.ok(refreshed.viewState.preview.vehicles[0].totalTravelSeconds > 0); }); test('refreshPlan uses dominant unassigned-delivery hard penalty', () => { const plan = basePlan(); plan.vehicles[0].deliveryOrder = [0]; const refreshed = refreshPlan(plan); assert.equal(refreshed.viewState.preview.unassignedDeliveryIds.length, 1); assert.ok( refreshed.viewState.preview.hardScore <= -1_000_000, `expected unassigned hard penalty to dominate, got ${refreshed.viewState.preview.hardScore}`, ); }); test('timeline model builders emit lane collections', () => { const preview = refreshPlan(basePlan()).viewState.preview; const vehicleModel = buildVehicleTimelineModel(preview); const deliveryModel = buildDeliveryTimelineModel(preview); assert.equal(vehicleModel.lanes.length, 1); assert.equal(vehicleModel.lanes[0].items.length, 2); assert.equal(deliveryModel.lanes.length, 2); assert.ok(deliveryModel.lanes[0].items.length >= 1); }); test('vehicle map colors are unique across the ten-vehicle tutorial dataset', () => { const colors = Array.from({ length: 10 }, (_, vehicleId) => colorForVehicle(vehicleId)); assert.equal(new Set(colors).size, 10); assert.notEqual(colorForVehicle(1), colorForVehicle(9)); }); test('route highlight style is keyed by vehicle id, not color reuse', () => { assert.deepEqual(routeStyleForVehicle(1, 1), { color: colorForVehicle(1), opacity: 1, weight: 5, }); assert.deepEqual(routeStyleForVehicle(9, 1), { color: colorForVehicle(9), opacity: 0.2, weight: 2, }); });