This commit is contained in:
2026-08-15 12:12:40 +08:00
parent f7166f2eba
commit 03734c8f25
4 changed files with 144 additions and 35 deletions
+2 -1
View File
@@ -63,7 +63,8 @@ test('picking page exposes five evidence slots, retry and remote completion stat
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\)\.reduce/)
assert.match(page, /this\.evidenceFiles = this\.evidenceItems\(result\)[\s\S]*?\.reduce/)
assert.match(page, /cacheEvidencePreview\(current\.fileId, current\.localPath/)
})
test('PDA cabinet picking adapter claims online and submits one atomic batch', () => {
+32 -8
View File
@@ -4,11 +4,11 @@ import { readFile } from 'node:fs/promises'
const page = await readFile(new URL('../pages/picking/picking.vue', import.meta.url), 'utf8')
test('loading evidence is mounted only after the current picking task is complete', () => {
assert.match(page, /v-if="loadingStageReady && activeStage === 'evidence'" class="loading-evidence-section"/)
test('picking and photo workspaces are independently selectable', () => {
assert.match(page, /v-if="activeStage === 'evidence'" 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.doesNotMatch(page, /class="loading-evidence-section" v-if="currentBox\.inboundId"/)
assert.match(page, /照片可先暂存/)
})
test('loading evidence is not requested before picking completion', () => {
@@ -26,7 +26,7 @@ test('operators receive actionable refresh guidance without internal version wor
assert.match(complete, /if \(!this\.requireEvidenceStage\(\)\) return/)
})
test('AWAITING_REVIEW alone cannot mount or request evidence without a server loading version', () => {
test('AWAITING_REVIEW alone cannot request or mutate server evidence without a server loading version', () => {
assert.match(page, /loadingStageReady\(\)[\s\S]*?this\.pickingCompleted[\s\S]*?this\.loadingVersion !== null[\s\S]*?Number\.isFinite/)
assert.match(page, /拣货已完成,装柜状态尚未同步,请刷新重试/)
assert.match(page, /if \(!this\.loadingStageReady \|\| !this\.evidenceIdentity/)
@@ -37,8 +37,13 @@ test('picking and evidence are separate operator-selected stages', () => {
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]*?stage === 'evidence'[\s\S]*?!this\.loadingStageReady[\s\S]*?请先完成拣货并刷新任务/)
assert.match(page, /activeStage === 'picking' \|\| !loadingStageReady/)
assert.match(page, /selectStage\(stage\) \{[\s\S]*?this\.activeStage = stage/)
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, /本地暂存,待自动上传/)
})
test('evidence identity is bound to task, inbound, loading plan and container booking', () => {
@@ -49,14 +54,33 @@ test('evidence identity is bound to task, inbound, loading plan and container bo
assert.match(page, /this\.evidenceIdentity = this\.captureEvidenceIdentity\(\)/)
})
test('evidence mutations defensively reject calls before picking completion', () => {
test('server evidence mutations remain closed before the loading stage is ready', () => {
assert.match(page, /requireEvidenceStage\(\)[\s\S]*?if \(!this\.pickingCompleted\)[\s\S]*?请先提交拣货完成[\s\S]*?if \(!this\.loadingStageReady\)/)
for (const method of ['chooseEvidence', 'queueEvidenceUpload', 'retryEvidence', 'saveEvidence', 'saveSealNo', 'voidEvidencePhoto', 'completeLoadingTask']) {
const queue = page.match(/async queueEvidenceUpload\([^)]*\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
assert.match(queue, /if \(!this\.loadingStageReady\) return/)
for (const method of ['retryEvidence', 'saveEvidence', 'voidEvidencePhoto', 'completeLoadingTask']) {
const body = page.match(new RegExp(`(?:async )?${method}\\([^)]*\\) \\{[\\s\\S]*?\\n\\t\\t\\t\\},`))?.[0] || ''
assert.match(body, /if \(!this\.requireEvidenceStage\(\)\)(?: return| \{)/, `${method} should guard the evidence stage`)
}
})
test('refresh preserves local photos for the same evidence identity and flushes them after loading readiness', () => {
assert.match(page, /this\.rememberEvidenceDraft\(\)/)
assert.match(page, /this\.restoreEvidenceDraft\(\)/)
assert.match(page, /async flushPendingEvidence\(\)[\s\S]*?queueEvidenceUpload/)
assert.match(page, /const localFiles = Object\.fromEntries/)
})
test('evidence photos render thumbnails and support full-screen preview', () => {
assert.match(page, /class="evidence-thumbnail" :src="evidencePreviewSource\(photo\)"/)
assert.match(page, /@tap="previewEvidencePhoto\(photo, slot\.type\)"/)
assert.match(page, /evidencePreviewSource\(photo\)[\s\S]*?localPath[\s\S]*?previewUrl[\s\S]*?fileUrl/)
assert.match(page, /previewEvidencePhoto\(photo, type\)[\s\S]*?uni\.previewImage\([\s\S]*?current[\s\S]*?urls/)
assert.match(page, /cacheEvidencePreview\(fileId, localPath/)
assert.match(page, /withCachedEvidencePreview\(photo[\s\S]*?evidencePreviewCache/)
assert.match(page, /已上传并保存/)
})
test('switching cabinets invalidates old sync and evidence upload state', () => {
const selector = page.match(/selectBox\(index\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
assert.match(selector, /this\.taskRequestId \+= 1/)