diff --git a/package.json b/package.json
index cd48433dd09..9f7065ad039 100644
--- a/package.json
+++ b/package.json
@@ -114,8 +114,7 @@
"eslint --cache --fix"
],
"templates/website/**/*": "sh -c \"cd templates/website; pnpm install --no-frozen-lockfile --ignore-workspace; pnpm run lint --fix\"",
- "templates/**/pnpm-lock.yaml": "pnpm runts scripts/remove-template-lock-files.ts",
- "tsconfig.json": "node scripts/reset-tsconfig.js"
+ "templates/**/pnpm-lock.yaml": "pnpm runts scripts/remove-template-lock-files.ts"
},
"devDependencies": {
"@jest/globals": "29.7.0",
diff --git a/scripts/reset-tsconfig.js b/scripts/reset-tsconfig.js
deleted file mode 100644
index 9a75103e725..00000000000
--- a/scripts/reset-tsconfig.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// @ts-check
-
-/**
- * Parse tsconfig.json and ensure
- * - compilerOptions.paths['@payload-config'] is set to ['./test/_community/config.ts']
- * - Ends with a newline
- */
-
-import { parse, stringify } from 'comment-json'
-
-import path from 'path'
-import fs from 'fs/promises'
-import { fileURLToPath } from 'url'
-import { existsSync } from 'fs'
-
-const filename = fileURLToPath(import.meta.url)
-const dirname = path.dirname(filename)
-
-const tsConfigBasePath = path.resolve(dirname, '../tsconfig.base.json')
-const tsConfigPath = existsSync(tsConfigBasePath)
- ? tsConfigBasePath
- : path.resolve(dirname, '../tsconfig.json')
-
-
-const tsConfigContent = await fs.readFile(tsConfigPath, 'utf8')
-const tsConfig = parse(tsConfigContent)
-
-tsConfig.compilerOptions.paths['@payload-config'] = ['./test/_community/config.ts']
-const output = stringify(tsConfig, null, 2) + `\n`
-await fs.writeFile(tsConfigPath, output)
diff --git a/test/app/(app)/layout.tsx b/test/app/(app)/layout.tsx
deleted file mode 100644
index dd4142d17fb..00000000000
--- a/test/app/(app)/layout.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react'
-
-export const metadata = {
- description: 'Generated by Next.js',
- title: 'Next.js',
-}
-
-export default function RootLayout({ children }: { children: React.ReactNode }) {
- return (
-
-
{children}
-
- )
-}
diff --git a/test/app/(app)/test/page.tsx b/test/app/(app)/test/page.tsx
deleted file mode 100644
index b6921c27a5e..00000000000
--- a/test/app/(app)/test/page.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import configPromise from '@payload-config'
-import { getPayload } from 'payload'
-
-export const Page = async ({ params, searchParams }) => {
- const payload = await getPayload({
- config: configPromise,
- })
- return test ${payload?.config?.collections?.length}
-}
-
-export default Page
diff --git a/test/config-imports.ts b/test/config-imports.ts
new file mode 100644
index 00000000000..1391aeb1d3e
--- /dev/null
+++ b/test/config-imports.ts
@@ -0,0 +1,65 @@
+export const staticConfigImports = {
+ _community: () => import('./_community/config.js'),
+ 'access-control': () => import('./access-control/config.js'),
+ 'admin-bar': () => import('./admin-bar/config.js'),
+ 'admin-root': () => import('./admin-root/config.js'),
+ admin: () => import('./admin/config.js'),
+ 'array-update': () => import('./array-update/config.js'),
+ 'auth-basic': () => import('./auth-basic/config.js'),
+ auth: () => import('./auth/config.js'),
+ 'benchmark-blocks': () => import('./benchmark-blocks/config.js'),
+ 'bulk-edit': () => import('./bulk-edit/config.js'),
+ 'collections-graphql': () => import('./collections-graphql/config.js'),
+ 'collections-rest': () => import('./collections-rest/config.js'),
+ config: () => import('./config/config.js'),
+ 'custom-graphql': () => import('./custom-graphql/config.js'),
+ database: () => import('./database/config.js'),
+ dataloader: () => import('./dataloader/config.js'),
+ 'email-nodemailer': () => import('./email-nodemailer/config.js'),
+ 'email-resend': () => import('./email-resend/config.js'),
+ email: () => import('./email/config.js'),
+ endpoints: () => import('./endpoints/config.js'),
+ 'field-error-states': () => import('./field-error-states/config.js'),
+ 'field-perf': () => import('./field-perf/config.js'),
+ 'fields-relationship': () => import('./fields-relationship/config.js'),
+ fields: () => import('./fields/config.js'),
+ 'form-state': () => import('./form-state/config.js'),
+ globals: () => import('./globals/config.js'),
+ 'graphql-schema-gen': () => import('./graphql-schema-gen/config.js'),
+ graphql: () => import('./graphql/config.js'),
+ hooks: () => import('./hooks/config.js'),
+ i18n: () => import('./i18n/config.js'),
+ joins: () => import('./joins/config.js'),
+ 'lexical-mdx': () => import('./lexical-mdx/config.js'),
+ 'live-preview': () => import('./live-preview/config.js'),
+ 'localization-rtl': () => import('./localization-rtl/config.js'),
+ localization: () => import('./localization/config.js'),
+ 'locked-documents': () => import('./locked-documents/config.js'),
+ 'login-with-username': () => import('./login-with-username/config.js'),
+ 'migrations-cli': () => import('./migrations-cli/config.js'),
+ 'nested-fields': () => import('./nested-fields/config.js'),
+ 'payload-cloud': () => import('./payload-cloud/config.js'),
+ 'plugin-cloud-storage': () => import('./plugin-cloud-storage/config.js'),
+ 'plugin-form-builder': () => import('./plugin-form-builder/config.js'),
+ 'plugin-import-export': () => import('./plugin-import-export/config.js'),
+ 'plugin-multi-tenant': () => import('./plugin-multi-tenant/config.js'),
+ 'plugin-nested-docs': () => import('./plugin-nested-docs/config.js'),
+ 'plugin-redirects': () => import('./plugin-redirects/config.js'),
+ 'plugin-search': () => import('./plugin-search/config.js'),
+ 'plugin-sentry': () => import('./plugin-sentry/config.js'),
+ 'plugin-seo': () => import('./plugin-seo/config.js'),
+ 'plugin-stripe': () => import('./plugin-stripe/config.js'),
+ plugins: () => import('./plugins/config.js'),
+ 'query-presets': () => import('./query-presets/config.js'),
+ queues: () => import('./queues/config.js'),
+ relationships: () => import('./relationships/config.js'),
+ select: () => import('./select/config.js'),
+ sort: () => import('./sort/config.js'),
+ 'storage-azure': () => import('./storage-azure/config.js'),
+ 'storage-gcs': () => import('./storage-gcs/config.js'),
+ 'storage-s3': () => import('./storage-s3/config.js'),
+ 'storage-uploadthing': () => import('./storage-uploadthing/config.js'),
+ 'storage-vercel-blob': () => import('./storage-vercel-blob/config.js'),
+ uploads: () => import('./uploads/config.js'),
+ versions: () => import('./versions/config.js'),
+} as const
diff --git a/test/dev.ts b/test/dev.ts
index 368ed124be4..98f00cc3dbb 100644
--- a/test/dev.ts
+++ b/test/dev.ts
@@ -10,6 +10,7 @@ import open from 'open'
import { loadEnv } from 'payload/node'
import { parse } from 'url'
+import { staticConfigImports } from './config-imports.js'
import { getNextRootDir } from './helpers/getNextRootDir.js'
import startMemoryDB from './helpers/startMemoryDB.js'
import { runInit } from './runInit.js'
@@ -55,13 +56,25 @@ if (!testSuiteArg || !fs.existsSync(path.resolve(dirname, testSuiteArg))) {
process.exit(0)
}
+if (!(testSuiteArg in staticConfigImports)) {
+ console.log(
+ chalk.red(
+ [
+ `ERROR: The test folder "${testSuiteArg}" exists, but you need to add`,
+ `it to the static config imports object in /test/config-imports.ts`,
+ ].join(' '),
+ ),
+ )
+ process.exit(0)
+}
+
console.log(`Selected test suite: ${testSuiteArg}`)
if (args.turbo === true) {
process.env.TURBOPACK = '1'
}
-const { beforeTest } = await createTestHooks(testSuiteArg, testSuiteConfigOverride)
+const { beforeTest } = createTestHooks(testSuiteArg, testSuiteConfigOverride)
await beforeTest()
const { rootDir, adminRoute } = getNextRootDir(testSuiteArg)
diff --git a/test/dynamic-config.ts b/test/dynamic-config.ts
new file mode 100644
index 00000000000..a46206654b4
--- /dev/null
+++ b/test/dynamic-config.ts
@@ -0,0 +1,22 @@
+/* eslint-disable no-restricted-exports */
+
+import { staticConfigImports } from './config-imports.js'
+
+if (!process.env.PAYLOAD_CONFIG_PATH) {
+ throw new Error('PAYLOAD_CONFIG_PATH environment variable is required')
+}
+
+// Extract the suite name from the path
+const suiteName = process.env.PAYLOAD_CONFIG_PATH.split('/').slice(
+ -2,
+)[0] as keyof typeof staticConfigImports
+
+if (!(suiteName in staticConfigImports)) {
+ throw new Error(
+ `Unknown test suite: ${suiteName}. This error should have been
+caught several seconds earlier in dev.ts.`,
+ )
+}
+
+const config = await staticConfigImports[suiteName]()
+export default config.default
diff --git a/test/testHooks.ts b/test/testHooks.ts
index 47e1f844a0a..5d0d5e93afd 100644
--- a/test/testHooks.ts
+++ b/test/testHooks.ts
@@ -1,30 +1,34 @@
-import { parse, stringify } from 'comment-json'
import { existsSync, promises } from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import { getNextRootDir } from './helpers/getNextRootDir.js'
-const { readFile, writeFile, rm } = promises
+const { rm } = promises
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
-export const createTestHooks = async (
- testSuiteName = '_community',
- testSuiteConfig = 'config.ts',
-) => {
+export const createTestHooks = (testSuiteName = '_community', testSuiteConfig = 'config.ts') => {
const rootDir = getNextRootDir().rootDir
- const tsConfigBasePath = path.resolve(rootDir, './tsconfig.base.json')
- const tsConfigPath = existsSync(tsConfigBasePath)
- ? tsConfigBasePath
- : path.resolve(rootDir, './tsconfig.json')
- const tsConfigContent = await readFile(tsConfigPath, 'utf8')
- const tsConfig = parse(tsConfigContent)
+ process.env.PAYLOAD_CONFIG_PATH =
+ process.env.PAYLOAD_TEST_PROD === 'true'
+ ? `./${testSuiteName}/${testSuiteConfig}`
+ : `./test/${testSuiteName}/${testSuiteConfig}`
+
+ console.log('Debug paths:', {
+ rootDir,
+ dirname,
+ testSuiteName,
+ testSuiteConfig,
+ configPath: process.env.PAYLOAD_CONFIG_PATH,
+ cwd: process.cwd(),
+ NODE_PATH: process.env.NODE_PATH,
+ })
return {
/**
- * Clear next webpack cache and set '@payload-config' path in tsconfig.json
+ * Clear next webpack cache and set 'PAYLOAD_CONFIG_PATH' environment variable
*/
beforeTest: async () => {
// Delete entire .next cache folder
@@ -32,18 +36,6 @@ export const createTestHooks = async (
if (existsSync(nextCache)) {
await rm(nextCache, { recursive: true })
}
-
- // Set '@payload-config' in tsconfig.json
-
- // @ts-expect-error
- tsConfig.compilerOptions.paths['@payload-config'] = [
- process.env.PAYLOAD_TEST_PROD === 'true'
- ? `./${testSuiteName}/${testSuiteConfig}`
- : `./test/${testSuiteName}/${testSuiteConfig}`,
- ]
- await writeFile(tsConfigPath, stringify(tsConfig, null, 2) + '\n')
-
- process.env.PAYLOAD_CONFIG_PATH = path.resolve(dirname, testSuiteName, testSuiteConfig)
},
}
}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index c9793d25c61..b05ee2bde1f 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -31,7 +31,7 @@
}
],
"paths": {
- "@payload-config": ["./test/_community/config.ts"],
+ "@payload-config": ["./test/dynamic-config.ts"],
"@payloadcms/admin-bar": ["./packages/admin-bar/src"],
"@payloadcms/live-preview": ["./packages/live-preview/src"],
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],