* Verify that ESLint class receives correct opts via await cli.execute().
* @param {string} cmd CLI command.
* @param {Object} opts Options hash that should match that received by ESLint class.
+ * @param {string} configType The config type to work with.
* @returns {void}
*/
- async function verifyESLintOpts(cmd, opts) {
+ async function verifyESLintOpts(cmd, opts, configType) {
// create a fake ESLint class to test with
const fakeESLint = sinon.mock().withExactArgs(sinon.match(opts));
const localCLI = proxyquire("../../lib/cli", {
"./eslint": { ESLint: fakeESLint },
+ "./flat-eslint": { FlatESLint: fakeESLint, findFlatConfigFile: () => null },
"./shared/logging": log
});
- await localCLI.execute(cmd);
+ await localCLI.execute(cmd, null, configType === "flat");
sinon.verifyAndRestore();
}
sh.rm("-r", fixtureDir);
});
- describe("execute()", () => {
- it("should return error when text with incorrect quotes is passed as argument", async () => {
- const configFile = getFixturePath("configurations", "quotes-error.json");
- const result = await cli.execute(`-c ${configFile}`, "var foo = 'bar';");
+ ["eslintrc", "flat"].forEach(configType => {
- assert.strictEqual(result, 1);
- });
+ const useFlatConfig = configType === "flat";
- it("should not print debug info when passed the empty string as text", async () => {
- const result = await cli.execute(["--stdin", "--no-eslintrc"], "");
+ describe("execute()", () => {
- assert.strictEqual(result, 0);
- assert.isTrue(log.info.notCalled);
- });
+ it(`should return error when text with incorrect quotes is passed as argument with configType:${configType}`, async () => {
+ const configFile = getFixturePath("configurations", "quotes-error.js");
+ const result = await cli.execute(`-c ${configFile} --stdin --stdin-filename foo.js`, "var foo = 'bar';", useFlatConfig);
- it("should return no error when --ext .js2 is specified", async () => {
- const filePath = getFixturePath("files");
- const result = await cli.execute(`--ext .js2 ${filePath}`);
+ assert.strictEqual(result, 1);
+ });
- assert.strictEqual(result, 0);
- });
+ it(`should not print debug info when passed the empty string as text with configType:${configType}`, async () => {
+ const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+ const result = await cli.execute(["--stdin", flag, "--stdin-filename", "foo.js"], "", useFlatConfig);
- it("should exit with console error when passed unsupported arguments", async () => {
- const filePath = getFixturePath("files");
- const result = await cli.execute(`--blah --another ${filePath}`);
+ assert.strictEqual(result, 0);
+ assert.isTrue(log.info.notCalled);
+ });
+
+ it(`should exit with console error when passed unsupported arguments with configType:${configType}`, async () => {
+ const filePath = getFixturePath("files");
+ const result = await cli.execute(`--blah --another ${filePath}`, null, useFlatConfig);
+
+ assert.strictEqual(result, 2);
+ });
- assert.strictEqual(result, 2);
});
- });
+ describe("when given a config with rules with options and severity level set to error", () => {
- describe("when given a config file", () => {
- it("should load the specified config file", async () => {
- const configPath = getFixturePath(".eslintrc");
- const filePath = getFixturePath("passing.js");
+ const originalCwd = process.cwd;
- await cli.execute(`--config ${configPath} ${filePath}`);
- });
- });
+ beforeEach(() => {
+ process.cwd = () => getFixturePath();
+ });
- describe("when there is a local config file", () => {
- const code = "lib/cli.js";
+ afterEach(() => {
+ process.cwd = originalCwd;
+ });
+
+ it(`should exit with an error status (1) with configType:${configType}`, async () => {
+ const configPath = getFixturePath("configurations", "quotes-error.js");
+ const filePath = getFixturePath("single-quoted.js");
+ const code = `--no-ignore --config ${configPath} ${filePath}`;
- it("should load the local config file", async () => {
+ const exitStatus = await cli.execute(code, null, useFlatConfig);
- // Mock CWD
- process.eslintCwd = getFixturePath("configurations", "single-quotes");
+ assert.strictEqual(exitStatus, 1);
+ });
+ });
- await cli.execute(code);
+ describe("when given a config file and a directory of files", () => {
+ it(`should load and execute without error with configType:${configType}`, async () => {
+ const configPath = getFixturePath("configurations", "semi-error.js");
+ const filePath = getFixturePath("formatters");
+ const code = `--config ${configPath} ${filePath}`;
+ const exitStatus = await cli.execute(code, null, useFlatConfig);
- process.eslintCwd = null;
+ assert.strictEqual(exitStatus, 0);
+ });
});
- });
- describe("when given a config with rules with options and severity level set to error", () => {
- it("should exit with an error status (1)", async () => {
- const configPath = getFixturePath("configurations", "quotes-error.json");
- const filePath = getFixturePath("single-quoted.js");
- const code = `--no-ignore --config ${configPath} ${filePath}`;
+ describe("when there is a local config file", () => {
+
+ it(`should load the local config file with configType:${configType}`, async () => {
+ await cli.execute("lib/cli.js", null, useFlatConfig);
+ });
- const exitStatus = await cli.execute(code);
+ if (useFlatConfig) {
+ it(`should load the local config file with glob pattern and configType:${configType}`, async () => {
+ await cli.execute("lib/cli*.js", null, useFlatConfig);
+ });
+ }
- assert.strictEqual(exitStatus, 1);
+ // only works on Windows
+ if (os.platform() === "win32") {
+ it(`should load the local config file with Windows slashes glob pattern and configType:${configType}`, async () => {
+ await cli.execute("lib\\cli*.js", null, useFlatConfig);
+ });
+ }
});
- });
- describe("when given a config file and a directory of files", () => {
- it("should load and execute without error", async () => {
- const configPath = getFixturePath("configurations", "semi-error.json");
- const filePath = getFixturePath("formatters");
- const code = `--config ${configPath} ${filePath}`;
+ describe("Formatters", () => {
- const exitStatus = await cli.execute(code);
+ describe("when given a valid built-in formatter name", () => {
+ it(`should execute without any errors with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing.js");
+ const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+ const exit = await cli.execute(`${flag} -f checkstyle ${filePath}`, null, useFlatConfig);
- assert.strictEqual(exitStatus, 0);
- });
- });
+ assert.strictEqual(exit, 0);
+ });
+ });
- describe("when given a config with environment set to browser", () => {
- it("should execute without any errors", async () => {
- const configPath = getFixturePath("configurations", "env-browser.json");
- const filePath = getFixturePath("globals-browser.js");
- const code = `--config ${configPath} ${filePath}`;
+ describe("when given a valid built-in formatter name that uses rules meta.", () => {
+
+ const originalCwd = process.cwd;
+
+ beforeEach(() => {
+ process.cwd = () => getFixturePath();
+ });
+
+ afterEach(() => {
+ process.cwd = originalCwd;
+ });
+
+ it(`should execute without any errors with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing.js");
+ const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+ const exit = await cli.execute(`--no-ignore -f json-with-metadata ${filePath} ${flag}`, null, useFlatConfig);
+
+ assert.strictEqual(exit, 0);
+
+ /*
+ * Note: There is a behavior difference between eslintrc and flat config
+ * when using formatters. For eslintrc, rulesMeta always contains every
+ * rule that was loaded during the last run; for flat config, rulesMeta
+ * only contains meta data for the rules that triggered messages in the
+ * results. (Flat config uses ESLint#getRulesMetaForResults().)
+ */
+
+ // Check metadata.
+ const { metadata } = JSON.parse(log.info.args[0][0]);
+ const expectedMetadata = {
+ cwd: process.cwd(),
+ rulesMeta: useFlatConfig ? {} : Array.from(BuiltinRules).reduce((obj, [ruleId, rule]) => {
+ obj[ruleId] = rule.meta;
+ return obj;
+ }, {})
+ };
+
+ assert.deepStrictEqual(metadata, expectedMetadata);
+ });
+ });
- const exit = await cli.execute(code);
+ describe("when given an invalid built-in formatter name", () => {
+ it(`should execute with error: with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing.js");
+ const exit = await cli.execute(`-f fakeformatter ${filePath}`);
- assert.strictEqual(exit, 0);
- });
- });
+ assert.strictEqual(exit, 2);
+ });
+ });
- describe("when given a config with environment set to Node.js", () => {
- it("should execute without any errors", async () => {
- const configPath = getFixturePath("configurations", "env-node.json");
- const filePath = getFixturePath("globals-node.js");
- const code = `--config ${configPath} ${filePath}`;
+ describe("when given a valid formatter path", () => {
+ it(`should execute without any errors with configType:${configType}`, async () => {
+ const formatterPath = getFixturePath("formatters", "simple.js");
+ const filePath = getFixturePath("passing.js");
+ const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
- const exit = await cli.execute(code);
+ assert.strictEqual(exit, 0);
+ });
+ });
- assert.strictEqual(exit, 0);
- });
- });
+ describe("when given an invalid formatter path", () => {
+ it(`should execute with error with configType:${configType}`, async () => {
+ const formatterPath = getFixturePath("formatters", "file-does-not-exist.js");
+ const filePath = getFixturePath("passing.js");
+ const exit = await cli.execute(`-f ${formatterPath} ${filePath}`, null, useFlatConfig);
- describe("when given a config with environment set to Nashorn", () => {
- it("should execute without any errors", async () => {
- const configPath = getFixturePath("configurations", "env-nashorn.json");
- const filePath = getFixturePath("globals-nashorn.js");
- const code = `--config ${configPath} ${filePath}`;
+ assert.strictEqual(exit, 2);
+ });
+ });
- const exit = await cli.execute(code);
+ describe("when given an async formatter path", () => {
+ it(`should execute without any errors with configType:${configType}`, async () => {
+ const formatterPath = getFixturePath("formatters", "async.js");
+ const filePath = getFixturePath("passing.js");
+ const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
- assert.strictEqual(exit, 0);
+ assert.strictEqual(log.info.getCall(0).args[0], "from async formatter");
+ assert.strictEqual(exit, 0);
+ });
+ });
});
- });
- describe("when given a config with environment set to WebExtensions", () => {
- it("should execute without any errors", async () => {
- const configPath = getFixturePath("configurations", "env-webextensions.json");
- const filePath = getFixturePath("globals-webextensions.js");
- const code = `--config ${configPath} ${filePath}`;
+ describe("Exit Codes", () => {
- const exit = await cli.execute(code);
+ const originalCwd = process.cwd;
- assert.strictEqual(exit, 0);
- });
- });
+ beforeEach(() => {
+ process.cwd = () => getFixturePath();
+ });
- describe("when given a valid built-in formatter name", () => {
- it("should execute without any errors", async () => {
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`-f checkstyle ${filePath}`);
+ afterEach(() => {
+ process.cwd = originalCwd;
+ });
- assert.strictEqual(exit, 0);
- });
- });
+ describe("when executing a file with a lint error", () => {
- describe("when given a valid built-in formatter name that uses rules meta.", () => {
- it("should execute without any errors", async () => {
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`-f json-with-metadata ${filePath} --no-eslintrc`);
+ it(`should exit with error with configType:${configType}`, async () => {
+ const filePath = getFixturePath("undef.js");
+ const code = `--no-ignore --rule no-undef:2 ${filePath}`;
- assert.strictEqual(exit, 0);
+ const exit = await cli.execute(code, null, useFlatConfig);
- // Check metadata.
- const { metadata } = JSON.parse(log.info.args[0][0]);
- const expectedMetadata = {
- cwd: process.cwd(),
- rulesMeta: Array.from(BuiltinRules).reduce((obj, [ruleId, rule]) => {
- obj[ruleId] = rule.meta;
- return obj;
- }, {})
- };
+ assert.strictEqual(exit, 1);
+ });
+ });
- assert.deepStrictEqual(metadata, expectedMetadata);
- });
- });
+ describe("when using --fix-type without --fix or --fix-dry-run", () => {
+ it(`should exit with error with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing.js");
+ const code = `--fix-type suggestion ${filePath}`;
- describe("when given an invalid built-in formatter name", () => {
- it("should execute with error", async () => {
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`-f fakeformatter ${filePath}`);
+ const exit = await cli.execute(code, null, useFlatConfig);
- assert.strictEqual(exit, 2);
- });
- });
+ assert.strictEqual(exit, 2);
+ });
+ });
- describe("when given a valid formatter path", () => {
- it("should execute without any errors", async () => {
- const formatterPath = getFixturePath("formatters", "simple.js");
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
+ describe("when executing a file with a syntax error", () => {
+ it(`should exit with error with configType:${configType}`, async () => {
+ const filePath = getFixturePath("syntax-error.js");
+ const exit = await cli.execute(`--no-ignore ${filePath}`, null, useFlatConfig);
+
+ assert.strictEqual(exit, 1);
+ });
+ });
- assert.strictEqual(exit, 0);
});
- });
- describe("when given an invalid formatter path", () => {
- it("should execute with error", async () => {
- const formatterPath = getFixturePath("formatters", "file-does-not-exist.js");
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
+ describe("when calling execute more than once", () => {
- assert.strictEqual(exit, 2);
- });
- });
+ const originalCwd = process.cwd;
- describe("when given an async formatter path", () => {
- it("should execute without any errors", async () => {
- const formatterPath = getFixturePath("formatters", "async.js");
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
+ beforeEach(() => {
+ process.cwd = () => getFixturePath();
+ });
- assert.strictEqual(log.info.getCall(0).args[0], "from async formatter");
- assert.strictEqual(exit, 0);
- });
- });
+ afterEach(() => {
+ process.cwd = originalCwd;
+ });
- describe("when executing a file with a lint error", () => {
- it("should exit with error", async () => {
- const filePath = getFixturePath("undef.js");
- const code = `--no-ignore --rule no-undef:2 ${filePath}`;
+ it(`should not print the results from previous execution with configType:${configType}`, async () => {
+ const filePath = getFixturePath("missing-semicolon.js");
+ const passingPath = getFixturePath("passing.js");
- const exit = await cli.execute(code);
+ await cli.execute(`--no-ignore --rule semi:2 ${filePath}`, null, useFlatConfig);
- assert.strictEqual(exit, 1);
- });
- });
+ assert.isTrue(log.info.called, "Log should have been called.");
- describe("when using --fix-type without --fix or --fix-dry-run", () => {
- it("should exit with error", async () => {
- const filePath = getFixturePath("passing.js");
- const code = `--fix-type suggestion ${filePath}`;
+ log.info.resetHistory();
- const exit = await cli.execute(code);
+ await cli.execute(`--no-ignore --rule semi:2 ${passingPath}`, null, useFlatConfig);
+ assert.isTrue(log.info.notCalled);
- assert.strictEqual(exit, 2);
+ });
});
- });
- describe("when executing a file with a syntax error", () => {
- it("should exit with error", async () => {
- const filePath = getFixturePath("syntax-error.js");
- const exit = await cli.execute(`--no-ignore ${filePath}`);
-
- assert.strictEqual(exit, 1);
+ describe("when executing with version flag", () => {
+ it(`should print out current version with configType:${configType}`, async () => {
+ assert.strictEqual(await cli.execute("-v", null, useFlatConfig), 0);
+ assert.strictEqual(log.info.callCount, 1);
+ });
});
- });
- describe("when calling execute more than once", () => {
- it("should not print the results from previous execution", async () => {
- const filePath = getFixturePath("missing-semicolon.js");
- const passingPath = getFixturePath("passing.js");
+ describe("when executing with env-info flag", () => {
- await cli.execute(`--no-ignore --rule semi:2 ${filePath}`);
+ it(`should print out environment information with configType:${configType}`, async () => {
+ assert.strictEqual(await cli.execute("--env-info", null, useFlatConfig), 0);
+ assert.strictEqual(log.info.callCount, 1);
+ });
- assert.isTrue(log.info.called, "Log should have been called.");
+ describe("With error condition", () => {
- log.info.resetHistory();
+ beforeEach(() => {
+ RuntimeInfo.environment = sinon.stub().throws("There was an error!");
+ });
- await cli.execute(`--no-ignore --rule semi:2 ${passingPath}`);
- assert.isTrue(log.info.notCalled);
+ afterEach(() => {
+ RuntimeInfo.environment = sinon.stub();
+ });
- });
- });
+ it(`should print error message and return error code with configType:${configType}`, async () => {
+
+ assert.strictEqual(await cli.execute("--env-info", null, useFlatConfig), 2);
+ assert.strictEqual(log.error.callCount, 1);
+ });
+ });
- describe("when executing with version flag", () => {
- it("should print out current version", async () => {
- assert.strictEqual(await cli.execute("-v"), 0);
- assert.strictEqual(log.info.callCount, 1);
});
- });
- describe("when executing with env-info flag", () => {
- it("should print out environment information", async () => {
- assert.strictEqual(await cli.execute("--env-info"), 0);
- assert.strictEqual(log.info.callCount, 1);
+ describe("when executing with help flag", () => {
+ it(`should print out help with configType:${configType}`, async () => {
+ assert.strictEqual(await cli.execute("-h", null, useFlatConfig), 0);
+ assert.strictEqual(log.info.callCount, 1);
+ });
});
- it("should print error message and return error code", async () => {
- RuntimeInfo.environment.throws("There was an error!");
+ describe("when executing a file with a shebang", () => {
+ it(`should execute without error with configType:${configType}`, async () => {
+ const filePath = getFixturePath("shebang.js");
+ const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+ const exit = await cli.execute(`${flag} --no-ignore ${filePath}`, null, useFlatConfig);
- assert.strictEqual(await cli.execute("--env-info"), 2);
- assert.strictEqual(log.error.callCount, 1);
+ assert.strictEqual(exit, 0);
+ });
});
- });
- describe("when executing without no-error-on-unmatched-pattern flag", () => {
- it("should throw an error on unmatched glob pattern", async () => {
- const filePath = getFixturePath("unmatched-patterns");
- const globPattern = "*.js3";
+ describe("FixtureDir Dependent Tests", () => {
- await stdAssert.rejects(async () => {
- await cli.execute(`"${filePath}/${globPattern}"`);
- }, new Error(`No files matching '${filePath}/${globPattern}' were found.`));
- });
+ const originalCwd = process.cwd;
- it("should throw an error on unmatched --ext", async () => {
- const filePath = getFixturePath("unmatched-patterns");
- const extension = ".js3";
+ beforeEach(() => {
+ process.cwd = () => getFixturePath();
+ });
- await stdAssert.rejects(async () => {
- await cli.execute(`--ext ${extension} ${filePath}`);
- }, `No files matching '${filePath}' were found`);
- });
- });
+ afterEach(() => {
+ process.cwd = originalCwd;
+ });
- describe("when executing with no-error-on-unmatched-pattern flag", () => {
- it("should not throw an error on unmatched node glob syntax patterns", async () => {
- const filePath = getFixturePath("unmatched-patterns");
- const exit = await cli.execute(`--no-error-on-unmatched-pattern "${filePath}/*.js3"`);
+ describe("when executing with global flag", () => {
- assert.strictEqual(exit, 0);
- });
+ it(`should default defined variables to read-only with configType:${configType}`, async () => {
+ const filePath = getFixturePath("undef.js");
+ const exit = await cli.execute(`--global baz,bat --no-ignore --rule no-global-assign:2 ${filePath}`, null, useFlatConfig);
- it("should not throw an error on unmatched --ext", async () => {
- const filePath = getFixturePath("unmatched-patterns");
- const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 ${filePath}`);
+ assert.isTrue(log.info.calledOnce);
+ assert.strictEqual(exit, 1);
+ });
- assert.strictEqual(exit, 0);
- });
- });
+ it(`should allow defining writable global variables with configType:${configType}`, async () => {
+ const filePath = getFixturePath("undef.js");
+ const exit = await cli.execute(`--global baz:false,bat:true --no-ignore ${filePath}`, null, useFlatConfig);
- describe("when executing with no-error-on-unmatched-pattern flag and multiple patterns", () => {
- it("should not throw an error on multiple unmatched node glob syntax patterns", async () => {
- const filePath = getFixturePath("unmatched-patterns");
- const exit = await cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js4`);
+ assert.isTrue(log.info.notCalled);
+ assert.strictEqual(exit, 0);
+ });
- assert.strictEqual(exit, 0);
- });
+ it(`should allow defining variables with multiple flags with configType:${configType}`, async () => {
+ const filePath = getFixturePath("undef.js");
+ const exit = await cli.execute(`--global baz --global bat:true --no-ignore ${filePath}`);
- it("should still throw an error on when a matched pattern has lint errors", async () => {
- const filePath = getFixturePath("unmatched-patterns");
- const exit = await cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js`);
+ assert.isTrue(log.info.notCalled);
+ assert.strictEqual(exit, 0);
+ });
+ });
- assert.strictEqual(exit, 1);
- });
- });
- describe("when executing with no-error-on-unmatched-pattern flag and multiple --ext arguments", () => {
- it("should not throw an error on multiple unmatched --ext arguments", async () => {
- const filePath = getFixturePath("unmatched-patterns");
- const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js4 ${filePath}`);
+ describe("when supplied with rule flag and severity level set to error", () => {
- assert.strictEqual(exit, 0);
- });
- it("should still throw an error on when a matched pattern has lint errors", async () => {
- const filePath = getFixturePath("unmatched-patterns");
- const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js ${filePath}`);
+ it(`should exit with an error status (2) with configType:${configType}`, async () => {
+ const filePath = getFixturePath("single-quoted.js");
+ const code = `--no-ignore --rule 'quotes: [2, double]' ${filePath}`;
+ const exitStatus = await cli.execute(code, null, useFlatConfig);
- assert.strictEqual(exit, 1);
- });
- });
+ assert.strictEqual(exitStatus, 1);
+ });
+ });
- describe("when executing with help flag", () => {
- it("should print out help", async () => {
- assert.strictEqual(await cli.execute("-h"), 0);
- assert.strictEqual(log.info.callCount, 1);
- });
- });
+ describe("when the quiet option is enabled", () => {
- describe("when given a directory with eslint excluded files in the directory", () => {
- it("should throw an error and not process any files", async () => {
- const ignorePath = getFixturePath(".eslintignore");
- const filePath = getFixturePath("cli");
+ it(`should only print error with configType:${configType}`, async () => {
+ const filePath = getFixturePath("single-quoted.js");
+ const cliArgs = `--no-ignore --quiet -f compact --rule 'quotes: [2, double]' --rule 'no-unused-vars: 1' ${filePath}`;
- await stdAssert.rejects(async () => {
- await cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
- }, new Error(`All files matched by '${filePath}' are ignored.`));
- });
- });
+ await cli.execute(cliArgs, null, useFlatConfig);
- describe("when given a file in excluded files list", () => {
- it("should not process the file", async () => {
- const ignorePath = getFixturePath(".eslintignore");
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
+ sinon.assert.calledOnce(log.info);
- // a warning about the ignored file
- assert.isTrue(log.info.called);
- assert.strictEqual(exit, 0);
- });
+ const formattedOutput = log.info.firstCall.args[0];
- it("should process the file when forced", async () => {
- const ignorePath = getFixturePath(".eslintignore");
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`--ignore-path ${ignorePath} --no-ignore ${filePath}`);
+ assert.include(formattedOutput, "Error");
+ assert.notInclude(formattedOutput, "Warning");
+ });
- // no warnings
- assert.isFalse(log.info.called);
- assert.strictEqual(exit, 0);
- });
- });
+ it(`should print nothing if there are no errors with configType:${configType}`, async () => {
+ const filePath = getFixturePath("single-quoted.js");
+ const cliArgs = `--quiet -f compact --rule 'quotes: [1, double]' --rule 'no-unused-vars: 1' ${filePath}`;
- describe("when given a pattern to ignore", () => {
- it("should not process any files", async () => {
- const ignoredFile = getFixturePath("cli/syntax-error.js");
- const filePath = getFixturePath("cli/passing.js");
- const exit = await cli.execute(`--ignore-pattern cli/ ${ignoredFile} ${filePath}`);
+ await cli.execute(cliArgs, null, useFlatConfig);
- // warnings about the ignored files
- assert.isTrue(log.info.called);
- assert.strictEqual(exit, 0);
- });
- });
+ sinon.assert.notCalled(log.info);
+ });
+ });
- describe("when given patterns to ignore", () => {
- it("should not process any matching files", async () => {
- const ignorePaths = ["a", "b"];
- const cmd = ignorePaths.map(ignorePath => `--ignore-pattern ${ignorePath}`).concat(".").join(" ");
+ describe("no-error-on-unmatched-pattern flag", () => {
- const opts = {
- overrideConfig: {
- ignorePatterns: ignorePaths
- }
- };
+ describe("when executing without no-error-on-unmatched-pattern flag", () => {
+ it(`should throw an error on unmatched glob pattern with configType:${configType}`, async () => {
+ let filePath = getFixturePath("unmatched-patterns");
+ const globPattern = "unmatched*.js";
- await verifyESLintOpts(cmd, opts);
- });
- });
+ if (useFlatConfig) {
+ filePath = filePath.replace(/\\/gu, "/");
+ }
- describe("when executing a file with a shebang", () => {
- it("should execute without error", async () => {
- const filePath = getFixturePath("shebang.js");
- const exit = await cli.execute(`--no-ignore ${filePath}`);
+ await stdAssert.rejects(async () => {
+ await cli.execute(`"${filePath}/${globPattern}"`, null, useFlatConfig);
+ }, new Error(`No files matching '${filePath}/${globPattern}' were found.`));
+ });
- assert.strictEqual(exit, 0);
- });
- });
+ });
- describe("when loading a custom rule", () => {
- it("should return an error when rule isn't found", async () => {
- const rulesPath = getFixturePath("rules", "wrong");
- const configPath = getFixturePath("rules", "eslint.json");
- const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
- const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
+ describe("when executing with no-error-on-unmatched-pattern flag", () => {
+ it(`should not throw an error on unmatched node glob syntax patterns with configType:${configType}`, async () => {
+ const filePath = getFixturePath("unmatched-patterns");
+ const exit = await cli.execute(`--no-error-on-unmatched-pattern "${filePath}/unmatched*.js"`, null, useFlatConfig);
- await stdAssert.rejects(async () => {
- const exit = await cli.execute(code);
+ assert.strictEqual(exit, 0);
+ });
+ });
- assert.strictEqual(exit, 2);
- }, /Error while loading rule 'custom-rule': Boom!/u);
- });
+ describe("when executing with no-error-on-unmatched-pattern flag and multiple patterns", () => {
+ it(`should not throw an error on multiple unmatched node glob syntax patterns with configType:${configType}`, async () => {
+ const filePath = getFixturePath("unmatched-patterns/js3");
+ const exit = await cli.execute(`--no-error-on-unmatched-pattern ${filePath}/unmatched1*.js ${filePath}/unmatched2*.js`, null, useFlatConfig);
- it("should return a warning when rule is matched", async () => {
- const rulesPath = getFixturePath("rules");
- const configPath = getFixturePath("rules", "eslint.json");
- const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
- const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
+ assert.strictEqual(exit, 0);
+ });
- await cli.execute(code);
+ it(`should still throw an error on when a matched pattern has lint errors with configType:${configType}`, async () => {
+ const filePath = getFixturePath("unmatched-patterns");
+ const exit = await cli.execute(`--no-ignore --no-error-on-unmatched-pattern ${filePath}/unmatched1*.js ${filePath}/failing.js`, null, useFlatConfig);
- assert.isTrue(log.info.calledOnce);
- assert.isTrue(log.info.neverCalledWith(""));
- });
+ assert.strictEqual(exit, 1);
+ });
+ });
- it("should return warnings from multiple rules in different directories", async () => {
- const rulesPath = getFixturePath("rules", "dir1");
- const rulesPath2 = getFixturePath("rules", "dir2");
- const configPath = getFixturePath("rules", "multi-rulesdirs.json");
- const filePath = getFixturePath("rules", "test-multi-rulesdirs.js");
- const code = `--rulesdir ${rulesPath} --rulesdir ${rulesPath2} --config ${configPath} --no-ignore ${filePath}`;
- const exit = await cli.execute(code);
-
- const call = log.info.getCall(0);
-
- assert.isTrue(log.info.calledOnce);
- assert.isTrue(call.args[0].indexOf("String!") > -1);
- assert.isTrue(call.args[0].indexOf("Literal!") > -1);
- assert.isTrue(call.args[0].indexOf("2 problems") > -1);
- assert.isTrue(log.info.neverCalledWith(""));
- assert.strictEqual(exit, 1);
- });
+ });
+ describe("Parser Options", () => {
- });
+ describe("when given parser options", () => {
+ it(`should exit with error if parser options are invalid with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing.js");
+ const exit = await cli.execute(`--no-ignore --parser-options test111 ${filePath}`, null, useFlatConfig);
- describe("when executing with no-eslintrc flag", () => {
- it("should ignore a local config file", async () => {
- const filePath = getFixturePath("eslintrc", "quotes.js");
- const exit = await cli.execute(`--no-eslintrc --no-ignore ${filePath}`);
+ assert.strictEqual(exit, 2);
+ });
- assert.isTrue(log.info.notCalled);
- assert.strictEqual(exit, 0);
- });
- });
+ it(`should exit with no error if parser is valid with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing.js");
+ const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`, null, useFlatConfig);
- describe("when executing without no-eslintrc flag", () => {
- it("should load a local config file", async () => {
- const filePath = getFixturePath("eslintrc", "quotes.js");
- const exit = await cli.execute(`--no-ignore ${filePath}`);
+ assert.strictEqual(exit, 0);
+ });
- assert.isTrue(log.info.calledOnce);
- assert.strictEqual(exit, 1);
- });
- });
+ it(`should exit with an error on ecmaVersion 7 feature in ecmaVersion 6 with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing-es7.js");
+ const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`, null, useFlatConfig);
- describe("when executing without env flag", () => {
- it("should not define environment-specific globals", async () => {
- const files = [
- getFixturePath("globals-browser.js"),
- getFixturePath("globals-node.js")
- ];
+ assert.strictEqual(exit, 1);
+ });
- await cli.execute(`--no-eslintrc --config ./conf/eslint-recommended.js --no-ignore ${files.join(" ")}`);
+ it(`should exit with no error on ecmaVersion 7 feature in ecmaVersion 7 with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing-es7.js");
+ const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:7 ${filePath}`, null, useFlatConfig);
- assert.strictEqual(log.info.args[0][0].split("\n").length, 10);
- });
- });
+ assert.strictEqual(exit, 0);
+ });
- describe("when executing with global flag", () => {
- it("should default defined variables to read-only", async () => {
- const filePath = getFixturePath("undef.js");
- const exit = await cli.execute(`--global baz,bat --no-ignore --rule no-global-assign:2 ${filePath}`);
+ it(`should exit with no error on ecmaVersion 7 feature with config ecmaVersion 6 and command line ecmaVersion 7 with configType:${configType}`, async () => {
+ const configPath = useFlatConfig
+ ? getFixturePath("configurations", "es6.js")
+ : getFixturePath("configurations", "es6.json");
+ const filePath = getFixturePath("passing-es7.js");
+ const exit = await cli.execute(`--no-ignore --config ${configPath} --parser-options=ecmaVersion:7 ${filePath}`, null, useFlatConfig);
- assert.isTrue(log.info.calledOnce);
- assert.strictEqual(exit, 1);
- });
+ assert.strictEqual(exit, 0);
+ });
+ });
+ });
- it("should allow defining writable global variables", async () => {
- const filePath = getFixturePath("undef.js");
- const exit = await cli.execute(`--global baz:false,bat:true --no-ignore ${filePath}`);
+ describe("when given the max-warnings flag", () => {
- assert.isTrue(log.info.notCalled);
- assert.strictEqual(exit, 0);
- });
+ let filePath, configFilePath;
- it("should allow defining variables with multiple flags", async () => {
- const filePath = getFixturePath("undef.js");
- const exit = await cli.execute(`--global baz --global bat:true --no-ignore ${filePath}`);
+ before(() => {
+ filePath = getFixturePath("max-warnings/six-warnings.js");
+ configFilePath = getFixturePath(useFlatConfig ? "max-warnings/eslint.config.js" : "max-warnings/.eslintrc");
+ });
- assert.isTrue(log.info.notCalled);
- assert.strictEqual(exit, 0);
- });
- });
+ it(`should not change exit code if warning count under threshold with configType:${configType}`, async () => {
+ const exitCode = await cli.execute(`--no-ignore --max-warnings 10 ${filePath} -c ${configFilePath}`, null, useFlatConfig);
- describe("when supplied with rule flag and severity level set to error", () => {
- it("should exit with an error status (2)", async () => {
- const filePath = getFixturePath("single-quoted.js");
- const code = `--no-ignore --rule 'quotes: [2, double]' ${filePath}`;
- const exitStatus = await cli.execute(code);
+ assert.strictEqual(exitCode, 0);
+ });
- assert.strictEqual(exitStatus, 1);
- });
- });
+ it(`should exit with exit code 1 if warning count exceeds threshold with configType:${configType}`, async () => {
+ const exitCode = await cli.execute(`--no-ignore --max-warnings 5 ${filePath} -c ${configFilePath}`, null, useFlatConfig);
- describe("when the quiet option is enabled", () => {
+ assert.strictEqual(exitCode, 1);
+ assert.ok(log.error.calledOnce);
+ assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
+ });
- it("should only print error", async () => {
- const filePath = getFixturePath("single-quoted.js");
- const cliArgs = `--no-ignore --quiet -f compact --rule 'quotes: [2, double]' --rule 'no-unused-vars: 1' ${filePath}`;
+ it(`should exit with exit code 1 without printing warnings if the quiet option is enabled and warning count exceeds threshold with configType:${configType}`, async () => {
+ const exitCode = await cli.execute(`--no-ignore --quiet --max-warnings 5 ${filePath} -c ${configFilePath}`, null, useFlatConfig);
- await cli.execute(cliArgs);
+ assert.strictEqual(exitCode, 1);
+ assert.ok(log.error.calledOnce);
+ assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
+ assert.ok(log.info.notCalled); // didn't print warnings
+ });
- sinon.assert.calledOnce(log.info);
+ it(`should not change exit code if warning count equals threshold with configType:${configType}`, async () => {
+ const exitCode = await cli.execute(`--no-ignore --max-warnings 6 ${filePath} -c ${configFilePath}`, null, useFlatConfig);
- const formattedOutput = log.info.firstCall.args[0];
+ assert.strictEqual(exitCode, 0);
+ });
- assert.include(formattedOutput, "Error");
- assert.notInclude(formattedOutput, "Warning");
- });
+ it(`should not change exit code if flag is not specified and there are warnings with configType:${configType}`, async () => {
+ const exitCode = await cli.execute(`-c ${configFilePath} ${filePath}`, null, useFlatConfig);
- it("should print nothing if there are no errors", async () => {
- const filePath = getFixturePath("single-quoted.js");
- const cliArgs = `--quiet -f compact --rule 'quotes: [1, double]' --rule 'no-unused-vars: 1' ${filePath}`;
+ assert.strictEqual(exitCode, 0);
+ });
+ });
- await cli.execute(cliArgs);
+ describe("when given the exit-on-fatal-error flag", () => {
+ it(`should not change exit code if no fatal errors are reported with configType:${configType}`, async () => {
+ const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error.js");
+ const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`, null, useFlatConfig);
- sinon.assert.notCalled(log.info);
- });
- });
+ assert.strictEqual(exitCode, 0);
+ });
- describe("when supplied with report output file path", () => {
- afterEach(() => {
- sh.rm("-rf", "tests/output");
- });
+ it(`should exit with exit code 1 if no fatal errors are found, but rule violations are found with configType:${configType}`, async () => {
+ const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error-rule-violation.js");
+ const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`, null, useFlatConfig);
- it("should write the file and create dirs if they don't exist", async () => {
- const filePath = getFixturePath("single-quoted.js");
- const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
+ assert.strictEqual(exitCode, 1);
+ });
- await cli.execute(code);
+ it(`should exit with exit code 2 if fatal error is found with configType:${configType}`, async () => {
+ const filePath = getFixturePath("exit-on-fatal-error", "fatal-error.js");
+ const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`, null, useFlatConfig);
- assert.include(fs.readFileSync("tests/output/eslint-output.txt", "utf8"), filePath);
- assert.isTrue(log.info.notCalled);
- });
+ assert.strictEqual(exitCode, 2);
+ });
- it("should return an error if the path is a directory", async () => {
- const filePath = getFixturePath("single-quoted.js");
- const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output ${filePath}`;
+ it(`should exit with exit code 2 if fatal error is found in any file with configType:${configType}`, async () => {
+ const filePath = getFixturePath("exit-on-fatal-error");
+ const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`, null, useFlatConfig);
- fs.mkdirSync("tests/output");
+ assert.strictEqual(exitCode, 2);
+ });
- const exit = await cli.execute(code);
- assert.strictEqual(exit, 2);
- assert.isTrue(log.info.notCalled);
- assert.isTrue(log.error.calledOnce);
- });
+ });
- it("should return an error if the path could not be written to", async () => {
- const filePath = getFixturePath("single-quoted.js");
- const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
- fs.writeFileSync("tests/output", "foo");
+ describe("Ignores", () => {
+
+ describe("when given a directory with eslint excluded files in the directory", () => {
+ it(`should throw an error and not process any files with configType:${configType}`, async () => {
+ const ignorePath = getFixturePath(".eslintignore");
+ const filePath = getFixturePath("cli");
+ const expectedMessage = useFlatConfig
+ ? `All files matched by '${filePath.replace(/\\/gu, "/")}/**/*.js' are ignored.`
+ : `All files matched by '${filePath}' are ignored.`;
+
+ await stdAssert.rejects(async () => {
+ await cli.execute(`--ignore-path ${ignorePath} ${filePath}`, null, useFlatConfig);
+ }, new Error(expectedMessage));
+ });
+ });
+
+ describe("when given a file in excluded files list", () => {
+ it(`should not process the file with configType:${configType}`, async () => {
+ const ignorePath = getFixturePath(".eslintignore");
+ const filePath = getFixturePath("passing.js");
+ const exit = await cli.execute(`--ignore-path ${ignorePath} ${filePath}`, null, useFlatConfig);
+
+ // a warning about the ignored file
+ assert.isTrue(log.info.called);
+ assert.strictEqual(exit, 0);
+ });
+
+ it(`should process the file when forced with configType:${configType}`, async () => {
+ const ignorePath = getFixturePath(".eslintignore");
+ const filePath = getFixturePath("passing.js");
+ const exit = await cli.execute(`--ignore-path ${ignorePath} --no-ignore ${filePath}`, null, useFlatConfig);
+
+ // no warnings
+ assert.isFalse(log.info.called);
+ assert.strictEqual(exit, 0);
+ });
+ });
+
+ describe("when given a pattern to ignore", () => {
+ it(`should not process any files with configType:${configType}`, async () => {
+ const ignoredFile = getFixturePath("cli/syntax-error.js");
+ const filePath = getFixturePath("cli/passing.js");
+ const exit = await cli.execute(`--ignore-pattern cli/ ${ignoredFile} ${filePath}`, null, useFlatConfig);
+
+ // warnings about the ignored files
+ assert.isTrue(log.info.called);
+ assert.strictEqual(exit, 0);
+ });
+ });
- const exit = await cli.execute(code);
+ });
- assert.strictEqual(exit, 2);
- assert.isTrue(log.info.notCalled);
- assert.isTrue(log.error.calledOnce);
});
- });
- describe("when supplied with a plugin", () => {
- it("should pass plugins to ESLint", async () => {
- const examplePluginName = "eslint-plugin-example";
- await verifyESLintOpts(`--no-ignore --plugin ${examplePluginName} foo.js`, {
- overrideConfig: {
- plugins: [examplePluginName]
- }
- });
- });
+ describe("when given a parser name", () => {
- });
+ it(`should exit with a fatal error if parser is invalid with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing.js");
- describe("when supplied with a plugin-loading path", () => {
- it("should pass the option to ESLint", async () => {
- const examplePluginDirPath = "foo/bar";
+ await stdAssert.rejects(async () => await cli.execute(`--no-ignore --parser test111 ${filePath}`, null, useFlatConfig), "Cannot find module 'test111'");
+ });
+
+ it(`should exit with no error if parser is valid with configType:${configType}`, async () => {
+ const filePath = getFixturePath("passing.js");
+ const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc";
+ const exit = await cli.execute(`${flag} --no-ignore --parser espree ${filePath}`, null, useFlatConfig);
- await verifyESLintOpts(`--resolve-plugins-relative-to ${examplePluginDirPath} foo.js`, {
- resolvePluginsRelativeTo: examplePluginDirPath
+ assert.strictEqual(exit, 0);
});
+
});
- });
- describe("when given an parser name", () => {
- it("should exit with a fatal error if parser is invalid", async () => {
- const filePath = getFixturePath("passing.js");
+ describe("when supplied with report output file path", () => {
+ afterEach(() => {
+ sh.rm("-rf", "tests/output");
+ });
- await stdAssert.rejects(async () => await cli.execute(`--no-ignore --parser test111 ${filePath}`), "Cannot find module 'test111'");
- });
+ it(`should write the file and create dirs if they don't exist with configType:${configType}`, async () => {
+ const filePath = getFixturePath("single-quoted.js");
+ const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
- it("should exit with no error if parser is valid", async () => {
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`--no-ignore --parser espree ${filePath}`);
+ await cli.execute(code, null, useFlatConfig);
- assert.strictEqual(exit, 0);
- });
- });
+ assert.include(fs.readFileSync("tests/output/eslint-output.txt", "utf8"), filePath);
+ assert.isTrue(log.info.notCalled);
+ });
- describe("when given parser options", () => {
- it("should exit with error if parser options are invalid", async () => {
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`--no-ignore --parser-options test111 ${filePath}`);
+ it(`should return an error if the path is a directory with configType:${configType}`, async () => {
+ const filePath = getFixturePath("single-quoted.js");
+ const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output ${filePath}`;
- assert.strictEqual(exit, 2);
- });
+ fs.mkdirSync("tests/output");
- it("should exit with no error if parser is valid", async () => {
- const filePath = getFixturePath("passing.js");
- const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`);
+ const exit = await cli.execute(code, null, useFlatConfig);
- assert.strictEqual(exit, 0);
- });
+ assert.strictEqual(exit, 2);
+ assert.isTrue(log.info.notCalled);
+ assert.isTrue(log.error.calledOnce);
+ });
- it("should exit with an error on ecmaVersion 7 feature in ecmaVersion 6", async () => {
- const filePath = getFixturePath("passing-es7.js");
- const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`);
+ it(`should return an error if the path could not be written to with configType:${configType}`, async () => {
+ const filePath = getFixturePath("single-quoted.js");
+ const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
- assert.strictEqual(exit, 1);
- });
+ fs.writeFileSync("tests/output", "foo");
- it("should exit with no error on ecmaVersion 7 feature in ecmaVersion 7", async () => {
- const filePath = getFixturePath("passing-es7.js");
- const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:7 ${filePath}`);
+ const exit = await cli.execute(code, null, useFlatConfig);
- assert.strictEqual(exit, 0);
+ assert.strictEqual(exit, 2);
+ assert.isTrue(log.info.notCalled);
+ assert.isTrue(log.error.calledOnce);
+ });
});
- it("should exit with no error on ecmaVersion 7 feature with config ecmaVersion 6 and command line ecmaVersion 7", async () => {
- const configPath = getFixturePath("configurations", "es6.json");
- const filePath = getFixturePath("passing-es7.js");
- const exit = await cli.execute(`--no-ignore --config ${configPath} --parser-options=ecmaVersion:7 ${filePath}`);
+ describe("when passed --no-inline-config", () => {
+ let localCLI;
- assert.strictEqual(exit, 0);
- });
- });
+ afterEach(() => {
+ sinon.verifyAndRestore();
+ });
- describe("when given the max-warnings flag", () => {
- it("should not change exit code if warning count under threshold", async () => {
- const filePath = getFixturePath("max-warnings");
- const exitCode = await cli.execute(`--no-ignore --max-warnings 10 ${filePath}`);
+ it(`should pass allowInlineConfig:false to ESLint when --no-inline-config is used with configType:${configType}`, async () => {
+
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: false }));
+
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns([{
+ filePath: "./foo.js",
+ output: "bar",
+ messages: [
+ {
+ severity: 2,
+ message: "Fake message"
+ }
+ ],
+ errorCount: 1,
+ warningCount: 0
+ }]);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.outputFixes = sinon.stub();
+
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
+ "./shared/logging": log
+ });
+
+ await localCLI.execute("--no-inline-config .", null, useFlatConfig);
+ });
- assert.strictEqual(exitCode, 0);
- });
+ it(`should not error and allowInlineConfig should be true by default with configType:${configType}`, async () => {
- it("should exit with exit code 1 if warning count exceeds threshold", async () => {
- const filePath = getFixturePath("max-warnings");
- const exitCode = await cli.execute(`--no-ignore --max-warnings 5 ${filePath}`);
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: true }));
- assert.strictEqual(exitCode, 1);
- assert.ok(log.error.calledOnce);
- assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
- });
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.outputFixes = sinon.stub();
- it("should exit with exit code 1 without printing warnings if the quiet option is enabled and warning count exceeds threshold", async () => {
- const filePath = getFixturePath("max-warnings");
- const exitCode = await cli.execute(`--no-ignore --quiet --max-warnings 5 ${filePath}`);
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
+ "./shared/logging": log
+ });
- assert.strictEqual(exitCode, 1);
- assert.ok(log.error.calledOnce);
- assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
- assert.ok(log.info.notCalled); // didn't print warnings
- });
+ const exitCode = await localCLI.execute(".", null, useFlatConfig);
- it("should not change exit code if warning count equals threshold", async () => {
- const filePath = getFixturePath("max-warnings");
- const exitCode = await cli.execute(`--no-ignore --max-warnings 6 ${filePath}`);
+ assert.strictEqual(exitCode, 0);
+
+ });
- assert.strictEqual(exitCode, 0);
});
- it("should not change exit code if flag is not specified and there are warnings", async () => {
- const filePath = getFixturePath("max-warnings");
- const exitCode = await cli.execute(filePath);
+ describe("when passed --fix", () => {
+ let localCLI;
- assert.strictEqual(exitCode, 0);
- });
- });
+ afterEach(() => {
+ sinon.verifyAndRestore();
+ });
- describe("when given the exit-on-fatal-error flag", () => {
- it("should not change exit code if no fatal errors are reported", async () => {
- const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error.js");
- const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+ it(`should pass fix:true to ESLint when executing on files with configType:${configType}`, async () => {
- assert.strictEqual(exitCode, 0);
- });
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
- it("should exit with exit code 1 if no fatal errors are found, but rule violations are found", async () => {
- const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error-rule-violation.js");
- const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.outputFixes = sinon.mock().once();
- assert.strictEqual(exitCode, 1);
- });
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
+ "./shared/logging": log
+ });
- it("should exit with exit code 2 if fatal error is found", async () => {
- const filePath = getFixturePath("exit-on-fatal-error", "fatal-error.js");
- const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+ const exitCode = await localCLI.execute("--fix .", null, useFlatConfig);
- assert.strictEqual(exitCode, 2);
- });
+ assert.strictEqual(exitCode, 0);
- it("should exit with exit code 2 if fatal error is found in any file", async () => {
- const filePath = getFixturePath("exit-on-fatal-error");
- const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+ });
- assert.strictEqual(exitCode, 2);
- });
+ it(`should rewrite files when in fix mode with configType:${configType}`, async () => {
- });
+ const report = [{
+ filePath: "./foo.js",
+ output: "bar",
+ messages: [
+ {
+ severity: 2,
+ message: "Fake message"
+ }
+ ],
+ errorCount: 1,
+ warningCount: 0
+ }];
- describe("when passed --no-inline-config", () => {
- let localCLI;
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
- afterEach(() => {
- sinon.verifyAndRestore();
- });
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
- it("should pass allowInlineConfig:false to ESLint when --no-inline-config is used", async () => {
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: false }));
+ "./shared/logging": log
+ });
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns([{
- filePath: "./foo.js",
- output: "bar",
- messages: [
- {
- severity: 2,
- message: "Fake message"
- }
- ],
- errorCount: 1,
- warningCount: 0
- }]);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.outputFixes = sinon.stub();
+ const exitCode = await localCLI.execute("--fix .", null, useFlatConfig);
+
+ assert.strictEqual(exitCode, 1);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
});
- await localCLI.execute("--no-inline-config .");
- });
+ it(`should provide fix predicate and rewrite files when in fix mode and quiet mode with configType:${configType}`, async () => {
- it("should not error and allowInlineConfig should be true by default", async () => {
+ const report = [{
+ filePath: "./foo.js",
+ output: "bar",
+ messages: [
+ {
+ severity: 1,
+ message: "Fake message"
+ }
+ ],
+ errorCount: 0,
+ warningCount: 1
+ }];
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: true }));
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.outputFixes = sinon.stub();
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.getErrorResults = sinon.stub().returns([]);
+ fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
- });
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
- const exitCode = await localCLI.execute(".");
+ "./shared/logging": log
+ });
- assert.strictEqual(exitCode, 0);
+ const exitCode = await localCLI.execute("--fix --quiet .", null, useFlatConfig);
- });
+ assert.strictEqual(exitCode, 0);
- });
+ });
- describe("when passed --fix", () => {
- let localCLI;
+ it(`should not call ESLint and return 2 when executing on text with configType:${configType}`, async () => {
- afterEach(() => {
- sinon.verifyAndRestore();
- });
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().never();
- it("should pass fix:true to ESLint when executing on files", async () => {
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+ "./shared/logging": log
+ });
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.outputFixes = sinon.mock().once();
+ const exitCode = await localCLI.execute("--fix .", "foo = bar;", null, useFlatConfig);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
+ assert.strictEqual(exitCode, 2);
});
- const exitCode = await localCLI.execute("--fix .");
+ });
- assert.strictEqual(exitCode, 0);
+ describe("when passed --fix-dry-run", () => {
+ let localCLI;
- });
+ afterEach(() => {
+ sinon.verifyAndRestore();
+ });
+ it(`should pass fix:true to ESLint when executing on files with configType:${configType}`, async () => {
- it("should rewrite files when in fix mode", async () => {
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
- const report = [{
- filePath: "./foo.js",
- output: "bar",
- messages: [
- {
- severity: 2,
- message: "Fake message"
- }
- ],
- errorCount: 1,
- warningCount: 0
- }];
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.outputFixes = sinon.mock().never();
+
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+ "./shared/logging": log
+ });
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
+ const exitCode = await localCLI.execute("--fix-dry-run .", null, useFlatConfig);
+
+ assert.strictEqual(exitCode, 0);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
});
- const exitCode = await localCLI.execute("--fix .");
+ it(`should pass fixTypes to ESLint when --fix-type is passed with configType:${configType}`, async () => {
- assert.strictEqual(exitCode, 1);
+ const expectedESLintOptions = {
+ fix: true,
+ fixTypes: ["suggestion"]
+ };
- });
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match(expectedESLintOptions));
- it("should provide fix predicate and rewrite files when in fix mode and quiet mode", async () => {
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.outputFixes = sinon.stub();
- const report = [{
- filePath: "./foo.js",
- output: "bar",
- messages: [
- {
- severity: 1,
- message: "Fake message"
- }
- ],
- errorCount: 0,
- warningCount: 1
- }];
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
+ "./shared/logging": log
+ });
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.getErrorResults = sinon.stub().returns([]);
- fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
+ const exitCode = await localCLI.execute("--fix-dry-run --fix-type suggestion .", null, useFlatConfig);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
+ assert.strictEqual(exitCode, 0);
});
- const exitCode = await localCLI.execute("--fix --quiet .");
+ it(`should not rewrite files when in fix-dry-run mode with configType:${configType}`, async () => {
- assert.strictEqual(exitCode, 0);
+ const report = [{
+ filePath: "./foo.js",
+ output: "bar",
+ messages: [
+ {
+ severity: 2,
+ message: "Fake message"
+ }
+ ],
+ errorCount: 1,
+ warningCount: 0
+ }];
- });
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.outputFixes = sinon.mock().never();
+
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
- it("should not call ESLint and return 2 when executing on text", async () => {
+ "./shared/logging": log
+ });
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().never();
+ const exitCode = await localCLI.execute("--fix-dry-run .", null, useFlatConfig);
+
+ assert.strictEqual(exitCode, 1);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
});
- const exitCode = await localCLI.execute("--fix .", "foo = bar;");
+ it(`should provide fix predicate when in fix-dry-run mode and quiet mode with configType:${configType}`, async () => {
- assert.strictEqual(exitCode, 2);
- });
+ const report = [{
+ filePath: "./foo.js",
+ output: "bar",
+ messages: [
+ {
+ severity: 1,
+ message: "Fake message"
+ }
+ ],
+ errorCount: 0,
+ warningCount: 1
+ }];
- });
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
- describe("when passed --fix-dry-run", () => {
- let localCLI;
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.getErrorResults = sinon.stub().returns([]);
+ fakeESLint.outputFixes = sinon.mock().never();
- afterEach(() => {
- sinon.verifyAndRestore();
- });
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
- it("should pass fix:true to ESLint when executing on files", async () => {
+ "./shared/logging": log
+ });
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+ const exitCode = await localCLI.execute("--fix-dry-run --quiet .", null, useFlatConfig);
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.outputFixes = sinon.mock().never();
+ assert.strictEqual(exitCode, 0);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
});
- const exitCode = await localCLI.execute("--fix-dry-run .");
+ it(`should allow executing on text with configType:${configType}`, async () => {
- assert.strictEqual(exitCode, 0);
+ const report = [{
+ filePath: "./foo.js",
+ output: "bar",
+ messages: [
+ {
+ severity: 2,
+ message: "Fake message"
+ }
+ ],
+ errorCount: 1,
+ warningCount: 0
+ }];
- });
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
- it("should pass fixTypes to ESLint when --fix-type is passed", async () => {
+ Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+ sinon.stub(fakeESLint.prototype, "lintText").returns(report);
+ sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+ fakeESLint.outputFixes = sinon.mock().never();
- const expectedESLintOptions = {
- fix: true,
- fixTypes: ["suggestion"]
- };
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match(expectedESLintOptions));
+ "./shared/logging": log
+ });
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.outputFixes = sinon.stub();
+ const exitCode = await localCLI.execute("--fix-dry-run .", "foo = bar;", useFlatConfig);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
+ assert.strictEqual(exitCode, 1);
});
- const exitCode = await localCLI.execute("--fix-dry-run --fix-type suggestion .");
+ it(`should not call ESLint and return 2 when used with --fix with configType:${configType}`, async () => {
+
+ // create a fake ESLint class to test with
+ const fakeESLint = sinon.mock().never();
+
+ localCLI = proxyquire("../../lib/cli", {
+ "./eslint": { ESLint: fakeESLint },
+ "./eslint/flat-eslint": { ESLint: fakeESLint, findFlatConfigFile: () => null },
+
+ "./shared/logging": log
+ });
- assert.strictEqual(exitCode, 0);
+ const exitCode = await localCLI.execute("--fix --fix-dry-run .", "foo = bar;", useFlatConfig);
+
+ assert.strictEqual(exitCode, 2);
+ });
});
- it("should not rewrite files when in fix-dry-run mode", async () => {
+ describe("when passing --print-config", () => {
+ it(`should print out the configuration with configType:${configType}`, async () => {
+ const filePath = getFixturePath("xxxx");
- const report = [{
- filePath: "./foo.js",
- output: "bar",
- messages: [
- {
- severity: 2,
- message: "Fake message"
- }
- ],
- errorCount: 1,
- warningCount: 0
- }];
+ const exitCode = await cli.execute(`--print-config ${filePath}`, null, useFlatConfig);
+
+ assert.isTrue(log.info.calledOnce);
+ assert.strictEqual(exitCode, 0);
+ });
+
+ it(`should error if any positional file arguments are passed with configType:${configType}`, async () => {
+ const filePath1 = getFixturePath("files", "bar.js");
+ const filePath2 = getFixturePath("files", "foo.js");
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+ const exitCode = await cli.execute(`--print-config ${filePath1} ${filePath2}`, null, useFlatConfig);
+
+ assert.isTrue(log.info.notCalled);
+ assert.isTrue(log.error.calledOnce);
+ assert.strictEqual(exitCode, 2);
+ });
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.outputFixes = sinon.mock().never();
+ it(`should error out when executing on text with configType:${configType}`, async () => {
+ const exitCode = await cli.execute("--print-config=myFile.js", "foo = bar;", useFlatConfig);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
+ assert.isTrue(log.info.notCalled);
+ assert.isTrue(log.error.calledOnce);
+ assert.strictEqual(exitCode, 2);
});
+ });
+
+ // ---------
+ });
- const exitCode = await localCLI.execute("--fix-dry-run .");
- assert.strictEqual(exitCode, 1);
+ describe("when given a config file", () => {
+ it("should load the specified config file", async () => {
+ const configPath = getFixturePath(".eslintrc");
+ const filePath = getFixturePath("passing.js");
+ await cli.execute(`--config ${configPath} ${filePath}`);
});
+ });
- it("should provide fix predicate when in fix-dry-run mode and quiet mode", async () => {
- const report = [{
- filePath: "./foo.js",
- output: "bar",
- messages: [
- {
- severity: 1,
- message: "Fake message"
- }
- ],
- errorCount: 0,
- warningCount: 1
- }];
+ describe("eslintrc Only", () => {
+
+ describe("Environments", () => {
+
+ describe("when given a config with environment set to browser", () => {
+ it("should execute without any errors", async () => {
+ const configPath = getFixturePath("configurations", "env-browser.json");
+ const filePath = getFixturePath("globals-browser.js");
+ const code = `--config ${configPath} ${filePath}`;
+
+ const exit = await cli.execute(code);
+
+ assert.strictEqual(exit, 0);
+ });
+ });
+
+ describe("when given a config with environment set to Node.js", () => {
+ it("should execute without any errors", async () => {
+ const configPath = getFixturePath("configurations", "env-node.json");
+ const filePath = getFixturePath("globals-node.js");
+ const code = `--config ${configPath} ${filePath}`;
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
+ const exit = await cli.execute(code);
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.getErrorResults = sinon.stub().returns([]);
- fakeESLint.outputFixes = sinon.mock().never();
+ assert.strictEqual(exit, 0);
+ });
+ });
+
+ describe("when given a config with environment set to Nashorn", () => {
+ it("should execute without any errors", async () => {
+ const configPath = getFixturePath("configurations", "env-nashorn.json");
+ const filePath = getFixturePath("globals-nashorn.js");
+ const code = `--config ${configPath} ${filePath}`;
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
+ const exit = await cli.execute(code);
+
+ assert.strictEqual(exit, 0);
+ });
});
- const exitCode = await localCLI.execute("--fix-dry-run --quiet .");
+ describe("when given a config with environment set to WebExtensions", () => {
+ it("should execute without any errors", async () => {
+ const configPath = getFixturePath("configurations", "env-webextensions.json");
+ const filePath = getFixturePath("globals-webextensions.js");
+ const code = `--config ${configPath} ${filePath}`;
- assert.strictEqual(exitCode, 0);
+ const exit = await cli.execute(code);
+ assert.strictEqual(exit, 0);
+ });
+ });
});
- it("should allow executing on text", async () => {
+ describe("when loading a custom rule", () => {
+ it("should return an error when rule isn't found", async () => {
+ const rulesPath = getFixturePath("rules", "wrong");
+ const configPath = getFixturePath("rules", "eslint.json");
+ const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
+ const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
- const report = [{
- filePath: "./foo.js",
- output: "bar",
- messages: [
- {
- severity: 2,
- message: "Fake message"
- }
- ],
- errorCount: 1,
- warningCount: 0
- }];
+ await stdAssert.rejects(async () => {
+ const exit = await cli.execute(code);
+
+ assert.strictEqual(exit, 2);
+ }, /Error while loading rule 'custom-rule': Boom!/u);
+ });
+
+ it("should return a warning when rule is matched", async () => {
+ const rulesPath = getFixturePath("rules");
+ const configPath = getFixturePath("rules", "eslint.json");
+ const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
+ const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+ await cli.execute(code);
- Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
- sinon.stub(fakeESLint.prototype, "lintText").returns(report);
- sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
- fakeESLint.outputFixes = sinon.mock().never();
+ assert.isTrue(log.info.calledOnce);
+ assert.isTrue(log.info.neverCalledWith(""));
+ });
+
+ it("should return warnings from multiple rules in different directories", async () => {
+ const rulesPath = getFixturePath("rules", "dir1");
+ const rulesPath2 = getFixturePath("rules", "dir2");
+ const configPath = getFixturePath("rules", "multi-rulesdirs.json");
+ const filePath = getFixturePath("rules", "test-multi-rulesdirs.js");
+ const code = `--rulesdir ${rulesPath} --rulesdir ${rulesPath2} --config ${configPath} --no-ignore ${filePath}`;
+ const exit = await cli.execute(code);
+
+ const call = log.info.getCall(0);
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
+ assert.isTrue(log.info.calledOnce);
+ assert.isTrue(call.args[0].includes("String!"));
+ assert.isTrue(call.args[0].includes("Literal!"));
+ assert.isTrue(call.args[0].includes("2 problems"));
+ assert.isTrue(log.info.neverCalledWith(""));
+ assert.strictEqual(exit, 1);
});
- const exitCode = await localCLI.execute("--fix-dry-run .", "foo = bar;");
- assert.strictEqual(exitCode, 1);
});
- it("should not call ESLint and return 2 when used with --fix", async () => {
+ describe("when executing with no-eslintrc flag", () => {
+ it("should ignore a local config file", async () => {
+ const filePath = getFixturePath("eslintrc", "quotes.js");
+ const exit = await cli.execute(`--no-eslintrc --no-ignore ${filePath}`);
- // create a fake ESLint class to test with
- const fakeESLint = sinon.mock().never();
-
- localCLI = proxyquire("../../lib/cli", {
- "./eslint": { ESLint: fakeESLint },
- "./shared/logging": log
+ assert.isTrue(log.info.notCalled);
+ assert.strictEqual(exit, 0);
});
+ });
- const exitCode = await localCLI.execute("--fix --fix-dry-run .", "foo = bar;");
+ describe("when executing without no-eslintrc flag", () => {
+ it("should load a local config file", async () => {
+ const filePath = getFixturePath("eslintrc", "quotes.js");
+ const exit = await cli.execute(`--no-ignore ${filePath}`);
- assert.strictEqual(exitCode, 2);
+ assert.isTrue(log.info.calledOnce);
+ assert.strictEqual(exit, 1);
+ });
});
- });
- describe("when passing --print-config", () => {
- it("should print out the configuration", async () => {
- const filePath = getFixturePath("xxxx");
+ describe("when executing without env flag", () => {
+ it("should not define environment-specific globals", async () => {
+ const files = [
+ getFixturePath("globals-browser.js"),
+ getFixturePath("globals-node.js")
+ ];
- const exitCode = await cli.execute(`--print-config ${filePath}`);
+ await cli.execute(`--no-eslintrc --config ./conf/eslint-recommended.js --no-ignore ${files.join(" ")}`);
- assert.isTrue(log.info.calledOnce);
- assert.strictEqual(exitCode, 0);
+ assert.strictEqual(log.info.args[0][0].split("\n").length, 10);
+ });
});
- it("should error if any positional file arguments are passed", async () => {
- const filePath1 = getFixturePath("files", "bar.js");
- const filePath2 = getFixturePath("files", "foo.js");
- const exitCode = await cli.execute(`--print-config ${filePath1} ${filePath2}`);
+ describe("when supplied with a plugin", () => {
+ it("should pass plugins to ESLint", async () => {
+ const examplePluginName = "eslint-plugin-example";
+
+ await verifyESLintOpts(`--no-ignore --plugin ${examplePluginName} foo.js`, {
+ overrideConfig: {
+ plugins: [examplePluginName]
+ }
+ });
+ });
- assert.isTrue(log.info.notCalled);
- assert.isTrue(log.error.calledOnce);
- assert.strictEqual(exitCode, 2);
});
- it("should error out when executing on text", async () => {
- const exitCode = await cli.execute("--print-config=myFile.js", "foo = bar;");
+ describe("when supplied with a plugin-loading path", () => {
+ it("should pass the option to ESLint", async () => {
+ const examplePluginDirPath = "foo/bar";
- assert.isTrue(log.info.notCalled);
- assert.isTrue(log.error.calledOnce);
- assert.strictEqual(exitCode, 2);
+ await verifyESLintOpts(`--resolve-plugins-relative-to ${examplePluginDirPath} foo.js`, {
+ resolvePluginsRelativeTo: examplePluginDirPath
+ });
+ });
});
+
+
});
+
});