2026-08-14 17:53:09 +08:00
|
|
|
import assert from 'node:assert/strict'
|
|
|
|
|
import { readFileSync } from 'node:fs'
|
|
|
|
|
import test from 'node:test'
|
2026-10-21 15:53:33 +08:00
|
|
|
import { normalizeModuleOrder } from '../admin-test-env-acceptance.mjs'
|
2026-08-14 17:53:09 +08:00
|
|
|
|
|
|
|
|
import {
|
2026-10-21 15:53:33 +08:00
|
|
|
validRecognition, sameOptionalWeight, confirmedVersion,
|
2026-08-14 17:53:09 +08:00
|
|
|
confirmedNetSummary,
|
2026-09-04 16:04:12 +08:00
|
|
|
isTransientGatewayFailure,
|
2026-08-27 13:50:33 +08:00
|
|
|
normalizeWeightPalletOptionPage,
|
2026-08-14 17:53:09 +08:00
|
|
|
normalizedGrossKg,
|
2026-08-27 11:07:57 +08:00
|
|
|
palletOptionsPath,
|
2026-08-14 17:53:09 +08:00
|
|
|
selectWeightPallet,
|
2026-08-27 11:07:57 +08:00
|
|
|
WEIGHT_PALLET_OPTIONS_PAGE_SIZE,
|
|
|
|
|
weightPalletOptionRecords,
|
2026-08-14 17:53:09 +08:00
|
|
|
workspaceWeightMatchesBaseline,
|
|
|
|
|
} from './inbound-weight-ocr.mjs'
|
|
|
|
|
|
2026-10-21 15:53:33 +08:00
|
|
|
test('OCR failure permits absent optional values but recognition requires a valid weight; correction and confirmation each advance version', () => {
|
|
|
|
|
assert.equal(validRecognition({ recognitionStatus: 'FAILED' }), true)
|
|
|
|
|
assert.equal(validRecognition({ recognitionStatus: 'RECOGNIZED' }), false)
|
|
|
|
|
assert.equal(validRecognition({ recognitionStatus: 'RECOGNIZED', weightValue: 45, weightUnit: 'KG', confidence: 0.9 }), true)
|
|
|
|
|
assert.equal(validRecognition({ recognitionStatus: 'RECOGNIZED', weightValue: 45, weightUnit: 'KG', confidence: 2 }), false)
|
|
|
|
|
assert.equal(sameOptionalWeight(undefined, null), true)
|
|
|
|
|
assert.equal(sameOptionalWeight(undefined, 0), false)
|
|
|
|
|
assert.equal(sameOptionalWeight(5, 6), false)
|
|
|
|
|
assert.equal(confirmedVersion(3, false), 4)
|
|
|
|
|
assert.equal(confirmedVersion(3, true), 5)
|
|
|
|
|
})
|
|
|
|
|
|
2026-09-04 16:04:12 +08:00
|
|
|
test('retries only transient gateway failures for the unauthenticated upload probe', () => {
|
2026-10-21 15:53:33 +08:00
|
|
|
const modules = normalizeModuleOrder(['inbound-weight-ocr'])
|
|
|
|
|
assert.ok(modules.indexOf('merchant-qualification-fixture') < modules.indexOf('orders'))
|
|
|
|
|
assert.ok(modules.indexOf('orders') < modules.indexOf('inbound-weight-ocr'))
|
2026-09-04 16:04:12 +08:00
|
|
|
assert.equal(isTransientGatewayFailure({ http: 0 }), true)
|
|
|
|
|
assert.equal(isTransientGatewayFailure({ http: 502 }), true)
|
|
|
|
|
assert.equal(isTransientGatewayFailure({ http: 503 }), true)
|
|
|
|
|
assert.equal(isTransientGatewayFailure({ http: 401 }), false)
|
|
|
|
|
assert.equal(isTransientGatewayFailure({ http: 403 }), false)
|
|
|
|
|
assert.equal(isTransientGatewayFailure({ http: 500 }), false)
|
|
|
|
|
})
|
|
|
|
|
|
2026-08-14 17:53:09 +08:00
|
|
|
test('selects a stable complete pallet snapshot without status or availability', () => {
|
|
|
|
|
const selected = selectWeightPallet([
|
|
|
|
|
{ palletId: '20', palletCode: 'P-20', palletType: 'STANDARD', capacityCbm: 2, tareWeightKg: 18.5 },
|
|
|
|
|
{ palletId: '3', palletCode: 'P-03', palletType: 'STANDARD', capacityCbm: 1.5, tareWeightKg: 12 },
|
|
|
|
|
])
|
|
|
|
|
assert.equal(selected.palletId, '3')
|
|
|
|
|
assert.equal(selectWeightPallet([]), null)
|
|
|
|
|
assert.equal(selectWeightPallet([
|
|
|
|
|
{ palletId: '3', palletCode: 'P-03', palletType: 'STANDARD', capacityCbm: 1.5 },
|
|
|
|
|
]), null)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('normalizes gross weight and summarizes confirmed net weight only', () => {
|
|
|
|
|
assert.equal(normalizedGrossKg(50.125, 'LB'), 22.736)
|
|
|
|
|
assert.equal(normalizedGrossKg(30, 'KG'), 30)
|
|
|
|
|
assert.equal(normalizedGrossKg(30, 'UNKNOWN'), null)
|
|
|
|
|
assert.deepEqual(confirmedNetSummary({ weightResults: [
|
|
|
|
|
{ recognitionStatus: 'CONFIRMED', netWeightKg: 11.5 },
|
|
|
|
|
{ recognitionStatus: 'PENDING_CONFIRM', netWeightKg: 99 },
|
|
|
|
|
{ recognitionStatus: 'CONFIRMED', netWeightKg: 2.125 },
|
|
|
|
|
] }), { count: 2, complete: true, total: 13.625 })
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('cleanup restores a non-empty carton fallback when there were no confirmed images', () => {
|
|
|
|
|
const initial = { actualGrossWeightKg: 54.4, weightResults: [] }
|
|
|
|
|
assert.deepEqual(confirmedNetSummary(initial), { count: 0, complete: true, total: 0 })
|
|
|
|
|
assert.equal(workspaceWeightMatchesBaseline({ actualGrossWeightKg: 54.4 }, 54.4), true)
|
|
|
|
|
assert.equal(workspaceWeightMatchesBaseline({ actualGrossWeightKg: null }, 54.4), false)
|
|
|
|
|
assert.equal(workspaceWeightMatchesBaseline({ actualGrossWeightKg: null }, null), true)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('HTTP scenario uses pallet option and net weight contracts without legacy final weight', () => {
|
|
|
|
|
const source = readFileSync(new URL('inbound-weight-ocr.mjs', import.meta.url), 'utf8')
|
2026-08-27 11:07:57 +08:00
|
|
|
const optionsPath = palletOptionsPath('10001', '20001', ' TP-09 ')
|
|
|
|
|
assert.match(optionsPath, /\/weight-pallet-options\?tenantId=10001&(?:page=1&size=50|size=50&page=1)/)
|
|
|
|
|
assert.match(optionsPath, /keyword=TP-09/)
|
|
|
|
|
assert.equal(WEIGHT_PALLET_OPTIONS_PAGE_SIZE, 50)
|
|
|
|
|
assert.deepEqual(weightPalletOptionRecords({
|
2026-08-27 13:50:33 +08:00
|
|
|
records: [{ palletId: '1' }], page: '1', size: '50', total: '1000', pages: '20',
|
2026-08-27 11:07:57 +08:00
|
|
|
}), [{ palletId: '1' }])
|
2026-08-27 13:50:33 +08:00
|
|
|
assert.deepEqual(normalizeWeightPalletOptionPage({
|
|
|
|
|
records: [], page: '1', size: '20', total: '0', pages: '0',
|
|
|
|
|
}), { records: [], page: 1, size: 20, total: 0, pages: 0 })
|
2026-08-27 11:07:57 +08:00
|
|
|
assert.equal(weightPalletOptionRecords([{ palletId: '1' }]), null)
|
2026-08-27 13:50:33 +08:00
|
|
|
assert.equal(weightPalletOptionRecords({ records: [], page: 1, size: 1000, total: 0, pages: 0 }), null)
|
2026-08-14 17:53:09 +08:00
|
|
|
assert.ok(source.indexOf('const palletOptionsResponse') < source.lastIndexOf('const uploadPath'))
|
|
|
|
|
assert.match(source, /form\.append\('file'/)
|
|
|
|
|
assert.doesNotMatch(source, /form\.append\('palletId'/)
|
|
|
|
|
assert.match(source, /palletId:\s*id\(pallet\.palletId\)/)
|
|
|
|
|
assert.match(source, /grossWeightKg/)
|
|
|
|
|
assert.match(source, /netWeightKg/)
|
|
|
|
|
assert.match(source, /palletTareWeightKg/)
|
|
|
|
|
assert.doesNotMatch(source, /finalWeightKg/)
|
|
|
|
|
assert.doesNotMatch(source, /pallet\.(?:status|available)/)
|
|
|
|
|
assert.doesNotMatch(source, /platform:pallet:list/)
|
|
|
|
|
assert.match(source, /verifyDeleted\(context, target, original, baselineWorkspaceWeight\)/)
|
|
|
|
|
assert.match(source, /workspaceWeightMatchesBaseline\(cleanup\.workspace, baselineWorkspaceWeight\)/)
|
|
|
|
|
assert.doesNotMatch(source, /verifyDeleted\([^\n]+baselineConfirmedNet/)
|
|
|
|
|
})
|