mirror of
https://github.com/transloadit/uppy.git
synced 2026-01-23 02:25:07 +00:00
fix retry after setting missed metaFields (#5805)
This commit is contained in:
parent
bff36260cd
commit
eee05db260
3 changed files with 177 additions and 4 deletions
5
.changeset/rude-onions-smoke.md
Normal file
5
.changeset/rude-onions-smoke.md
Normal 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.
|
||||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue