2019-07-17 22:53:56 +02:00
|
|
|
/* eslint-env jest */
|
|
|
|
import execa from 'execa'
|
2020-05-26 18:39:18 +02:00
|
|
|
import fs from 'fs-extra'
|
2019-07-17 22:53:56 +02:00
|
|
|
import os from 'os'
|
2020-05-26 18:39:18 +02:00
|
|
|
import path from 'path'
|
2019-07-17 22:53:56 +02:00
|
|
|
|
2019-07-19 21:55:30 +02:00
|
|
|
const cli = require.resolve('create-next-app/dist/index.js')
|
2019-07-17 22:53:56 +02:00
|
|
|
|
2020-05-26 18:39:18 +02:00
|
|
|
jest.setTimeout(1000 * 60 * 5)
|
2020-05-16 22:56:06 +02:00
|
|
|
|
|
|
|
const run = (cwd, ...args) => execa('node', [cli, ...args], { cwd })
|
|
|
|
const runStarter = (cwd, ...args) => {
|
|
|
|
const res = run(cwd, ...args)
|
2020-04-07 19:11:29 +02:00
|
|
|
|
2020-05-18 21:24:37 +02:00
|
|
|
res.stdout.on('data', (data) => {
|
2020-04-07 19:11:29 +02:00
|
|
|
const stdout = data.toString()
|
|
|
|
|
|
|
|
if (/Pick a template/.test(stdout)) {
|
|
|
|
res.stdin.write('\n')
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return res
|
|
|
|
}
|
2019-07-17 22:53:56 +02:00
|
|
|
|
2020-05-16 22:56:06 +02:00
|
|
|
async function usingTempDir(fn) {
|
2020-05-18 21:24:37 +02:00
|
|
|
const folder = path.join(os.tmpdir(), Math.random().toString(36).substring(2))
|
2020-05-16 22:56:06 +02:00
|
|
|
await fs.mkdirp(folder)
|
|
|
|
try {
|
|
|
|
return await fn(folder)
|
|
|
|
} finally {
|
|
|
|
await fs.remove(folder)
|
|
|
|
}
|
|
|
|
}
|
2019-07-17 22:53:56 +02:00
|
|
|
|
2020-05-16 22:56:06 +02:00
|
|
|
describe('create next app', () => {
|
2019-07-17 22:53:56 +02:00
|
|
|
it('non-empty directory', async () => {
|
2020-05-18 21:24:37 +02:00
|
|
|
await usingTempDir(async (cwd) => {
|
2020-05-16 22:56:06 +02:00
|
|
|
const projectName = 'non-empty-directory'
|
|
|
|
await fs.mkdirp(path.join(cwd, projectName))
|
|
|
|
const pkg = path.join(cwd, projectName, 'package.json')
|
|
|
|
fs.writeFileSync(pkg, '{ "foo": "bar" }')
|
|
|
|
|
|
|
|
expect.assertions(1)
|
|
|
|
try {
|
|
|
|
await runStarter(cwd, projectName)
|
|
|
|
} catch (e) {
|
2020-05-20 13:37:35 +02:00
|
|
|
// eslint-disable-next-line jest/no-try-expect
|
2020-05-16 22:56:06 +02:00
|
|
|
expect(e.stdout).toMatch(/contains files that could conflict/)
|
|
|
|
}
|
|
|
|
})
|
2019-07-17 22:53:56 +02:00
|
|
|
})
|
|
|
|
|
2020-04-09 19:57:59 +02:00
|
|
|
// TODO: investigate why this test stalls on yarn install when
|
|
|
|
// stdin is piped instead of inherited on windows
|
|
|
|
if (process.platform !== 'win32') {
|
|
|
|
it('empty directory', async () => {
|
2020-05-18 21:24:37 +02:00
|
|
|
await usingTempDir(async (cwd) => {
|
2020-05-16 22:56:06 +02:00
|
|
|
const projectName = 'empty-directory'
|
|
|
|
const res = await runStarter(cwd, projectName)
|
|
|
|
|
|
|
|
expect(res.exitCode).toBe(0)
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'package.json'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/index.js'))
|
|
|
|
).toBeTruthy()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2020-04-09 19:57:59 +02:00
|
|
|
|
2020-05-16 22:56:06 +02:00
|
|
|
it('invalid example name', async () => {
|
2020-05-18 21:24:37 +02:00
|
|
|
await usingTempDir(async (cwd) => {
|
2020-05-16 22:56:06 +02:00
|
|
|
const projectName = 'invalid-example-name'
|
|
|
|
expect.assertions(2)
|
|
|
|
try {
|
|
|
|
await run(cwd, projectName, '--example', 'not a real example')
|
|
|
|
} catch (e) {
|
2020-05-20 13:37:35 +02:00
|
|
|
// eslint-disable-next-line jest/no-try-expect
|
2020-05-16 22:56:06 +02:00
|
|
|
expect(e.stderr).toMatch(/Could not locate an example named/i)
|
|
|
|
}
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'package.json'))
|
|
|
|
).toBeFalsy()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
it('valid example', async () => {
|
2020-05-18 21:24:37 +02:00
|
|
|
await usingTempDir(async (cwd) => {
|
2020-05-16 22:56:06 +02:00
|
|
|
const projectName = 'valid-example'
|
|
|
|
const res = await run(cwd, projectName, '--example', 'basic-css')
|
2020-04-09 19:57:59 +02:00
|
|
|
expect(res.exitCode).toBe(0)
|
2020-05-16 22:56:06 +02:00
|
|
|
|
2020-04-09 19:57:59 +02:00
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'package.json'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/index.js'))
|
|
|
|
).toBeTruthy()
|
2020-05-16 22:56:06 +02:00
|
|
|
// check we copied default `.gitignore`
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, '.gitignore'))
|
|
|
|
).toBeTruthy()
|
2020-04-09 19:57:59 +02:00
|
|
|
})
|
2019-07-17 22:53:56 +02:00
|
|
|
})
|
2020-02-27 16:32:33 +01:00
|
|
|
|
|
|
|
it('should allow example with GitHub URL', async () => {
|
2020-05-18 21:24:37 +02:00
|
|
|
await usingTempDir(async (cwd) => {
|
2020-05-16 22:56:06 +02:00
|
|
|
const projectName = 'github-app'
|
|
|
|
const res = await run(
|
|
|
|
cwd,
|
|
|
|
projectName,
|
|
|
|
'--example',
|
|
|
|
'https://github.com/zeit/next-learn-demo/tree/master/1-navigate-between-pages'
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(res.exitCode).toBe(0)
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'package.json'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/index.js'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/about.js'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, '.gitignore'))
|
|
|
|
).toBeTruthy()
|
|
|
|
})
|
2020-02-27 16:32:33 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should allow example with GitHub URL and example-path', async () => {
|
2020-05-18 21:24:37 +02:00
|
|
|
await usingTempDir(async (cwd) => {
|
2020-05-16 22:56:06 +02:00
|
|
|
const projectName = 'github-example-path'
|
|
|
|
const res = await run(
|
|
|
|
cwd,
|
|
|
|
projectName,
|
|
|
|
'--example',
|
|
|
|
'https://github.com/zeit/next-learn-demo/tree/master',
|
|
|
|
'--example-path',
|
|
|
|
'1-navigate-between-pages'
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(res.exitCode).toBe(0)
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'package.json'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/index.js'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/about.js'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, '.gitignore'))
|
|
|
|
).toBeTruthy()
|
|
|
|
})
|
2020-02-27 16:32:33 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should use --example-path over the file path in the GitHub URL', async () => {
|
2020-05-18 21:24:37 +02:00
|
|
|
await usingTempDir(async (cwd) => {
|
2020-05-16 22:56:06 +02:00
|
|
|
const projectName = 'github-example-path-2'
|
|
|
|
const res = await run(
|
|
|
|
cwd,
|
|
|
|
projectName,
|
|
|
|
'--example',
|
|
|
|
'https://github.com/zeit/next-learn-demo/tree/master/1-navigate-between-pages',
|
|
|
|
'--example-path',
|
|
|
|
'1-navigate-between-pages'
|
|
|
|
)
|
|
|
|
|
|
|
|
expect(res.exitCode).toBe(0)
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'package.json'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/index.js'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/about.js'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, '.gitignore'))
|
|
|
|
).toBeTruthy()
|
|
|
|
})
|
2020-02-27 16:32:33 +01:00
|
|
|
})
|
2020-04-07 19:11:29 +02:00
|
|
|
|
2020-04-09 19:57:59 +02:00
|
|
|
// TODO: investigate why this test stalls on yarn install when
|
|
|
|
// stdin is piped instead of inherited on windows
|
|
|
|
if (process.platform !== 'win32') {
|
2020-05-26 18:39:18 +02:00
|
|
|
it('should fall back to default template', async () => {
|
|
|
|
await usingTempDir(async (cwd) => {
|
|
|
|
const runExample = (...args) => {
|
|
|
|
const res = run(cwd, ...args)
|
|
|
|
|
|
|
|
function fallbackToTemplate(data) {
|
|
|
|
if (
|
|
|
|
/Do you want to use the default template instead/.test(
|
|
|
|
data.toString()
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
res.stdout.removeListener('data', fallbackToTemplate)
|
|
|
|
res.stdin.write('\n')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res.stdout.on('data', fallbackToTemplate)
|
|
|
|
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
const res = await runExample(
|
|
|
|
'fail-example',
|
|
|
|
'--example',
|
|
|
|
'__internal-testing-retry'
|
|
|
|
)
|
|
|
|
expect(res.exitCode).toBe(0)
|
|
|
|
})
|
|
|
|
})
|
2020-04-09 19:57:59 +02:00
|
|
|
}
|
2020-05-24 00:50:31 +02:00
|
|
|
|
|
|
|
it('should allow an example named default', async () => {
|
|
|
|
await usingTempDir(async (cwd) => {
|
|
|
|
const projectName = 'default-example'
|
|
|
|
const res = await run(cwd, projectName, '--example', 'default')
|
|
|
|
expect(res.exitCode).toBe(0)
|
|
|
|
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'package.json'))
|
|
|
|
).toBeTruthy()
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, 'pages/index.js'))
|
|
|
|
).toBeTruthy()
|
|
|
|
// check we copied default `.gitignore`
|
|
|
|
expect(
|
|
|
|
fs.existsSync(path.join(cwd, projectName, '.gitignore'))
|
|
|
|
).toBeTruthy()
|
|
|
|
})
|
|
|
|
})
|
2020-06-10 05:14:24 +02:00
|
|
|
|
|
|
|
it('should exit if example flag is empty', async () => {
|
|
|
|
await usingTempDir(async (cwd) => {
|
|
|
|
try {
|
|
|
|
const projectName = 'no-example-provided'
|
|
|
|
await run(cwd, projectName, '--example')
|
|
|
|
} catch (e) {
|
|
|
|
// eslint-disable-next-line jest/no-try-expect
|
|
|
|
expect(e.exitCode).toBe(1)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
2019-07-17 22:53:56 +02:00
|
|
|
})
|