Files
pda-overseas-uniapp/tests/business-identifiers-ui.test.mjs
T

94 lines
5.3 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
const read = (path) => readFile(new URL(path, import.meta.url), 'utf8')
const template = (source) => source.match(/<template>([\s\S]*?)<\/template>/)?.[1] || ''
const interpolations = (source) => [...template(source).matchAll(/\{\{([\s\S]*?)\}\}/g)].map((match) => match[1]).join('\n')
test('all registered user-facing pages avoid rendering internal identifiers', async () => {
const paths = [
'../src/pages/login/login.vue', '../src/pages/home/home.vue', '../src/pages/module/module.vue',
'../src/pages/operation/operation.vue', '../src/pages/pallet/pallet.vue', '../src/pages/profile/profile.vue',
'../src/pages/dispatch/dispatch.vue', '../src/pages/outbound/outbound.vue',
'../src/pages/stocktake/stocktake.vue', '../src/pages/move/move.vue', '../src/pages/relabel/relabel.vue', '../src/pages/query/query.vue',
'../src/pages/return-receipt/return-receipt.vue',
'../src/pages/return-packing/return-packing.vue',
'../src/pages/history/history.vue', '../src/pages/scanner-test/scanner-test.vue',
'../src/components/PortalHeader.vue', '../src/components/PopupHeader.vue',
'../src/components/ReceivingSessionSummary.vue', '../src/components/ScanTargetInput.vue'
]
const visibleExpressions = (await Promise.all(paths.map(read))).map(interpolations).join('\n')
for (const field of [
'orderId', 'inboundId', 'planId', 'containerBookingId', 'sourceContainerBookingId',
'warehouseId', 'palletId', 'locationId', 'positionId', 'user.id'
]) assert.doesNotMatch(visibleExpressions, new RegExp(field.replace('.', '\\.')))
})
test('operator and warehouse cards never fall back to internal IDs', async () => {
const [home, profile, session] = await Promise.all([
read('../src/pages/home/home.vue'),
read('../src/pages/profile/profile.vue'),
read('../src/stores/session.js')
])
assert.doesNotMatch(template(home), /warehouseId|warehouseCode|user\.warehouse/)
assert.doesNotMatch(home, /warehouseId\.slice|当前作业仓\s*·/)
assert.match(home, /warehouseName \|\| ''[\s\S]*海外仓未关联/)
assert.doesNotMatch(template(profile), /user\.id|user\.role|warehouseId|warehouseCode|user\.warehouse/)
assert.match(profile, /roleLabel\(\) \{ return '海外仓作业员' \}/)
assert.match(profile, /warehouseName \|\| ''[\s\S]*海外仓未关联/)
assert.doesNotMatch(session, /海外仓 #\$\{|warehouse:\s*profile\.warehouseCode/)
})
test('operation templates expose business references only and keep diagnostic evidence', async () => {
const [operation, pallet, summary, stocktake, move, relabel, query, returnReceipt, returnPacking, apiFiles] = await Promise.all([
read('../src/pages/operation/operation.vue'),
read('../src/pages/pallet/pallet.vue'),
read('../src/components/ReceivingSessionSummary.vue'),
read('../src/pages/stocktake/stocktake.vue'), read('../src/pages/move/move.vue'),
read('../src/pages/relabel/relabel.vue'), read('../src/pages/query/query.vue'),
read('../src/pages/return-receipt/return-receipt.vue'),
read('../src/pages/return-packing/return-packing.vue'),
Promise.all([
read('../src/api/inbound.js'), read('../src/api/pallet.js'),
read('../src/api/overseas.js'), read('../src/api/receiving-adapter.js'),
read('../src/api/warehouse-operations.js'), read('../src/api/relabel.js')
]).then((values) => values.join('\n'))
])
const forbiddenDisplayFields = [
'orderId', 'inboundId', 'planId', 'containerBookingId', 'sourceContainerBookingId',
'warehouseId', 'palletId', 'locationId', 'positionId'
]
for (const field of forbiddenDisplayFields) {
assert.doesNotMatch(template(operation), new RegExp(`\\b${field}\\b`))
assert.doesNotMatch(template(summary), new RegExp(`\\b${field}\\b`))
}
for (const field of ['orderId', 'inboundId', 'planId', 'containerBookingId', 'sourceContainerBookingId', 'warehouseId', 'palletId', 'locationId']) {
assert.doesNotMatch(template(pallet), new RegExp(`\\b${field}\\b`))
for (const page of [stocktake, move, relabel, query]) assert.doesNotMatch(template(page), new RegExp(`\\b${field}\\b`))
}
for (const field of [...forbiddenDisplayFields, 'customerId']) assert.doesNotMatch(template(returnReceipt), new RegExp(`\\b${field}\\b`))
for (const field of [...forbiddenDisplayFields, 'customerId']) assert.doesNotMatch(template(returnPacking), new RegExp(`\\b${field}\\b`))
for (const businessField of ['containerNo', 'inboundCode', 'cartonMark', 'palletCode']) {
assert.match(operation + pallet + summary, new RegExp(businessField))
}
assert.match(operation, /requestId[\s\S]*traceId/)
assert.match(pallet, /requestId[\s\S]*traceId/)
for (const page of [stocktake, move, relabel, query, returnReceipt, returnPacking]) assert.match(page, /requestId[\s\S]*traceId/)
assert.doesNotMatch(apiFiles, /\/api\/platform\/v1\/|inbound-code-relationships/)
})
test('missing user-visible relationships use explicit empty labels instead of ID-shaped fallbacks', async () => {
const [summary, pallet] = await Promise.all([
read('../src/components/ReceivingSessionSummary.vue'),
read('../src/pages/pallet/pallet.vue')
])
assert.match(summary, /overseasWarehouseCode[\s\S]*overseasWarehouseName/)
assert.match(summary, /unique\.length \? unique : \['—'\]/)
assert.match(pallet, /inboundCode \|\| '无入仓码'/)
assert.match(pallet, /locationCode \|\| '未绑定库位'/)
})