This commit is contained in:
2026-10-19 16:40:51 +08:00
parent 54764156bf
commit 53cb68a8bc
7 changed files with 152 additions and 28 deletions
+3 -2
View File
@@ -46,7 +46,7 @@ test('palletization UI accepts carton and pre-generated pallet scans in either o
assert.match(work, /减少 \$\{line\.skuCode\} 清点数量/)
assert.match(work, /增加 \$\{line\.skuCode\} 清点数量/)
for (const text of ['compact-metrics', 'compact-action']) assert.match(work, new RegExp(text))
assert.doesNotMatch(work, /task\.customerName/)
assert.match(work, /task\.customerName/)
assert.match(work, /\.task-summary-card, \.section-card \{[^}]*border:\s*0;[^}]*border-bottom:\s*6px solid[^}]*border-radius:\s*0;[^}]*box-shadow:\s*none;/)
assert.match(work, /\.carton-card, \.pallet-card \{[^}]*border:\s*0;[^}]*border-top:\s*1px solid[^}]*border-radius:\s*0;[^}]*background:\s*transparent;/)
for (const text of ['计划 {{ carton.expectedSkuQuantity', "carton.cargoName", "carton.countStatus === 'UNCOUNTED'"]) assert.doesNotMatch(work, new RegExp(text))
@@ -54,7 +54,8 @@ test('palletization UI accepts carton and pre-generated pallet scans in either o
for (const text of ['expectedPalletCount', 'generatedPalletCount', 'palletSetupReady', 'palletSetupMessage']) assert.match(work, new RegExp(text))
assert.match(work, /<template v-if="palletSetupReady">[\s\S]*?ScanTargetInput[\s\S]*?count-unavailable/)
assert.match(work, /if \(!this\.palletSetupReady\) \{ this\.error = this\.palletSetupMessage; return \}/)
for (const text of ['绑定到扫描托盘', '生成 DP 托盘并绑定', '确认封托']) assert.doesNotMatch(work, new RegExp(text))
for (const text of ['绑定到扫描托盘', '生成 DP 托盘并绑定']) assert.doesNotMatch(work, new RegExp(text))
assert.match(work, /uni\.showModal\([\s\S]*?确认封托/)
assert.match(work, /class="task-summary-card"/)
assert.match(work, /\.task-summary-card\s*\{\s*display:\s*block;/)
assert.doesNotMatch(work, /class="summary-card"/)
+1 -1
View File
@@ -21,7 +21,7 @@ test('palletization uses the test workbench and canonical routes', async () => {
assert.match(await read('../pages/home/home.vue'), /'一件代发': '\/pages\/dropship-tasks\/dropship-tasks'/)
})
test('formal palletization preserves both scan orders, moves, sealing and safe unsealing', () => {
for (const symbol of ['resolveDropshipCarton', 'countDropshipCarton', 'bindDropshipPendingCartons', 'moveDropshipCarton', 'sealDropshipPallet', 'unsealDropshipPallet', 'planDropshipScan', 'restoreDropshipPalletizingDraft']) assert.ok(page.includes(symbol))
for (const symbol of ['resolveDropshipWorkspaceCarton', 'resolveDropshipWorkspacePallet', 'countDropshipCarton', 'bindDropshipPendingCartons', 'moveDropshipCarton', 'sealDropshipPallet', 'unsealDropshipPallet', 'planDropshipScan', 'restoreDropshipPalletizingDraft']) assert.ok(page.includes(symbol))
assert.match(page, /移回待绑托/)
assert.match(page, /palletSetupReady/)
assert.match(page, /pallet\?\.status === 'SEALED'/)
+72
View File
@@ -0,0 +1,72 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import vm from 'node:vm'
const source = await readFile(new URL('../pages/dropship-palletization/dropship-palletization.vue', import.meta.url), 'utf8')
const script = source.match(/<script>([\s\S]*?)<\/script>/)[1].replace(/^\s*import .*$/gm, '').replace('export default', 'globalThis.page =')
function harness(overrides = {}) {
const calls = []
const target = { taskId: '9007199254740999', customerName: '客户B', taskStatus: 'PENDING', palletSetupReady: true, pallets: [] }
const pallet = { palletId: '9007199254740998', palletNo: 'DP-261019-0001', status: 'OPEN', cartonCount: 2 }
const context = {
PortalHeader: {}, PopupHeader: {}, ScanTargetInput: {}, session: { currentUser: { id: '7' } },
getDropshipPalletizationTask: async (id) => { calls.push(['get', id]); return { ...target, taskId: id } },
claimDropshipPalletizationTask: async (id) => { calls.push(['claim', id]); return { ...target, taskId: id, taskStatus: 'CLAIMED' } },
resolveDropshipWorkspaceCarton: async () => ({ task: target, carton: { boxCode: 'BOX-B', canCount: true, skuLines: [{ skuCode: 'S', inboundDetailId: '44', expectedQuantity: 3 }] } }),
resolveDropshipWorkspacePallet: async () => ({ pallet, members: [] }),
countDropshipCarton: async (id, payload) => { calls.push(['count', id, payload]); return { carton: {} } },
moveDropshipCarton: async (id, cartonId, payload) => { calls.push(['move', id, cartonId, payload]); return { ...target, taskId: id } },
saveDropshipPalletizingDraft: () => {}, clearDropshipPalletizingDraft: () => {}, stableOperationId: () => 'stable-key',
isOnline: () => true, formatApiError: (error) => error.message, uni: { redirectTo: (value) => calls.push(['redirect', value]) },
...overrides
}
vm.runInNewContext(script, context)
const state = context.page.data()
Object.assign(state, context.page.methods, { taskId: '10', warehouseId: '100', task: { taskStatus: 'CLAIMED', palletSetupReady: true, version: 1 }, loading: false })
for (const [key, value] of Object.entries(context.page.computed)) Object.defineProperty(state, key, { get: () => value.call(state), configurable: true })
return { state, calls, pallet, target }
}
test('cross customer scan remains read only until confirmation and then claims original task', async () => {
const { state, calls, pallet, target } = harness()
state.workspace = { pallet, members: [] }; state.selectedPalletNo = pallet.palletNo
await state.resolveCarton('BOX-B')
assert.equal(state.taskId, '10')
assert.equal(state.scanTask.taskId, target.taskId)
assert.equal(calls.length, 0)
await state.confirmCarton()
assert.equal(calls[0][0], 'get')
assert.equal(calls[1][0], 'claim')
const counted = calls.find((call) => call[0] === 'count')
assert.equal(counted[1], target.taskId)
assert.equal(counted[2].palletNo, pallet.palletNo)
assert.equal(state.taskId, target.taskId)
})
test('failed pallet lookup removes stale active pallet and blocks counting', async () => {
const { state, pallet } = harness({ resolveDropshipWorkspacePallet: async () => { throw new Error('托盘不存在') } })
state.workspace = { pallet, members: [] }; state.selectedPalletNo = pallet.palletNo
state.carton = { canCount: true }; state.skuCounts = [{ actualQuantity: 1, expectedQuantity: 1 }]
await state.selectPallet('DP-261019-9999')
assert.equal(state.currentPallet, null)
assert.equal(state.canSubmitCarton, false)
})
test('moving another customers carton submits its own task id', async () => {
const { state, calls, pallet, target } = harness()
state.workspace = { pallet, members: [{ taskId: target.taskId, inboundId: '31', customerId: '2', customerName: '客户B' }] }
state.selectedPalletNo = pallet.palletNo
await state.moveCarton({ cartonId: '99', inboundId: '31' }, null)
assert.equal(calls.find((call) => call[0] === 'move')[1], target.taskId)
})
test('switching tickets carries only validated open pallet and scanner cannot race submission', async () => {
const { state, calls, pallet } = harness()
state.workspace = { pallet, members: [] }; state.selectedPalletNo = pallet.palletNo
state.continueOtherTask()
assert.match(calls[0][1].url, /palletNo=DP-261019-0001/)
state.submitting = true
await state.selectPallet('DP-261019-0002')
assert.equal(state.currentPallet.palletNo, pallet.palletNo)
})