fix retry after setting missed metaFields (#5805)

This commit is contained in:
Prakash 2025-08-11 17:45:16 +05:30 committed by GitHub
parent bff36260cd
commit eee05db260
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 177 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
"@uppy/core": patch
---
Fix retry after setting missed metaFields requiring you to click "retry" and then "upload" again. Now "retry" immediately restarts the upload.

View file

@ -1472,6 +1472,163 @@ describe('src/Core', () => {
await core.retryAll()
expect(onUpload).not.toHaveBeenCalled()
})
describe('with required metadata', () => {
it('should not retry files that have missing required metadata', async () => {
const onUpload = vi.fn()
const onRetryAll = vi.fn()
const core = new Core({
restrictions: {
requiredMetaFields: ['caption'],
},
})
core.on('upload', onUpload)
core.on('retry-all', onRetryAll)
const fileId = core.addFile({
source: 'vi',
name: 'foo.jpg',
type: 'image/jpeg',
data: testImage,
})
// Simulate an upload attempt which triggers metadata validation
try {
await core.upload()
} catch (error) {
expect(error).toBeInstanceOf(RestrictionError)
expect(error.message).toContain('Missing required meta fields')
}
// File should now have missing metadata error after upload attempt
const file = core.getFile(fileId)
expect(file.missingRequiredMetaFields).toEqual(['caption'])
expect(file.error).toContain('Missing required meta fields in foo.jpg')
// Should not retry files with outstanding metadata issues
await core.retryAll()
expect(onRetryAll.mock.calls[0][0]).toEqual([])
expect(onUpload).toHaveBeenCalledTimes(0)
})
it('should retry files after metadata is corrected', async () => {
const onUpload = vi.fn()
const onRetryAll = vi.fn()
const core = new Core({
restrictions: {
requiredMetaFields: ['caption'],
},
})
core.on('upload', onUpload)
core.on('retry-all', onRetryAll)
const fileId = core.addFile({
source: 'vi',
name: 'foo.jpg',
type: 'image/jpeg',
data: testImage,
})
try {
await core.upload()
} catch (error) {
expect(error).toBeInstanceOf(RestrictionError)
expect(error.message).toContain('Missing required meta fields')
}
// Verify file has missing metadata error after upload attempt
const file = core.getFile(fileId)
expect(file.missingRequiredMetaFields).toEqual(['caption'])
expect(file.error).toContain('Missing required meta fields in foo.jpg')
// Fix the metadata
core.setFileMeta(fileId, { caption: 'Test caption' })
// Trigger the dashboard:file-edit-complete event to update validation state
// @ts-ignore
core.emit('dashboard:file-edit-complete', core.getFile(fileId))
const updatedFile = core.getFile(fileId)
expect(updatedFile.missingRequiredMetaFields).toEqual([])
// Now retry should work
await core.retryAll()
expect(onRetryAll.mock.calls[0][0]).toContainEqual(
expect.objectContaining({ id: fileId }),
)
expect(onUpload).toHaveBeenCalledTimes(1) // Called once during retry (initial upload failed at validation)
})
it('should handle multiple files with mixed metadata states', async () => {
const onUpload = vi.fn()
const onRetryAll = vi.fn()
const core = new Core({
restrictions: {
requiredMetaFields: ['caption'],
},
})
core.on('upload', onUpload)
core.on('retry-all', onRetryAll)
// Add files with missing metadata
const fileId1 = core.addFile({
source: 'vi',
name: 'file1.jpg',
type: 'image/jpeg',
data: testImage,
})
const _fileId2 = core.addFile({
source: 'vi',
name: 'file2.jpg',
type: 'image/jpeg',
data: testImage,
})
const fileId3 = core.addFile({
source: 'vi',
name: 'file3.jpg',
type: 'image/jpeg',
data: testImage,
})
try {
await core.upload()
} catch (error) {
expect(error).toBeInstanceOf(RestrictionError)
expect(error.message).toContain('Missing required meta fields')
}
// Give one file a different error (not metadata-related)
core.setFileState(fileId3, {
error: 'Network error',
missingRequiredMetaFields: [],
})
// Fix metadata for first file only
core.setFileMeta(fileId1, { caption: 'Fixed caption' })
// @ts-ignore
core.emit('dashboard:file-edit-complete', core.getFile(fileId1))
// Add an error to file1 so it can be retried
core.setFileState(fileId1, {
error: 'Upload failed',
})
// Retry should only include file1 and file3 (file2 still has missing metadata)
await core.retryAll()
const retriedFiles = onRetryAll.mock.calls[0][0]
expect(retriedFiles).toContainEqual(
expect.objectContaining({ id: fileId1 }),
)
expect(retriedFiles).toContainEqual(
expect.objectContaining({ id: fileId3 }),
)
expect(onUpload).toHaveBeenCalledTimes(1)
})
})
})
describe('restoring a file', () => {

View file

@ -918,13 +918,18 @@ export class Uppy<
this.#restricter.getMissingRequiredMetaFields(file)
if (missingFields.length > 0) {
this.setFileState(file.id, { missingRequiredMetaFields: missingFields })
this.setFileState(file.id, {
missingRequiredMetaFields: missingFields,
error: error.message,
})
this.log(error.message)
this.emit('restriction-failed', file, error)
return false
}
if (missingFields.length === 0 && file.missingRequiredMetaFields) {
this.setFileState(file.id, { missingRequiredMetaFields: [] })
this.setFileState(file.id, {
missingRequiredMetaFields: [],
})
}
return true
}
@ -1378,8 +1383,14 @@ export class Uppy<
#getFilesToRetry() {
const { files } = this.getState()
return Object.keys(files).filter((file) => {
return files[file].error
return Object.keys(files).filter((fileId) => {
const file = files[fileId]
// Only retry files that have errors AND don't have missing required metadata
return (
file.error &&
(!file.missingRequiredMetaFields ||
file.missingRequiredMetaFields.length === 0)
)
})
}