Skip to content

Commit f9c1046

Browse files
authored
Run dev tests against default CNA templates (vercel#45211)
1 parent 45a9373 commit f9c1046

File tree

8 files changed

+139
-34
lines changed

8 files changed

+139
-34
lines changed

.github/actions/next-stats-action/src/prepare/repo-setup.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ module.exports = (actionInfo) => {
7373
})
7474

7575
const pkgPaths = new Map()
76-
const pkgs = await fs.readdir(path.join(repoDir, 'packages'))
76+
const pkgs = (await fs.readdir(path.join(repoDir, 'packages'))).filter(
77+
(item) => !item.startsWith('.')
78+
)
7779

7880
pkgs.forEach((pkgDirname) => {
7981
const { name } = require(path.join(

lint-staged.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const eslint = new ESLint()
55
const isWin = process.platform === 'win32'
66

77
module.exports = {
8-
'**/*.{js,jsx,ts,tsx}': (filenames) => {
8+
'**/*.{js,jsx,mjs,ts,tsx,mts}': (filenames) => {
99
const escapedFileNames = filenames
1010
.map((filename) => (isWin ? filename : escape([filename])))
1111
.join(' ')

packages/create-next-app/templates/index.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,16 @@ export const installTemplate = async ({
7070
/**
7171
* Default dependencies.
7272
*/
73-
const dependencies = ['react', 'react-dom', 'next', '@next/font']
73+
const dependencies = [
74+
'react',
75+
'react-dom',
76+
`next${
77+
process.env.NEXT_PRIVATE_TEST_VERSION
78+
? `@${process.env.NEXT_PRIVATE_TEST_VERSION}`
79+
: ''
80+
}`,
81+
'@next/font',
82+
]
7483
/**
7584
* TypeScript projects will have type definitions and other devDependencies.
7685
*/

scripts/test-pack-package.mts

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ const main = async () => {
1616
const getPackageJsonPath = (pkgDirname: string) =>
1717
path.join(pkgsDir, pkgDirname, `package.json`)
1818

19-
const allPkgDirnames = await fs.readdir(pkgsDir)
19+
const allPkgDirnames = (await fs.readdir(pkgsDir)).filter(
20+
(item) => !item.startsWith('.')
21+
)
22+
2023
if (!allPkgDirnames.includes(currentPkgDirname)) {
2124
throw new Error(`Unknown package '${currentPkgDirname}'`)
2225
}

test/integration/create-next-app/lib/utils.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ const cli = require.resolve('create-next-app/dist/index.js')
2222
/**
2323
* Run the built version of `create-next-app` with the given arguments.
2424
*/
25-
export const createNextApp = (args: string[], options?: SpawnOptions) => {
25+
export const createNextApp = (
26+
args: string[],
27+
options?: SpawnOptions,
28+
testVersion?: string
29+
) => {
2630
const conf = new Conf({ projectName: 'create-next-app' })
2731
conf.clear()
2832

@@ -39,6 +43,11 @@ export const createNextApp = (args: string[], options?: SpawnOptions) => {
3943
CONTINUOUS_INTEGRATION: '',
4044
RUN_ID: '',
4145
BUILD_NUMBER: '',
46+
...(testVersion
47+
? {
48+
NEXT_PRIVATE_TEST_VERSION: testVersion,
49+
}
50+
: {}),
4251
...options.env,
4352
},
4453
})

test/integration/create-next-app/templates.test.ts

+108-27
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
* JavaScript (default), TypeScript, and appDir.
77
*/
88

9+
import path from 'path'
10+
import fs from 'fs-extra'
911
import {
1012
createNextApp,
1113
projectFilesShouldExist,
@@ -16,13 +18,53 @@ import {
1618
} from './lib/utils'
1719

1820
import { useTempDir } from '../../../test/lib/use-temp-dir'
21+
import { fetchViaHTTP, findPort, killApp, launchApp } from 'next-test-utils'
22+
import resolveFrom from 'resolve-from'
23+
import { getPkgPaths } from '../../../test/lib/create-next-install'
24+
25+
const startsWithoutError = async (
26+
appDir: string,
27+
modes = ['default', 'turbo']
28+
) => {
29+
for (const mode of modes) {
30+
appDir = await fs.realpath(appDir)
31+
const appPort = await findPort()
32+
const app = await launchApp(appDir, appPort, {
33+
turbo: mode === 'turbo',
34+
cwd: appDir,
35+
nextBin: resolveFrom(appDir, 'next/dist/bin/next'),
36+
})
37+
38+
try {
39+
const res = await fetchViaHTTP(appPort, '/')
40+
expect(res.status).toBe(200)
41+
expect(await res.text()).toContain('Get started by editing')
42+
43+
const apiRes = await fetchViaHTTP(appPort, '/api/hello')
44+
expect(apiRes.status).toBe(200)
45+
expect(await apiRes.json()).toEqual({ name: 'John Doe' })
46+
} finally {
47+
await killApp(app)
48+
}
49+
}
50+
}
51+
let testVersion
1952

2053
describe('create-next-app templates', () => {
2154
if (!process.env.NEXT_TEST_CNA) {
2255
it('should skip when env is not set', () => {})
2356
return
2457
}
2558

59+
beforeAll(async () => {
60+
testVersion = (
61+
await getPkgPaths({
62+
repoDir: path.join(__dirname, '../../../'),
63+
nextSwcVersion: '',
64+
})
65+
).get('next')
66+
})
67+
2668
it('should prompt user to choose if --ts or --js is not provided', async () => {
2769
useTempDir(async (cwd) => {
2870
const projectName = 'choose-ts-js'
@@ -36,9 +78,12 @@ describe('create-next-app templates', () => {
3678
'--eslint',
3779
'--no-src-dir',
3880
'--no-experimental-app',
39-
`--import-alias="@/*"`,
81+
`--import-alias=@/*`,
4082
],
41-
{ cwd }
83+
{
84+
cwd,
85+
},
86+
testVersion
4287
)
4388
/**
4489
* Wait for the prompt to display.
@@ -47,8 +92,8 @@ describe('create-next-app templates', () => {
4792
/**
4893
* Bind the exit listener.
4994
*/
50-
await new Promise<void>((resolve) => {
51-
childProcess.on('exit', (exitCode) => {
95+
await new Promise<void>((resolve, reject) => {
96+
childProcess.on('exit', async (exitCode) => {
5297
expect(exitCode).toBe(0)
5398
/**
5499
* Verify it correctly emitted a TS project by looking for tsconfig.
@@ -78,16 +123,19 @@ describe('create-next-app templates', () => {
78123
'--eslint',
79124
'--no-src-dir',
80125
'--no-experimental-app',
81-
`--import-alias="@/*"`,
126+
`--import-alias=@/*`,
82127
],
83128
{
84129
cwd,
85-
}
130+
},
131+
testVersion
86132
)
87133
const exitCode = await spawnExitPromise(childProcess)
88134

89135
expect(exitCode).toBe(0)
90136
shouldBeTypescriptProject({ cwd, projectName, template: 'default' })
137+
138+
await startsWithoutError(path.join(cwd, projectName))
91139
})
92140
})
93141

@@ -101,11 +149,12 @@ describe('create-next-app templates', () => {
101149
'--eslint',
102150
'--src-dir',
103151
'--no-experimental-app',
104-
`--import-alias="@/*"`,
152+
`--import-alias=@/*`,
105153
],
106154
{
107155
cwd,
108-
}
156+
},
157+
testVersion
109158
)
110159
const exitCode = await spawnExitPromise(childProcess)
111160

@@ -116,24 +165,30 @@ describe('create-next-app templates', () => {
116165
template: 'default',
117166
srcDir: true,
118167
})
168+
await startsWithoutError(path.join(cwd, projectName))
119169
})
120170
})
121171

122172
it('should create TS projects with --ts, --typescript with CI=1', async () => {
123173
await useTempDir(async (cwd) => {
124174
const projectName = 'typescript-test'
125-
const childProcess = createNextApp([projectName, '--ts', '--eslint'], {
126-
cwd,
127-
env: {
128-
...process.env,
129-
CI: '1',
130-
GITHUB_ACTIONS: '1',
175+
const childProcess = createNextApp(
176+
[projectName, '--ts', '--eslint'],
177+
{
178+
cwd,
179+
env: {
180+
...process.env,
181+
CI: '1',
182+
GITHUB_ACTIONS: '1',
183+
},
131184
},
132-
})
185+
testVersion
186+
)
133187
const exitCode = await spawnExitPromise(childProcess)
134188

135189
expect(exitCode).toBe(0)
136190
shouldBeTypescriptProject({ cwd, projectName, template: 'default' })
191+
await startsWithoutError(path.join(cwd, projectName))
137192
})
138193
})
139194

@@ -147,16 +202,20 @@ describe('create-next-app templates', () => {
147202
'--eslint',
148203
'--no-src-dir',
149204
'--no-experimental-app',
150-
`--import-alias="@/*"`,
205+
`--import-alias=@/*`,
151206
],
152207
{
153208
cwd,
154-
}
209+
},
210+
testVersion
155211
)
156212
const exitCode = await spawnExitPromise(childProcess)
157213

158214
expect(exitCode).toBe(0)
159215
shouldBeJavascriptProject({ cwd, projectName, template: 'default' })
216+
// TODO: enable turbo mode as well once jsconfig paths support
217+
// is landed
218+
await startsWithoutError(path.join(cwd, projectName), ['default'])
160219
})
161220
})
162221

@@ -170,11 +229,12 @@ describe('create-next-app templates', () => {
170229
'--eslint',
171230
'--src-dir',
172231
'--no-experimental-app',
173-
`--import-alias="@/*"`,
232+
`--import-alias=@/*`,
174233
],
175234
{
176235
cwd,
177-
}
236+
},
237+
testVersion
178238
)
179239
const exitCode = await spawnExitPromise(childProcess)
180240

@@ -185,6 +245,9 @@ describe('create-next-app templates', () => {
185245
template: 'default',
186246
srcDir: true,
187247
})
248+
// TODO: enable turbo mode as well once jsconfig paths support
249+
// is landed
250+
await startsWithoutError(path.join(cwd, projectName), ['default'])
188251
})
189252
})
190253
})
@@ -195,6 +258,16 @@ describe('create-next-app --experimental-app-dir', () => {
195258
return
196259
}
197260

261+
beforeAll(async () => {
262+
if (testVersion) return
263+
testVersion = (
264+
await getPkgPaths({
265+
repoDir: path.join(__dirname, '../../../'),
266+
nextSwcVersion: '',
267+
})
268+
).get('next')
269+
})
270+
198271
it('should create TS appDir projects with --ts', async () => {
199272
await useTempDir(async (cwd) => {
200273
const projectName = 'appdir-test'
@@ -205,17 +278,18 @@ describe('create-next-app --experimental-app-dir', () => {
205278
'--experimental-app',
206279
'--eslint',
207280
'--no-src-dir',
208-
'--no-experimental-app',
209-
`--import-alias="@/*"`,
281+
`--import-alias=@/*`,
210282
],
211283
{
212284
cwd,
213-
}
285+
},
286+
testVersion
214287
)
215288

216289
const exitCode = await spawnExitPromise(childProcess)
217290
expect(exitCode).toBe(0)
218291
shouldBeTemplateProject({ cwd, projectName, template: 'app', mode: 'ts' })
292+
await startsWithoutError(path.join(cwd, projectName))
219293
})
220294
})
221295

@@ -229,17 +303,20 @@ describe('create-next-app --experimental-app-dir', () => {
229303
'--experimental-app',
230304
'--eslint',
231305
'--no-src-dir',
232-
'--no-experimental-app',
233-
`--import-alias="@/*"`,
306+
`--import-alias=@/*`,
234307
],
235308
{
236309
cwd,
237-
}
310+
},
311+
testVersion
238312
)
239313

240314
const exitCode = await spawnExitPromise(childProcess)
241315
expect(exitCode).toBe(0)
242316
shouldBeTemplateProject({ cwd, projectName, template: 'app', mode: 'js' })
317+
// TODO: enable turbo mode as well once jsconfig paths support
318+
// is landed
319+
await startsWithoutError(path.join(cwd, projectName), ['default'])
243320
})
244321
})
245322

@@ -253,12 +330,13 @@ describe('create-next-app --experimental-app-dir', () => {
253330
'--experimental-app',
254331
'--eslint',
255332
'--src-dir',
256-
'--import-alias="@/*"',
333+
'--import-alias=@/*',
257334
],
258335
{
259336
cwd,
260337
stdio: 'inherit',
261-
}
338+
},
339+
testVersion
262340
)
263341

264342
const exitCode = await spawnExitPromise(childProcess)
@@ -270,6 +348,9 @@ describe('create-next-app --experimental-app-dir', () => {
270348
mode: 'js',
271349
srcDir: true,
272350
})
351+
// TODO: enable turbo mode as well once jsconfig paths support
352+
// is landed
353+
await startsWithoutError(path.join(cwd, projectName), ['default'])
273354
})
274355
})
275356
})

test/lib/create-next-install.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ async function createNextInstall({
2727
require('console').log('Creating next instance in:')
2828
require('console').log(installDir)
2929

30-
await rootSpan.traceChild(' enruse swc binary').traceAsyncFn(async () => {
30+
await rootSpan.traceChild('ensure swc binary').traceAsyncFn(async () => {
3131
// ensure swc binary is present in the native folder if
3232
// not already built
3333
for (const folder of await fs.readdir(
@@ -129,4 +129,5 @@ async function createNextInstall({
129129

130130
module.exports = {
131131
createNextInstall,
132+
getPkgPaths: linkPackages,
132133
}

test/lib/next-test-utils.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ export function runNextCommand(argv, options = {}) {
283283

284284
export function runNextCommandDev(argv, stdOut, opts = {}) {
285285
const nextDir = path.dirname(require.resolve('next/package'))
286-
const nextBin = path.join(nextDir, 'dist/bin/next')
286+
const nextBin = opts.nextBin || path.join(nextDir, 'dist/bin/next')
287287
const cwd = opts.cwd || nextDir
288288
const env = {
289289
...process.env,

0 commit comments

Comments
 (0)