Files
baiyue-firstleg/scripts/admin-test-env-modules/fleet-handover-acceptance-contract.test.mjs
T

307 lines
23 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import { verifyFleetHandover, cleanupFleetHandoverResources } from './fleet-handover-acceptance.mjs'
const copy = value => value == null ? value : structuredClone(value)
function fixture(fault = '') {
const marker = 'TEST-HANDOVER-RUN', now = new Date(Date.now() - 60000).toISOString()
const proof = { marker: 'FT-CONTROLLED', tripNo: 'TR-ONE', vehicleId: '11', driverId: '21', warehouseId: '92',
stops: [{ name: 'Origin' }, { name: 'Destination', destinationKey: 'FBA:ONE' }] }
const originalTransport = { vehiclePlate: 'ORIGINAL', driverName: '原司机', driverPhone: '111' }
const trip = { tripNo: proof.tripNo, vehicleId: '11', driverId: '21', warehouseId: '92', ...originalTransport, status: 'IN_TRANSIT',
recordVersion: '7', departedAt: now, expectedDriverEndAt: new Date(Date.now() + 86400000).toISOString(), maxPalletSpaces: 30, maxLoadKg: 18000, maxVolumeCbm: 90 }
const dispatchDetails = ['A', 'B'].map(customer => ({ dispatchNo: `PC-${customer}`, customerId: customer, overseasWarehouseId: '92',
status: 'READY_TO_DEPART', packageCount: 10, pickedPackageCount: 10, shippedPackageCount: 0, ...originalTransport,
items: [{ id: `ITEM-${customer}`, warehousePalletId: 'PALLET-INTERNAL', inboundCode: `IN-${customer}`, packageCount: 10 }] }))
if (fault === 'r5-layout') {
Object.assign(dispatchDetails[0], { packageCount: 5, pickedPackageCount: 5, items: [
{ id: 'ITEM-A1', warehousePalletId: 'PALLET-1', packageCount: 1 }, { id: 'ITEM-A2', warehousePalletId: 'PALLET-2', packageCount: 4 }] })
Object.assign(dispatchDetails[1], { packageCount: 1, pickedPackageCount: 1, items: [{ id: 'ITEM-B1', warehousePalletId: 'PALLET-3', packageCount: 1 }] })
}
const liveDispatches = dispatchDetails.map(({ customerId, ...row }) => ({ ...row, status: 'DEPARTED', shippedPackageCount: row.packageCount }))
const cargo = dispatchDetails.flatMap(row => row.items.map((item, index) => ({ customerId: row.customerId, dispatchNo: row.dispatchNo,
dispatchItemId: item.id, warehousePalletId: item.warehousePalletId, palletNo: 'PAL-REAL', packages: item.packageCount,
destinationKey: fault === 'r5-layout' && index === 1 ? 'FBA:TWO' : 'FBA:ONE' })))
const pallets = [...new Set(cargo.map(row => row.warehousePalletId))].map(warehousePalletId => ({ warehousePalletId, palletSpaces: 1, weightKg: 100, volumeCbm: 1 }))
const originalHistory = { action: 'DEPART', recordVersion: '7', snapshot: { trip: copy(trip), confirmedLoad: { cargo,
pallets } } }
const resources = new Map([['VEHICLE:11', 'TR-ONE'], ['DRIVER:21', 'TR-ONE']])
const vehicles = new Map(), drivers = new Map(), probes = new Map(), calls = []
let createdVehicles = fault === 'reviewed-vehicle' ? 1 : 0, handover = null, preview = null
if (fault === 'reviewed-vehicle') vehicles.set('12', { id: '12', plateNumber: 'HO-24255909-3BC', recordVersion: '0',
status: 'IN_SERVICE', region: 'OVERSEAS', ownership: 'OWNED', maxPalletSpaces: 30, maxLoadKg: 18000, maxVolumeCbm: 90 })
const ok = data => ({ http: 200, body: { code: '200', data: copy(data) }, requestId: 'request', traceId: 'trace' })
const conflict = message => ({ http: 200, body: { code: 'A0409', message }, requestId: 'request', traceId: 'trace' })
const bump = () => { trip.recordVersion = String(BigInt(trip.recordVersion) + 1n) }
const bindings = dispatchDetails.map(row => ({ dispatchNo: row.dispatchNo, customerId: row.customerId }))
if (fault === 'binding-customer') bindings[0].customerId = 'OTHER'
if (fault === 'dispatch-cargo') liveDispatches[0].items = [{ ...liveDispatches[0].items[0], id: 'OTHER-ITEM' }]
const context = {
context: { async checkpointFleetHandover() {} },
marker, createdResources: { fleetTrips: [proof], fleetAcceptance: { marker, tripNo: proof.tripNo,
departure: { tripNo: proof.tripNo, status: 'IN_TRANSIT', departedAt: now, shippedPackages: dispatchDetails.reduce((n,row)=>n+row.packageCount,0), dispatches: dispatchDetails.map(row => ({ dispatchNo: row.dispatchNo, shippedPackages: row.packageCount })) } } },
assert(_module, label, _response, passed) { calls.push({ assertion: label, passed }) },
async requestMultipart(method, path, file) {
calls.push({ method, path, certificate: file.name }); assert.ok(file.name.includes('TEST-NOT-REAL')); assert.ok(file.content.byteLength > 0)
Object.assign(drivers.get('22'), { recordVersion: '1', licenseFileId: 'TEST-LICENSE-FILE' });
return ok(fault === 'upload-identity' ? { ...drivers.get('22'), id: 'OTHER' } : drivers.get('22'))
},
async request(method, path, body, token) {
calls.push({ method, path, body: copy(body), token })
if (path.includes('/finance-fee-sources?')) {
const customer = new URLSearchParams(path.split('?')[1]).get('customerId')
return ok([{ sourceFeeId: `FEE-${customer}`, sourceVersion: 1, sourceStatus: 'ACTIVE', feeItemCode: 'DELIVERY_FEE', direction: 'RECEIVABLE', originalCurrency: 'CNY', originalAmount: fault === 'fee-changed' && handover ? 99 : 10 }])
}
if (path.includes('/handover-status')) {
assert.equal(token, 'picker-secret')
const dispatchNo = path.split('/').at(-2), customer = dispatchNo.slice(-1)
const current = handover && fault !== 'pda-keeps-original' ? handover.snapshot.replacement : originalTransport
return ok({ dispatchNo, tripNo: trip.tripNo, originalDeparture: fault === 'rewritten-pda-departure' && handover ? current : originalTransport,
deliveries: cargo.filter(row=>row.dispatchNo===dispatchNo).map((row,index)=>({ deliveryNo: `DL-${customer}-${index}`, status: 'WAIT_DELIVERY', packages: row.packages, terminalAt: null,
transport: { vehiclePlate: current.vehiclePlate, driverName: current.driverName, driverPhone: current.driverPhone } })),
latestHandover: handover ? { handoverNo: handover.handoverNo } : null })
}
if (path.startsWith('/api/platform/v1/last-leg/dispatches/')) return ok(liveDispatches.find(row => row.dispatchNo === path.split('/').at(-1)))
if (path.endsWith('/master-data/vehicles') && method === 'POST') {
assert.equal(body.plateNumber, body.plateNumber.toUpperCase(), 'request must use the formal uppercase vehicle plate')
const vehicle = { ...body, id: String(12 + createdVehicles++), recordVersion: '0' }; vehicles.set(vehicle.id, vehicle); return ok(vehicle)
}
if (path.includes('/master-data/vehicles/')) {
const id = path.match(/\/vehicles\/([^/]+)/)[1], vehicle = vehicles.get(id)
if (method === 'PATCH') { vehicle.status = body.status; vehicle.recordVersion = '1' }
return ok(vehicle)
}
if (path.endsWith('/fleet/drivers') && method === 'POST') {
const profile = fault === 'driver-default-null' ? { warehouseId: null, vehicleModels: null, languagesAndArea: null,
medicalExpiresOn: null, trainingExpiresOn: null, insuranceExpiresOn: null } : {}
const driver = { id: '22', driverNo: 'DR-TEST', recordVersion: '0', details: { ...body, profile,
...(fault === 'driver-default-null' ? { licenseIssuedOn: null } : {}) }, active: true, reviewStatus: 'PENDING' }; drivers.set(driver.id, driver);
if (fault === 'driver-default-nonempty') driver.details.profile.warehouseId = 'OTHER'
return ok(fault === 'driver-identity' ? { ...driver, recordVersion: '3' } : driver)
}
if (path.includes('/fleet/drivers/')) {
const driver = drivers.get('22')
if (path.endsWith('/review')) { driver.reviewStatus = 'APPROVED'; driver.recordVersion = '2' }
if (path.endsWith('/status')) { driver.active = body.active; driver.recordVersion = '3' }
return ok(fault === 'review-version' && path.endsWith('/review') ? { ...driver, recordVersion: '1' } : driver)
}
if (path.endsWith('/fleet/trips') && method === 'POST') {
const next = { ...body, tripNo: `PROBE-${probes.size + 1}`, status: 'PLANNED', recordVersion: '0' }; probes.set(next.tripNo, next); return ok({ trip: next, dispatches: [] })
}
if (path.includes('/trips/PROBE-')) {
const number = path.match(/\/trips\/([^/]+)/)[1], probe = probes.get(number)
if (path.endsWith('/assignment')) {
if (resources.has(`VEHICLE:${body.vehicleId}`)) return conflict('车辆已被车次占用')
if (resources.has(`DRIVER:${body.driverId}`)) return conflict('司机已被车次占用')
resources.set(`VEHICLE:${body.vehicleId}`, number); resources.set(`DRIVER:${body.driverId}`, number)
Object.assign(probe, { vehicleId: body.vehicleId, driverId: body.driverId, recordVersion: '1' })
}
if (path.endsWith('/cancel')) {
for (const [resource, owner] of resources) if (owner === number) resources.delete(resource)
probe.status = 'CANCELLED'
}
return ok({ trip: probe, dispatches: [] })
}
if (path.includes('/history?')) {
const departure = copy(originalHistory)
if (handover && fault === 'rewritten-departure') departure.snapshot.trip.vehiclePlate = 'WRONG'
const records = handover ? [departure, { action: 'HANDOVER', recordVersion: '8' }] : [departure]
return ok({ records, total: records.length })
}
if (path.endsWith('/handovers/preview')) {
preview = { tripNo: trip.tripNo, recordVersion: trip.recordVersion,
previous: { vehicleId: '11', driverId: '21', ...originalTransport }, replacement: { vehicleId: '12', driverId: '22' },
capacity: { palletSpaces: 30, weightKg: 18000, volumeCbm: 90 }, cargoHash: 'a'.repeat(64), driverQualification: { canDispatch: true }, cargo: { remainingCargo: cargo.map(row => ({ customerId: row.customerId, dispatchNo: row.dispatchNo, itemId: row.dispatchItemId,
palletId: row.warehousePalletId, destinationKey: row.destinationKey, packages: row.packages })), completedDeliveries: [], remainingPalletIds: pallets.map(row=>row.warehousePalletId), occupied: { palletSpaces: pallets.length, weightKg: pallets.length*100, volumeCbm: pallets.length } } }
if (fault === 'wrong-customer') preview.cargo.remainingCargo[0].customerId = 'OTHER'
if (fault === 'preview-identity') preview.replacement.driverId = 'OTHER'
if (fault === 'preview-capacity') preview.capacity.palletSpaces = 29
if (fault === 'double-count-pallet') preview.cargo.occupied.palletSpaces = 2
return ok(preview)
}
if (path.endsWith('/handovers') && method === 'POST') {
if (handover && body.idempotencyKey === proof.handover.confirmRequest.idempotencyKey) return ok(handover)
if (String(body.selection.recordVersion) !== trip.recordVersion) {
if (fault === 'stale-accepted') return ok(handover)
return conflict(fault === 'unrelated-conflict' ? '费用正在处理中' : '车次已变化,请刷新后重新核对')
}
handover = { handoverNo: 'HO-REAL', tripNo: trip.tripNo, recordVersion: '0', snapshot: {
previous: { vehicleId: '11', driverId: '21', ...originalTransport }, replacement: { vehicleId: '12', driverId: '22', vehiclePlate: vehicles.get('12').plateNumber, driverName: '接替司机', driverPhone: '222' }, cargo: preview.cargo }, vehicleRelease: null, driverRelease: null }
Object.assign(trip, handover.snapshot.replacement); bump()
resources.set('VEHICLE:12', 'TR-ONE'); resources.set('DRIVER:22', 'TR-ONE')
if (fault === 'unknown-confirmation') throw new Error('connection lost after commit')
return ok(handover)
}
if (path.includes('/handovers?')) return ok({ records: handover ? [handover] : [], total: handover ? 1 : 0 })
if (path.endsWith('/resources/release')) {
const vehicle = body.resourceKind === 'VEHICLE', field = vehicle ? 'vehicleRelease' : 'driverRelease', resource = vehicle ? 'VEHICLE:11' : 'DRIVER:21'
if (handover[field]) {
if (fault === 'replay-releases-next') resources.delete(resource)
return ok(handover)
}
assert.equal(String(body.recordVersion), handover.recordVersion)
resources.delete(resource); handover[field] = { actualEndAt: body.actualEndAt, location: body.location,
idempotencyKey: body.idempotencyKey, vehicleStatus: body.vehicleStatus }
handover.recordVersion = String(BigInt(handover.recordVersion) + 1n); bump();
return ok(fault === 'release-version' && vehicle ? { ...handover, recordVersion: '99' } : handover)
}
if (path.endsWith('/trips/TR-ONE') && method === 'GET') return ok({ trip, dispatches: bindings })
throw new Error(`Unexpected test route ${method} ${path}`)
},
}
return { context, proof, dispatchDetails, calls, trip, resources, probes, vehicles, drivers }
}
test('fresh real departure carries all customer cargo, preserves DEPART and fees, and verifies both old-resource releases', async () => {
const f = fixture(), result = await verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails)
assert.equal(result.status, 'VERIFIED'); assert.equal(result.pdaReadCount, 4)
assert.equal(result.browser.originalVehiclePlate, 'ORIGINAL'); assert.match(result.browser.replacementVehiclePlate, /^HO-/)
assert.equal(f.proof.vehicleId, '12'); assert.equal(f.proof.driverId, '22'); assert.equal(f.proof.licenseFileId, 'TEST-LICENSE-FILE')
assert.equal(result.replacement.certificate.synthetic, true); assert.ok(result.replacement.certificate.contentBase64)
assert.doesNotMatch(JSON.stringify(result), /picker-secret/)
assert.ok(f.calls.filter(row => row.assertion).every(row => row.passed))
assert.ok(!f.calls.some(row => row.path?.endsWith('/depart') || row.path?.endsWith('/complete') || row.path?.endsWith('/cancel')))
assert.equal(f.resources.get('VEHICLE:11'), 'PROBE-1'); assert.equal(f.resources.get('DRIVER:21'), 'PROBE-1')
})
test('marker mismatch, unregistered copied proof and missing actual departure fail without HTTP', async () => {
for (const fault of ['marker', 'unregistered', 'departure']) {
const f = fixture(); let proof = f.proof
if (fault === 'marker') f.context.createdResources.fleetAcceptance.marker = 'ANOTHER-RUN'
if (fault === 'unregistered') proof = structuredClone(proof)
if (fault === 'departure') delete f.context.createdResources.fleetAcceptance.departure
await assert.rejects(verifyFleetHandover(f.context, 'test', proof, 'picker-secret', f.dispatchDetails), /本轮|当前marker/)
assert.equal(f.calls.length, 0)
}
})
test('unknown successful write preserves the original command and blocks automatic rerun and cleanup', async () => {
const f = fixture('unknown-confirmation')
const saved = []
f.context.context.checkpointFleetHandover = async proof => saved.push(copy(proof))
await assert.rejects(verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails), /connection lost/)
assert.equal(f.proof.handover.status, 'FAILED'); assert.ok(f.proof.handover.confirmRequest.idempotencyKey)
assert.equal(f.proof.handover.requests.at(-1).status, 'UNKNOWN_RESULT')
const sending = saved.find(row => row.requests.at(-1).path.endsWith('/handovers') && row.requests.at(-1).status === 'SENDING')
assert.deepEqual(sending.requests.at(-1).body, f.proof.handover.confirmRequest)
assert.equal(saved.at(-1).requests.at(-1).status, 'UNKNOWN_RESULT')
assert.ok(!JSON.stringify(saved).includes('picker-secret'))
const calls = f.calls.length
await assert.rejects(verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails), /不自动续跑/)
await assert.rejects(cleanupFleetHandoverResources(f.context, 'test', f.proof), /仅允许/)
assert.equal(f.calls.length, calls); assert.equal(f.proof.vehicleId, '11')
})
test('missing persistence and failed pre-send checkpoints cannot send HTTP', async () => {
const missing = fixture(); delete missing.context.context.checkpointFleetHandover
await assert.rejects(verifyFleetHandover(missing.context, 'test', missing.proof, 'picker-secret', missing.dispatchDetails), /持久化/)
assert.equal(missing.calls.length, 0)
for (const target of ['vehicle', 'multipart']) {
const f = fixture()
let blocked
f.context.context.checkpointFleetHandover = async proof => {
const entry = proof.requests.at(-1)
if (entry.status === 'SENDING' && (target === 'multipart' ? entry.file : entry.method === 'POST')) {
blocked = copy(entry); throw Error('disk full')
}
}
await assert.rejects(verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails), /disk full/)
assert.ok(blocked)
assert.ok(!f.calls.some(row => row.method === blocked.method && row.path === blocked.path))
if (target === 'multipart') {
assert.match(blocked.file.sha256, /^[a-f0-9]{64}$/); assert.ok(blocked.file.bytes > 0)
assert.equal(blocked.file.content, undefined)
}
}
})
test('every HTTP call observes a completed pre-send checkpoint; post-response disk failure stops the chain', async () => {
const f = fixture(), original = f.context.request.bind(f.context), saved = []
f.context.context.checkpointFleetHandover = async proof => {
const entry = proof.requests.at(-1)
if (entry.status === 'RESPONDED' && entry.method === 'POST') throw Error('response disk failure')
saved.push(copy(proof))
}
f.context.request = async (...args) => {
const entry = saved.at(-1).requests.at(-1)
assert.equal(entry.status, 'SENDING'); assert.equal(entry.path, args[1]); assert.deepEqual(entry.body, args[2])
return original(...args)
}
await assert.rejects(verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails), /response disk failure/)
assert.equal(f.calls.filter(row => row.method === 'POST').length, 1)
assert.equal(saved.at(-1).requests.at(-1).status, 'SENDING')
})
for (const [fault, message] of Object.entries({ 'driver-default-nonempty': '接替司机返回身份和版本', 'driver-identity': '接替司机返回身份和版本', 'upload-identity': '测试证照有正式文件归属',
'review-version': '接替司机已正式审核', 'preview-identity': '交接预览绑定原车次', 'preview-capacity': '交接预览容量', 'release-version': '原车辆已结束',
'binding-customer': '每张排车已发车', 'dispatch-cargo': '每张排车已发车', 'wrong-customer': '预览精确包含', 'double-count-pallet': '共享实托只计一次', 'stale-accepted': '陈旧版本交接必须拒绝', 'unrelated-conflict': '陈旧版本交接必须拒绝',
'pda-keeps-original': 'PDA保持原发车资源', 'rewritten-pda-departure': 'PDA保持原发车资源', 'fee-changed': '交接不新增或改写派送费用',
'rewritten-departure': '只新增一次交接且原DEPART内容保持不变', 'replay-releases-next': '旧请求重放不能释放下一计划车辆' })) {
test(`business counterexample ${fault} cannot be reported as successful handover`, async () => {
const f = fixture(fault)
await assert.rejects(verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails), new RegExp(message))
assert.equal(f.proof.handover.status, 'FAILED'); assert.ok(f.proof.handover.requests.length > 0)
assert.ok(!f.calls.some(row => row.path?.endsWith('/cancel')))
})
}
test('cleanup cannot run before genuine cargo completion and current-resource release', async () => {
const f = fixture(); await verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails)
const before = f.calls.length
await assert.rejects(cleanupFleetHandoverResources(f.context, 'test', f.proof), /整车结案/)
assert.ok(f.calls.slice(before).filter(row => row.method).every(row => row.method === 'GET'))
assert.equal(f.proof.handover.cleanup.status, 'FAILED')
})
test('missing diagnostic correlation blocks the run before creating replacement resources', async () => {
const f = fixture(), original = f.context.request.bind(f.context)
f.context.request = async (...args) => { const response = await original(...args); delete response.traceId; return response }
await assert.rejects(verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails), /读取真实在途车次/)
assert.equal(f.vehicles.size, 0); assert.equal(f.proof.handover.requests.length, 1)
assert.equal(f.proof.handover.requests[0].status, 'RESPONDED')
})
test('explicit closure cleanup cancels only test probes and disables newly created resources without deletion', async () => {
const f = fixture(); await verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails)
f.trip.status = 'COMPLETED'; f.trip.vehicleRelease = { actualEndAt: new Date().toISOString() }; f.trip.driverRelease = { actualEndAt: new Date().toISOString() }
f.resources.delete('VEHICLE:12'); f.resources.delete('DRIVER:22')
const result = await cleanupFleetHandoverResources(f.context, 'test', f.proof)
assert.equal(result.status, 'COMPLETED'); assert.ok([...f.probes.values()].every(row => row.status === 'CANCELLED'))
assert.ok([...f.vehicles.values()].every(row => row.status === 'INACTIVE')); assert.equal(f.drivers.get('22').active, false)
assert.ok(!f.calls.some(row => row.method === 'DELETE'))
})
test('formal driver response accepts empty profile with omitted or NULL optional fields', async () => {
const f = fixture('driver-default-null')
assert.equal((await verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails)).status, 'VERIFIED')
})
test('r5 two dispatches, three pallets and three deliveries preserve multi-destination cargo through handover and cleanup', async () => {
const f = fixture('r5-layout')
const result = await verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails)
assert.equal(result.status, 'VERIFIED'); assert.equal(result.pdaAfter.flatMap(row=>row.deliveries).length, 3)
assert.equal(result.preview.cargo.remainingPalletIds.length, 3)
f.proof.closure = { status: 'CARGO_COMPLETED_AND_RESOURCES_RELEASED' }
f.trip.status = 'COMPLETED'; f.trip.vehicleRelease = { actualEndAt: new Date().toISOString() }; f.trip.driverRelease = { actualEndAt: new Date().toISOString() }
f.resources.delete('VEHICLE:12'); f.resources.delete('DRIVER:22')
assert.equal((await cleanupFleetHandoverResources(f.context, 'test', f.proof)).status, 'COMPLETED')
})
test('explicit reviewed vehicle reuse skips the original POST and proceeds from driver creation', async () => {
const f = fixture('reviewed-vehicle'), snapshot = copy(f.vehicles.get('12'))
const reviewedVehicle = { snapshot, occupation: { vehicleId: '12', assignmentCount: 0 },
creationRequest: { method: 'POST', status: 'RESPONDED', http: 200, code: '200', requestId: 'r', traceId: 't',
body: { plateNumber: 'HO-24255909-3bc' }, result: snapshot } }
const result = await verifyFleetHandover(f.context, 'test', f.proof, 'picker-secret', f.dispatchDetails, { reviewedVehicle })
assert.equal(result.status, 'VERIFIED'); assert.equal(result.replacement.vehicleId, '12')
const created = f.calls.filter(row=>row.method==='POST' && row.path?.endsWith('/master-data/vehicles'))
assert.equal(created.length, 1); assert.match(created[0].body.plateNumber, /^HO-PROBE-/)
})
test('internal helper has no environment loader, SQL or standalone execution path', async () => {
const source = await readFile(new URL('./fleet-handover-acceptance.mjs', import.meta.url), 'utf8')
assert.doesNotMatch(source, /process\.env|process\.argv|fetch\(|execFile|INSERT INTO|UPDATE ll_|DELETE FROM/)
assert.match(source, /export async function verifyFleetHandover\(context, module, tripProof, pickerToken, dispatchDetails, \{ reviewedVehicle \} = \{\}\)/)
})