import { run, tryNextDev, useTempDir } from '../utils' describe.each(['app', 'pages'] as const)( 'CNA options matrix - %s', (pagesOrApp) => { let nextTgzFilename: string beforeAll(() => { if (!process.env.NEXT_TEST_PKG_PATHS) { throw new Error('This test needs to be run with `node run-tests.js`.') } const pkgPaths = new Map( JSON.parse(process.env.NEXT_TEST_PKG_PATHS) ) nextTgzFilename = pkgPaths.get('next')! }) const isApp = pagesOrApp === 'app' const allFlagValues = { app: [isApp ? '--app' : '--no-app'], ts: ['--js', '--ts'], importAlias: [ '--import-alias=@acme/*', '--import-alias=@/*', '--no-import-alias', ], // doesn't affect if the app builds or not // eslint: ['--eslint', '--no-linter'], eslint: ['--eslint'], // Trading test perf for robustness: // srcDir and reactCompiler don't interact so we're testing them together // instead of all permutations. srcDirAndCompiler: [ '--src-dir --react-compiler --no-agents-md', '--no-src-dir --no-react-compiler --no-agents-md', ], tailwind: ['--tailwind', '--no-tailwind'], // shouldn't affect if the app builds or not // packageManager: ['--use-npm', '--use-pnpm', '--use-yarn', '--use-bun'], } const getCombinations = (items: string[][]): string[][] => { if (!items.length) return [[]] const [first, ...rest] = items const children = getCombinations(rest) return first.flatMap((value) => children.map((child) => [...value.split(' '), ...child]) ) } const flagCombinations = getCombinations(Object.values(allFlagValues)) const testCases = flagCombinations.map((flags) => ({ name: flags.join(' '), flags, })) let id = 0 it.each(testCases)('$name', async ({ flags }) => { await useTempDir(async (cwd) => { const projectName = `cna-matrix-${pagesOrApp}-${id++}` const { exitCode } = await run( [ projectName, ...flags, ...(process.env.NEXT_RSPACK ? ['--rspack'] : []), ], nextTgzFilename, { cwd, } ) expect(exitCode).toBe(0) await tryNextDev({ cwd, projectName, isApp, }) }) }) } )