This commit is contained in:
2026-09-29 17:56:05 +08:00
parent ef5c8250c5
commit 0aaf855ce2
13 changed files with 121 additions and 145 deletions
+19 -22
View File
@@ -15,7 +15,6 @@ function tokens(version = 'old') {
const base = { user_id: 42, membership_id: 84, tenant_id: 0, app_code: 'PLATFORM', overseas_warehouse_id: 900, exp: future(), version }
return {
accessToken: jwt({ ...base, username: 'picker-42' }),
overseasAccessToken: jwt(base),
refreshToken: `refresh-${version}`,
roles: [PDA_ROLE], authorities: [PDA_AUTHORITY]
}
@@ -43,7 +42,7 @@ test('H5 proxy and App API roots normalize request upload and download paths to
globalThis.uni.uploadFile = (options) => { uploads.push(options.url); options.success({ statusCode: 200, data: JSON.stringify({ code: '200', data: { fileId: '1' } }), header: {} }) }
globalThis.uni.downloadFile = (options) => { downloads.push(options.url); options.success({ statusCode: 200, tempFilePath: '/tmp/photo.jpg', header: {} }) }
session.apiBase = '/overseas-api'
session.apiBase = '/api'
await resolvePallet('PLT-1')
await overseasUpload('/api/pda/v1/last-leg/photos/files', '/tmp/photo.jpg')
await overseasDownload('/api/pda/v1/last-leg/photos/files/1/download')
@@ -54,15 +53,15 @@ test('H5 proxy and App API roots normalize request upload and download paths to
await overseasDownload('/api/pda/v1/last-leg/photos/files/1/download')
assert.deepEqual(requests, [
'/overseas-api/pda/v1/last-leg/pallet-operations/pallets/resolve',
'/api/pda/v1/last-leg/pallet-operations/pallets/resolve',
'https://overseas.example.com/api/pda/v1/last-leg/pallet-operations/pallets/resolve'
])
assert.deepEqual(uploads, [
'/overseas-api/pda/v1/last-leg/photos/files',
'/api/pda/v1/last-leg/photos/files',
'https://overseas.example.com/api/pda/v1/last-leg/photos/files'
])
assert.deepEqual(downloads, [
'/overseas-api/pda/v1/last-leg/photos/files/1/download',
'/api/pda/v1/last-leg/photos/files/1/download',
'https://overseas.example.com/api/pda/v1/last-leg/photos/files/1/download'
])
for (const url of [...requests, ...uploads, ...downloads]) assert.doesNotMatch(url, /\/api\/api\//)
@@ -76,11 +75,11 @@ test('concurrent old-token 401 responses share one refresh and each replay once
refreshCount += 1
return setTimeout(() => options.success(ok(next)), 10)
}
if (options.header.Authorization === `Bearer ${old.overseasAccessToken}`) {
if (options.header.Authorization === `Bearer ${old.accessToken}`) {
oldCalls += 1
return setTimeout(() => options.success(denied()), oldCalls === 1 ? 0 : 30)
}
assert.equal(options.header.Authorization, `Bearer ${next.overseasAccessToken}`)
assert.equal(options.header.Authorization, `Bearer ${next.accessToken}`)
newCalls += 1
setTimeout(() => options.success(ok({ call: newCalls })), 0)
}
@@ -92,8 +91,7 @@ test('concurrent old-token 401 responses share one refresh and each replay once
assert.equal(refreshCount, 1)
assert.equal(oldCalls, 2)
assert.equal(newCalls, 2)
assert.equal(session.token, next.overseasAccessToken)
assert.equal(session.domesticToken, next.accessToken)
assert.equal(session.token, next.accessToken)
})
test('request retries only once and preserves the final request and trace identifiers', async () => {
@@ -134,7 +132,6 @@ test('refresh rejection clears every local token and returns the auth trace', as
})
assert.equal(session.currentUser, null)
assert.equal(session.token, '')
assert.equal(session.domesticToken, '')
assert.equal(session.refreshToken, '')
})
@@ -148,7 +145,7 @@ test('photo upload refreshes and replays once while retaining the file payload',
}
globalThis.uni.uploadFile = (options) => {
uploads.push({ filePath: options.filePath, name: options.name, authorization: options.header.Authorization })
if (options.header.Authorization === `Bearer ${old.overseasAccessToken}`) {
if (options.header.Authorization === `Bearer ${old.accessToken}`) {
return options.success({ statusCode: 401, data: JSON.stringify({ code: 'A0401', requestId: 'upload-old', traceId: 'upload-old-trace' }), header: {} })
}
options.success({ statusCode: 200, data: JSON.stringify({ code: '200', data: { fileId: '99' } }), header: {} })
@@ -178,11 +175,11 @@ test('H5 blob photo uses authenticated multipart fetch instead of uni.uploadFile
return new Response(JSON.stringify({ code: '200', data: { fileId: 'h5-1' } }), { status: 200 })
}
try {
session.apiBase = '/overseas-api'
session.apiBase = '/api'
assert.deepEqual(await overseasUpload('/api/pda/v1/last-leg/photos/files', 'blob:http://localhost/photo'), { fileId: 'h5-1' })
assert.equal(uploadFileCalls, 0)
assert.equal(uploaded.url, '/overseas-api/pda/v1/last-leg/photos/files')
assert.equal(uploaded.options.headers.Authorization, `Bearer ${value.overseasAccessToken}`)
assert.equal(uploaded.url, '/api/pda/v1/last-leg/photos/files')
assert.equal(uploaded.options.headers.Authorization, `Bearer ${value.accessToken}`)
assert.ok(uploaded.options.body instanceof FormData)
} finally {
globalThis.fetch = originalFetch
@@ -203,14 +200,14 @@ test('H5 File photo is appended directly without rereading a temporary blob URL'
let calls = 0
globalThis.uni.uploadFile = (options) => {
calls += 1
assert.equal(options.url, '/overseas-api/pda/photo')
assert.equal(options.header.Authorization, `Bearer ${value.overseasAccessToken}`)
assert.equal(options.url, '/api/pda/photo')
assert.equal(options.header.Authorization, `Bearer ${value.accessToken}`)
assert.equal(options.files[0].file, selected)
assert.equal(options.files[0].name, 'file')
options.success({ statusCode: 200, data: JSON.stringify({ code: '200', data: { fileId: 'direct-file' } }), header: {} })
}
try {
session.apiBase = '/overseas-api'
session.apiBase = '/api'
assert.deepEqual(await overseasUpload('/pda/photo', selected), { fileId: 'direct-file' })
assert.equal(calls, 1)
} finally {
@@ -225,13 +222,13 @@ test('native file runtime rejects an H5-relative overseas root before upload wit
prepareSession()
const originalLocation = globalThis.location
globalThis.location = { protocol: 'file:' }
session.apiBase = '/overseas-api'
session.apiBase = '/api'
let uploadCalls = 0
globalThis.uni.uploadFile = () => { uploadCalls += 1 }
try {
await assert.rejects(overseasUpload('/pda/photo', '_doc/photo.jpg'), (error) => {
assert.equal(error.code, 'PDA_OVERSEAS_API_BASE_REQUIRED')
assert.match(error.message, /VITE_OVERSEAS_API_BASE_URL/)
assert.equal(error.code, 'PDA_API_BASE_REQUIRED')
assert.match(error.message, /VITE_API_BASE_URL/)
assert.match(error.message, /HTTP\(S\)/)
return true
})
@@ -270,8 +267,8 @@ test('authenticated photo download maps the public api path through the H5 overs
}
assert.equal(await overseasDownload('/api/pda/v1/last-leg/receiving-containers/current/unload-photos/files/99/download'), '/tmp/restored.jpg')
assert.equal(calls.length, 1)
assert.equal(calls[0].url, '/overseas-api/pda/v1/last-leg/receiving-containers/current/unload-photos/files/99/download')
assert.equal(calls[0].header.Authorization, `Bearer ${value.overseasAccessToken}`)
assert.equal(calls[0].url, '/api/pda/v1/last-leg/receiving-containers/current/unload-photos/files/99/download')
assert.equal(calls[0].header.Authorization, `Bearer ${value.accessToken}`)
})
test('native image download accepts a valid temp file when App-Plus omits response headers', async () => {