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
This commit is contained in:
Patrik
2025-02-25 16:55:44 -05:00
committed by GitHub
parent 6b6c289d79
commit 81fd42ef69
7 changed files with 84 additions and 5 deletions

View File

@@ -19,7 +19,8 @@ export const addDataAndFileToRequest: AddDataAndFileToRequest = async (req) => {
if (contentType === 'application/json') {
let data = {}
try {
data = await req.json()
const text = await req.text()
data = text ? JSON.parse(text) : {}
} catch (error) {
req.payload.logger.error(error)
} finally {

View File

@@ -3,6 +3,7 @@
import type { Data, DocumentSlots, FormState, SanitizedDocumentPermissions } from 'payload'
import { useModal } from '@faceless-ui/modal'
import { isImage } from 'payload/shared'
import * as qs from 'qs-esm'
import React from 'react'
import { toast } from 'sonner'
@@ -122,7 +123,7 @@ export function FormsManagerProvider({ children }: FormsManagerProps) {
const file = formsRef.current[i].formState.file.value as File
// Skip if already processed
if (processedFiles.current.has(file) || !file) {
if (processedFiles.current.has(file) || !file || !isImage(file.type)) {
continue
}
processedFiles.current.add(file)

View File

@@ -391,9 +391,13 @@ export async function switchTab(page: Page, selector: string) {
*
* Useful to prevent the e2e test from passing when, for example, there are react missing key prop errors
* @param page
* @param options
*/
export function initPageConsoleErrorCatch(page: Page, options?: { ignoreCORS?: boolean }) {
const { ignoreCORS = false } = options || {} // Default to not ignoring CORS errors
const consoleErrors: string[] = []
let shouldCollectErrors = false
page.on('console', (msg) => {
if (
@@ -435,6 +439,21 @@ export function initPageConsoleErrorCatch(page: Page, options?: { ignoreCORS?: b
console.log(`Ignoring expected network error: ${msg.text()}`)
}
})
// Capture uncaught errors that do not appear in the console
page.on('pageerror', (error) => {
if (shouldCollectErrors) {
consoleErrors.push(`Page error: ${error.message}`)
} else {
throw new Error(`Page error: ${error.message}`)
}
})
return {
consoleErrors,
collectErrors: () => (shouldCollectErrors = true), // Enable collection of errors for specific tests
stopCollectingErrors: () => (shouldCollectErrors = false), // Disable collection of errors after the test
}
}
export function describeIfInCIOrHasLocalstack(): jest.Describe {

View File

@@ -26,7 +26,7 @@ export const Uploads1: CollectionConfig = {
relationTo: 'uploads-2',
filterOptions: {
mimeType: {
equals: 'image/png',
in: ['image/png', 'application/pdf'],
},
},
hasMany: true,

View File

@@ -65,6 +65,9 @@ let uploadsOne: AdminUrlUtil
let uploadsTwo: AdminUrlUtil
let customUploadFieldURL: AdminUrlUtil
let hideFileInputOnCreateURL: AdminUrlUtil
let consoleErrorsFromPage: string[] = []
let collectErrorsFromPage: () => boolean
let stopCollectingErrorsFromPage: () => boolean
describe('Uploads', () => {
let page: Page
@@ -99,7 +102,14 @@ describe('Uploads', () => {
const context = await browser.newContext()
page = await context.newPage()
initPageConsoleErrorCatch(page, { ignoreCORS: true })
const { consoleErrors, collectErrors, stopCollectingErrors } = initPageConsoleErrorCatch(page, {
ignoreCORS: true,
})
consoleErrorsFromPage = consoleErrors
collectErrorsFromPage = collectErrors
stopCollectingErrorsFromPage = stopCollectingErrors
await ensureCompilationIsDone({ page, serverURL })
})
@@ -744,6 +754,55 @@ describe('Uploads', () => {
await saveDocAndAssert(page)
})
test('should bulk upload non-image files without page errors', async () => {
// Enable collection ONLY for this test
collectErrorsFromPage()
// Navigate to the upload creation page
await page.goto(uploadsOne.create)
await page.waitForURL(uploadsOne.create)
// Upload single file
await page.setInputFiles(
'.file-field input[type="file"]',
path.resolve(dirname, './image.png'),
)
const filename = page.locator('.file-field__filename')
await expect(filename).toHaveValue('image.png')
const bulkUploadButton = page.locator('#field-hasManyUpload button', {
hasText: exactText('Create New'),
})
await bulkUploadButton.click()
const bulkUploadModal = page.locator('#bulk-upload-drawer-slug-1')
await expect(bulkUploadModal).toBeVisible()
await page.setInputFiles('#bulk-upload-drawer-slug-1 .dropzone input[type="file"]', [
path.resolve(dirname, './test-pdf.pdf'),
])
await page
.locator('.bulk-upload--file-manager .render-fields #field-prefix')
.fill('prefix-one')
const saveButton = page.locator('.bulk-upload--actions-bar__saveButtons button')
await saveButton.click()
await page.waitForSelector('#field-hasManyUpload .upload--has-many__dragItem')
const itemCount = await page
.locator('#field-hasManyUpload .upload--has-many__dragItem')
.count()
expect(itemCount).toEqual(1)
await saveDocAndAssert(page)
// Assert no console errors occurred for this test only
expect(consoleErrorsFromPage).toEqual([])
// Reset global behavior for other tests
stopCollectingErrorsFromPage()
})
test('should apply field value to all bulk upload files after edit many', async () => {
// Navigate to the upload creation page
await page.goto(uploadsOne.create)

View File

@@ -64,7 +64,6 @@ export interface Config {
auth: {
users: UserAuthOperations;
};
blocks: {};
collections: {
relation: Relation;
audio: Audio;

BIN
test/uploads/test-pdf.pdf Normal file

Binary file not shown.