Skip to content

Commit a188556

Browse files
authored
chore: bump monorepo Next.js version to 16.2.0 (#15992)
This PR does not bump the Next.js version in the templates yet. First, let's run our test suite against 16.2.0 and make sure it's fully compatible.
1 parent 57a0edc commit a188556

16 files changed

Lines changed: 1609 additions & 1569 deletions

File tree

.github/workflows/e2e.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export default createE2EConfig([
5151
{ file: 'fields__collections__UploadPoly', shards: 1 },
5252
{ file: 'fields__collections__UploadMultiPoly', shards: 1 },
5353
{ file: 'group-by', shards: 1 },
54-
{ file: 'folders', shards: 1 },
54+
{ file: 'folders', shards: 3 },
5555
{ file: 'hooks', shards: 1 },
5656
// TODO: Enable parallel mode again when ensureCompilationIsDone is extracted into a playwright hook. Otherwise,
5757
// it runs multiple times in parallel, for each single test, which causes the tests to fail occasionally in CI.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@
143143
"devDependencies": {
144144
"@axe-core/playwright": "4.11.0",
145145
"@libsql/client": "0.14.0",
146-
"@next/bundle-analyzer": "16.2.0-canary.90",
146+
"@next/bundle-analyzer": "16.2.0",
147147
"@payloadcms/db-postgres": "workspace:*",
148148
"@payloadcms/eslint-config": "workspace:*",
149149
"@payloadcms/eslint-plugin": "workspace:*",
@@ -180,7 +180,7 @@
180180
"lint-staged": "15.2.7",
181181
"minimist": "1.2.8",
182182
"mongoose": "8.15.1",
183-
"next": "16.2.0-canary.90",
183+
"next": "16.2.0",
184184
"node-gyp": "12.2.0",
185185
"open": "^10.1.0",
186186
"p-limit": "^5.0.0",

packages/next/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
"@babel/preset-env": "7.27.2",
132132
"@babel/preset-react": "7.27.1",
133133
"@babel/preset-typescript": "7.27.1",
134-
"@next/eslint-plugin-next": "16.2.0-canary.90",
134+
"@next/eslint-plugin-next": "16.2.0",
135135
"@payloadcms/eslint-config": "workspace:*",
136136
"@types/busboy": "1.5.4",
137137
"@types/react": "19.2.9",

packages/payload/src/utilities/addDataAndFileToRequest.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,14 @@ export const addDataAndFileToRequest: AddDataAndFileToRequest = async (req) => {
5151
}
5252

5353
if (!req.file && fields?.file && typeof fields?.file === 'string') {
54-
const { clientUploadContext, collectionSlug, filename, mimeType, size } = JSON.parse(
55-
fields.file,
56-
)
54+
let clientUploadContext, collectionSlug, filename, mimeType, size
55+
try {
56+
;({ clientUploadContext, collectionSlug, filename, mimeType, size } = JSON.parse(
57+
fields.file,
58+
))
59+
} catch {
60+
throw new APIError('A file name is required.', 400)
61+
}
5762
const uploadConfig = req.payload.collections[collectionSlug]!.config.upload
5863

5964
if (!uploadConfig.handlers) {

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

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -414,24 +414,41 @@ export function FormsManagerProvider({ children }: FormsManagerProps) {
414414
if (missingFile || exceedsLimit || missingFilename) {
415415
currentForms[i].formState.file.valid = false
416416

417-
// neeed to get the field state to extract count since field errors
417+
// File/Blob objects cannot be serialized via the RSC flight protocol,
418+
// so replace with a plain object before calling the server function.
419+
const originalFileValue = currentForms[i].formState.file?.value
420+
const formStateForServer = { ...currentForms[i].formState }
421+
if (originalFileValue instanceof File) {
422+
formStateForServer.file = {
423+
...formStateForServer.file,
424+
value: { name: originalFileValue.name },
425+
}
426+
}
427+
428+
// Need to get the field state to extract count since field errors
418429
// are not returned when file is missing or exceeds limit
419430
const { state: newState } = await getFormState({
420431
collectionSlug,
421432
docPermissions,
422433
docPreferences: null,
423-
formState: currentForms[i].formState,
434+
formState: formStateForServer,
424435
operation: 'update',
425436
schemaPath: collectionSlug,
426437
})
427438

428-
currentForms[i] = {
429-
errorCount: Object.values(newState).reduce(
430-
(acc, value) => (value?.valid === false ? acc + 1 : acc),
431-
0,
432-
),
433-
formID: currentForms[i].formID,
434-
formState: newState,
439+
if (newState) {
440+
if (originalFileValue instanceof File && newState.file) {
441+
newState.file = { ...newState.file, value: originalFileValue }
442+
}
443+
444+
currentForms[i] = {
445+
errorCount: Object.values(newState).reduce(
446+
(acc, value) => (value?.valid === false ? acc + 1 : acc),
447+
0,
448+
),
449+
formID: currentForms[i].formID,
450+
formState: newState,
451+
}
435452
}
436453

437454
toast.error(nonFieldErrors[0]?.message)

pnpm-lock.yaml

Lines changed: 1504 additions & 1508 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/__helpers/e2e/folders/createFolder.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export async function createFolder({
1414
page,
1515
folderType = ['Posts'],
1616
}: Args): Promise<void> {
17+
const drawer = page.locator('dialog .collection-edit--payload-folders')
18+
1719
if (fromDropdown) {
1820
const titleActionsLocator = page.locator('.list-header__title-actions')
1921
const folderDropdown = titleActionsLocator.locator('.create-new-doc-in-folder__action-popup', {
@@ -23,12 +25,22 @@ export async function createFolder({
2325
const createFolderButton = page.locator('.popup__content .popup-button-list__button', {
2426
hasText: 'Folder',
2527
})
26-
await createFolderButton.click()
28+
await expect(async () => {
29+
if (await drawer.isHidden()) {
30+
await createFolderButton.click()
31+
}
32+
await expect(drawer).toBeVisible()
33+
}).toPass({ timeout: 30000 })
2734
} else {
2835
const createFolderButton = page.locator(
2936
'.list-header__title-and-actions .create-new-doc-in-folder__button:has-text("Create folder")',
3037
)
31-
await createFolderButton.click()
38+
await expect(async () => {
39+
if (await drawer.isHidden()) {
40+
await createFolderButton.click()
41+
}
42+
await expect(drawer).toBeVisible()
43+
}).toPass({ timeout: 30000 })
3244
}
3345

3446
await createFolderDoc({

test/__helpers/e2e/folders/createFolderFromDoc.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { expect, type Page } from '@playwright/test'
22

3-
import { createFolder } from './createFolder.js'
43
import { createFolderDoc } from './createFolderDoc.js'
54

65
type Args = {
@@ -17,7 +16,14 @@ export async function createFolderFromDoc({
1716
const addFolderButton = page.locator('.create-new-doc-in-folder__button', {
1817
hasText: 'Create folder',
1918
})
20-
await addFolderButton.click()
19+
const drawer = page.locator('dialog .collection-edit--payload-folders')
20+
21+
await expect(async () => {
22+
if (await drawer.isHidden()) {
23+
await addFolderButton.click()
24+
}
25+
await expect(drawer).toBeVisible()
26+
}).toPass({ timeout: 15000 })
2127

2228
await createFolderDoc({
2329
page,

test/__helpers/e2e/folders/selectFolderAndConfirmMoveFromList.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import type { Page } from '@playwright/test'
22

3+
import { expect } from '@playwright/test'
4+
35
import { clickFolderCard } from './clickFolderCard.js'
46

57
type Args = {
@@ -14,7 +16,14 @@ export async function selectFolderAndConfirmMoveFromList({
1416
}: Args): Promise<void> {
1517
const firstListItem = page.locator(`tbody .row-${rowIndex}`)
1618
const folderPill = firstListItem.locator('.move-doc-to-folder')
17-
await folderPill.click()
19+
const moveDrawer = page.locator('dialog .move-folder-drawer')
20+
21+
await expect(async () => {
22+
if (await moveDrawer.isHidden()) {
23+
await folderPill.click()
24+
}
25+
await expect(moveDrawer).toBeVisible()
26+
}).toPass({ timeout: 30000 })
1827

1928
if (folderName) {
2029
await clickFolderCard({ folderName, doubleClick: true, page })

test/admin-root/e2e.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import * as path from 'path'
55
import { adminRoute } from 'shared.js'
66
import { fileURLToPath } from 'url'
77

8+
import { login } from '../__helpers/e2e/auth/login.js'
89
import {
910
ensureCompilationIsDone,
1011
initPageConsoleErrorCatch,
1112
saveDocAndAssert,
1213
// throttleTest,
1314
} from '../__helpers/e2e/helpers.js'
1415
import { AdminUrlUtil } from '../__helpers/shared/adminUrlUtil.js'
15-
import { login } from '../__helpers/e2e/auth/login.js'
1616
import { initPayloadE2ENoConfig } from '../__helpers/shared/initPayloadE2ENoConfig.js'
1717
import { TEST_TIMEOUT_LONG } from '../playwright.config.js'
1818

@@ -131,7 +131,7 @@ test.describe('Admin Panel (Root)', () => {
131131
await expect(favicons.nth(0)).toHaveAttribute('sizes', '32x32')
132132
await expect(favicons.nth(1)).toHaveAttribute('sizes', '32x32')
133133
await expect(favicons.nth(1)).toHaveAttribute('media', '(prefers-color-scheme: dark)')
134-
await expect(favicons.nth(1)).toHaveAttribute('href', /\/payload-favicon-light\.[a-z\d]+\.png/)
134+
await expect(favicons.nth(1)).toHaveAttribute('href', /\/payload-favicon-light\.[a-z\d_]+\.png/)
135135
})
136136

137137
test('config.admin.theme should restrict the theme', async () => {

0 commit comments

Comments
 (0)