This commit is contained in:
2026-08-17 15:41:50 +08:00
parent 6bbbcb7750
commit bab911028d
2 changed files with 150 additions and 24 deletions
+42 -10
View File
@@ -5,10 +5,10 @@ import { readFile } from 'node:fs/promises'
const page = await readFile(new URL('../pages/picking/picking.vue', import.meta.url), 'utf8')
test('picking and photo workspaces are independently selectable', () => {
assert.match(page, /v-if="activeStage === 'evidence'" class="loading-evidence-section"/)
assert.match(page, /v-if="activeStage === 'evidence' && loadingStageReady" class="loading-evidence-section"/)
assert.match(page, /isPickingCompleteTask\(task\)[\s\S]*?AWAITING_REVIEW[\s\S]*?COMPLETED/)
assert.match(page, /pickingCompleted\(\)[\s\S]*?completedBoxes\[this\.currentBoxIndex\][\s\S]*?isPickingCompleteTask\(this\.remotePick\)/)
assert.match(page, /照片可先暂存/)
assert.match(page, /pickingCompleted\(\)[\s\S]*?if \(this\.remotePick\)[\s\S]*?hasServerPending[\s\S]*?isPickingCompleteTask\(this\.remotePick\) && !hasServerPending/)
assert.match(page, /请先处理并提交全部待拣明细/)
})
test('loading evidence is not requested before picking completion', () => {
@@ -36,17 +36,49 @@ test('AWAITING_REVIEW alone cannot request or mutate server evidence without a s
assert.doesNotMatch(page, /if \(this\.pickingCompleted\) await this\.loadLoadingEvidence\(\)/)
})
test('picking and evidence are separate operator-selected stages', () => {
test('dynamic pending items withdraw evidence until the server task is picking-complete again', () => {
assert.match(page, /class="stage-switch" role="tablist"/)
assert.match(page, /@tap="selectStage\('picking'\)"/)
assert.match(page, /@tap="selectStage\('evidence'\)"/)
assert.match(page, /selectStage\(stage\) \{[\s\S]*?this\.activeStage = stage/)
assert.match(page, /selectStage\(stage\) \{[\s\S]*?stage === 'evidence' && !this\.loadingStageReady[\s\S]*?请先完成新增待拣明细[\s\S]*?return[\s\S]*?this\.activeStage = stage/)
assert.match(page, /class="stage-tab"[\s\S]*?:disabled="!loadingStageReady"[\s\S]*?装柜取证/)
assert.match(page, /activeStage === 'picking'/)
assert.doesNotMatch(page, /activeStage === 'picking' \|\| !loadingStageReady/)
assert.match(page, /requireEvidenceCapture\(\)[\s\S]*?evidenceIdentity\?\.inboundId/)
assert.match(page, /if \(this\.loadingStageReady\) this\.queueEvidenceUpload/)
assert.match(page, /照片已暂存,装柜状态同步后自动上传/)
assert.match(page, /本地暂存,待自动上传/)
assert.match(page, /:disabled="submitting \|\| !loadingStageReady \|\| pickingVersion === null/)
})
test('incremental refresh merges new pending items without overwriting submitted server results', () => {
const restore = page.match(/restoreRemoteDraft\(\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
assert.match(restore, /const serverStates = \{ \.\.\.this\.itemStates \}/)
assert.match(restore, /serverStates\[id\] !== ITEM_STATUS\.PENDING/)
assert.match(restore, /status === ITEM_STATUS\.PARTIAL[\s\S]*?partial >= Number\(item\?\.qty/)
assert.match(restore, /this\.remotePick && !isPickingCompleteTask\(this\.remotePick\)[\s\S]*?delete completedBoxes\[this\.currentBoxIndex\]/)
assert.match(page, /const previousTaskVersion = this\.pickingVersion/)
assert.match(page, /const previousItemIds = new Set/)
assert.match(page, /previousEvidenceState[\s\S]*?isSameEvidenceIdentity\(previousEvidenceState\.identity, this\.evidenceIdentity\)[\s\S]*?this\.evidenceFiles = \{ \.\.\.this\.evidenceFiles, \.\.\.previousEvidenceState\.files \}/)
assert.match(page, /if \(!this\.pickingCompleted\)[\s\S]*?delete completedBoxes\[this\.currentBoxIndex\][\s\S]*?this\.activeStage = 'picking'/)
assert.match(page, /refresh\.incremental[\s\S]*?addedItemIds/)
})
test('incremental batch submits only current server-pending items and refreshes stale inventory conflicts', () => {
const submit = page.match(/async performSubmit\([^)]*\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
assert.match(submit, /item\.itemStatus && !\['PENDING', 'PICKING'\]\.includes\(item\.itemStatus\)\) return null/)
assert.match(submit, /const versionConflict = this\.isTaskConflict\(error\)/)
assert.match(submit, /await this\.refreshAfterTaskConflict\(conflictMessage\)/)
assert.match(submit, /const inventorySnapshot = await this\.refreshInventorySnapshot\(\)/)
assert.match(page, /refreshAfterTaskConflict\(message\)[\s\S]*?this\.submitId = ''[\s\S]*?await this\.syncRemoteTask\(\)[\s\S]*?await this\.refreshInventorySnapshot\(\)/)
assert.match(page, /refreshInventorySnapshot\(\)[\s\S]*?getPickingInventorySnapshot\(this\.remoteTaskId, warehouseId\)[\s\S]*?String\(snapshot\.version\) !== String\(this\.pickingVersion\)[\s\S]*?error\.code = 'A0409'/)
assert.match(page, /this\.pickingVersion = this\.remotePick\.pickingVersion \?\? this\.remotePick\.version/)
})
test('final completion preserves backend gate errors and refreshes after an atomic A0409', () => {
const complete = page.match(/async completeLoadingTask\(\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
assert.match(complete, /this\.isTaskConflict\(error\)[\s\S]*?await this\.refreshAfterTaskConflict\(error\.message \|\| '装柜前置条件已变化,请刷新后重试'\)/)
const save = page.match(/async saveEvidence\([^)]*\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
assert.match(save, /this\.isTaskConflict\(error\)[\s\S]*?refreshAfterTaskConflict/)
const flush = page.match(/async flushPendingEvidence\(\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
assert.match(flush, /!entry\.id && entry\.localPath/)
assert.match(flush, /if \(item\.fileId\) await this\.saveEvidence\(item\.type, null, item\.path\)/)
assert.match(flush, /else await this\.queueEvidenceUpload\(item\.type, item\.path\)/)
})
test('evidence identity is bound to task, inbound, loading plan and container booking', () => {