fix: complete October 22 workflow feedback and request failure recovery
This commit is contained in:
@@ -274,6 +274,49 @@ test('H5 blob photo uses authenticated multipart fetch instead of uni.uploadFile
|
||||
}
|
||||
})
|
||||
|
||||
test('H5 XMLHttpRequest timeout and abort reject once so the page can retry without an automatic upload replay', async () => {
|
||||
prepareSession()
|
||||
const originals = { window: globalThis.window, location: globalThis.location, fetch: globalThis.fetch, XMLHttpRequest: globalThis.XMLHttpRequest }
|
||||
globalThis.window = {}; globalThis.location = { protocol: 'http:' }
|
||||
globalThis.fetch = async () => new Response(new Blob(['photo'], { type: 'image/png' }))
|
||||
const requests = []
|
||||
globalThis.XMLHttpRequest = class {
|
||||
constructor() { requests.push(this) }
|
||||
open() {} setRequestHeader() {}
|
||||
send() { queueMicrotask(() => requests.length === 1 ? this.ontimeout() : this.onabort()) }
|
||||
}
|
||||
try {
|
||||
await assert.rejects(overseasUpload('/pda/photo', 'blob:photo'), error => error.network && /超时/.test(error.message))
|
||||
assert.equal(requests.length, 1); assert.equal(requests[0].timeout, 60000)
|
||||
await assert.rejects(overseasUpload('/pda/photo', 'blob:photo'), error => error.network && /中断/.test(error.message))
|
||||
assert.equal(requests.length, 2)
|
||||
} finally {
|
||||
for (const [key, value] of Object.entries(originals)) { if (value === undefined) delete globalThis[key]; else globalThis[key] = value }
|
||||
}
|
||||
})
|
||||
|
||||
test('H5 fetch upload aborts a stalled transfer, clears its timer, and permits a later upload', async () => {
|
||||
prepareSession()
|
||||
const originals = { window: globalThis.window, location: globalThis.location, fetch: globalThis.fetch, XMLHttpRequest: globalThis.XMLHttpRequest, setTimeout: globalThis.setTimeout, clearTimeout: globalThis.clearTimeout }
|
||||
let timeoutCallback, posts = 0, cleared = 0
|
||||
globalThis.window = {}; globalThis.location = { protocol: 'http:' }; delete globalThis.XMLHttpRequest
|
||||
globalThis.setTimeout = (callback, delay) => { assert.equal(delay, 60000); timeoutCallback = callback; return 'upload-timer' }
|
||||
globalThis.clearTimeout = handle => { assert.equal(handle, 'upload-timer'); cleared++ }
|
||||
globalThis.fetch = async (url, options) => {
|
||||
if (String(url).startsWith('blob:')) return new Response(new Blob(['photo'], { type: 'image/png' }))
|
||||
if (++posts === 1) return new Promise((_resolve, reject) => { options.signal.addEventListener('abort', () => reject(new Error('aborted'))); queueMicrotask(timeoutCallback) })
|
||||
return new Response(JSON.stringify({ code: '200', data: { fileId: 'retried-photo' } }), { status: 200 })
|
||||
}
|
||||
try {
|
||||
await assert.rejects(overseasUpload('/pda/photo', 'blob:photo'), error => error.network && /超时/.test(error.message))
|
||||
assert.equal(posts, 1); assert.equal(cleared, 1)
|
||||
assert.deepEqual(await overseasUpload('/pda/photo', 'blob:photo'), { fileId: 'retried-photo' })
|
||||
assert.equal(posts, 2); assert.equal(cleared, 2)
|
||||
} finally {
|
||||
for (const [key, value] of Object.entries(originals)) { if (value === undefined) delete globalThis[key]; else globalThis[key] = value }
|
||||
}
|
||||
})
|
||||
|
||||
test('H5 File photo is appended directly without rereading a temporary blob URL', async () => {
|
||||
const value = prepareSession()
|
||||
const originalWindow = globalThis.window
|
||||
|
||||
Reference in New Issue
Block a user