diff --git a/.eslintrc.json b/.eslintrc.json index b642bbc5c14..40029410cce 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,7 +4,8 @@ "browser": true, "commonjs": true, "node": true, - "es6": true + "es6": true, + "jest": true }, "parserOptions": { "ecmaVersion": 2018 diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml new file mode 100644 index 00000000000..1249f20532f --- /dev/null +++ b/.github/workflows/integration.yml @@ -0,0 +1,36 @@ +name: Integration Tests + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + job: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: ['ubuntu-latest', 'macos-latest', 'windows-latest'] + node: ['10', '12', '14'] + steps: + - uses: actions/checkout@v2 + - name: Setup node + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + - name: Cache dependencies + id: cache + uses: actions/cache@v2 + with: + path: | + node_modules + */*/node_modules + key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock', './yarn.lock') }} + - name: Install packages + if: steps.cache.outputs.cache-hit != 'true' + run: yarn --frozen-lockfile --prefer-offline + - name: Run integration tests + run: yarn test:integration diff --git a/package.json b/package.json index e7eaac5d085..a5c093bf32e 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "screencast": "node ./tasks/screencast.js", "screencast:error": "svg-term --cast jyu19xGl88FQ3poMY8Hbmfw8y --out screencast-error.svg --window --at 12000 --no-cursor", "alex": "alex .", + "test:integration": "jest test/integration", "test": "cd packages/react-scripts && node bin/react-scripts.js test", "format": "prettier --write 'packages/*/*.js' 'packages/*/!(node_modules)/**/*.js'", "compile:lockfile": "node tasks/compile-lockfile.js" diff --git a/test/integration/create-react-app/index.test.js b/test/integration/create-react-app/index.test.js new file mode 100644 index 00000000000..875fd8ca348 --- /dev/null +++ b/test/integration/create-react-app/index.test.js @@ -0,0 +1,90 @@ +'use strict'; + +const execa = require('execa'); +const { mkdirp, remove, writeFileSync } = require('fs-extra'); +const { join } = require('path'); + +const cli = require.resolve('create-react-app/index.js'); + +jest.setTimeout(1000 * 60 * 5); + +const projectName = 'test-app'; +const genPath = join(__dirname, projectName); + +const generatedFiles = ['.gitignore', 'package.json', 'src', 'yarn.lock']; + +beforeEach(() => remove(genPath)); +afterAll(() => remove(genPath)); + +const run = (args, options) => execa('node', [cli].concat(args), options); + +describe('create-react-app', () => { + it('asks to supply an argument if none supplied', async () => { + const { stderr } = await run([], { reject: false }); + expect(stderr).toContain('Please specify the project directory'); + }); + + it('creates a project on supplying a name as the argument', async () => { + await run([projectName], { cwd: __dirname }); + + // Assert for the generated files + generatedFiles.forEach(file => expect(join(genPath, file)).toBeTruthy()); + }); + + it('warns about conflicting files in path', async () => { + // Create the temporary directory + await mkdirp(genPath); + + // Create a package.json file + const pkgJson = join(genPath, 'package.json'); + writeFileSync(pkgJson, '{ "foo": "bar" }'); + + const { stdout } = await run([projectName], { + cwd: __dirname, + reject: false, + }); + + // Assert for the expected message + expect(stdout).toContain( + `The directory ${projectName} contains files that could conflict` + ); + }); + + it('creates a project in the current directory', async () => { + // Create temporary directory + await mkdirp(genPath); + + // Create a project in the current directory + await run(['.'], { cwd: genPath }); + + // Assert for the generated files + generatedFiles.forEach(file => expect(join(genPath, file)).toBeTruthy()); + }); + + it('uses npm as the package manager', async () => { + await run([projectName, '--use-npm'], { + cwd: __dirname, + }); + + // Assert for the generated files + const generatedFilesWithNpm = [ + ...generatedFiles.filter(file => file !== 'yarn.lock'), + 'package-lock.json', + ]; + + generatedFilesWithNpm.forEach(file => + expect(join(genPath, file)).toBeTruthy() + ); + }); + + it('creates a project based on the typescript template', async () => { + await run([projectName, '--template', 'typescript'], { + cwd: __dirname, + }); + + // Assert for the generated files + [...generatedFiles, 'tsconfig.json'].forEach(file => + expect(join(genPath, file)).toBeTruthy() + ); + }); +});