Skip to content

Commit 81fd42e

Browse files
authored
fix(ui): skip bulk upload thumbnail generation on non-image files (#11378)
This PR fixes an issue where bulk upload attempts to generate thumbnails for non-image files, causing errors on the page. The fix ensures that thumbnail generation is skipped for non-image files, preventing unnecessary errors. Fixes #10428
1 parent 6b6c289 commit 81fd42e

File tree

7 files changed

+84
-5
lines changed

7 files changed

+84
-5
lines changed

packages/payload/src/utilities/addDataAndFileToRequest.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export const addDataAndFileToRequest: AddDataAndFileToRequest = async (req) => {
1919
if (contentType === 'application/json') {
2020
let data = {}
2121
try {
22-
data = await req.json()
22+
const text = await req.text()
23+
data = text ? JSON.parse(text) : {}
2324
} catch (error) {
2425
req.payload.logger.error(error)
2526
} finally {

packages/ui/src/elements/BulkUpload/FormsManager/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import type { Data, DocumentSlots, FormState, SanitizedDocumentPermissions } from 'payload'
44

55
import { useModal } from '@faceless-ui/modal'
6+
import { isImage } from 'payload/shared'
67
import * as qs from 'qs-esm'
78
import React from 'react'
89
import { toast } from 'sonner'
@@ -122,7 +123,7 @@ export function FormsManagerProvider({ children }: FormsManagerProps) {
122123
const file = formsRef.current[i].formState.file.value as File
123124

124125
// Skip if already processed
125-
if (processedFiles.current.has(file) || !file) {
126+
if (processedFiles.current.has(file) || !file || !isImage(file.type)) {
126127
continue
127128
}
128129
processedFiles.current.add(file)

test/helpers.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,13 @@ export async function switchTab(page: Page, selector: string) {
391391
*
392392
* Useful to prevent the e2e test from passing when, for example, there are react missing key prop errors
393393
* @param page
394+
* @param options
394395
*/
395396
export function initPageConsoleErrorCatch(page: Page, options?: { ignoreCORS?: boolean }) {
396397
const { ignoreCORS = false } = options || {} // Default to not ignoring CORS errors
398+
const consoleErrors: string[] = []
399+
400+
let shouldCollectErrors = false
397401

398402
page.on('console', (msg) => {
399403
if (
@@ -435,6 +439,21 @@ export function initPageConsoleErrorCatch(page: Page, options?: { ignoreCORS?: b
435439
console.log(`Ignoring expected network error: ${msg.text()}`)
436440
}
437441
})
442+
443+
// Capture uncaught errors that do not appear in the console
444+
page.on('pageerror', (error) => {
445+
if (shouldCollectErrors) {
446+
consoleErrors.push(`Page error: ${error.message}`)
447+
} else {
448+
throw new Error(`Page error: ${error.message}`)
449+
}
450+
})
451+
452+
return {
453+
consoleErrors,
454+
collectErrors: () => (shouldCollectErrors = true), // Enable collection of errors for specific tests
455+
stopCollectingErrors: () => (shouldCollectErrors = false), // Disable collection of errors after the test
456+
}
438457
}
439458

440459
export function describeIfInCIOrHasLocalstack(): jest.Describe {

test/uploads/collections/Upload1/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const Uploads1: CollectionConfig = {
2626
relationTo: 'uploads-2',
2727
filterOptions: {
2828
mimeType: {
29-
equals: 'image/png',
29+
in: ['image/png', 'application/pdf'],
3030
},
3131
},
3232
hasMany: true,

test/uploads/e2e.spec.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ let uploadsOne: AdminUrlUtil
6565
let uploadsTwo: AdminUrlUtil
6666
let customUploadFieldURL: AdminUrlUtil
6767
let hideFileInputOnCreateURL: AdminUrlUtil
68+
let consoleErrorsFromPage: string[] = []
69+
let collectErrorsFromPage: () => boolean
70+
let stopCollectingErrorsFromPage: () => boolean
6871

6972
describe('Uploads', () => {
7073
let page: Page
@@ -99,7 +102,14 @@ describe('Uploads', () => {
99102
const context = await browser.newContext()
100103
page = await context.newPage()
101104

102-
initPageConsoleErrorCatch(page, { ignoreCORS: true })
105+
const { consoleErrors, collectErrors, stopCollectingErrors } = initPageConsoleErrorCatch(page, {
106+
ignoreCORS: true,
107+
})
108+
109+
consoleErrorsFromPage = consoleErrors
110+
collectErrorsFromPage = collectErrors
111+
stopCollectingErrorsFromPage = stopCollectingErrors
112+
103113
await ensureCompilationIsDone({ page, serverURL })
104114
})
105115

@@ -744,6 +754,55 @@ describe('Uploads', () => {
744754
await saveDocAndAssert(page)
745755
})
746756

757+
test('should bulk upload non-image files without page errors', async () => {
758+
// Enable collection ONLY for this test
759+
collectErrorsFromPage()
760+
761+
// Navigate to the upload creation page
762+
await page.goto(uploadsOne.create)
763+
await page.waitForURL(uploadsOne.create)
764+
765+
// Upload single file
766+
await page.setInputFiles(
767+
'.file-field input[type="file"]',
768+
path.resolve(dirname, './image.png'),
769+
)
770+
const filename = page.locator('.file-field__filename')
771+
await expect(filename).toHaveValue('image.png')
772+
773+
const bulkUploadButton = page.locator('#field-hasManyUpload button', {
774+
hasText: exactText('Create New'),
775+
})
776+
await bulkUploadButton.click()
777+
778+
const bulkUploadModal = page.locator('#bulk-upload-drawer-slug-1')
779+
await expect(bulkUploadModal).toBeVisible()
780+
781+
await page.setInputFiles('#bulk-upload-drawer-slug-1 .dropzone input[type="file"]', [
782+
path.resolve(dirname, './test-pdf.pdf'),
783+
])
784+
785+
await page
786+
.locator('.bulk-upload--file-manager .render-fields #field-prefix')
787+
.fill('prefix-one')
788+
const saveButton = page.locator('.bulk-upload--actions-bar__saveButtons button')
789+
await saveButton.click()
790+
791+
await page.waitForSelector('#field-hasManyUpload .upload--has-many__dragItem')
792+
const itemCount = await page
793+
.locator('#field-hasManyUpload .upload--has-many__dragItem')
794+
.count()
795+
expect(itemCount).toEqual(1)
796+
797+
await saveDocAndAssert(page)
798+
799+
// Assert no console errors occurred for this test only
800+
expect(consoleErrorsFromPage).toEqual([])
801+
802+
// Reset global behavior for other tests
803+
stopCollectingErrorsFromPage()
804+
})
805+
747806
test('should apply field value to all bulk upload files after edit many', async () => {
748807
// Navigate to the upload creation page
749808
await page.goto(uploadsOne.create)

test/uploads/payload-types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export interface Config {
6464
auth: {
6565
users: UserAuthOperations;
6666
};
67-
blocks: {};
6867
collections: {
6968
relation: Relation;
7069
audio: Audio;

test/uploads/test-pdf.pdf

1.76 MB
Binary file not shown.

0 commit comments

Comments
 (0)