diff --git a/.gitignore b/.gitignore index 3c508998a3f..cac442b27ff 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,4 @@ packages/**/*.map # temporary test files test-assets/ + diff --git a/package.json b/package.json index 254364233b2..d3bb59c00f9 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "chalk": "^3.0.0", "commitlint": "^8.3.5", "commitlint-config-cz": "^0.13.0", + "concat-stream": "^2.0.0", "cz-customizable": "^6.2.0", "del-cli": "^3.0.0", "eslint": "^6.8.0", diff --git a/packages/webpack-cli/.gitignore b/packages/webpack-cli/.gitignore index 6cdf0169865..39454064e96 100644 --- a/packages/webpack-cli/.gitignore +++ b/packages/webpack-cli/.gitignore @@ -47,3 +47,7 @@ junit.xml #typescript source maps packages/**/*.map + +# ignore scaffolded files due to tests of init +__tests__/init/* +!__tests__/init/**/*.test.js diff --git a/packages/webpack-cli/__tests__/init/auto/init-auto.test.js b/packages/webpack-cli/__tests__/init/auto/init-auto.test.js new file mode 100644 index 00000000000..408c7ae5cd2 --- /dev/null +++ b/packages/webpack-cli/__tests__/init/auto/init-auto.test.js @@ -0,0 +1,31 @@ +/* eslint-disable node/no-unpublished-require */ +'use strict'; + +const firstPrompt = 'Will your application have multiple bundles?'; +const fs = require('fs'); +const { join } = require('path'); +const { run } = require('../../../../../test/utils/test-utils'); + +jest.setTimeout(200000); +describe('init auto flag', () => { + it('should prompt with w/o auto flag', () => { + const { stdout, stderr } = run(__dirname, ['init'], false); + expect(stdout).toBeTruthy(); + expect(stderr).toBeFalsy(); + expect(stdout).toContain(firstPrompt); + }); + + it('should scaffold and not prompt with auto flag', () => { + const { stdout } = run(__dirname, ['init', '--auto'], false); + // Test no prompts are present + expect(stdout).toBeTruthy(); + expect(stdout).not.toContain(firstPrompt); + + // Test regressively files are scaffolded + const files = ['./sw.js', './package.json', './yarn.lock', './src/index.js']; + // eslint-disable-next-line prettier/prettier + files.forEach((file) => { + expect(fs.existsSync(join(__dirname, file))).toBeTruthy(); + }); + }); +}); diff --git a/packages/webpack-cli/__tests__/init/coreFlags/init-flags.test.js b/packages/webpack-cli/__tests__/init/coreFlags/init-flags.test.js new file mode 100644 index 00000000000..3ca1f7c73ab --- /dev/null +++ b/packages/webpack-cli/__tests__/init/coreFlags/init-flags.test.js @@ -0,0 +1,15 @@ +/* eslint-disable node/no-unpublished-require */ +'use strict'; + +const firstPrompt = 'Will your application have multiple bundles?'; +const { run } = require('../../../../../test/utils/test-utils'); + +describe('init with core flags', () => { + it('should output help with --help flag', () => { + const { stdout, stderr } = run(__dirname, ['init', '--help'], false); + expect(stdout).toBeTruthy(); + expect(stderr).toBeFalsy(); + expect(stdout).not.toContain(firstPrompt); + expect(stdout).toContain('Initialize a new webpack configuration'); + }); +}); diff --git a/packages/webpack-cli/__tests__/init/generator/init-inquirer.test.js b/packages/webpack-cli/__tests__/init/generator/init-inquirer.test.js new file mode 100644 index 00000000000..d554ccecb1e --- /dev/null +++ b/packages/webpack-cli/__tests__/init/generator/init-inquirer.test.js @@ -0,0 +1,27 @@ +/* eslint-disable node/no-unpublished-require */ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const { runInitWithAnswers } = require('../../../../../test/utils/test-utils'); +const firstPrompt = 'Will your application have multiple bundles?'; + +const ENTER = '\x0D'; + +jest.setTimeout(200000); + +describe('init', () => { + it('should scaffold when given answers', async () => { + const stdout = await runInitWithAnswers(__dirname, ['N', ENTER, ENTER, ENTER, ENTER, ENTER, ENTER, ENTER]); + + expect(stdout).toBeTruthy(); + expect(stdout).toContain(firstPrompt); + + // Test regressively files are scaffolded + const files = ['./sw.js', './package.json', './yarn.lock', './src/index.js']; + // eslint-disable-next-line prettier/prettier + files.forEach((file) => { + expect(fs.existsSync(path.join(__dirname, file))).toBeTruthy(); + }); + }); +}); diff --git a/test/utils/test-utils.js b/test/utils/test-utils.js index a9cb59769a2..fb7418dc78f 100644 --- a/test/utils/test-utils.js +++ b/test/utils/test-utils.js @@ -4,6 +4,8 @@ const fs = require('fs'); const execa = require('execa'); const { sync: spawnSync } = execa; const { Writable } = require('readable-stream'); +const concat = require('concat-stream'); + const WEBPACK_PATH = path.resolve(__dirname, '../../packages/webpack-cli/bin/cli.js'); const ENABLE_LOG_COMPILATION = process.env.ENABLE_PIPE || false; @@ -79,6 +81,39 @@ function runAndGetWatchProc(testCase, args = [], setOutput = true) { return webpackProc; } +/** + * runInitWithAnswers + * @param {string} location location of current working directory + * @param {string[]} answers answers to be passed to stdout for inquirer question + */ +const runInitWithAnswers = async (location, answers) => { + const runner = runAndGetWatchProc(location, ['init'], false); + runner.stdin.setDefaultEncoding('utf-8'); + + // Simulate answers by sending the answers after waiting for 2s + const simulateAnswers = answers.reduce((prevAnswer, answer) => { + return prevAnswer.then(() => { + return new Promise((resolvePromise) => { + setTimeout(() => { + runner.stdin.write(answer); + resolvePromise(); + }, 2000); + }); + }); + }, Promise.resolve()); + + await simulateAnswers.then(() => { + runner.stdin.end(); + }); + + return new Promise((resolve) => { + runner.stdout.pipe( + concat((result) => { + resolve(result.toString()); + }), + ); + }); +}; function extractSummary(stdout) { if (stdout === '') { @@ -205,6 +240,7 @@ module.exports = { runServe, runAndGetWatchProc, extractSummary, + runInitWithAnswers, appendDataIfFileExists, copyFile, copyFileAsync,