51 lines
4.1 KiB
JavaScript
51 lines
4.1 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { readFile } from 'node:fs/promises'
|
|
import vm from 'node:vm'
|
|
import { getDispatchHandoverStatus, normalizeHandoverStatus } from '../src/api/trip-handover.js'
|
|
import { session } from '../src/stores/session.js'
|
|
|
|
const wire = () => ({ dispatchNo: 'PC-ONE', tripNo: 'TR-ONE', tripStatus: 'IN_TRANSIT', tripRecordVersion: '90071992547409931',
|
|
originalDeparture: { vehiclePlate: 'ORIGINAL', driverName: '原司机' },
|
|
deliveries: [{ deliveryNo: 'DL-DONE', status: 'DELIVERED', packages: '10', remainingPackages: 0, terminalAt: '2026-10-03T01:00:00Z', transport: { vehiclePlate: 'ORIGINAL', driverName: '原司机' } },
|
|
{ deliveryNo: 'DL-PENDING', status: 'WAIT_DELIVERY', packages: 20, remainingPackages: 16, terminalAt: null, transport: { vehiclePlate: 'NEW', driverName: '接替司机' } }], latestHandover: null })
|
|
|
|
test('PDA query stays a GET in the dedicated namespace and never supplies customer or warehouse', async () => {
|
|
const calls = []; session.apiBase = '/gateway-api'; session.token = 'test-token'
|
|
globalThis.uni = { request(options) { calls.push(options); options.success({ statusCode: 200, data: { code: '200', data: wire() }, header: {} }) } }
|
|
const result = await getDispatchHandoverStatus('PC-ONE')
|
|
assert.equal(calls.length, 1); assert.equal(calls[0].method, 'GET'); assert.match(calls[0].url, /\/pda\/v1\/last-leg\/dispatches\/PC-ONE\/handover-status$/)
|
|
assert.ok(!calls[0].data?.customerId); assert.ok(!calls[0].data?.warehouseId)
|
|
assert.equal(result.tripRecordVersion, '90071992547409931'); assert.equal(result.deliveries[0].transport.vehiclePlate, 'ORIGINAL'); assert.equal(result.deliveries[1].transport.vehiclePlate, 'NEW')
|
|
})
|
|
test('normalization exposes only business references and does not replace missing fields with internal IDs', () => {
|
|
const data = wire(); data.customerId = 'secret-customer'; data.originalDeparture = { vehicleId: 'secret-vehicle' }; data.deliveries[0].id = 'secret-id'
|
|
const value = normalizeHandoverStatus(data)
|
|
assert.doesNotMatch(JSON.stringify(value), /secret-/); assert.equal(value.originalDeparture.vehiclePlate, '')
|
|
assert.equal(value.deliveries[0].packages, 10)
|
|
assert.equal(value.deliveries[1].remainingPackages, 16)
|
|
for (const remainingPackages of [null, '', -1, 21, '1.5']) assert.throws(() => normalizeHandoverStatus({ ...data, deliveries: [{ ...data.deliveries[1], remainingPackages }] }), /剩余箱数无效/)
|
|
for (const packages of [null, '', -1, 0, '1.5']) assert.throws(() => normalizeHandoverStatus({ ...data, deliveries: [{ ...data.deliveries[0], packages }] }), /箱数无效/)
|
|
})
|
|
test('a response for another dispatch is rejected', async () => {
|
|
session.apiBase = '/gateway-api'; session.token = 'test-token'
|
|
globalThis.uni = { request(options) { options.success({ statusCode: 200, data: { code: '200', data: wire() }, header: {} }) } }
|
|
await assert.rejects(getDispatchHandoverStatus('PC-OTHER'), /不属于当前排车/)
|
|
})
|
|
test('the component ignores stale responses after switching task and has no write commands', async () => {
|
|
const file = await readFile(new URL('../src/components/DispatchHandoverStatus.vue', import.meta.url), 'utf8')
|
|
const pending = []
|
|
const context = { getDispatchHandoverStatus: () => new Promise(resolve => pending.push(resolve)), toDispatchError: error => ({ message: error.message }) }
|
|
const source = file.match(/<script>([\s\S]*?)<\/script>/)[1].replace(/^import .*$/gm, '').replace('export default', 'component =')
|
|
vm.runInNewContext(source, context)
|
|
const component = context.component, state = { ...component.data(), dispatchNo: 'PC-OLD' }
|
|
const first = component.methods.load.call(state)
|
|
state.dispatchNo = 'PC-NEW'; const second = component.methods.load.call(state)
|
|
pending[1]({ dispatchNo: 'PC-NEW' }); await second
|
|
pending[0]({ dispatchNo: 'PC-OLD' }); await first
|
|
assert.equal(state.status.dispatchNo, 'PC-NEW')
|
|
assert.doesNotMatch(file, /confirmTripHandover|departDispatch|pickDispatchItem|POST/)
|
|
const page = await readFile(new URL('../src/pages/dispatch/dispatch.vue', import.meta.url), 'utf8')
|
|
assert.match(page, /DispatchHandoverStatus v-if="departed" :dispatch-no="current.dispatchNo"/)
|
|
})
|