From f2f05df26cf95213ec0790ac2ac10d4e2db430b8 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Fri, 16 Sep 2022 19:08:53 +0530 Subject: [PATCH] refactor: run `info` under the hood for the `version` command (#3370) --- packages/info/package.json | 6 - packages/info/src/index.ts | 85 +---- packages/webpack-cli/package.json | 4 + packages/webpack-cli/src/types.ts | 2 + packages/webpack-cli/src/webpack-cli.ts | 193 +++++----- smoketests/missing-packages/webpack.test.js | 2 +- .../help.test.js.snap.devServer4.webpack5 | 14 +- test/version/additional-package.test.js | 91 +++++ test/version/basic.test.js | 69 ++++ test/version/output.test.js | 58 +++ test/version/version.test.js | 334 ------------------ 11 files changed, 337 insertions(+), 521 deletions(-) create mode 100644 test/version/additional-package.test.js create mode 100644 test/version/basic.test.js create mode 100644 test/version/output.test.js delete mode 100644 test/version/version.test.js diff --git a/packages/info/package.json b/packages/info/package.json index 5adfde3a678..007f8b46878 100644 --- a/packages/info/package.json +++ b/packages/info/package.json @@ -19,15 +19,9 @@ "files": [ "lib" ], - "dependencies": { - "envinfo": "^7.7.3" - }, "gitHead": "fb50f766851f500ca12867a2aa9de81fa6e368f9", "peerDependencies": { "webpack": "5.x.x", "webpack-cli": "4.x.x" - }, - "devDependencies": { - "@types/envinfo": "^7.8.1" } } diff --git a/packages/info/src/index.ts b/packages/info/src/index.ts index 23410db7034..fb8c9f54e18 100644 --- a/packages/info/src/index.ts +++ b/packages/info/src/index.ts @@ -1,15 +1,5 @@ -import envinfo from "envinfo"; import { IWebpackCLI } from "webpack-cli"; -interface Information { - Binaries?: string[]; - Browsers?: string[]; - Monorepos?: string[]; - System?: string[]; - npmGlobalPackages?: string[]; - npmPackages?: string | string[]; -} - class InfoCommand { async apply(cli: IWebpackCLI): Promise { await cli.makeCommand( @@ -20,80 +10,9 @@ class InfoCommand { usage: "[options]", pkg: "@webpack-cli/info", }, - [ - { - name: "output", - alias: "o", - configs: [ - { - type: "string", - }, - ], - description: "To get the output in a specified format ( accept json or markdown )", - }, - { - name: "additional-package", - alias: "a", - configs: [{ type: "string" }], - multiple: true, - description: "Adds additional packages to the output", - }, - ], + cli.getInfoOptions(), async (options: { output: string; additionalPackage: string[] }) => { - let { output } = options; - - const envinfoConfig: { [key: string]: boolean } = {}; - - if (output) { - // Remove quotes if exist - output = output.replace(/['"]+/g, ""); - - switch (output) { - case "markdown": - envinfoConfig["markdown"] = true; - break; - case "json": - envinfoConfig["json"] = true; - break; - default: - cli.logger.error(`'${output}' is not a valid value for output`); - process.exit(2); - } - } - - const defaultInformation: Information = { - Binaries: ["Node", "Yarn", "npm"], - Browsers: [ - "Brave Browser", - "Chrome", - "Chrome Canary", - "Edge", - "Firefox", - "Firefox Developer Edition", - "Firefox Nightly", - "Internet Explorer", - "Safari", - "Safari Technology Preview", - ], - Monorepos: ["Yarn Workspaces", "Lerna"], - System: ["OS", "CPU", "Memory"], - npmGlobalPackages: ["webpack", "webpack-cli", "webpack-dev-server"], - }; - - let defaultPackages: string[] = ["webpack", "loader", "@webpack-cli/"]; - - if (typeof options.additionalPackage !== "undefined") { - defaultPackages = [...defaultPackages, ...options.additionalPackage]; - } - - defaultInformation.npmPackages = `{${defaultPackages - .map((item) => `*${item}*`) - .join(",")}}`; - - let info = await envinfo.run(defaultInformation, envinfoConfig); - - info = info.replace(/npmPackages/g, "Packages"); - info = info.replace(/npmGlobalPackages/g, "Global Packages"); + const info = await cli.getInfoOutput(options); cli.logger.raw(info); }, diff --git a/packages/webpack-cli/package.json b/packages/webpack-cli/package.json index e08fd2a0fa4..30fb1b66503 100644 --- a/packages/webpack-cli/package.json +++ b/packages/webpack-cli/package.json @@ -41,12 +41,16 @@ "colorette": "^2.0.14", "commander": "^7.0.0", "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", "interpret": "^2.2.0", "rechoir": "^0.7.0", "webpack-merge": "^5.7.3" }, + "devDependencies": { + "@types/envinfo": "^7.8.1" + }, "peerDependencies": { "webpack": "5.x.x" }, diff --git a/packages/webpack-cli/src/types.ts b/packages/webpack-cli/src/types.ts index e34f061d478..2afbaa471e5 100644 --- a/packages/webpack-cli/src/types.ts +++ b/packages/webpack-cli/src/types.ts @@ -47,6 +47,8 @@ interface IWebpackCLI { doInstall(packageName: string, options?: PackageInstallOptions): Promise; loadJSONFile(path: Path, handleError: boolean): Promise; tryRequireThenImport(module: ModuleName, handleError: boolean): Promise; + getInfoOptions(): WebpackCLIBuiltInOption[]; + getInfoOutput(options: { output: string; additionalPackage: string[] }): Promise; makeCommand( commandOptions: WebpackCLIOptions, options: WebpackCLICommandOptions, diff --git a/packages/webpack-cli/src/webpack-cli.ts b/packages/webpack-cli/src/webpack-cli.ts index b4487aaa0bb..cc7a8821d20 100644 --- a/packages/webpack-cli/src/webpack-cli.ts +++ b/packages/webpack-cli/src/webpack-cli.ts @@ -19,7 +19,6 @@ import { WebpackConfiguration, Argv, BasicPrimitive, - BasicPackageJsonContent, CallableOption, Callback, CLIPluginOptions, @@ -58,10 +57,20 @@ const { pathToFileURL } = require("url"); const util = require("util"); const { program, Option } = require("commander"); +const envinfo = require("envinfo"); const WEBPACK_PACKAGE = process.env.WEBPACK_PACKAGE || "webpack"; const WEBPACK_DEV_SERVER_PACKAGE = process.env.WEBPACK_DEV_SERVER_PACKAGE || "webpack-dev-server"; +interface Information { + Binaries?: string[]; + Browsers?: string[]; + Monorepos?: string[]; + System?: string[]; + npmGlobalPackages?: string[]; + npmPackages?: string | string[]; +} + class WebpackCLI implements IWebpackCLI { colors: WebpackCLIColors; logger: WebpackCLILogger; @@ -359,6 +368,84 @@ class WebpackCLI implements IWebpackCLI { return result; } + getInfoOptions(): WebpackCLIBuiltInOption[] { + return [ + { + name: "output", + alias: "o", + configs: [ + { + type: "string", + }, + ], + description: "To get the output in a specified format ( accept json or markdown )", + }, + { + name: "additional-package", + alias: "a", + configs: [{ type: "string" }], + multiple: true, + description: "Adds additional packages to the output", + }, + ]; + } + + async getInfoOutput(options: { output: string; additionalPackage: string[] }): Promise { + let { output } = options; + const envinfoConfig: { [key: string]: boolean } = {}; + + if (output) { + // Remove quotes if exist + output = output.replace(/['"]+/g, ""); + + switch (output) { + case "markdown": + envinfoConfig["markdown"] = true; + break; + case "json": + envinfoConfig["json"] = true; + break; + default: + this.logger.error(`'${output}' is not a valid value for output`); + process.exit(2); + } + } + + const defaultInformation: Information = { + Binaries: ["Node", "Yarn", "npm"], + Browsers: [ + "Brave Browser", + "Chrome", + "Chrome Canary", + "Edge", + "Firefox", + "Firefox Developer Edition", + "Firefox Nightly", + "Internet Explorer", + "Safari", + "Safari Technology Preview", + ], + Monorepos: ["Yarn Workspaces", "Lerna"], + System: ["OS", "CPU", "Memory"], + npmGlobalPackages: ["webpack", "webpack-cli", "webpack-dev-server"], + }; + + let defaultPackages: string[] = ["webpack", "loader", "@webpack-cli/"]; + + if (typeof options.additionalPackage !== "undefined") { + defaultPackages = [...defaultPackages, ...options.additionalPackage]; + } + + defaultInformation.npmPackages = `{${defaultPackages.map((item) => `*${item}*`).join(",")}}`; + + let info = await envinfo.run(defaultInformation, envinfoConfig); + + info = info.replace(/npmPackages/g, "Packages"); + info = info.replace(/npmGlobalPackages/g, "Global Packages"); + + return info; + } + async makeCommand( commandOptions: WebpackCLIOptions, options: WebpackCLICommandOptions, @@ -925,8 +1012,9 @@ class WebpackCLI implements IWebpackCLI { dependencies: [WEBPACK_PACKAGE], }; const versionCommandOptions = { - name: "version [commands...]", + name: "version", alias: "v", + usage: "[options]", description: "Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands.", }; @@ -1044,8 +1132,15 @@ class WebpackCLI implements IWebpackCLI { this.makeCommand(helpCommandOptions, [], () => {}); } else if (isCommand(commandName, versionCommandOptions)) { // Stub for the `version` command - // eslint-disable-next-line @typescript-eslint/no-empty-function - this.makeCommand(versionCommandOptions, [], () => {}); + this.makeCommand( + versionCommandOptions, + this.getInfoOptions(), + async (options: { output: string; additionalPackage: string[] }) => { + const info = await cli.getInfoOutput(options); + + cli.logger.raw(info); + }, + ); } else { const builtInExternalCommandInfo = externalBuiltInCommandsInfo.find( (externalBuiltInCommandInfo) => @@ -1181,84 +1276,6 @@ class WebpackCLI implements IWebpackCLI { cli.colors = cli.createColors(color); }); - // Make `-v, --version` options - // Make `version|v [commands...]` command - const outputVersion = async (options: string[]) => { - // Filter `bundle`, `watch`, `version` and `help` commands - const possibleCommandNames = options.filter( - (option) => - !isCommand(option, buildCommandOptions) && - !isCommand(option, watchCommandOptions) && - !isCommand(option, versionCommandOptions) && - !isCommand(option, helpCommandOptions), - ); - - possibleCommandNames.forEach((possibleCommandName) => { - if (!isOption(possibleCommandName)) { - return; - } - - this.logger.error(`Unknown option '${possibleCommandName}'`); - this.logger.error("Run 'webpack --help' to see available commands and options"); - process.exit(2); - }); - - if (possibleCommandNames.length > 0) { - await Promise.all( - possibleCommandNames.map((possibleCommand) => loadCommandByName(possibleCommand)), - ); - - for (const possibleCommandName of possibleCommandNames) { - const foundCommand = findCommandByName(possibleCommandName) as WebpackCLICommand; - - if (!foundCommand) { - this.logger.error(`Unknown command '${possibleCommandName}'`); - this.logger.error("Run 'webpack --help' to see available commands and options"); - process.exit(2); - } - - try { - const { name, version } = this.loadJSONFile( - `${foundCommand.pkg}/package.json`, - ); - - this.logger.raw(`${name} ${version}`); - } catch (e) { - this.logger.error(`Error: External package '${foundCommand.pkg}' not found`); - process.exit(2); - } - } - } - - let webpack; - - try { - webpack = await this.loadWebpack(false); - } catch (_error) { - // Nothing - } - - this.logger.raw(`webpack: ${webpack ? webpack.version : "not installed"}`); - - const pkgJSON = this.loadJSONFile("../package.json"); - - this.logger.raw(`webpack-cli: ${pkgJSON.version}`); - - let devServer; - - try { - devServer = await this.loadJSONFile( - "webpack-dev-server/package.json", - false, - ); - } catch (_error) { - // Nothing - } - - this.logger.raw(`webpack-dev-server ${devServer ? devServer.version : "not installed"}`); - - process.exit(0); - }; this.program.option( "-v, --version", "Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands.", @@ -1625,15 +1642,11 @@ class WebpackCLI implements IWebpackCLI { } const isVersionOption = typeof options.version !== "undefined"; - const isVersionCommandSyntax = isCommand(operand, versionCommandOptions); - - if (isVersionOption || isVersionCommandSyntax) { - const optionsForVersion = ([] as string[]) - .concat(isVersionOption ? [operand] : []) - .concat(operands.slice(1)) - .concat(unknown); - await outputVersion(optionsForVersion); + if (isVersionOption) { + const info = await this.getInfoOutput({ output: "", additionalPackage: [] }); + this.logger.raw(info); + process.exit(0); } let commandToRun = operand; diff --git a/smoketests/missing-packages/webpack.test.js b/smoketests/missing-packages/webpack.test.js index 99ce50e4072..90d8f0abb61 100644 --- a/smoketests/missing-packages/webpack.test.js +++ b/smoketests/missing-packages/webpack.test.js @@ -37,7 +37,7 @@ const serveCommand = () => { const versionCommand = () => { const packageName = "webpack"; const args = ["version"]; - const logMessage = "webpack-cli:"; + const logMessage = "System:"; return runTestStdout({ packageName, cliArgs: args, logMessage }); }; diff --git a/test/help/__snapshots__/help.test.js.snap.devServer4.webpack5 b/test/help/__snapshots__/help.test.js.snap.devServer4.webpack5 index 1f337327b83..aaee31a9d20 100644 --- a/test/help/__snapshots__/help.test.js.snap.devServer4.webpack5 +++ b/test/help/__snapshots__/help.test.js.snap.devServer4.webpack5 @@ -134,7 +134,7 @@ Commands: loader|l [output-path] [options] Scaffold a loader. plugin|p [output-path] [options] Scaffold a plugin. serve|server|s [entries...] [options] Run the webpack dev server. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + version|v [options] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. watch|w [entries...] [options] Run webpack and watch for files changes. To see list of all supported commands and options run 'webpack --help=verbose'. @@ -193,7 +193,7 @@ Commands: loader|l [output-path] [options] Scaffold a loader. plugin|p [output-path] [options] Scaffold a plugin. serve|server|s [entries...] [options] Run the webpack dev server. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + version|v [options] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. watch|w [entries...] [options] Run webpack and watch for files changes. To see list of all supported commands and options run 'webpack --help=verbose'. @@ -252,7 +252,7 @@ Commands: loader|l [output-path] [options] Scaffold a loader. plugin|p [output-path] [options] Scaffold a plugin. serve|server|s [entries...] [options] Run the webpack dev server. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + version|v [options] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. watch|w [entries...] [options] Run webpack and watch for files changes. To see list of all supported commands and options run 'webpack --help=verbose'. @@ -1845,7 +1845,7 @@ Commands: loader|l [output-path] [options] Scaffold a loader. plugin|p [output-path] [options] Scaffold a plugin. serve|server|s [entries...] [options] Run the webpack dev server. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + version|v [options] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. watch|w [entries...] [options] Run webpack and watch for files changes. To see list of all supported commands and options run 'webpack --help=verbose'. @@ -1904,7 +1904,7 @@ Commands: loader|l [output-path] [options] Scaffold a loader. plugin|p [output-path] [options] Scaffold a plugin. serve|server|s [entries...] [options] Run the webpack dev server. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + version|v [options] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. watch|w [entries...] [options] Run webpack and watch for files changes. To see list of all supported commands and options run 'webpack --help=verbose'. @@ -2153,7 +2153,7 @@ Commands: loader|l [output-path] [options] Scaffold a loader. plugin|p [output-path] [options] Scaffold a plugin. serve|server|s [entries...] [options] Run the webpack dev server. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + version|v [options] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. watch|w [entries...] [options] Run webpack and watch for files changes. To see list of all supported commands and options run 'webpack --help=verbose'. @@ -2210,7 +2210,7 @@ Commands: loader|l [output-path] [options] Scaffold a loader. plugin|p [output-path] [options] Scaffold a plugin. serve|server|s [entries...] [options] Run the webpack dev server. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + version|v [options] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. watch|w [entries...] [options] Run webpack and watch for files changes. To see list of all supported commands and options run 'webpack --help=verbose'. diff --git a/test/version/additional-package.test.js b/test/version/additional-package.test.js new file mode 100644 index 00000000000..0f71229b894 --- /dev/null +++ b/test/version/additional-package.test.js @@ -0,0 +1,91 @@ +"use strict"; + +const { join } = require("path"); +const { run } = require("../utils/test-utils"); + +describe("'-a, --additional-package ' usage", () => { + it("should work with only one package", async () => { + const { exitCode, stdout, stderr } = await run(join(__dirname, "../../"), [ + "version", + "--additional-package", + "typescript", + ]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + expect(stdout).toContain("typescript"); + }); + + it("should work with only one package using '-a' alias", async () => { + const { exitCode, stdout, stderr } = await run(join(__dirname, "../../"), [ + "version", + "-a", + "typescript", + ]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + expect(stdout).toContain("typescript"); + }); + + it("should work with multiple packages", async () => { + const { exitCode, stdout, stderr } = await run(join(__dirname, "../../"), [ + "version", + "--additional-package", + "typescript", + "--additional-package", + "eslint", + ]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + expect(stdout).toContain("typescript"); + expect(stdout).toContain("eslint"); + expect(stdout).toContain("eslint-config-prettier"); + expect(stdout).toContain("eslint-plugin-node"); + }); + + it("should work with multiple packages using '-a' alias", async () => { + const { exitCode, stdout, stderr } = await run(join(__dirname, "../../"), [ + "version", + "-a", + "typescript", + "-a", + "eslint", + ]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + expect(stdout).toContain("typescript"); + expect(stdout).toContain("eslint"); + expect(stdout).toContain("eslint-config-prettier"); + expect(stdout).toContain("eslint-plugin-node"); + }); + + it("should throw an error on invalid usage", async () => { + const { exitCode, stdout, stderr } = await run(join(__dirname, "../../"), [ + "version", + "--additional-package", + ]); + + expect(exitCode).toBe(2); + expect(stderr).toContain(`Option '-a, --additional-package ' argument missing`); + expect(stdout).toBeFalsy(); + }); +}); diff --git a/test/version/basic.test.js b/test/version/basic.test.js new file mode 100644 index 00000000000..568e85b5362 --- /dev/null +++ b/test/version/basic.test.js @@ -0,0 +1,69 @@ +const { join } = require("path"); +const { run } = require("../utils/test-utils"); + +describe("basic usage", () => { + it("should work", async () => { + const { exitCode, stdout, stderr } = await run(__dirname, ["version"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + }); + + it("should work with v alias", async () => { + const { exitCode, stdout, stderr } = await run(__dirname, ["v"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + }); + + it("should work with --version", async () => { + const { exitCode, stdout, stderr } = await run(__dirname, ["--version"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + }); + + it("should work with -v alias", async () => { + const { exitCode, stdout, stderr } = await run(__dirname, ["-v"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + }); + + it("should work and gets more info in project root", async () => { + const { exitCode, stderr, stdout } = await run(join(__dirname, "../../"), ["version"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Monorepos:"); + expect(stdout).toContain("Packages:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + }); + + it("shows an appropriate warning on supplying unknown args", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--unknown"]); + + expect(exitCode).toBe(2); + expect(stderr).toContain("Error: Unknown option '--unknown'"); + expect(stdout).toBeFalsy(); + }); +}); diff --git a/test/version/output.test.js b/test/version/output.test.js new file mode 100644 index 00000000000..1c2f7f04448 --- /dev/null +++ b/test/version/output.test.js @@ -0,0 +1,58 @@ +"use strict"; + +const { run } = require("../utils/test-utils"); + +describe("'-o, --output ' usage", () => { + it("gets info text by default", async () => { + const { exitCode, stdout, stderr } = await run(__dirname, ["version"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("System:"); + expect(stdout).toContain("Node"); + expect(stdout).toContain("npm"); + expect(stdout).toContain("Yarn"); + }); + + it("gets info as json", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--output=json"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain('"System":'); + + const parse = () => { + const output = JSON.parse(stdout); + expect(output["System"]).toBeTruthy(); + expect(output["Binaries"]).toBeTruthy(); + expect(output["System"]["OS"]).toBeTruthy(); + expect(output["System"]["CPU"]).toBeTruthy(); + }; + + expect(parse).not.toThrow(); + }); + + it("gets info as markdown", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--output", "markdown"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("## System:"); + }); + + it("shows a warning if an invalid value is supplied", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--output", "unknown"]); + + expect(exitCode).toBe(2); + expect(stderr).toContain(`'unknown' is not a valid value for output`); + expect(stdout).toBeFalsy(); + }); + + it("recognizes '-o' as an alias for '--output'", async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ["version", "-o", "markdown"]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("## System:"); + }); +}); diff --git a/test/version/version.test.js b/test/version/version.test.js deleted file mode 100644 index 604636ccc59..00000000000 --- a/test/version/version.test.js +++ /dev/null @@ -1,334 +0,0 @@ -"use strict"; - -const { run, normalizeStderr, normalizeStdout } = require("../utils/test-utils"); - -describe("single version flag", () => { - it("outputs versions with command syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs versions with dashed syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs versions with alias syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["-v"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with info", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["info", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with info using option alias", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["info", "-v"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with info using command syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "info"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with info using command alias", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["v", "info"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with build", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["build", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with bundle", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["bundle", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with b", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["b", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with watch", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["watch", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with w", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["w", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with plugin", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["plugin", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with loader", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["loader", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with init", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["init", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with serve", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["serve", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs version with the alias c for init", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["c", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should log error when unknown command using command syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "unknown"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should log version for known command and log error for unknown command using command syntax with multi commands", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "info", "unknown"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should work for multiple commands", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["info", "serve", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should output versions for multiple commands using command syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "info", "serve"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should output versions with help command using command syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "help"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it('should log version for known command and log error for unknown command using the "--version" option', async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["serve", "abc", "--version"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it('should log version for known command and log error for unknown command using the "-v" option', async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["serve", "abc", "-v"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should not output version with help dashed", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--help"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs versions with --color using option syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["--version", "--color"], { - env: { FORCE_COLOR: true }, - }); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs versions with --no-color using option syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["--version", "--no-color"], { - env: { FORCE_COLOR: true }, - }); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs versions with --color using command syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--color"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("outputs versions with --no-color using command syntax", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--no-color"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should log error when unknown command used", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "abc"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("throws error if invalid option is passed with version command", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--abc"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should log error when unknown command used with --version flag", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["--version", "abc"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("throws error if invalid option is passed with --version flag", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["--version", "--abc"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should log error when unknown command used with -v alias", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["-v", "abc"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("throws error if invalid option is passed with -v alias", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["-v", "--abc"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it('should work using command syntax with the "version" value', async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it('should work using command syntax and the "--version" argument', async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--version"]); - - expect(exitCode).toBe(0); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should log an error using command syntax with unknown argument", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "--unknown"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should log an error using command syntax with unknown argument #2", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, ["version", "info", "--unknown"]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); - - it("should log an error using command syntax with multiple commands with unknown argument", async () => { - const { exitCode, stderr, stdout } = await run(__dirname, [ - "version", - "info", - "serve", - "--unknown", - ]); - - expect(exitCode).toBe(2); - expect(normalizeStderr(stderr)).toMatchSnapshot("stderr"); - expect(normalizeStdout(stdout)).toMatchSnapshot("stdout"); - }); -});