119 lines
6.9 KiB
JavaScript
119 lines
6.9 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { readFile } from 'node:fs/promises'
|
|
|
|
const source = await readFile(new URL('../api/pda-loading.js', import.meta.url), 'utf8')
|
|
const page = await readFile(new URL('../pages/picking/picking.vue', import.meta.url), 'utf8')
|
|
|
|
test('PDA loading adapter keeps C04 read and write paths', () => {
|
|
for (const path of [
|
|
'/first-leg/pda-loading/tasks/pending',
|
|
'/loading/picking?tenantId=',
|
|
'/loading/picking/start?tenantId=',
|
|
'/loading/picking/complete?tenantId=',
|
|
'/loading/evidence/pda?tenantId=',
|
|
'/loading/complete?tenantId='
|
|
]) assert.match(source, new RegExp(path.replace(/[?]/g, '\\?')))
|
|
assert.match(source, /'Idempotency-Key'/)
|
|
assert.match(source, /PHOTO_STEP_1[\s\S]*PHOTO_STEP_4[\s\S]*SEAL/)
|
|
for (const label of ['空仓照片', '半仓照片', '满仓照片', '锁仓照片', '带锁码照']) assert.match(source, new RegExp(label))
|
|
assert.match(source, /uni\.uploadFile/)
|
|
assert.match(source, /\/files\/loading-evidence\//)
|
|
assert.match(source, /loading\/evidence\/pda\?tenantId=/)
|
|
assert.match(source, /loading\/evidence\/\$\{encodeURIComponent\(evidenceId\)\}\/void\/pda\?tenantId=/)
|
|
})
|
|
|
|
test('PDA adapter does not treat non-200 response bodies or network failures as success', () => {
|
|
assert.match(source, /if \(code !== '200'\)/)
|
|
assert.match(source, /next\.network = true/)
|
|
assert.match(source, /throw new Error\('缺少客户隔离标识 tenantId/)
|
|
})
|
|
|
|
test('C02 identifiers and separate picking/inbound versions are normalized explicitly', () => {
|
|
assert.match(source, /inboundId: row\.inboundId/)
|
|
assert.match(source, /inboundVersion: row\.inboundVersion/)
|
|
assert.match(source, /pickingVersion: row\.pickingVersion \?\? row\.loading\?\.pickingVersion/)
|
|
assert.match(source, /pickingVersion: task\.pickingVersion \?\? task\.version/)
|
|
assert.match(page, /expectedVersion: Number\(this\.pickingVersion\)/)
|
|
assert.match(page, /ITEM_STATUS, classifyScan, createItemStates, getPickSummary, submitStates/)
|
|
assert.match(page, /taskItemId: item\.id \?\? item\.itemId/)
|
|
assert.match(page, /submit\.batch/)
|
|
assert.match(page, /item\.itemStatus === 'PICKED'/)
|
|
assert.match(page, /item\.itemStatus === 'PARTIAL'/)
|
|
assert.match(page, /pickingCompleted \|\| !summary\.canSubmit/)
|
|
assert.match(page, /this\.loadingVersion = this\.remotePick\.inboundVersion \?\? this\.remotePick\.loadingVersion/)
|
|
assert.match(page, /状态尚未同步,请刷新重试/)
|
|
})
|
|
|
|
test('picking page exposes five evidence slots, retry and remote completion states', () => {
|
|
for (const text of ['PHOTO_STEP_1', 'PHOTO_STEP_4', 'SEAL', '网络失败', '确认装柜完成', 'loadingVersion']) {
|
|
assert.match(`${source}\n${page}`, new RegExp(text))
|
|
}
|
|
assert.match(page, /createEvidenceUploadQueue/)
|
|
assert.match(page, /retryEvidence/)
|
|
assert.match(page, /uploadEvidenceFile/)
|
|
assert.match(page, /submitting \|\| completedBoxes\[currentBoxIndex\]/)
|
|
assert.match(page, /completePicking\(/)
|
|
assert.match(page, /sourceType: \['camera'\]/)
|
|
assert.doesNotMatch(page, /sourceType: \['camera', 'album'\]/)
|
|
assert.match(page, /evidenceEntries\(slot\.type\)/)
|
|
assert.match(page, /voidEvidencePhoto\(/)
|
|
assert.match(page, /evidenceComplete/)
|
|
})
|
|
|
|
test('PDA evidence binding unwraps the nested loading action response before rendering saved files', () => {
|
|
assert.match(page, /evidenceItems\(result\)[\s\S]*?Array\.isArray\(result\?\.evidences\?\.evidences\)[\s\S]*?result\.evidences\.evidences/)
|
|
assert.match(page, /this\.evidenceFiles = this\.evidenceItems\(result\)[\s\S]*?\.reduce/)
|
|
assert.match(page, /cacheEvidencePreview\(current\.fileId, current\.localPath/)
|
|
})
|
|
|
|
test('PDA downloads authenticated evidence previews returned by the backend', () => {
|
|
assert.match(source, /export function getEvidencePreviewUrl\(inboundId, evidenceId, tenantId\)/)
|
|
assert.match(source, /loading\/evidence\/\$\{encodeURIComponent\(evidenceId\)\}\/content\/pda\?tenantId=/)
|
|
assert.match(source, /export function downloadEvidencePreview\(previewUrl\)/)
|
|
assert.match(source, /uni\.downloadFile\(/)
|
|
assert.match(source, /headers\.Authorization = `Bearer \$\{session\.token\}`/)
|
|
assert.match(source, /response\.tempFilePath/)
|
|
assert.match(source, /evidence\.preview\.response/)
|
|
assert.match(source, /\^image\\\//)
|
|
})
|
|
|
|
test('PDA cabinet picking adapter claims online and submits one atomic batch', () => {
|
|
assert.match(source, /\/first-leg\/pda-loading\/tasks\/pending/)
|
|
assert.doesNotMatch(source, /query\.push\(`cabinetNo=/)
|
|
assert.doesNotMatch(source, /query\.push\(`loadingPlanId=/)
|
|
assert.match(source, /tasks\/\$\{encodeURIComponent\(taskId\)\}\/claim/)
|
|
assert.match(source, /tasks\/\$\{encodeURIComponent\(task\.taskId\)\}\/batch/)
|
|
assert.match(source, /tasks\/\$\{encodeURIComponent\(taskId\)\}\/inventory-snapshot\?warehouseId=/)
|
|
assert.match(source, /submitContainerPickingBatch/)
|
|
assert.match(source, /stableIdempotencyKey/)
|
|
assert.match(source, /Math\.imul\(hash, 16777619\)/)
|
|
assert.match(source, /slice\(0, 128\)/)
|
|
assert.match(page, /claimContainerPickingTask\(/)
|
|
assert.match(page, /submitContainerPickingBatch\(/)
|
|
assert.match(page, /任务版本已变化,请刷新后重试/)
|
|
assert.match(source, /data: \{ warehouseId, loadingPlanId: task\.loadingPlanId, containerBookingId: task\.containerBookingId, expectedVersion, inventorySnapshotToken, items \}/)
|
|
assert.doesNotMatch(source, /query\.push\(`containerNo=/)
|
|
assert.doesNotMatch(page, /getContainerPickingTask\([^\n]*containerNo:/)
|
|
assert.match(source, /tasks\/\$\{encodeURIComponent\(taskId\)\}\?warehouseId=/)
|
|
assert.match(source, /currentContainerNo/)
|
|
assert.match(source, /getPickingInventorySnapshot[\s\S]*?\.then\(normalizeInventorySnapshot\)/)
|
|
assert.doesNotMatch(source.match(/export async function submitContainerPickingBatch[\s\S]*?\n\}/)?.[0] || '', /containerNo/)
|
|
assert.doesNotMatch(page, /claim-[^`]*currentBox\.boxNo/)
|
|
assert.doesNotMatch(page.match(/stableOperationId\('submit'[\s\S]*?\n/)?.[0] || '', /boxNo|containerNo|currentContainerNo/)
|
|
assert.match(page, /await getPickingInventorySnapshot\([\s\S]*await submitContainerPickingBatch/)
|
|
assert.match(page, /库存已变化,请刷新后重试/)
|
|
assert.doesNotMatch(source.match(/export async function submitContainerPickingBatch[\s\S]*?\n\}/)?.[0] || '', /for \(/)
|
|
assert.match(page, /version: Number\(item\.version \|\| 0\)/)
|
|
assert.match(page, /refreshTask/)
|
|
assert.match(page, /remoteError && !pickingCompleted/)
|
|
assert.match(page, /库存快照未同步,请刷新任务后重试/)
|
|
assert.match(page, /拣货完成未提交,请查看错误提示/)
|
|
assert.match(page, /if \(remoteTask\.workflowStatus === 'UNASSIGNED'\)[\s\S]*claimContainerPickingTask/)
|
|
assert.match(page, /this\.loadingVersion = this\.remotePick\.inboundVersion \?\? this\.remotePick\.loadingVersion/)
|
|
assert.match(page, /taskRequestId/)
|
|
assert.match(page, /resetEvidenceState/)
|
|
assert.match(page, /availablePickQuantity/)
|
|
assert.match(page, /库存\/库位可用量不足/)
|
|
})
|