From aed5242192b65018f5bc5a99b5c1b163305a76a3 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Thu, 16 May 2024 09:59:41 -0700 Subject: [PATCH] Run CNA tests with Next.js from branch (#65852) This is probably not complete but something in that direction. --------- Co-authored-by: Jiachi Liu --- .../create-next-app/examples.test.ts | 47 +++++++++++++++---- .../integration/create-next-app/index.test.ts | 13 +++++ .../package-manager/bun.test.ts | 25 ++++++++-- .../package-manager/npm.test.ts | 25 ++++++++-- .../package-manager/pnpm.test.ts | 25 ++++++++-- .../package-manager/yarn.test.ts | 18 +++++-- test/integration/create-next-app/utils.ts | 10 ++-- 7 files changed, 133 insertions(+), 30 deletions(-) diff --git a/test/integration/create-next-app/examples.test.ts b/test/integration/create-next-app/examples.test.ts index 64bd81ecb141a..b37d214d97c07 100644 --- a/test/integration/create-next-app/examples.test.ts +++ b/test/integration/create-next-app/examples.test.ts @@ -1,3 +1,5 @@ +import { trace } from 'next/dist/trace' +import { createNextInstall } from '../../lib/create-next-install' import { EXAMPLE_PATH, EXAMPLE_REPO, @@ -10,12 +12,23 @@ import { } from './utils' describe('create-next-app --example', () => { + let nextInstall: Awaited> + beforeAll(async () => { + nextInstall = await createNextInstall({ + parentSpan: trace('test'), + keepRepoDir: Boolean(process.env.NEXT_TEST_SKIP_CLEANUP), + }) + }) it('should create on valid Next.js example name', async () => { await useTempDir(async (cwd) => { const projectName = 'valid-example' - const res = await run([projectName, '--example', 'basic-css'], { - cwd, - }) + const res = await run( + [projectName, '--example', 'basic-css'], + nextInstall.installDir, + { + cwd, + } + ) expect(res.exitCode).toBe(0) projectFilesShouldExist({ cwd, @@ -34,9 +47,13 @@ describe('create-next-app --example', () => { it('should create with GitHub URL', async () => { await useTempDir(async (cwd) => { const projectName = 'github-url' - const res = await run([projectName, '--example', FULL_EXAMPLE_PATH], { - cwd, - }) + const res = await run( + [projectName, '--example', FULL_EXAMPLE_PATH], + nextInstall.installDir, + { + cwd, + } + ) expect(res.exitCode).toBe(0) projectFilesShouldExist({ @@ -64,6 +81,7 @@ describe('create-next-app --example', () => { // GH#39665 'https://github.com/vercel/nextjs-portfolio-starter/', ], + nextInstall.installDir, { cwd, } @@ -97,6 +115,7 @@ describe('create-next-app --example', () => { '--example-path', EXAMPLE_PATH, ], + nextInstall.installDir, { cwd, } @@ -131,6 +150,7 @@ describe('create-next-app --example', () => { '--example-path', EXAMPLE_PATH, ], + nextInstall.installDir, { cwd, } @@ -168,6 +188,7 @@ describe('create-next-app --example', () => { '__internal-testing-retry', '--import-alias=@/*', ], + nextInstall.installDir, { cwd, input: '\n', // 'Yes' to retry @@ -199,6 +220,7 @@ describe('create-next-app --example', () => { 'default', '--import-alias=@/*', ], + nextInstall.installDir, { cwd, } @@ -217,10 +239,14 @@ describe('create-next-app --example', () => { it('should not create if --example flag value is invalid', async () => { await useTempDir(async (cwd) => { const projectName = 'invalid-example' - const res = await run([projectName, '--example', 'not a real example'], { - cwd, - reject: false, - }) + const res = await run( + [projectName, '--example', 'not a real example'], + nextInstall.installDir, + { + cwd, + reject: false, + } + ) expect(res.exitCode).toBe(1) projectFilesShouldNotExist({ @@ -244,6 +270,7 @@ describe('create-next-app --example', () => { '--no-tailwind', '--example', ], + nextInstall.installDir, { cwd, reject: false, diff --git a/test/integration/create-next-app/index.test.ts b/test/integration/create-next-app/index.test.ts index ca008dbf66317..09ae4757e170f 100644 --- a/test/integration/create-next-app/index.test.ts +++ b/test/integration/create-next-app/index.test.ts @@ -6,6 +6,16 @@ import { projectFilesShouldExist, projectFilesShouldNotExist, } from './utils' +import { createNextInstall } from '../../lib/create-next-install' +import { trace } from 'next/dist/trace' + +let nextInstall: Awaited> +beforeAll(async () => { + nextInstall = await createNextInstall({ + parentSpan: trace('test'), + keepRepoDir: Boolean(process.env.NEXT_TEST_SKIP_CLEANUP), + }) +}) describe('create-next-app', () => { it('should not create if the target directory is not empty', async () => { @@ -25,6 +35,7 @@ describe('create-next-app', () => { '--no-src-dir', '--no-import-alias', ], + nextInstall.installDir, { cwd, reject: false, @@ -64,6 +75,7 @@ describe('create-next-app', () => { '--no-src-dir', '--no-import-alias', ], + nextInstall.installDir, { cwd, reject: false, @@ -93,6 +105,7 @@ describe('create-next-app', () => { '--no-import-alias', '--skip-install', ], + nextInstall.installDir, { cwd, } diff --git a/test/integration/create-next-app/package-manager/bun.test.ts b/test/integration/create-next-app/package-manager/bun.test.ts index fa1973a66030f..0000597ab5e50 100644 --- a/test/integration/create-next-app/package-manager/bun.test.ts +++ b/test/integration/create-next-app/package-manager/bun.test.ts @@ -1,3 +1,5 @@ +import { trace } from 'next/dist/trace' +import { createNextInstall } from '../../../lib/create-next-install' import { command, DEFAULT_FILES, @@ -16,6 +18,14 @@ beforeEach(async () => { .catch(() => command('npm', ['i', '-g', 'bun'])) }) +let nextInstall: Awaited> +beforeAll(async () => { + nextInstall = await createNextInstall({ + parentSpan: trace('test'), + keepRepoDir: Boolean(process.env.NEXT_TEST_SKIP_CLEANUP), + }) +}) + describe('create-next-app with package manager bun', () => { it('should use bun for --use-bun flag', async () => { await useTempDir(async (cwd) => { @@ -31,6 +41,7 @@ describe('create-next-app with package manager bun', () => { '--no-tailwind', '--no-import-alias', ], + nextInstall.installDir, { cwd, } @@ -59,6 +70,7 @@ it('should use bun when user-agent is bun', async () => { '--no-tailwind', '--no-import-alias', ], + nextInstall.installDir, { cwd, env: { npm_config_user_agent: 'bun' }, @@ -79,6 +91,7 @@ it('should use bun for --use-bun flag with example', async () => { const projectName = 'use-bun-with-example' const res = await run( [projectName, '--use-bun', '--example', FULL_EXAMPLE_PATH], + nextInstall.installDir, { cwd } ) @@ -94,10 +107,14 @@ it('should use bun for --use-bun flag with example', async () => { it('should use bun when user-agent is bun with example', async () => { await useTempDir(async (cwd) => { const projectName = 'user-agent-bun-with-example' - const res = await run([projectName, '--example', FULL_EXAMPLE_PATH], { - cwd, - env: { npm_config_user_agent: 'bun' }, - }) + const res = await run( + [projectName, '--example', FULL_EXAMPLE_PATH], + nextInstall.installDir, + { + cwd, + env: { npm_config_user_agent: 'bun' }, + } + ) expect(res.exitCode).toBe(0) projectFilesShouldExist({ diff --git a/test/integration/create-next-app/package-manager/npm.test.ts b/test/integration/create-next-app/package-manager/npm.test.ts index cafbf60cf60e7..7cdffabb89496 100644 --- a/test/integration/create-next-app/package-manager/npm.test.ts +++ b/test/integration/create-next-app/package-manager/npm.test.ts @@ -1,3 +1,4 @@ +import { trace } from 'next/dist/trace' import { DEFAULT_FILES, FULL_EXAMPLE_PATH, @@ -5,10 +6,19 @@ import { run, useTempDir, } from '../utils' +import { createNextInstall } from '../../../lib/create-next-install' const lockFile = 'package-lock.json' const files = [...DEFAULT_FILES, lockFile] +let nextInstall: Awaited> +beforeAll(async () => { + nextInstall = await createNextInstall({ + parentSpan: trace('test'), + keepRepoDir: Boolean(process.env.NEXT_TEST_SKIP_CLEANUP), + }) +}) + describe('create-next-app with package manager npm', () => { it('should use npm for --use-npm flag', async () => { await useTempDir(async (cwd) => { @@ -24,6 +34,7 @@ describe('create-next-app with package manager npm', () => { '--no-tailwind', '--no-import-alias', ], + nextInstall.installDir, { cwd, } @@ -52,6 +63,7 @@ it('should use npm when user-agent is npm', async () => { '--no-tailwind', '--no-import-alias', ], + nextInstall.installDir, { cwd, env: { npm_config_user_agent: 'npm' }, @@ -72,6 +84,7 @@ it('should use npm for --use-npm flag with example', async () => { const projectName = 'use-npm-with-example' const res = await run( [projectName, '--use-npm', '--example', FULL_EXAMPLE_PATH], + nextInstall.installDir, { cwd } ) @@ -87,10 +100,14 @@ it('should use npm for --use-npm flag with example', async () => { it('should use npm when user-agent is npm with example', async () => { await useTempDir(async (cwd) => { const projectName = 'user-agent-npm-with-example' - const res = await run([projectName, '--example', FULL_EXAMPLE_PATH], { - cwd, - env: { npm_config_user_agent: 'npm' }, - }) + const res = await run( + [projectName, '--example', FULL_EXAMPLE_PATH], + nextInstall.installDir, + { + cwd, + env: { npm_config_user_agent: 'npm' }, + } + ) expect(res.exitCode).toBe(0) projectFilesShouldExist({ diff --git a/test/integration/create-next-app/package-manager/pnpm.test.ts b/test/integration/create-next-app/package-manager/pnpm.test.ts index fa44eacc907a0..3b788f3b77ba9 100644 --- a/test/integration/create-next-app/package-manager/pnpm.test.ts +++ b/test/integration/create-next-app/package-manager/pnpm.test.ts @@ -1,3 +1,5 @@ +import { trace } from 'next/dist/trace' +import { createNextInstall } from '../../../lib/create-next-install' import { command, DEFAULT_FILES, @@ -10,6 +12,14 @@ import { const lockFile = 'pnpm-lock.yaml' const files = [...DEFAULT_FILES, lockFile] +let nextInstall: Awaited> +beforeAll(async () => { + nextInstall = await createNextInstall({ + parentSpan: trace('test'), + keepRepoDir: Boolean(process.env.NEXT_TEST_SKIP_CLEANUP), + }) +}) + beforeEach(async () => { await command('pnpm', ['--version']) // install pnpm if not available @@ -32,6 +42,7 @@ describe('create-next-app with package manager pnpm', () => { '--no-tailwind', '--no-import-alias', ], + nextInstall.installDir, { cwd, } @@ -60,6 +71,7 @@ it('should use pnpm when user-agent is pnpm', async () => { '--no-tailwind', '--no-import-alias', ], + nextInstall.installDir, { cwd, env: { npm_config_user_agent: 'pnpm' }, @@ -80,6 +92,7 @@ it('should use pnpm for --use-pnpm flag with example', async () => { const projectName = 'use-pnpm-with-example' const res = await run( [projectName, '--use-pnpm', '--example', FULL_EXAMPLE_PATH], + nextInstall.installDir, { cwd } ) @@ -95,10 +108,14 @@ it('should use pnpm for --use-pnpm flag with example', async () => { it('should use pnpm when user-agent is pnpm with example', async () => { await useTempDir(async (cwd) => { const projectName = 'user-agent-pnpm-with-example' - const res = await run([projectName, '--example', FULL_EXAMPLE_PATH], { - cwd, - env: { npm_config_user_agent: 'pnpm' }, - }) + const res = await run( + [projectName, '--example', FULL_EXAMPLE_PATH], + nextInstall.installDir, + { + cwd, + env: { npm_config_user_agent: 'pnpm' }, + } + ) expect(res.exitCode).toBe(0) projectFilesShouldExist({ diff --git a/test/integration/create-next-app/package-manager/yarn.test.ts b/test/integration/create-next-app/package-manager/yarn.test.ts index 09dde41a67bc3..a821bd35829a5 100644 --- a/test/integration/create-next-app/package-manager/yarn.test.ts +++ b/test/integration/create-next-app/package-manager/yarn.test.ts @@ -10,6 +10,9 @@ import { const lockFile = 'yarn.lock' const files = [...DEFAULT_FILES, lockFile] +// Don't install local next build here as yarn will error with: +// Usage Error: This project is configured to use pnpm + beforeEach(async () => { await command('yarn', ['--version']) // install yarn if not available @@ -32,6 +35,7 @@ describe('create-next-app with package manager yarn', () => { '--no-tailwind', '--no-import-alias', ], + 'canary', { cwd, } @@ -60,6 +64,7 @@ it('should use yarn when user-agent is yarn', async () => { '--no-tailwind', '--no-import-alias', ], + 'canary', { cwd, env: { npm_config_user_agent: 'yarn' }, @@ -80,6 +85,7 @@ it('should use yarn for --use-yarn flag with example', async () => { const projectName = 'use-yarn-with-example' const res = await run( [projectName, '--use-yarn', '--example', FULL_EXAMPLE_PATH], + 'canary', { cwd } ) @@ -95,10 +101,14 @@ it('should use yarn for --use-yarn flag with example', async () => { it('should use yarn when user-agent is yarn with example', async () => { await useTempDir(async (cwd) => { const projectName = 'user-agent-yarn-with-example' - const res = await run([projectName, '--example', FULL_EXAMPLE_PATH], { - cwd, - env: { npm_config_user_agent: 'yarn' }, - }) + const res = await run( + [projectName, '--example', FULL_EXAMPLE_PATH], + 'canary', + { + cwd, + env: { npm_config_user_agent: 'yarn' }, + } + ) expect(res.exitCode).toBe(0) projectFilesShouldExist({ diff --git a/test/integration/create-next-app/utils.ts b/test/integration/create-next-app/utils.ts index 648ab7dc1b747..5b1fe07cf67f2 100644 --- a/test/integration/create-next-app/utils.ts +++ b/test/integration/create-next-app/utils.ts @@ -14,25 +14,27 @@ export const DEFAULT_FILES = [ 'node_modules/next', ] -export const run = ( +export const run = async ( args: string[], + nextJSVersion: string, options: | execa.Options | { reject?: boolean env?: Record } -) => - execa('node', [CNA_PATH].concat(args), { +) => { + return execa('node', [CNA_PATH].concat(args), { // tests with options.reject false are expected to exit(1) so don't inherit stdio: options.reject === false ? 'pipe' : 'inherit', ...options, env: { ...process.env, ...options.env, - NEXT_PRIVATE_TEST_VERSION: 'canary', + NEXT_PRIVATE_TEST_VERSION: nextJSVersion, }, }) +} export const command = (cmd: string, args: string[]) => execa(cmd, args, {