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"],