This commit is contained in:
2026-08-27 13:50:44 +08:00
parent 35d0595d85
commit c704032d66
12 changed files with 128 additions and 84 deletions
+18 -10
View File
@@ -5,10 +5,12 @@ 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' && loadingStageReady" class="loading-evidence-section"/)
assert.match(page, /v-if="activeStage === 'evidence'" class="loading-evidence-section"/)
assert.match(page, /selectStage\(stage\) \{[\s\S]*?this\.activeStage = stage/)
assert.doesNotMatch(page, /:disabled="!loadingStageReady"/)
assert.match(page, /isPickingCompleteTask\(task\)[\s\S]*?AWAITING_REVIEW[\s\S]*?COMPLETED/)
assert.match(page, /pickingCompleted\(\)[\s\S]*?this\.remoteTaskId \|\| this\.currentBox\.taskId[\s\S]*?if \(!this\.remotePick\) return false[\s\S]*?hasServerPending[\s\S]*?isPickingCompleteTask\(this\.remotePick\) && !hasServerPending/)
assert.match(page, /请先处理并提交全部待拣明细/)
assert.doesNotMatch(page, /任务增量更新后|evidence-stage-hint/)
})
test('a server task never inherits a completed marker from the previously opened local cabinet', () => {
@@ -46,12 +48,12 @@ test('AWAITING_REVIEW alone cannot request or mutate server evidence without a s
assert.doesNotMatch(page, /if \(this\.pickingCompleted\) await this\.loadLoadingEvidence\(\)/)
})
test('dynamic pending items withdraw evidence until the server task is picking-complete again', () => {
test('dynamic pending items do not block switching between picking and evidence', () => {
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' && !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.doesNotMatch(page, /stage === 'evidence' && !this\.loadingStageReady/)
assert.doesNotMatch(page, /请先完成新增待拣明细/)
assert.match(page, /activeStage === 'picking'/)
assert.match(page, /:disabled="submitting \|\| !loadingStageReady \|\| pickingVersion === null/)
})
@@ -65,7 +67,8 @@ test('incremental refresh merges new pending items without overwriting submitted
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, /if \(!this\.pickingCompleted\)[\s\S]*?delete completedBoxes\[this\.currentBoxIndex\]/)
assert.doesNotMatch(page, /delete completedBoxes\[this\.currentBoxIndex\][\s\S]{0,160}?this\.activeStage = 'picking'/)
assert.match(page, /refresh\.incremental[\s\S]*?addedItemIds/)
})
@@ -139,11 +142,16 @@ test('merged or non-active cabinet details are rejected before claim and clear s
for (const reset of ['remoteLoading = false', 'submitting = false', 'remoteTaskId = null', 'loadingVersion = null', 'scanHistory = []', 'currentBox.containerBookingId = null', 'currentBox.currentContainerNo = null', 'resetEvidenceState()']) assert.match(clear, new RegExp(reset.replace(/[.()[\]]/g, '\\$&')))
})
test('server evidence mutations remain closed before the loading stage is ready', () => {
test('photos upload before picking completion while evidence binding remains gated', () => {
assert.match(page, /requireEvidenceStage\(\)[\s\S]*?if \(!this\.pickingCompleted\)[\s\S]*?请先提交拣货完成[\s\S]*?if \(!this\.loadingStageReady\)/)
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']) {
assert.ok(queue.indexOf('await queue.flush()') < queue.indexOf('if (!this.loadingStageReady)'))
assert.ok(queue.indexOf('if (!this.loadingStageReady)') < queue.indexOf('await this.saveEvidence(type, null, path)'))
assert.match(page, /chooseEvidence\(slot\)[\s\S]*?this\.queueEvidenceUpload\(slot\.type, path\)/)
const retry = page.match(/async retryEvidence\([^)]*\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
assert.match(retry, /if \(!this\.requireEvidenceCapture\(\)\) return/)
assert.ok(retry.indexOf('await queue.flush()') < retry.indexOf('if (!this.loadingStageReady)'))
for (const method of ['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`)
}
@@ -158,7 +166,7 @@ test('refresh preserves local photos for the same evidence identity and flushes
test('evidence photos render thumbnails and support full-screen preview', () => {
assert.match(page, /class="evidence-thumbnail" :src="evidencePreviewSource\(photo\)"/)
assert.match(page, /class="work-content" :class="\{ 'evidence-active': activeStage === 'evidence' && loadingStageReady \}"/)
assert.match(page, /class="work-content" :class="\{ 'evidence-active': activeStage === 'evidence' \}"/)
assert.match(page, /class="evidence-photo-grid"/)
assert.match(page, /class="evidence-count"/)
assert.match(page, /@tap="previewEvidencePhoto\(photo, slot\.type\)"/)