mirror of https://github.com/webpack/webpack.git
608 lines
14 KiB
JavaScript
608 lines
14 KiB
JavaScript
"use strict";
|
|
|
|
const { createColors, getArguments, isColorSupported, processArguments } =
|
|
require("../").cli;
|
|
|
|
describe("Cli", () => {
|
|
describe("getArguments", () => {
|
|
it("should generate the correct cli flags", () => {
|
|
expect(getArguments()).toMatchSnapshot();
|
|
});
|
|
|
|
it("should generate the correct cli flags with custom schema", () => {
|
|
const schema = {
|
|
title: "custom CLI options",
|
|
type: "object",
|
|
additionalProperties: false,
|
|
properties: {
|
|
"with-reset-description": {
|
|
type: "array",
|
|
items: {
|
|
type: "string"
|
|
},
|
|
description: "original description",
|
|
cli: {
|
|
resetDescription: "custom reset"
|
|
}
|
|
},
|
|
"with-cli-description": {
|
|
type: "string",
|
|
description: "original description",
|
|
cli: {
|
|
description: "description for CLI option"
|
|
}
|
|
},
|
|
"with-negative-description": {
|
|
type: "boolean",
|
|
description: "original description",
|
|
cli: {
|
|
negatedDescription: "custom negative description"
|
|
}
|
|
},
|
|
"with-both-cli-and-negative-description": {
|
|
type: "boolean",
|
|
description: "original description",
|
|
cli: {
|
|
description: "description for CLI option",
|
|
negatedDescription: "custom negative description"
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
expect(getArguments(schema)).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe("processArguments", () => {
|
|
const test = (name, values, config, fn) => {
|
|
it(`should correctly process arguments for ${name}`, () => {
|
|
const args = getArguments();
|
|
const problems = processArguments(args, config, values);
|
|
fn(expect(problems || config));
|
|
});
|
|
};
|
|
|
|
test("none", {}, {}, (e) => e.toMatchInlineSnapshot("Object {}"));
|
|
|
|
test("root boolean", { bail: true }, {}, (e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"bail": true,
|
|
}
|
|
`)
|
|
);
|
|
|
|
test("root single item of multiple", { entry: "./a.js" }, {}, (e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"entry": Array [
|
|
"./a.js",
|
|
],
|
|
}
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"root single item of multiple with existing item",
|
|
{ entry: "./a.js" },
|
|
{ entry: "./old.js" },
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"entry": Array [
|
|
"./old.js",
|
|
"./a.js",
|
|
],
|
|
}
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"root single item of multiple with existing items",
|
|
{ entry: "./a.js" },
|
|
{ entry: ["./old1.js", "./old2.js"] },
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"entry": Array [
|
|
"./old1.js",
|
|
"./old2.js",
|
|
"./a.js",
|
|
],
|
|
}
|
|
`)
|
|
);
|
|
|
|
test("root multiple items", { entry: ["./a.js", "./b.js"] }, {}, (e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"entry": Array [
|
|
"./a.js",
|
|
"./b.js",
|
|
],
|
|
}
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"root multiple items with existing item",
|
|
{ entry: ["./a.js", "./b.js"] },
|
|
{ entry: "./old.js" },
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"entry": Array [
|
|
"./old.js",
|
|
"./a.js",
|
|
"./b.js",
|
|
],
|
|
}
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"root multiple items with existing items",
|
|
{ entry: ["./a.js", "./b.js"] },
|
|
{ entry: ["./old1.js", "./old2.js"] },
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"entry": Array [
|
|
"./old1.js",
|
|
"./old2.js",
|
|
"./a.js",
|
|
"./b.js",
|
|
],
|
|
}
|
|
`)
|
|
);
|
|
|
|
test("nested boolean", { "experiments-top-level-await": true }, {}, (e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Array [
|
|
Object {
|
|
"argument": "experiments-top-level-await",
|
|
"path": "",
|
|
"type": "unknown-argument",
|
|
},
|
|
]
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"nested regexp",
|
|
{ "stats-warnings-filter": ["/module/", "path"] },
|
|
{},
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"stats": Object {
|
|
"warningsFilter": Array [
|
|
/module/,
|
|
"path",
|
|
],
|
|
},
|
|
}
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"nested multiple",
|
|
{
|
|
"module-rules-test": ["/\\.css$/", "/\\.js$/"],
|
|
"module-rules-use": ["css-loader", "babel-loader"]
|
|
},
|
|
{},
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"module": Object {
|
|
"rules": Array [
|
|
Object {
|
|
"test": /\\\\\\.css\\$/,
|
|
"use": "css-loader",
|
|
},
|
|
Object {
|
|
"test": /\\\\\\.js\\$/,
|
|
"use": "babel-loader",
|
|
},
|
|
],
|
|
},
|
|
}
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"reset array",
|
|
{
|
|
"stats-warnings-filter-reset": true,
|
|
"stats-warnings-filter": "path",
|
|
"module-rules-reset": true,
|
|
"module-rules-test": ["/\\.css$/", "/\\.js$/"],
|
|
"module-rules-use": ["css-loader", "babel-loader"]
|
|
},
|
|
{
|
|
stats: { warningsFilter: [/a/, /b/] },
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.js$/,
|
|
use: "typescript-loader"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"module": Object {
|
|
"rules": Array [
|
|
Object {
|
|
"test": /\\\\\\.css\\$/,
|
|
"use": "css-loader",
|
|
},
|
|
Object {
|
|
"test": /\\\\\\.js\\$/,
|
|
"use": "babel-loader",
|
|
},
|
|
],
|
|
},
|
|
"stats": Object {
|
|
"warningsFilter": Array [
|
|
"path",
|
|
],
|
|
},
|
|
}
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"numbers",
|
|
{
|
|
"watch-options-aggregate-timeout": 100,
|
|
"watch-options-poll": "100",
|
|
"output-chunk-load-timeout": "20000"
|
|
},
|
|
{},
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"output": Object {
|
|
"chunkLoadTimeout": 20000,
|
|
},
|
|
"watchOptions": Object {
|
|
"aggregateTimeout": 100,
|
|
"poll": 100,
|
|
},
|
|
}
|
|
`)
|
|
);
|
|
|
|
test(
|
|
"booleans and enums",
|
|
{
|
|
"optimization-used-exports": true,
|
|
"output-compare-before-emit": false,
|
|
"output-iife": "true",
|
|
"output-library-name": ["hello", "world"],
|
|
"output-library-umd-named-define": "false",
|
|
"stats-logging": "verbose",
|
|
amd: "false"
|
|
},
|
|
{},
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Object {
|
|
"amd": false,
|
|
"optimization": Object {
|
|
"usedExports": true,
|
|
},
|
|
"output": Object {
|
|
"compareBeforeEmit": false,
|
|
"iife": true,
|
|
"library": Object {
|
|
"name": Array [
|
|
"hello",
|
|
"world",
|
|
],
|
|
"umdNamedDefine": false,
|
|
},
|
|
},
|
|
"stats": Object {
|
|
"logging": "verbose",
|
|
},
|
|
}
|
|
`)
|
|
);
|
|
|
|
// cspell:ignore filsystem
|
|
test(
|
|
"errors",
|
|
{
|
|
"output-library-name": "non-object",
|
|
"resolve-loader-unsafe-cache": [true, false],
|
|
"output-chunk-load-timeout": "20000x",
|
|
"cache-type": "filsystem",
|
|
"entry-reset": false,
|
|
"module-unknown-context-reg-exp": "ab?c*",
|
|
"module-wrapped-context-reg-exp": 123,
|
|
"my-argument": true
|
|
},
|
|
{
|
|
output: {
|
|
library: "hello"
|
|
}
|
|
},
|
|
(e) =>
|
|
e.toMatchInlineSnapshot(`
|
|
Array [
|
|
Object {
|
|
"argument": "output-library-name",
|
|
"index": undefined,
|
|
"path": "output",
|
|
"type": "unexpected-non-object-in-path",
|
|
"value": "non-object",
|
|
},
|
|
Object {
|
|
"argument": "resolve-loader-unsafe-cache",
|
|
"index": 0,
|
|
"path": "resolveLoader.unsafeCache",
|
|
"type": "multiple-values-unexpected",
|
|
"value": true,
|
|
},
|
|
Object {
|
|
"argument": "resolve-loader-unsafe-cache",
|
|
"index": 1,
|
|
"path": "resolveLoader.unsafeCache",
|
|
"type": "multiple-values-unexpected",
|
|
"value": false,
|
|
},
|
|
Object {
|
|
"argument": "output-chunk-load-timeout",
|
|
"expected": "number",
|
|
"index": undefined,
|
|
"path": "output.chunkLoadTimeout",
|
|
"type": "invalid-value",
|
|
"value": "20000x",
|
|
},
|
|
Object {
|
|
"argument": "cache-type",
|
|
"expected": "memory",
|
|
"index": undefined,
|
|
"path": "cache.type",
|
|
"type": "invalid-value",
|
|
"value": "filsystem",
|
|
},
|
|
Object {
|
|
"argument": "cache-type",
|
|
"expected": "filesystem",
|
|
"index": undefined,
|
|
"path": "cache.type",
|
|
"type": "invalid-value",
|
|
"value": "filsystem",
|
|
},
|
|
Object {
|
|
"argument": "entry-reset",
|
|
"expected": "true (will reset the previous value to an empty array)",
|
|
"index": undefined,
|
|
"path": "entry",
|
|
"type": "invalid-value",
|
|
"value": false,
|
|
},
|
|
Object {
|
|
"argument": "module-unknown-context-reg-exp",
|
|
"expected": "regular expression (example: /ab?c*/)",
|
|
"index": undefined,
|
|
"path": "module.unknownContextRegExp",
|
|
"type": "invalid-value",
|
|
"value": "ab?c*",
|
|
},
|
|
Object {
|
|
"argument": "module-unknown-context-reg-exp",
|
|
"expected": "true | false",
|
|
"index": undefined,
|
|
"path": "module.unknownContextRegExp",
|
|
"type": "invalid-value",
|
|
"value": "ab?c*",
|
|
},
|
|
Object {
|
|
"argument": "module-wrapped-context-reg-exp",
|
|
"expected": "regular expression (example: /ab?c*/)",
|
|
"index": undefined,
|
|
"path": "module.wrappedContextRegExp",
|
|
"type": "invalid-value",
|
|
"value": 123,
|
|
},
|
|
Object {
|
|
"argument": "my-argument",
|
|
"path": "",
|
|
"type": "unknown-argument",
|
|
},
|
|
]
|
|
`)
|
|
);
|
|
});
|
|
|
|
describe("isColorSupported", () => {
|
|
const OLD_ENV = process.env;
|
|
|
|
beforeEach(() => {
|
|
// Most important - it clears the cache
|
|
jest.resetModules();
|
|
process.env = { ...OLD_ENV };
|
|
// Prevent `process.env.FORCE_COLOR` from being auto set by `jest-worker`
|
|
if (OLD_ENV.FORCE_COLOR) {
|
|
delete process.env.FORCE_COLOR;
|
|
}
|
|
// Prevent `process.env.TERM` default value
|
|
if (OLD_ENV.TERM) {
|
|
delete process.env.TERM;
|
|
}
|
|
});
|
|
|
|
afterAll(() => {
|
|
process.env = OLD_ENV;
|
|
});
|
|
|
|
it("env NO_COLOR", () => {
|
|
process.env.NO_COLOR = "1";
|
|
|
|
expect(isColorSupported()).toBe(false);
|
|
});
|
|
|
|
it("env FORCE_COLOR", () => {
|
|
process.env.FORCE_COLOR = "1";
|
|
|
|
expect(isColorSupported()).toBe(true);
|
|
});
|
|
|
|
it("env TERM", () => {
|
|
const isCI =
|
|
"CI" in process.env &&
|
|
("GITHUB_ACTIONS" in process.env ||
|
|
"GITLAB_CI" in process.env ||
|
|
"CIRCLECI" in process.env);
|
|
|
|
process.env.TERM = "dumb";
|
|
|
|
expect(isColorSupported()).toBe(isCI);
|
|
});
|
|
|
|
it("env GITHUB_ACTIONS", () => {
|
|
process.env.CI = "1";
|
|
process.env.GITHUB_ACTIONS = "1";
|
|
|
|
expect(isColorSupported()).toBe(true);
|
|
});
|
|
|
|
it("env GITLAB_CI", () => {
|
|
process.env.CI = "1";
|
|
process.env.GITLAB_CI = "1";
|
|
|
|
expect(isColorSupported()).toBe(true);
|
|
});
|
|
|
|
it("env CIRCLECI", () => {
|
|
process.env.CI = "1";
|
|
process.env.CIRCLECI = "1";
|
|
|
|
expect(isColorSupported()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("createColors", () => {
|
|
const colorsMap = [
|
|
["reset", "\u001B[0m", "\u001B[0m"],
|
|
["bold", "\u001B[1m", "\u001B[22m"],
|
|
["dim", "\u001B[2m", "\u001B[22m"],
|
|
["italic", "\u001B[3m", "\u001B[23m"],
|
|
["underline", "\u001B[4m", "\u001B[24m"],
|
|
["inverse", "\u001B[7m", "\u001B[27m"],
|
|
["hidden", "\u001B[8m", "\u001B[28m"],
|
|
["strikethrough", "\u001B[9m", "\u001B[29m"],
|
|
["black", "\u001B[30m", "\u001B[39m"],
|
|
["red", "\u001B[31m", "\u001B[39m"],
|
|
["green", "\u001B[32m", "\u001B[39m"],
|
|
["yellow", "\u001B[33m", "\u001B[39m"],
|
|
["blue", "\u001B[34m", "\u001B[39m"],
|
|
["magenta", "\u001B[35m", "\u001B[39m"],
|
|
["cyan", "\u001B[36m", "\u001B[39m"],
|
|
["white", "\u001B[37m", "\u001B[39m"],
|
|
["gray", "\u001B[90m", "\u001B[39m"],
|
|
["bgBlack", "\u001B[40m", "\u001B[49m"],
|
|
["bgRed", "\u001B[41m", "\u001B[49m"],
|
|
["bgGreen", "\u001B[42m", "\u001B[49m"],
|
|
["bgYellow", "\u001B[43m", "\u001B[49m"],
|
|
["bgBlue", "\u001B[44m", "\u001B[49m"],
|
|
["bgMagenta", "\u001B[45m", "\u001B[49m"],
|
|
["bgCyan", "\u001B[46m", "\u001B[49m"],
|
|
["bgWhite", "\u001B[47m", "\u001B[49m"],
|
|
["blackBright", "\u001B[90m", "\u001B[39m"],
|
|
["redBright", "\u001B[91m", "\u001B[39m"],
|
|
["greenBright", "\u001B[92m", "\u001B[39m"],
|
|
["yellowBright", "\u001B[93m", "\u001B[39m"],
|
|
["blueBright", "\u001B[94m", "\u001B[39m"],
|
|
["magentaBright", "\u001B[95m", "\u001B[39m"],
|
|
["cyanBright", "\u001B[96m", "\u001B[39m"],
|
|
["whiteBright", "\u001B[97m", "\u001B[39m"],
|
|
["bgBlackBright", "\u001B[100m", "\u001B[49m"],
|
|
["bgRedBright", "\u001B[101m", "\u001B[49m"],
|
|
["bgGreenBright", "\u001B[102m", "\u001B[49m"],
|
|
["bgYellowBright", "\u001B[103m", "\u001B[49m"],
|
|
["bgBlueBright", "\u001B[104m", "\u001B[49m"],
|
|
["bgMagentaBright", "\u001B[105m", "\u001B[49m"],
|
|
["bgCyanBright", "\u001B[106m", "\u001B[49m"],
|
|
["bgWhiteBright", "\u001B[107m", "\u001B[49m"]
|
|
];
|
|
|
|
const colors = createColors({ useColor: true });
|
|
|
|
it("simple", () => {
|
|
for (const [name, open, close] of colorsMap) {
|
|
expect(colors[name](name)).toBe(open + name + close);
|
|
}
|
|
});
|
|
|
|
it("nesting", () => {
|
|
expect(
|
|
colors.bold(`bold ${colors.red(`red ${colors.dim("dim")} red`)} bold`)
|
|
).toBe(
|
|
/* cspell:disable-next-line */
|
|
"\u001B[1mbold \u001B[31mred \u001B[2mdim\u001B[22m\u001B[1m red\u001B[39m bold\u001B[22m"
|
|
);
|
|
expect(
|
|
colors.magenta(
|
|
`magenta ${colors.yellow(
|
|
`yellow ${colors.cyan("cyan")} ${colors.red("red")} ${colors.green(
|
|
"green"
|
|
)} yellow`
|
|
)} magenta`
|
|
)
|
|
).toBe(
|
|
/* cspell:disable-next-line */
|
|
"\u001B[35mmagenta \u001B[33myellow \u001B[36mcyan\u001B[33m \u001B[31mred\u001B[33m \u001B[32mgreen\u001B[33m yellow\u001B[35m magenta\u001B[39m"
|
|
);
|
|
});
|
|
|
|
it("numbers & others", () => {
|
|
for (const n of [new Date(), -1e10, -1, -0.1, 0, 0.1, 1, 1e10]) {
|
|
expect(colors.red(n)).toBe(`\u001B[31m${n}\u001B[39m`);
|
|
}
|
|
});
|
|
|
|
it("empty & falsy values", () => {
|
|
expect(colors.blue()).toBe("");
|
|
expect(colors.blue("")).toBe("");
|
|
expect(colors.blue(undefined)).toBe("");
|
|
expect(colors.blue(0)).toBe("\u001B[34m0\u001B[39m");
|
|
// eslint-disable-next-line unicorn/prefer-number-properties
|
|
expect(colors.blue(NaN)).toBe("\u001B[34mNaN\u001B[39m");
|
|
expect(colors.blue(Number.NaN)).toBe("\u001B[34mNaN\u001B[39m");
|
|
/* cspell:disable-next-line */
|
|
expect(colors.blue(null)).toBe("\u001B[34mnull\u001B[39m");
|
|
/* cspell:disable-next-line */
|
|
expect(colors.blue(true)).toBe("\u001B[34mtrue\u001B[39m");
|
|
/* cspell:disable-next-line */
|
|
expect(colors.blue(false)).toBe("\u001B[34mfalse\u001B[39m");
|
|
expect(colors.blue(Infinity)).toBe("\u001B[34mInfinity\u001B[39m");
|
|
});
|
|
|
|
const noColors = createColors({ useColor: false });
|
|
|
|
it("simple (no colors)", () => {
|
|
for (const [name] of colorsMap) {
|
|
expect(noColors[name](name)).toBe(name);
|
|
}
|
|
});
|
|
|
|
const defaultColors = createColors();
|
|
|
|
it("simple (colors by default)", () => {
|
|
for (const [name, open, close] of colorsMap) {
|
|
expect(defaultColors[name](name)).toBe(open + name + close);
|
|
}
|
|
});
|
|
});
|
|
});
|