优化
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { resolveEvidencePreviewUrl } from '../utils/api-url.js'
|
||||
|
||||
const previewPath = '/api/platform/v1/inbounds/100/loading/evidence/200/content/pda?tenantId=300'
|
||||
|
||||
test('evidence preview uses the H5 gateway proxy prefix after reopening a task', () => {
|
||||
assert.equal(
|
||||
resolveEvidencePreviewUrl(previewPath, '/gateway-api/platform/v1'),
|
||||
'/gateway-api/platform/v1/inbounds/100/loading/evidence/200/content/pda?tenantId=300'
|
||||
)
|
||||
})
|
||||
|
||||
test('evidence preview uses the configured absolute gateway origin on a PDA', () => {
|
||||
assert.equal(
|
||||
resolveEvidencePreviewUrl(previewPath, 'https://test.example.com/api/platform/v1'),
|
||||
'https://test.example.com/api/platform/v1/inbounds/100/loading/evidence/200/content/pda?tenantId=300'
|
||||
)
|
||||
})
|
||||
|
||||
test('absolute evidence preview URLs remain unchanged', () => {
|
||||
const absoluteUrl = 'https://files.example.com/evidence/200.png'
|
||||
assert.equal(resolveEvidencePreviewUrl(absoluteUrl, '/gateway-api/platform/v1'), absoluteUrl)
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
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')
|
||||
|
||||
test('empty evidence slots stay compact and completed slots expand with photos', async () => {
|
||||
const [page, styles] = await Promise.all([
|
||||
read('../pages/picking/picking.vue'),
|
||||
read('../styles/pda.scss')
|
||||
])
|
||||
|
||||
assert.match(page, /每类至少 1 张,拍照后自动上传,可继续追加/)
|
||||
assert.match(page, /v-for="\(slot, slotIndex\) in evidenceSlots"/)
|
||||
assert.match(page, /class="evidence-step"[\s\S]*?slotIndex \+ 1/)
|
||||
assert.match(page, /evidenceEntries\(slot\.type\)\.length \? '✓'/)
|
||||
assert.doesNotMatch(page, /class="evidence-empty-hint"/)
|
||||
assert.match(styles, /\.evidence-card-header \{[^}]*min-height: 44px/)
|
||||
assert.match(styles, /\.evidence-add-btn \{[^}]*min-height: 42px/)
|
||||
assert.match(styles, /\.evidence-photo-grid \{[^}]*grid-template-columns/)
|
||||
})
|
||||
@@ -125,7 +125,7 @@ test('non-picking operations remain complete static task pages', async () => {
|
||||
|
||||
test('picking page keeps scan, draft and risky transition contracts', async () => {
|
||||
const [page, scanner] = await Promise.all([read('../pages/picking/picking.vue'), read('../utils/scan-broadcast.js')])
|
||||
for (const text of ['确认拣出', '部分拣货', '跳拣', '提交拣货完成', '下一箱', '最近扫码']) assert.match(page, new RegExp(text))
|
||||
for (const text of ['确认拣出', '部分拣货', '跳拣', '提交拣货完成', '去拍照', '最近扫码']) assert.match(page, new RegExp(text))
|
||||
assert.match(page, /saveCurrentBoxDraft\(\)[\s\S]*?this\.boxDrafts =/)
|
||||
assert.match(page, /loadBoxState\(index\)[\s\S]*?const draft = this\.boxDrafts\[index\]/)
|
||||
assert.match(page, /requestBoxSwitch\(index\)[\s\S]*?this\.openOverlay\('switchBoxConfirm'\)/)
|
||||
@@ -213,10 +213,10 @@ test('business dialogs use uni-ui popup components consistently', async () => {
|
||||
assert.match(profile, /<uni-popup ref="logoutPopup" type="center"[\s\S]*?:is-mask-click="true"[\s\S]*?@change="handleLogoutChange"/)
|
||||
assert.match(profile, /<PopupHeader title="确认退出登录?"[\s\S]*?@close="closeLogout"/)
|
||||
assert.match(profile, /class="logout-dialog-confirm"/)
|
||||
for (const name of ['boxList', 'skip', 'partial', 'switchBoxConfirm', 'submitConfirm', 'complete', 'allComplete']) {
|
||||
for (const name of ['boxList', 'skip', 'partial', 'switchBoxConfirm', 'submitConfirm', 'complete']) {
|
||||
assert.match(picking, new RegExp(`<uni-popup ref="${name}Popup"[^>]*:is-mask-click="true"[^>]*@change="handleOverlayChange\\('${name}', \\$event\\)"`))
|
||||
}
|
||||
assert.equal((picking.match(/<PopupHeader\b/g) || []).length, 7)
|
||||
assert.equal((picking.match(/<PopupHeader\b/g) || []).length, 6)
|
||||
assert.match(picking, /openOverlay\(name\)[\s\S]*?this\.\$refs\[`\$\{name\}Popup`\]/)
|
||||
assert.match(picking, /closeOverlay\(\)[\s\S]*?popup\.close\(\)/)
|
||||
assert.match(picking, /handleOverlayChange\(name, event\)[\s\S]*?!event\.show[\s\S]*?this\.resetOverlayState\(\)/)
|
||||
@@ -274,12 +274,17 @@ test('shared visual contracts preserve accessible PDA targets', async () => {
|
||||
assert.match(app, /@import '@\/styles\/pda\.scss'/)
|
||||
assert.doesNotMatch(styles, /<\/?style\b/)
|
||||
for (const className of ['pick-btn', 'partial-quick-btn']) assert.match(styles, new RegExp(`\\.${className}\\s*\\{[\\s\\S]*?height:\\s*48px;`))
|
||||
assert.match(styles, /\.pick-item-actions\s*\{[^}]*grid-template-columns:\s*repeat\(3, minmax\(0, 1fr\)\);[^}]*width:\s*100%;/)
|
||||
assert.match(styles, /\.pick-btn\s*\{[^}]*width:\s*100%;[^}]*margin:\s*0;[^}]*align-items:\s*center;[^}]*justify-content:\s*center;/)
|
||||
assert.match(styles, /\.pick-btn::after\s*\{[^}]*border:\s*0;/)
|
||||
assert.match(styles, /\.processed-actions\s*\{[^}]*grid-template-columns:\s*1fr;/)
|
||||
assert.match(styles, /\.pick-btn-undo\s*\{[^}]*border-color:\s*#efb7b7;[^}]*color:\s*#b42323;[^}]*background:\s*#fff5f5;/)
|
||||
assert.doesNotMatch(styles, /\.scan-btn\s*\{/)
|
||||
assert.match(styles, /\.modal-cancel-btn,[\s\S]*?height:\s*48px;/)
|
||||
assert.match(styles, /\.modal-sheet\s*\{[\s\S]*?padding:\s*20px 18px 18px;/)
|
||||
assert.doesNotMatch(styles, /\.modal-sheet\s*\{[\s\S]*?padding:[^;]*env\(/)
|
||||
assert.match(styles, /\.submit-decision-modal\s*\{[^}]*padding:\s*18px 16px 16px;/)
|
||||
assert.match(styles, /\.evidence-card\s*\{[^}]*margin-bottom:\s*12px;/)
|
||||
assert.match(styles, /\.evidence-card\s*\{[^}]*margin-bottom:\s*8px;/)
|
||||
assert.match(styles, /\.evidence-card:last-child\s*\{[^}]*margin-bottom:\s*0;/)
|
||||
assert.match(tasks, /\.task-card\s*\{[^}]*margin:\s*0 0 12px;/)
|
||||
assert.match(tasks, /\.task-card:last-child\s*\{[^}]*margin-bottom:\s*0;/)
|
||||
|
||||
@@ -89,6 +89,8 @@ test('PDA downloads authenticated evidence previews returned by the backend', ()
|
||||
assert.match(source, /response\.tempFilePath/)
|
||||
assert.match(source, /evidence\.preview\.response/)
|
||||
assert.match(source, /\^image\\\//)
|
||||
assert.match(source, /resolveEvidencePreviewUrl/)
|
||||
assert.match(source, /const url = resolveEvidencePreviewUrl\(previewUrl, session\.apiBase/)
|
||||
})
|
||||
|
||||
test('PDA cabinet picking adapter claims online and submits one atomic batch', () => {
|
||||
|
||||
@@ -21,6 +21,15 @@ test('a server task never inherits a completed marker from the previously opened
|
||||
assert.match(page, /submitStatusHint\(\)[\s\S]*?if \(this\.pickingCompleted\) return '拣货已完成,请继续装柜取证'/)
|
||||
const submit = page.match(/async submitPicking\(\) \{[\s\S]*?\n\t\t\t\},/)?.[0] || ''
|
||||
assert.doesNotMatch(submit, /completedBoxes/)
|
||||
assert.match(page, /v-else-if="pickingOperationReady" class="pick-item-actions processed-actions"/)
|
||||
assert.doesNotMatch(page, /v-else-if="!(?:pickingCompleted|completedBoxes\[currentBoxIndex\])"/)
|
||||
})
|
||||
|
||||
test('picking completion leads to current cabinet evidence instead of an all-complete summary', () => {
|
||||
assert.match(page, /装柜照片已拍 \{\{ evidenceCapturedTypeCount \}\}\/\{\{ evidenceSlots\.length \}\} 类/)
|
||||
assert.match(page, /evidenceNextButtonText\(\)[\s\S]*?'查看装柜取证'[\s\S]*?'去拍照'/)
|
||||
assert.match(page, /continueToEvidence\(\)[\s\S]*?this\.activeStage = 'evidence'[\s\S]*?this\.scrollToTop\(\)/)
|
||||
assert.doesNotMatch(page, /查看全部完成|allCompletePopup|nextBox\(\)/)
|
||||
})
|
||||
|
||||
test('loading evidence is not requested before picking completion', () => {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
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')
|
||||
|
||||
test('direct H5 refresh restores the page user before rendering picking content', async () => {
|
||||
const page = await read('../pages/picking/picking.vue')
|
||||
|
||||
assert.match(page, /<view v-if="currentUser" class="page-shell">/)
|
||||
assert.match(page, /onLoad\(options = \{\}\) \{[\s\S]*?if \(!requireSession\(\)\) return[\s\S]*?this\.currentUser = session\.currentUser/)
|
||||
assert.match(page, /async onShow\(\) \{[\s\S]*?if \(!requireSession\(\)\) return[\s\S]*?this\.currentUser = session\.currentUser/)
|
||||
})
|
||||
|
||||
test('picking route carries only stable task and warehouse identity', async () => {
|
||||
const [tasks, page] = await Promise.all([
|
||||
read('../pages/tasks/tasks.vue'),
|
||||
read('../pages/picking/picking.vue')
|
||||
])
|
||||
const navigation = tasks.match(/uni\.navigateTo\(\{ url: `\/pages\/picking\/picking\?[^`]+` \}\)/)?.[0] || ''
|
||||
const onLoad = page.match(/onLoad\(options = \{\}\) \{[\s\S]*?\n\t\t\},\n\t\t\tasync onShow/)?.[0] || ''
|
||||
|
||||
assert.match(navigation, /\?taskId=\$\{encodeURIComponent\(task\.taskId\)\}&warehouseId=\$\{encodeURIComponent\(task\.warehouseId\)\}/)
|
||||
assert.doesNotMatch(navigation, /cabinetNo|currentContainerNo|orderNo|inboundId|tenantId/)
|
||||
assert.match(onLoad, /taskId: String\(options\.taskId\)/)
|
||||
assert.match(onLoad, /warehouseId: options\.warehouseId \? String\(options\.warehouseId\) : null/)
|
||||
assert.doesNotMatch(onLoad, /options\.(cabinetNo|currentContainerNo|orderNo|inboundId|inboundVersion|tenantId)/)
|
||||
})
|
||||
Reference in New Issue
Block a user