2 * @fileoverview Tests for CLIEngine.
3 * @author Nicholas C. Zakas
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const assert
= require("chai").assert
,
13 path
= require("path"),
14 sinon
= require("sinon"),
15 shell
= require("shelljs"),
18 hash
= require("../../../lib/cli-engine/hash"),
19 { CascadingConfigArrayFactory
} = require("@eslint/eslintrc/lib/cascading-config-array-factory"),
20 { unIndent
, createCustomTeardown
} = require("../../_utils");
22 const proxyquire
= require("proxyquire").noCallThru().noPreserveCache();
23 const fCache
= require("file-entry-cache");
25 //------------------------------------------------------------------------------
27 //------------------------------------------------------------------------------
29 describe("CLIEngine", () => {
31 const examplePluginName
= "eslint-plugin-example",
32 examplePluginNameWithNamespace
= "@eslint/eslint-plugin-example",
35 "example-rule": require("../../fixtures/rules/custom-rule"),
36 "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
39 examplePreprocessorName
= "eslint-plugin-processor",
40 originalDir
= process
.cwd(),
41 fixtureDir
= path
.resolve(fs
.realpathSync(os
.tmpdir()), "eslint/fixtures");
43 /** @type {import("../../../lib/cli-engine")["CLIEngine"]} */
46 /** @type {import("../../../lib/cli-engine/cli-engine")["getCLIEngineInternalSlots"]} */
47 let getCLIEngineInternalSlots;
50 * Returns the path inside of the fixture directory.
51 * @param {...string} args file path segments.
52 * @returns {string} The path inside the fixture directory.
55 function getFixturePath(...args
) {
56 const filepath
= path
.join(fixtureDir
, ...args
);
59 return fs
.realpathSync(filepath
);
66 * Create the CLIEngine object by mocking some of the plugins
67 * @param {Object} options options for CLIEngine
68 * @returns {CLIEngine} engine object
71 function cliEngineWithPlugins(options
) {
72 const engine
= new CLIEngine(options
);
74 // load the mocked plugins
75 engine
.addPlugin(examplePluginName
, examplePlugin
);
76 engine
.addPlugin(examplePluginNameWithNamespace
, examplePlugin
);
77 engine
.addPlugin(examplePreprocessorName
, require("../../fixtures/processors/custom-processor"));
82 // copy into clean area so as not to get "infected" by this project's .eslintrc files
86 * GitHub Actions Windows and macOS runners occasionally exhibit
87 * extremely slow filesystem operations, during which copying fixtures
88 * exceeds the default test timeout, so raise it just for this hook.
89 * Mocha uses `this` to set timeouts on an individual hook level.
91 this.timeout(60 * 1000); // eslint-disable-line no-invalid-this
92 shell
.mkdir("-p", fixtureDir
);
93 shell
.cp("-r", "./tests/fixtures/.", fixtureDir
);
97 ({ CLIEngine
, getCLIEngineInternalSlots
} = require("../../../lib/cli-engine/cli-engine"));
101 shell
.rm("-r", fixtureDir
);
104 describe("new CLIEngine(options)", () => {
105 it("the default value of 'options.cwd' should be the current working directory.", () => {
106 process
.chdir(__dirname
);
108 const engine
= new CLIEngine();
109 const internalSlots
= getCLIEngineInternalSlots(engine
);
111 assert
.strictEqual(internalSlots
.options
.cwd
, __dirname
);
113 process
.chdir(originalDir
);
117 it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
118 assert
.throws(() => {
119 // eslint-disable-next-line no-new
120 new CLIEngine({ ignorePath
: fixtureDir
});
121 }, `Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`);
124 // https://github.com/eslint/eslint/issues/2380
125 it("should not modify baseConfig when format is specified", () => {
126 const customBaseConfig
= { root
: true };
128 new CLIEngine({ baseConfig
: customBaseConfig
, format
: "foo" }); // eslint-disable-line no-new
130 assert
.deepStrictEqual(customBaseConfig
, { root
: true });
134 describe("executeOnText()", () => {
138 it("should report the total and per file errors when using local cwd .eslintrc", () => {
140 engine
= new CLIEngine();
142 const report
= engine
.executeOnText("var foo = 'bar';");
144 assert
.strictEqual(report
.results
.length
, 1);
145 assert
.strictEqual(report
.errorCount
, 5);
146 assert
.strictEqual(report
.warningCount
, 0);
147 assert
.strictEqual(report
.fixableErrorCount
, 3);
148 assert
.strictEqual(report
.fixableWarningCount
, 0);
149 assert
.strictEqual(report
.results
[0].messages
.length
, 5);
150 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "strict");
151 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-var");
152 assert
.strictEqual(report
.results
[0].messages
[2].ruleId
, "no-unused-vars");
153 assert
.strictEqual(report
.results
[0].messages
[3].ruleId
, "quotes");
154 assert
.strictEqual(report
.results
[0].messages
[4].ruleId
, "eol-last");
155 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 3);
156 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
159 it("should report the total and per file warnings when using local cwd .eslintrc", () => {
161 engine
= new CLIEngine({
171 const report
= engine
.executeOnText("var foo = 'bar';");
173 assert
.strictEqual(report
.results
.length
, 1);
174 assert
.strictEqual(report
.errorCount
, 0);
175 assert
.strictEqual(report
.warningCount
, 5);
176 assert
.strictEqual(report
.fixableErrorCount
, 0);
177 assert
.strictEqual(report
.fixableWarningCount
, 3);
178 assert
.strictEqual(report
.results
[0].messages
.length
, 5);
179 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "strict");
180 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-var");
181 assert
.strictEqual(report
.results
[0].messages
[2].ruleId
, "no-unused-vars");
182 assert
.strictEqual(report
.results
[0].messages
[3].ruleId
, "quotes");
183 assert
.strictEqual(report
.results
[0].messages
[4].ruleId
, "eol-last");
184 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
185 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 3);
188 it("should report one message when using specific config file", () => {
190 engine
= new CLIEngine({
191 configFile
: "fixtures/configurations/quotes-error.json",
193 cwd
: getFixturePath("..")
196 const report
= engine
.executeOnText("var foo = 'bar';");
198 assert
.strictEqual(report
.results
.length
, 1);
199 assert
.strictEqual(report
.errorCount
, 1);
200 assert
.strictEqual(report
.warningCount
, 0);
201 assert
.strictEqual(report
.fixableErrorCount
, 1);
202 assert
.strictEqual(report
.fixableWarningCount
, 0);
203 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
204 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
205 assert
.isUndefined(report
.results
[0].messages
[0].output
);
206 assert
.strictEqual(report
.results
[0].errorCount
, 1);
207 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
208 assert
.strictEqual(report
.results
[0].warningCount
, 0);
211 it("should report the filename when passed in", () => {
213 engine
= new CLIEngine({
215 cwd
: getFixturePath()
218 const report
= engine
.executeOnText("var foo = 'bar';", "test.js");
220 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("test.js"));
223 it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", () => {
224 engine
= new CLIEngine({
225 ignorePath
: getFixturePath(".eslintignore"),
226 cwd
: getFixturePath("..")
229 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js", true);
231 assert
.strictEqual(report
.results
.length
, 1);
232 assert
.strictEqual(report
.errorCount
, 0);
233 assert
.strictEqual(report
.warningCount
, 1);
234 assert
.strictEqual(report
.fixableErrorCount
, 0);
235 assert
.strictEqual(report
.fixableWarningCount
, 0);
236 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("passing.js"));
237 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
238 assert
.strictEqual(report
.results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
239 assert
.isUndefined(report
.results
[0].messages
[0].output
);
240 assert
.strictEqual(report
.results
[0].errorCount
, 0);
241 assert
.strictEqual(report
.results
[0].warningCount
, 1);
242 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
243 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
246 it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", () => {
247 engine
= new CLIEngine({
248 ignorePath
: getFixturePath(".eslintignore"),
249 cwd
: getFixturePath("..")
252 // intentional parsing error
253 const report
= engine
.executeOnText("va r bar = foo;", "fixtures/passing.js", false);
255 // should not report anything because the file is ignored
256 assert
.strictEqual(report
.results
.length
, 0);
259 it("should suppress excluded file warnings by default", () => {
260 engine
= new CLIEngine({
261 ignorePath
: getFixturePath(".eslintignore"),
262 cwd
: getFixturePath("..")
265 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
267 // should not report anything because there are no errors
268 assert
.strictEqual(report
.results
.length
, 0);
271 it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", () => {
273 engine
= new CLIEngine({
274 ignorePath
: "fixtures/.eslintignore",
275 cwd
: getFixturePath(".."),
283 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
285 assert
.strictEqual(report
.results
.length
, 1);
286 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("passing.js"));
287 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-undef");
288 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
289 assert
.isUndefined(report
.results
[0].messages
[0].output
);
292 it("should return a message and fixed text when in fix mode", () => {
294 engine
= new CLIEngine({
301 cwd
: getFixturePath()
304 const report
= engine
.executeOnText("var bar = foo", "passing.js");
306 assert
.deepStrictEqual(report
, {
309 filePath
: getFixturePath("passing.js"),
313 fixableErrorCount
: 0,
314 fixableWarningCount
: 0,
315 output
: "var bar = foo;"
320 fixableErrorCount
: 0,
321 fixableWarningCount
: 0,
322 usedDeprecatedRules
: []
326 it("correctly autofixes semicolon-conflicting-fixes", () => {
327 engine
= new CLIEngine({
328 cwd
: path
.join(fixtureDir
, ".."),
332 const inputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.js");
333 const outputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
334 const report
= engine
.executeOnFiles([inputPath
]);
335 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
337 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
340 it("correctly autofixes return-conflicting-fixes", () => {
341 engine
= new CLIEngine({
342 cwd
: path
.join(fixtureDir
, ".."),
346 const inputPath
= getFixturePath("autofix/return-conflicting-fixes.js");
347 const outputPath
= getFixturePath("autofix/return-conflicting-fixes.expected.js");
348 const report
= engine
.executeOnFiles([inputPath
]);
349 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
351 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
354 describe("Fix Types", () => {
356 it("should throw an error when an invalid fix type is specified", () => {
357 assert
.throws(() => {
358 engine
= new CLIEngine({
359 cwd
: path
.join(fixtureDir
, ".."),
364 }, /invalid fix type/iu);
367 it("should not fix any rules when fixTypes is used without fix", () => {
368 engine
= new CLIEngine({
369 cwd
: path
.join(fixtureDir
, ".."),
375 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
376 const report
= engine
.executeOnFiles([inputPath
]);
378 assert
.isUndefined(report
.results
[0].output
);
381 it("should not fix non-style rules when fixTypes has only 'layout'", () => {
382 engine
= new CLIEngine({
383 cwd
: path
.join(fixtureDir
, ".."),
388 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
389 const outputPath
= getFixturePath("fix-types/fix-only-semi.expected.js");
390 const report
= engine
.executeOnFiles([inputPath
]);
391 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
393 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
396 it("should not fix style or problem rules when fixTypes has only 'suggestion'", () => {
397 engine
= new CLIEngine({
398 cwd
: path
.join(fixtureDir
, ".."),
401 fixTypes
: ["suggestion"]
403 const inputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
404 const outputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
405 const report
= engine
.executeOnFiles([inputPath
]);
406 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
408 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
411 it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", () => {
412 engine
= new CLIEngine({
413 cwd
: path
.join(fixtureDir
, ".."),
416 fixTypes
: ["suggestion", "layout"]
418 const inputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
419 const outputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
420 const report
= engine
.executeOnFiles([inputPath
]);
421 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
423 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
426 it("should not throw an error when a rule doesn't have a 'meta' property", () => {
427 engine
= new CLIEngine({
428 cwd
: path
.join(fixtureDir
, ".."),
431 fixTypes
: ["layout"],
432 rulePaths
: [getFixturePath("rules", "fix-types-test")]
435 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
436 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
437 const report
= engine
.executeOnFiles([inputPath
]);
438 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
440 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
443 it("should not throw an error when a rule is loaded after initialization with executeOnFiles()", () => {
444 engine
= new CLIEngine({
445 cwd
: path
.join(fixtureDir
, ".."),
450 const internalSlots
= getCLIEngineInternalSlots(engine
);
452 internalSlots
.linter
.defineRule(
454 require(getFixturePath("rules", "fix-types-test", "no-program.js"))
457 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
458 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
459 const report
= engine
.executeOnFiles([inputPath
]);
460 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
462 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
465 it("should not throw an error when a rule is loaded after initialization with executeOnText()", () => {
466 engine
= new CLIEngine({
467 cwd
: path
.join(fixtureDir
, ".."),
472 const internalSlots
= getCLIEngineInternalSlots(engine
);
474 internalSlots
.linter
.defineRule(
476 require(getFixturePath("rules", "fix-types-test", "no-program.js"))
479 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
480 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
481 const report
= engine
.executeOnText(fs
.readFileSync(inputPath
, { encoding
: "utf8" }), inputPath
);
482 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
484 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
489 it("should return a message and omit fixed text when in fix mode and fixes aren't done", () => {
491 engine
= new CLIEngine({
498 cwd
: getFixturePath()
501 const report
= engine
.executeOnText("var bar = foo", "passing.js");
503 assert
.deepStrictEqual(report
, {
506 filePath
: getFixturePath("passing.js"),
512 message
: "'foo' is not defined.",
517 nodeType
: "Identifier"
522 fixableErrorCount
: 0,
523 fixableWarningCount
: 0,
524 source
: "var bar = foo"
529 fixableErrorCount
: 0,
530 fixableWarningCount
: 0,
531 usedDeprecatedRules
: []
535 it("should not delete code if there is a syntax error after trying to autofix.", () => {
536 engine
= cliEngineWithPlugins({
539 plugins
: ["example"],
541 "example/make-syntax-error": "error"
544 cwd
: getFixturePath()
547 const report
= engine
.executeOnText("var bar = foo", "test.js");
549 assert
.deepStrictEqual(report
, {
552 filePath
: getFixturePath("test.js"),
558 message
: "Parsing error: Unexpected token is",
565 fixableErrorCount
: 0,
566 fixableWarningCount
: 0,
567 output
: "var bar = foothis is a syntax error."
572 fixableErrorCount
: 0,
573 fixableWarningCount
: 0,
574 usedDeprecatedRules
: []
578 it("should not crash even if there are any syntax error since the first time.", () => {
579 engine
= new CLIEngine({
583 "example/make-syntax-error": "error"
586 cwd
: getFixturePath()
589 const report
= engine
.executeOnText("var bar =", "test.js");
591 assert
.deepStrictEqual(report
, {
594 filePath
: getFixturePath("test.js"),
600 message
: "Parsing error: Unexpected token",
607 fixableErrorCount
: 0,
608 fixableWarningCount
: 0,
614 fixableErrorCount
: 0,
615 fixableWarningCount
: 0,
616 usedDeprecatedRules
: []
620 it("should return source code of file in `source` property when errors are present", () => {
621 engine
= new CLIEngine({
626 const report
= engine
.executeOnText("var foo = 'bar'");
628 assert
.strictEqual(report
.results
[0].source
, "var foo = 'bar'");
631 it("should return source code of file in `source` property when warnings are present", () => {
632 engine
= new CLIEngine({
637 const report
= engine
.executeOnText("var foo = 'bar'");
639 assert
.strictEqual(report
.results
[0].source
, "var foo = 'bar'");
643 it("should not return a `source` property when no errors or warnings are present", () => {
644 engine
= new CLIEngine({
649 const report
= engine
.executeOnText("var foo = 'bar';");
651 assert
.lengthOf(report
.results
[0].messages
, 0);
652 assert
.isUndefined(report
.results
[0].source
);
655 it("should not return a `source` property when fixes are applied", () => {
656 engine
= new CLIEngine({
665 const report
= engine
.executeOnText("var msg = 'hi' + foo\n");
667 assert
.isUndefined(report
.results
[0].source
);
668 assert
.strictEqual(report
.results
[0].output
, "var msg = 'hi' + foo;\n");
671 it("should return a `source` property when a parsing error has occurred", () => {
672 engine
= new CLIEngine({
677 const report
= engine
.executeOnText("var bar = foothis is a syntax error.\n return bar;");
679 assert
.deepStrictEqual(report
, {
688 message
: "Parsing error: Unexpected token is",
695 fixableErrorCount
: 0,
696 fixableWarningCount
: 0,
697 source
: "var bar = foothis is a syntax error.\n return bar;"
702 fixableErrorCount
: 0,
703 fixableWarningCount
: 0,
704 usedDeprecatedRules
: []
708 // https://github.com/eslint/eslint/issues/5547
709 it("should respect default ignore rules, even with --no-ignore", () => {
711 engine
= new CLIEngine({
712 cwd
: getFixturePath(),
716 const report
= engine
.executeOnText("var bar = foo;", "node_modules/passing.js", true);
717 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
719 assert
.strictEqual(report
.results
.length
, 1);
720 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("node_modules/passing.js"));
721 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
724 // @scope for @scope/eslint-plugin
725 describe("(plugin shorthand)", () => {
726 const Module
= require("module");
727 let originalFindPath
= null;
729 /* eslint-disable no-underscore-dangle */
731 originalFindPath
= Module
._findPath
;
732 Module
._findPath = function(id
, ...otherArgs
) {
733 if (id
=== "@scope/eslint-plugin") {
734 return path
.resolve(__dirname
, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
736 return originalFindPath
.call(this, id
, ...otherArgs
);
740 Module
._findPath
= originalFindPath
;
742 /* eslint-enable no-underscore-dangle */
744 it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
745 engine
= new CLIEngine({ cwd
: getFixturePath("plugin-shorthand/basic") });
746 const report
= engine
.executeOnText("var x = 0", "index.js").results
[0];
748 assert
.strictEqual(report
.filePath
, getFixturePath("plugin-shorthand/basic/index.js"));
749 assert
.strictEqual(report
.messages
[0].ruleId
, "@scope/rule");
750 assert
.strictEqual(report
.messages
[0].message
, "OK");
753 it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
754 engine
= new CLIEngine({ cwd
: getFixturePath("plugin-shorthand/extends") });
755 const report
= engine
.executeOnText("var x = 0", "index.js").results
[0];
757 assert
.strictEqual(report
.filePath
, getFixturePath("plugin-shorthand/extends/index.js"));
758 assert
.strictEqual(report
.messages
[0].ruleId
, "@scope/rule");
759 assert
.strictEqual(report
.messages
[0].message
, "OK");
762 it("should warn when deprecated rules are found in a config", () => {
763 engine
= new CLIEngine({
766 configFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
769 const report
= engine
.executeOnText("foo");
771 assert
.deepStrictEqual(
772 report
.usedDeprecatedRules
,
773 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
778 describe("executeOnFiles()", () => {
780 /** @type {InstanceType<import("../../../lib/cli-engine")["CLIEngine"]>} */
783 it("should use correct parser when custom parser is specified", () => {
785 engine
= new CLIEngine({
790 const filePath
= path
.resolve(__dirname
, "../../fixtures/configurations/parser/custom.js");
791 const report
= engine
.executeOnFiles([filePath
]);
793 assert
.strictEqual(report
.results
.length
, 1);
794 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
795 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Parsing error: Boom!");
799 it("should report zero messages when given a config file and a valid file", () => {
801 engine
= new CLIEngine({
803 configFile
: ".eslintrc.js"
806 const report
= engine
.executeOnFiles(["lib/**/cli*.js"]);
808 assert
.strictEqual(report
.results
.length
, 2);
809 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
810 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
813 it("should handle multiple patterns with overlapping files", () => {
815 engine
= new CLIEngine({
817 configFile
: ".eslintrc.js"
820 const report
= engine
.executeOnFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
822 assert
.strictEqual(report
.results
.length
, 2);
823 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
824 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
827 it("should report zero messages when given a config file and a valid file and espree as parser", () => {
829 engine
= new CLIEngine({
837 const report
= engine
.executeOnFiles(["lib/cli.js"]);
839 assert
.strictEqual(report
.results
.length
, 1);
840 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
843 it("should report zero messages when given a config file and a valid file and esprima as parser", () => {
845 engine
= new CLIEngine({
850 const report
= engine
.executeOnFiles(["lib/cli.js"]);
852 assert
.strictEqual(report
.results
.length
, 1);
853 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
856 it("should throw an error when given a config file and a valid file and invalid parser", () => {
858 engine
= new CLIEngine({
863 assert
.throws(() => engine
.executeOnFiles(["lib/cli.js"]), "Cannot find module 'test11'");
866 it("should report zero messages when given a directory with a .js2 file", () => {
868 engine
= new CLIEngine({
869 cwd
: path
.join(fixtureDir
, ".."),
873 const report
= engine
.executeOnFiles([getFixturePath("files/foo.js2")]);
875 assert
.strictEqual(report
.results
.length
, 1);
876 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
879 it("should fall back to defaults when extensions is set to an empty array", () => {
881 engine
= new CLIEngine({
882 cwd
: getFixturePath("configurations"),
883 configFile
: getFixturePath("configurations", "quotes-error.json"),
886 const report
= engine
.executeOnFiles([getFixturePath("single-quoted.js")]);
888 assert
.strictEqual(report
.results
.length
, 1);
889 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
890 assert
.strictEqual(report
.errorCount
, 1);
891 assert
.strictEqual(report
.warningCount
, 0);
892 assert
.strictEqual(report
.fixableErrorCount
, 1);
893 assert
.strictEqual(report
.fixableWarningCount
, 0);
894 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
895 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
896 assert
.strictEqual(report
.results
[0].errorCount
, 1);
897 assert
.strictEqual(report
.results
[0].warningCount
, 0);
898 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
899 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
902 it("should report zero messages when given a directory with a .js and a .js2 file", () => {
904 engine
= new CLIEngine({
905 extensions
: [".js", ".js2"],
907 cwd
: getFixturePath("..")
910 const report
= engine
.executeOnFiles(["fixtures/files/"]);
912 assert
.strictEqual(report
.results
.length
, 2);
913 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
914 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
917 it("should report zero messages when given a '**' pattern with a .js and a .js2 file", () => {
919 engine
= new CLIEngine({
920 extensions
: [".js", ".js2"],
922 cwd
: path
.join(fixtureDir
, "..")
925 const report
= engine
.executeOnFiles(["fixtures/files/*"]);
927 assert
.strictEqual(report
.results
.length
, 2);
928 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
929 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
932 it("should resolve globs when 'globInputPaths' option is true", () => {
933 engine
= new CLIEngine({
934 extensions
: [".js", ".js2"],
936 cwd
: getFixturePath("..")
939 const report
= engine
.executeOnFiles(["fixtures/files/*"]);
941 assert
.strictEqual(report
.results
.length
, 2);
942 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
943 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
946 it("should not resolve globs when 'globInputPaths' option is false", () => {
947 engine
= new CLIEngine({
948 extensions
: [".js", ".js2"],
950 cwd
: getFixturePath(".."),
951 globInputPaths
: false
954 assert
.throws(() => {
955 engine
.executeOnFiles(["fixtures/files/*"]);
956 }, "No files matching 'fixtures/files/*' were found (glob was disabled).");
959 it("should report on all files passed explicitly, even if ignored by default", () => {
961 engine
= new CLIEngine({
962 cwd
: getFixturePath("cli-engine")
965 const report
= engine
.executeOnFiles(["node_modules/foo.js"]);
966 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
968 assert
.strictEqual(report
.results
.length
, 1);
969 assert
.strictEqual(report
.results
[0].errorCount
, 0);
970 assert
.strictEqual(report
.results
[0].warningCount
, 1);
971 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
972 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
973 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
976 it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", () => {
978 engine
= new CLIEngine({
979 cwd
: getFixturePath("cli-engine"),
981 quotes
: [2, "single"]
985 const report
= engine
.executeOnFiles(["hidden/.hiddenfolder/*.js"]);
987 assert
.strictEqual(report
.results
.length
, 1);
988 assert
.strictEqual(report
.results
[0].errorCount
, 1);
989 assert
.strictEqual(report
.results
[0].warningCount
, 0);
990 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
991 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
994 it("should not check default ignored files without --no-ignore flag", () => {
996 engine
= new CLIEngine({
997 cwd
: getFixturePath("cli-engine")
1000 assert
.throws(() => {
1001 engine
.executeOnFiles(["node_modules"]);
1002 }, "All files matched by 'node_modules' are ignored.");
1005 // https://github.com/eslint/eslint/issues/5547
1006 it("should not check node_modules files even with --no-ignore flag", () => {
1008 engine
= new CLIEngine({
1009 cwd
: getFixturePath("cli-engine"),
1013 assert
.throws(() => {
1014 engine
.executeOnFiles(["node_modules"]);
1015 }, "All files matched by 'node_modules' are ignored.");
1018 it("should not check .hidden files if they are passed explicitly without --no-ignore flag", () => {
1020 engine
= new CLIEngine({
1021 cwd
: getFixturePath(".."),
1024 quotes
: [2, "single"]
1028 const report
= engine
.executeOnFiles(["fixtures/files/.bar.js"]);
1029 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1031 assert
.strictEqual(report
.results
.length
, 1);
1032 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1033 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1034 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1035 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1036 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1039 // https://github.com/eslint/eslint/issues/12873
1040 it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", () => {
1041 engine
= new CLIEngine({
1042 cwd
: getFixturePath("cli-engine"),
1045 quotes
: [2, "single"]
1049 const report
= engine
.executeOnFiles(["hidden/.hiddenfolder/double-quotes.js"]);
1050 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1052 assert
.strictEqual(report
.results
.length
, 1);
1053 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1054 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1055 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1056 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1057 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1060 it("should check .hidden files if they are passed explicitly with --no-ignore flag", () => {
1062 engine
= new CLIEngine({
1063 cwd
: getFixturePath(".."),
1067 quotes
: [2, "single"]
1071 const report
= engine
.executeOnFiles(["fixtures/files/.bar.js"]);
1073 assert
.strictEqual(report
.results
.length
, 1);
1074 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1075 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1076 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1077 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1078 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1081 it("should check .hidden files if they are unignored with an --ignore-pattern", () => {
1083 engine
= new CLIEngine({
1084 cwd
: getFixturePath("cli-engine"),
1087 ignorePattern
: "!.hidden*",
1089 quotes
: [2, "single"]
1093 const report
= engine
.executeOnFiles(["hidden/"]);
1095 assert
.strictEqual(report
.results
.length
, 1);
1096 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1097 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1098 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1099 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1100 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1103 it("should report zero messages when given a pattern with a .js and a .js2 file", () => {
1105 engine
= new CLIEngine({
1106 extensions
: [".js", ".js2"],
1108 cwd
: path
.join(fixtureDir
, "..")
1111 const report
= engine
.executeOnFiles(["fixtures/files/*.?s*"]);
1113 assert
.strictEqual(report
.results
.length
, 2);
1114 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1115 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
1118 it("should return one error message when given a config with rules with options and severity level set to error", () => {
1120 engine
= new CLIEngine({
1121 cwd
: getFixturePath("configurations"),
1122 configFile
: getFixturePath("configurations", "quotes-error.json")
1124 const report
= engine
.executeOnFiles([getFixturePath("single-quoted.js")]);
1126 assert
.strictEqual(report
.results
.length
, 1);
1127 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1128 assert
.strictEqual(report
.errorCount
, 1);
1129 assert
.strictEqual(report
.warningCount
, 0);
1130 assert
.strictEqual(report
.fixableErrorCount
, 1);
1131 assert
.strictEqual(report
.fixableWarningCount
, 0);
1132 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1133 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1134 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1135 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1136 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1137 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1140 it("should return 3 messages when given a config file and a directory of 3 valid files", () => {
1142 engine
= new CLIEngine({
1143 cwd
: path
.join(fixtureDir
, ".."),
1144 configFile
: getFixturePath("configurations", "semi-error.json")
1147 const report
= engine
.executeOnFiles([getFixturePath("formatters")]);
1149 assert
.strictEqual(report
.results
.length
, 3);
1150 assert
.strictEqual(report
.errorCount
, 0);
1151 assert
.strictEqual(report
.warningCount
, 0);
1152 assert
.strictEqual(report
.fixableErrorCount
, 0);
1153 assert
.strictEqual(report
.fixableWarningCount
, 0);
1154 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1155 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
1156 assert
.strictEqual(report
.results
[2].messages
.length
, 0);
1157 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1158 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1159 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1160 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1161 assert
.strictEqual(report
.results
[1].errorCount
, 0);
1162 assert
.strictEqual(report
.results
[1].warningCount
, 0);
1163 assert
.strictEqual(report
.results
[1].fixableErrorCount
, 0);
1164 assert
.strictEqual(report
.results
[1].fixableWarningCount
, 0);
1165 assert
.strictEqual(report
.results
[2].errorCount
, 0);
1166 assert
.strictEqual(report
.results
[2].warningCount
, 0);
1167 assert
.strictEqual(report
.results
[2].fixableErrorCount
, 0);
1168 assert
.strictEqual(report
.results
[2].fixableWarningCount
, 0);
1172 it("should return the total number of errors when given multiple files", () => {
1174 engine
= new CLIEngine({
1175 cwd
: path
.join(fixtureDir
, ".."),
1176 configFile
: getFixturePath("configurations", "single-quotes-error.json")
1179 const report
= engine
.executeOnFiles([getFixturePath("formatters")]);
1181 assert
.strictEqual(report
.errorCount
, 6);
1182 assert
.strictEqual(report
.warningCount
, 0);
1183 assert
.strictEqual(report
.fixableErrorCount
, 6);
1184 assert
.strictEqual(report
.fixableWarningCount
, 0);
1185 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1186 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1187 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1188 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1189 assert
.strictEqual(report
.results
[1].errorCount
, 3);
1190 assert
.strictEqual(report
.results
[1].warningCount
, 0);
1191 assert
.strictEqual(report
.results
[1].fixableErrorCount
, 3);
1192 assert
.strictEqual(report
.results
[1].fixableWarningCount
, 0);
1193 assert
.strictEqual(report
.results
[2].errorCount
, 3);
1194 assert
.strictEqual(report
.results
[2].warningCount
, 0);
1195 assert
.strictEqual(report
.results
[2].fixableErrorCount
, 3);
1196 assert
.strictEqual(report
.results
[2].fixableWarningCount
, 0);
1199 it("should process when file is given by not specifying extensions", () => {
1201 engine
= new CLIEngine({
1203 cwd
: path
.join(fixtureDir
, "..")
1206 const report
= engine
.executeOnFiles(["fixtures/files/foo.js2"]);
1208 assert
.strictEqual(report
.results
.length
, 1);
1209 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1212 it("should return zero messages when given a config with environment set to browser", () => {
1214 engine
= new CLIEngine({
1215 cwd
: path
.join(fixtureDir
, ".."),
1216 configFile
: getFixturePath("configurations", "env-browser.json")
1219 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1221 assert
.strictEqual(report
.results
.length
, 1);
1222 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1225 it("should return zero messages when given an option to set environment to browser", () => {
1227 engine
= new CLIEngine({
1228 cwd
: path
.join(fixtureDir
, ".."),
1236 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1238 assert
.strictEqual(report
.results
.length
, 1);
1239 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1242 it("should return zero messages when given a config with environment set to Node.js", () => {
1244 engine
= new CLIEngine({
1245 cwd
: path
.join(fixtureDir
, ".."),
1246 configFile
: getFixturePath("configurations", "env-node.json")
1249 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-node.js"))]);
1251 assert
.strictEqual(report
.results
.length
, 1);
1252 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1255 it("should not return results from previous call when calling more than once", () => {
1257 engine
= new CLIEngine({
1258 cwd
: path
.join(fixtureDir
, ".."),
1265 const failFilePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1266 const passFilePath
= fs
.realpathSync(getFixturePath("passing.js"));
1268 let report
= engine
.executeOnFiles([failFilePath
]);
1270 assert
.strictEqual(report
.results
.length
, 1);
1271 assert
.strictEqual(report
.results
[0].filePath
, failFilePath
);
1272 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1273 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "semi");
1274 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1276 report
= engine
.executeOnFiles([passFilePath
]);
1277 assert
.strictEqual(report
.results
.length
, 1);
1278 assert
.strictEqual(report
.results
[0].filePath
, passFilePath
);
1279 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1283 it("should throw an error when given a directory with all eslint excluded files in the directory", () => {
1285 engine
= new CLIEngine({
1286 ignorePath
: getFixturePath(".eslintignore")
1289 assert
.throws(() => {
1290 engine
.executeOnFiles([getFixturePath("./cli-engine/")]);
1291 }, `All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`);
1294 it("should throw an error when all given files are ignored", () => {
1296 engine
= new CLIEngine({
1297 ignorePath
: getFixturePath(".eslintignore")
1300 assert
.throws(() => {
1301 engine
.executeOnFiles(["tests/fixtures/cli-engine/"]);
1302 }, "All files matched by 'tests/fixtures/cli-engine/' are ignored.");
1305 it("should throw an error when all given files are ignored even with a `./` prefix", () => {
1306 engine
= new CLIEngine({
1307 ignorePath
: getFixturePath(".eslintignore")
1310 assert
.throws(() => {
1311 engine
.executeOnFiles(["./tests/fixtures/cli-engine/"]);
1312 }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
1315 // https://github.com/eslint/eslint/issues/3788
1316 it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", () => {
1317 engine
= new CLIEngine({
1318 ignorePath
: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
1321 quotes
: [2, "double"]
1323 cwd
: getFixturePath("cli-engine", "nested_node_modules")
1326 const report
= engine
.executeOnFiles(["."]);
1328 assert
.strictEqual(report
.results
.length
, 1);
1329 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1330 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1331 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1332 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1335 // https://github.com/eslint/eslint/issues/3812
1336 it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", () => {
1337 engine
= new CLIEngine({
1338 ignorePath
: getFixturePath("cli-engine/.eslintignore2"),
1341 quotes
: [2, "double"]
1345 assert
.throws(() => {
1346 engine
.executeOnFiles(["./tests/fixtures/cli-engine/"]);
1347 }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
1350 it("should throw an error when all given files are ignored via ignore-pattern", () => {
1351 engine
= new CLIEngine({
1352 ignorePattern
: "tests/fixtures/single-quoted.js"
1355 assert
.throws(() => {
1356 engine
.executeOnFiles(["tests/fixtures/*-quoted.js"]);
1357 }, "All files matched by 'tests/fixtures/*-quoted.js' are ignored.");
1360 it("should return a warning when an explicitly given file is ignored", () => {
1361 engine
= new CLIEngine({
1362 ignorePath
: getFixturePath(".eslintignore"),
1363 cwd
: getFixturePath()
1366 const filePath
= getFixturePath("passing.js");
1368 const report
= engine
.executeOnFiles([filePath
]);
1370 assert
.strictEqual(report
.results
.length
, 1);
1371 assert
.strictEqual(report
.errorCount
, 0);
1372 assert
.strictEqual(report
.warningCount
, 1);
1373 assert
.strictEqual(report
.fixableErrorCount
, 0);
1374 assert
.strictEqual(report
.fixableWarningCount
, 0);
1375 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1376 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1377 assert
.strictEqual(report
.results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
1378 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1379 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1380 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1381 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1384 it("should return two messages when given a file in excluded files list while ignore is off", () => {
1386 engine
= new CLIEngine({
1387 ignorePath
: getFixturePath(".eslintignore"),
1394 const filePath
= fs
.realpathSync(getFixturePath("undef.js"));
1396 const report
= engine
.executeOnFiles([filePath
]);
1398 assert
.strictEqual(report
.results
.length
, 1);
1399 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1400 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-undef");
1401 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1402 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-undef");
1403 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 2);
1406 it("should return zero messages when executing a file with a shebang", () => {
1408 engine
= new CLIEngine({
1412 const report
= engine
.executeOnFiles([getFixturePath("shebang.js")]);
1414 assert
.strictEqual(report
.results
.length
, 1);
1415 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1418 it("should give a warning when loading a custom rule that doesn't exist", () => {
1420 engine
= new CLIEngine({
1422 rulesPaths
: [getFixturePath("rules", "dir1")],
1423 configFile
: getFixturePath("rules", "missing-rule.json")
1425 const report
= engine
.executeOnFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1427 assert
.strictEqual(report
.results
.length
, 1);
1428 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1429 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "missing-rule");
1430 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1431 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Definition for rule 'missing-rule' was not found.");
1436 it("should throw an error when loading a bad custom rule", () => {
1438 engine
= new CLIEngine({
1440 rulePaths
: [getFixturePath("rules", "wrong")],
1441 configFile
: getFixturePath("rules", "eslint.json")
1445 assert
.throws(() => {
1446 engine
.executeOnFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1447 }, /Error while loading rule 'custom-rule'/u);
1450 it("should return one message when a custom rule matches a file", () => {
1452 engine
= new CLIEngine({
1455 rulePaths
: [getFixturePath("rules/")],
1456 configFile
: getFixturePath("rules", "eslint.json")
1459 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1461 const report
= engine
.executeOnFiles([filePath
]);
1463 assert
.strictEqual(report
.results
.length
, 1);
1464 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1465 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1466 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "custom-rule");
1467 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1470 it("should load custom rule from the provided cwd", () => {
1471 const cwd
= path
.resolve(getFixturePath("rules"));
1473 engine
= new CLIEngine({
1477 configFile
: "eslint.json"
1480 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1482 const report
= engine
.executeOnFiles([filePath
]);
1484 assert
.strictEqual(report
.results
.length
, 1);
1485 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1486 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1487 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "custom-rule");
1488 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1491 it("should return messages when multiple custom rules match a file", () => {
1493 engine
= new CLIEngine({
1496 getFixturePath("rules", "dir1"),
1497 getFixturePath("rules", "dir2")
1499 configFile
: getFixturePath("rules", "multi-rulesdirs.json")
1502 const filePath
= fs
.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.js"));
1504 const report
= engine
.executeOnFiles([filePath
]);
1506 assert
.strictEqual(report
.results
.length
, 1);
1507 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1508 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1509 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-literals");
1510 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1511 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-strings");
1512 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 2);
1515 it("should return zero messages when executing without useEslintrc flag", () => {
1517 engine
= new CLIEngine({
1522 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1524 const report
= engine
.executeOnFiles([filePath
]);
1526 assert
.strictEqual(report
.results
.length
, 1);
1527 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1528 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1531 it("should return zero messages when executing without useEslintrc flag in Node.js environment", () => {
1533 engine
= new CLIEngine({
1539 const filePath
= fs
.realpathSync(getFixturePath("process-exit.js"));
1541 const report
= engine
.executeOnFiles([filePath
]);
1543 assert
.strictEqual(report
.results
.length
, 1);
1544 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1545 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1548 it("should return zero messages when executing with base-config flag set to false", () => {
1550 engine
= new CLIEngine({
1556 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1558 const report
= engine
.executeOnFiles([filePath
]);
1560 assert
.strictEqual(report
.results
.length
, 1);
1561 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1562 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1565 it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", () => {
1567 engine
= new CLIEngine({
1573 const filePath
= fs
.realpathSync(getFixturePath("eslintrc", "quotes.js"));
1575 const report
= engine
.executeOnFiles([filePath
]);
1577 assert
.strictEqual(report
.results
.length
, 1);
1578 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1579 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1582 it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", () => {
1584 engine
= new CLIEngine({
1590 const filePath
= fs
.realpathSync(getFixturePath("packagejson", "quotes.js"));
1592 const report
= engine
.executeOnFiles([filePath
]);
1594 assert
.strictEqual(report
.results
.length
, 1);
1595 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1596 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1599 it("should warn when deprecated rules are configured", () => {
1600 engine
= new CLIEngine({
1602 configFile
: ".eslintrc.js",
1610 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1612 assert
.sameDeepMembers(
1613 report
.usedDeprecatedRules
,
1615 { ruleId
: "indent-legacy", replacedBy
: ["indent"] },
1616 { ruleId
: "require-jsdoc", replacedBy
: [] },
1617 { ruleId
: "valid-jsdoc", replacedBy
: [] }
1622 it("should not warn when deprecated rules are not configured", () => {
1623 engine
= new CLIEngine({
1625 configFile
: ".eslintrc.js",
1626 rules
: { indent
: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
1629 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1631 assert
.deepStrictEqual(report
.usedDeprecatedRules
, []);
1634 it("should warn when deprecated rules are found in a config", () => {
1635 engine
= new CLIEngine({
1637 configFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
1641 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1643 assert
.deepStrictEqual(
1644 report
.usedDeprecatedRules
,
1645 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
1649 describe("Fix Mode", () => {
1651 it("should return fixed text on multiple files when in fix mode", () => {
1654 * Converts CRLF to LF in output.
1655 * This is a workaround for git's autocrlf option on Windows.
1656 * @param {Object} result A result object to convert.
1659 function convertCRLF(result
) {
1660 if (result
&& result
.output
) {
1661 result
.output
= result
.output
.replace(/\r\n/gu, "\n");
1665 engine
= new CLIEngine({
1666 cwd
: path
.join(fixtureDir
, ".."),
1671 quotes
: [2, "double"],
1674 "space-infix-ops": 2
1678 const report
= engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1680 report
.results
.forEach(convertCRLF
);
1681 assert
.deepStrictEqual(report
.results
, [
1683 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/multipass.js")),
1687 fixableErrorCount
: 0,
1688 fixableWarningCount
: 0,
1689 output
: "true ? \"yes\" : \"no\";\n"
1692 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/ok.js")),
1696 fixableErrorCount
: 0,
1697 fixableWarningCount
: 0
1700 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes-semi-eqeqeq.js")),
1707 message
: "Expected '===' and instead saw '=='.",
1708 messageId
: "unexpected",
1709 nodeType
: "BinaryExpression",
1716 fixableErrorCount
: 0,
1717 fixableWarningCount
: 0,
1718 output
: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n"
1721 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes.js")),
1729 message
: "'foo' is not defined.",
1730 nodeType
: "Identifier",
1737 fixableErrorCount
: 0,
1738 fixableWarningCount
: 0,
1739 output
: "var msg = \"hi\" + foo;\n"
1742 assert
.strictEqual(report
.errorCount
, 2);
1743 assert
.strictEqual(report
.warningCount
, 0);
1744 assert
.strictEqual(report
.fixableErrorCount
, 0);
1745 assert
.strictEqual(report
.fixableWarningCount
, 0);
1748 it("should run autofix even if files are cached without autofix results", () => {
1749 const baseOptions
= {
1750 cwd
: path
.join(fixtureDir
, ".."),
1754 quotes
: [2, "double"],
1757 "space-infix-ops": 2
1761 engine
= new CLIEngine(Object
.assign({}, baseOptions
, { cache
: true, fix
: false }));
1763 // Do initial lint run and populate the cache file
1764 engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1766 engine
= new CLIEngine(Object
.assign({}, baseOptions
, { cache
: true, fix
: true }));
1768 const report
= engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1770 assert
.ok(report
.results
.some(result
=> result
.output
));
1775 // These tests have to do with https://github.com/eslint/eslint/issues/963
1777 describe("configuration hierarchy", () => {
1779 // Default configuration - blank
1780 it("should return zero messages when executing with no .eslintrc", () => {
1782 engine
= new CLIEngine({
1783 cwd
: path
.join(fixtureDir
, ".."),
1787 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1789 assert
.strictEqual(report
.results
.length
, 1);
1790 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1793 // No default configuration rules - conf/environments.js (/*eslint-env node*/)
1794 it("should return zero messages when executing with no .eslintrc in the Node.js environment", () => {
1796 engine
= new CLIEngine({
1797 cwd
: path
.join(fixtureDir
, ".."),
1802 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
1804 assert
.strictEqual(report
.results
.length
, 1);
1805 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1808 // Project configuration - first level .eslintrc
1809 it("should return zero messages when executing with .eslintrc in the Node.js environment", () => {
1811 engine
= new CLIEngine({
1812 cwd
: path
.join(fixtureDir
, "..")
1815 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1817 assert
.strictEqual(report
.results
.length
, 1);
1818 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1821 // Project configuration - first level .eslintrc
1822 it("should return zero messages when executing with .eslintrc in the Node.js environment", () => {
1824 engine
= new CLIEngine({
1825 cwd
: path
.join(fixtureDir
, "..")
1828 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1830 assert
.strictEqual(report
.results
.length
, 1);
1831 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1834 // Project configuration - first level .eslintrc
1835 it("should return one message when executing with .eslintrc", () => {
1837 engine
= new CLIEngine({
1838 cwd
: path
.join(fixtureDir
, "..")
1841 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1843 assert
.strictEqual(report
.results
.length
, 1);
1844 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1845 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1846 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1849 // Project configuration - second level .eslintrc
1850 it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", () => {
1852 engine
= new CLIEngine({
1853 cwd
: path
.join(fixtureDir
, "..")
1856 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1858 assert
.strictEqual(report
.results
.length
, 1);
1859 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1860 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1861 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1864 // Project configuration - third level .eslintrc
1865 it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", () => {
1867 engine
= new CLIEngine({
1868 cwd
: path
.join(fixtureDir
, "..")
1871 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
1873 assert
.strictEqual(report
.results
.length
, 1);
1874 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1875 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1876 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1879 // Project configuration - first level package.json
1880 it("should return one message when executing with package.json", () => {
1882 engine
= new CLIEngine({
1883 cwd
: path
.join(fixtureDir
, "..")
1886 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
1888 assert
.strictEqual(report
.results
.length
, 1);
1889 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1890 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1891 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1894 // Project configuration - second level package.json
1895 it("should return zero messages when executing with local package.json that overrides parent package.json", () => {
1897 engine
= new CLIEngine({
1898 cwd
: path
.join(fixtureDir
, "..")
1901 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
1903 assert
.strictEqual(report
.results
.length
, 1);
1904 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1907 // Project configuration - third level package.json
1908 it("should return one message when executing with local package.json that overrides parent and grandparent package.json", () => {
1910 engine
= new CLIEngine({
1911 cwd
: path
.join(fixtureDir
, "..")
1914 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
1916 assert
.strictEqual(report
.results
.length
, 1);
1917 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1918 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1919 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1922 // Project configuration - .eslintrc overrides package.json in same directory
1923 it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", () => {
1925 engine
= new CLIEngine({
1926 cwd
: path
.join(fixtureDir
, "..")
1929 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
1931 assert
.strictEqual(report
.results
.length
, 1);
1932 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1933 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1934 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1937 // Command line configuration - --config with first level .eslintrc
1938 it("should return two messages when executing with config file that adds to local .eslintrc", () => {
1940 engine
= new CLIEngine({
1941 cwd
: path
.join(fixtureDir
, ".."),
1942 configFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1945 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1947 assert
.strictEqual(report
.results
.length
, 1);
1948 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1949 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1950 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1951 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "semi");
1952 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 1);
1955 // Command line configuration - --config with first level .eslintrc
1956 it("should return no messages when executing with config file that overrides local .eslintrc", () => {
1958 engine
= new CLIEngine({
1959 cwd
: path
.join(fixtureDir
, ".."),
1960 configFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1963 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1965 assert
.strictEqual(report
.results
.length
, 1);
1966 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1969 // Command line configuration - --config with second level .eslintrc
1970 it("should return two messages when executing with config file that adds to local and parent .eslintrc", () => {
1972 engine
= new CLIEngine({
1973 cwd
: path
.join(fixtureDir
, ".."),
1974 configFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1977 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1979 assert
.strictEqual(report
.results
.length
, 1);
1980 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1981 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1982 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1983 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "semi");
1984 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 1);
1987 // Command line configuration - --config with second level .eslintrc
1988 it("should return one message when executing with config file that overrides local and parent .eslintrc", () => {
1990 engine
= new CLIEngine({
1991 cwd
: path
.join(fixtureDir
, ".."),
1992 configFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml")
1995 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1997 assert
.strictEqual(report
.results
.length
, 1);
1998 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1999 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
2000 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2003 // Command line configuration - --config with first level .eslintrc
2004 it("should return no messages when executing with config file that overrides local .eslintrc", () => {
2006 engine
= new CLIEngine({
2007 cwd
: path
.join(fixtureDir
, ".."),
2008 configFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
2011 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2013 assert
.strictEqual(report
.results
.length
, 1);
2014 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
2017 // Command line configuration - --rule with --config and first level .eslintrc
2018 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", () => {
2020 engine
= new CLIEngine({
2021 cwd
: path
.join(fixtureDir
, ".."),
2022 configFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
2024 quotes
: [1, "double"]
2028 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2030 assert
.strictEqual(report
.results
.length
, 1);
2031 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2032 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2033 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2036 // Command line configuration - --rule with --config and first level .eslintrc
2037 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", () => {
2039 engine
= new CLIEngine({
2040 cwd
: path
.join(fixtureDir
, ".."),
2041 configFile
: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
2043 quotes
: [1, "double"]
2047 const report
= engine
.executeOnFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
2049 assert
.strictEqual(report
.results
.length
, 1);
2050 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2051 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2052 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2057 describe("plugins", () => {
2058 it("should return two messages when executing with config file that specifies a plugin", () => {
2059 engine
= cliEngineWithPlugins({
2060 cwd
: path
.join(fixtureDir
, ".."),
2061 configFile
: getFixturePath("configurations", "plugins-with-prefix.json"),
2065 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
2067 assert
.strictEqual(report
.results
.length
, 1);
2068 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2069 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2072 it("should return two messages when executing with config file that specifies a plugin with namespace", () => {
2073 engine
= cliEngineWithPlugins({
2074 cwd
: path
.join(fixtureDir
, ".."),
2075 configFile
: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
2079 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2081 assert
.strictEqual(report
.results
.length
, 1);
2082 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2083 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2086 it("should return two messages when executing with config file that specifies a plugin without prefix", () => {
2087 engine
= cliEngineWithPlugins({
2088 cwd
: path
.join(fixtureDir
, ".."),
2089 configFile
: getFixturePath("configurations", "plugins-without-prefix.json"),
2093 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2095 assert
.strictEqual(report
.results
.length
, 1);
2096 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2097 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2100 it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", () => {
2101 engine
= cliEngineWithPlugins({
2102 cwd
: path
.join(fixtureDir
, ".."),
2103 configFile
: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
2107 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2109 assert
.strictEqual(report
.results
.length
, 1);
2110 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2111 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2114 it("should return two messages when executing with cli option that specifies a plugin", () => {
2115 engine
= cliEngineWithPlugins({
2116 cwd
: path
.join(fixtureDir
, ".."),
2118 plugins
: ["example"],
2119 rules
: { "example/example-rule": 1 }
2122 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2124 assert
.strictEqual(report
.results
.length
, 1);
2125 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2126 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2129 it("should return two messages when executing with cli option that specifies preloaded plugin", () => {
2130 engine
= new CLIEngine({
2131 cwd
: path
.join(fixtureDir
, ".."),
2134 rules
: { "test/example-rule": 1 }
2137 engine
.addPlugin("eslint-plugin-test", { rules
: { "example-rule": require("../../fixtures/rules/custom-rule") } });
2139 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2141 assert
.strictEqual(report
.results
.length
, 1);
2142 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2143 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "test/example-rule");
2146 it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", () => {
2147 engine
= new CLIEngine({
2148 resolvePluginsRelativeTo
: getFixturePath("plugins"),
2150 plugins
: ["with-rules"],
2151 rules
: { "with-rules/rule1": "error" }
2156 const report
= engine
.executeOnText("foo");
2158 assert
.strictEqual(report
.results
.length
, 1);
2159 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2160 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "with-rules/rule1");
2161 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Rule report from plugin");
2165 describe("cache", () => {
2168 * helper method to delete a file without caring about exceptions
2169 * @param {string} filePath The file path
2172 function doDelete(filePath
) {
2174 fs
.unlinkSync(filePath
);
2178 * we don't care if the file didn't exist, since our
2179 * intention was to remove the file
2185 * helper method to delete the cache files created during testing
2188 function deleteCache() {
2189 doDelete(path
.resolve(".eslintcache"));
2190 doDelete(path
.resolve(".cache/custom-cache"));
2202 describe("when the cacheFile is a directory or looks like a directory", () => {
2205 * helper method to delete the cache files created during testing
2208 function deleteCacheDir() {
2210 fs
.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
2214 * we don't care if the file didn't exist, since our
2215 * intention was to remove the file
2227 it("should create the cache file inside the provided directory", () => {
2228 assert
.isFalse(shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2230 engine
= new CLIEngine({
2233 // specifying cache true the cache will be created
2235 cacheFile
: "./tmp/.cacheFileDir/",
2244 const file
= getFixturePath("cache/src", "test-file.js");
2246 engine
.executeOnFiles([file
]);
2248 assert
.isTrue(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2254 it("should create the cache file inside the provided directory using the cacheLocation option", () => {
2255 assert
.isFalse(shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2257 engine
= new CLIEngine({
2260 // specifying cache true the cache will be created
2262 cacheLocation
: "./tmp/.cacheFileDir/",
2271 const file
= getFixturePath("cache/src", "test-file.js");
2273 engine
.executeOnFiles([file
]);
2275 assert
.isTrue(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2280 it("should create the cache file inside cwd when no cacheLocation provided", () => {
2281 const cwd
= path
.resolve(getFixturePath("cli-engine"));
2283 engine
= new CLIEngine({
2294 const file
= getFixturePath("cli-engine", "console.js");
2296 engine
.executeOnFiles([file
]);
2298 assert
.isTrue(shell
.test("-f", path
.resolve(cwd
, ".eslintcache")), "the cache for eslint was created at provided cwd");
2301 it("should invalidate the cache if the configuration changed between executions", () => {
2302 assert
.isFalse(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2304 engine
= new CLIEngine({
2307 // specifying cache true the cache will be created
2317 let spy
= sinon
.spy(fs
, "readFileSync");
2319 let file
= getFixturePath("cache/src", "test-file.js");
2321 file
= fs
.realpathSync(file
);
2323 const result
= engine
.executeOnFiles([file
]);
2325 assert
.strictEqual(result
.errorCount
+ result
.warningCount
, 0, "the file passed without errors or warnings");
2326 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2327 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2332 engine
= new CLIEngine({
2335 // specifying cache true the cache will be created
2346 spy
= sinon
.spy(fs
, "readFileSync");
2348 const cachedResult
= engine
.executeOnFiles([file
]);
2350 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed because the config changed");
2351 assert
.strictEqual(cachedResult
.errorCount
, 1, "since configuration changed the cache was not used an one error was reported");
2352 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2355 it("should remember the files from a previous run and do not operate on them if not changed", () => {
2357 assert
.isFalse(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2359 engine
= new CLIEngine({
2362 // specifying cache true the cache will be created
2372 let spy
= sinon
.spy(fs
, "readFileSync");
2374 let file
= getFixturePath("cache/src", "test-file.js");
2376 file
= fs
.realpathSync(file
);
2378 const result
= engine
.executeOnFiles([file
]);
2380 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2381 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2386 engine
= new CLIEngine({
2389 // specifying cache true the cache will be created
2400 spy
= sinon
.spy(fs
, "readFileSync");
2402 const cachedResult
= engine
.executeOnFiles([file
]);
2404 assert
.deepStrictEqual(result
, cachedResult
, "the result is the same regardless of using cache or not");
2406 // assert the file was not processed because the cache was used
2407 assert
.isFalse(spy
.calledWith(file
), "the file was not loaded because it used the cache");
2410 it("should remember the files from a previous run and do not operate on then if not changed", () => {
2412 const cacheFile
= getFixturePath(".eslintcache");
2413 const cliEngineOptions
= {
2416 // specifying cache true the cache will be created
2424 cwd
: path
.join(fixtureDir
, "..")
2427 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint does not exist");
2429 engine
= new CLIEngine(cliEngineOptions
);
2431 let file
= getFixturePath("cache/src", "test-file.js");
2433 file
= fs
.realpathSync(file
);
2435 engine
.executeOnFiles([file
]);
2437 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint was created");
2439 cliEngineOptions
.cache
= false;
2440 engine
= new CLIEngine(cliEngineOptions
);
2442 engine
.executeOnFiles([file
]);
2444 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint was deleted since last run did not used the cache");
2447 it("should store in the cache a file that failed the test", () => {
2449 const cacheFile
= getFixturePath(".eslintcache");
2451 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint does not exist");
2453 engine
= new CLIEngine({
2454 cwd
: path
.join(fixtureDir
, ".."),
2457 // specifying cache true the cache will be created
2467 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2468 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2470 const result
= engine
.executeOnFiles([badFile
, goodFile
]);
2472 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint was created");
2474 const fileCache
= fCache
.createFromFile(cacheFile
);
2475 const { cache
} = fileCache
;
2477 assert
.isTrue(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2479 assert
.isTrue(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2481 const cachedResult
= engine
.executeOnFiles([badFile
, goodFile
]);
2483 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2486 it("should not contain in the cache a file that was deleted", () => {
2488 const cacheFile
= getFixturePath(".eslintcache");
2490 doDelete(cacheFile
);
2492 engine
= new CLIEngine({
2493 cwd
: path
.join(fixtureDir
, ".."),
2496 // specifying cache true the cache will be created
2506 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2507 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2508 const toBeDeletedFile
= fs
.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
2510 engine
.executeOnFiles([badFile
, goodFile
, toBeDeletedFile
]);
2512 const fileCache
= fCache
.createFromFile(cacheFile
);
2513 let { cache
} = fileCache
;
2515 assert
.isTrue(typeof cache
.getKey(toBeDeletedFile
) === "object", "the entry for the file to be deleted is in the cache");
2517 // delete the file from the file system
2518 fs
.unlinkSync(toBeDeletedFile
);
2521 * file-entry-cache@2.0.0 will remove from the cache deleted files
2522 * even when they were not part of the array of files to be analyzed
2524 engine
.executeOnFiles([badFile
, goodFile
]);
2526 cache
= JSON
.parse(fs
.readFileSync(cacheFile
));
2528 assert
.isTrue(typeof cache
[toBeDeletedFile
] === "undefined", "the entry for the file to be deleted is not in the cache");
2531 it("should contain files that were not visited in the cache provided they still exist", () => {
2533 const cacheFile
= getFixturePath(".eslintcache");
2535 doDelete(cacheFile
);
2537 engine
= new CLIEngine({
2538 cwd
: path
.join(fixtureDir
, ".."),
2541 // specifying cache true the cache will be created
2551 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2552 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2553 const testFile2
= fs
.realpathSync(getFixturePath("cache/src", "test-file2.js"));
2555 engine
.executeOnFiles([badFile
, goodFile
, testFile2
]);
2557 let fileCache
= fCache
.createFromFile(cacheFile
);
2558 let { cache
} = fileCache
;
2560 assert
.isTrue(typeof cache
.getKey(testFile2
) === "object", "the entry for the test-file2 is in the cache");
2563 * we pass a different set of files minus test-file2
2564 * previous version of file-entry-cache would remove the non visited
2565 * entries. 2.0.0 version will keep them unless they don't exist
2567 engine
.executeOnFiles([badFile
, goodFile
]);
2569 fileCache
= fCache
.createFromFile(cacheFile
);
2570 cache
= fileCache
.cache
;
2572 assert
.isTrue(typeof cache
.getKey(testFile2
) === "object", "the entry for the test-file2 is in the cache");
2575 it("should not delete cache when executing on text", () => {
2576 const cacheFile
= getFixturePath(".eslintcache");
2578 engine
= new CLIEngine({
2579 cwd
: path
.join(fixtureDir
, ".."),
2589 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2591 engine
.executeOnText("var foo = 'bar';");
2593 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2596 it("should not delete cache when executing on text with a provided filename", () => {
2597 const cacheFile
= getFixturePath(".eslintcache");
2599 engine
= new CLIEngine({
2600 cwd
: path
.join(fixtureDir
, ".."),
2610 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2612 engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
2614 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2617 it("should not delete cache when executing on files with --cache flag", () => {
2618 const cacheFile
= getFixturePath(".eslintcache");
2620 engine
= new CLIEngine({
2621 cwd
: path
.join(fixtureDir
, ".."),
2632 const file
= getFixturePath("cli-engine", "console.js");
2634 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2636 engine
.executeOnFiles([file
]);
2638 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2641 it("should delete cache when executing on files without --cache flag", () => {
2642 const cacheFile
= getFixturePath(".eslintcache");
2644 engine
= new CLIEngine({
2645 cwd
: path
.join(fixtureDir
, ".."),
2655 const file
= getFixturePath("cli-engine", "console.js");
2657 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2659 engine
.executeOnFiles([file
]);
2661 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint has been deleted");
2664 describe("cacheFile", () => {
2665 it("should use the specified cache file", () => {
2666 const customCacheFile
= path
.resolve(".cache/custom-cache");
2668 assert
.isFalse(shell
.test("-f", customCacheFile
), "the cache for eslint does not exist");
2670 engine
= new CLIEngine({
2673 // specify a custom cache file
2674 cacheFile
: customCacheFile
,
2676 // specifying cache true the cache will be created
2683 cwd
: path
.join(fixtureDir
, "..")
2686 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2687 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2689 const result
= engine
.executeOnFiles([badFile
, goodFile
]);
2691 assert
.isTrue(shell
.test("-f", customCacheFile
), "the cache for eslint was created");
2693 const fileCache
= fCache
.createFromFile(customCacheFile
);
2694 const { cache
} = fileCache
;
2696 assert
.isTrue(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2698 assert
.isTrue(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2700 const cachedResult
= engine
.executeOnFiles([badFile
, goodFile
]);
2702 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2707 describe("processors", () => {
2708 it("should return two messages when executing with config file that specifies a processor", () => {
2709 engine
= cliEngineWithPlugins({
2710 configFile
: getFixturePath("configurations", "processors.json"),
2712 extensions
: ["js", "txt"],
2713 cwd
: path
.join(fixtureDir
, "..")
2716 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2718 assert
.strictEqual(report
.results
.length
, 1);
2719 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2721 it("should return two messages when executing with config file that specifies preloaded processor", () => {
2722 engine
= new CLIEngine({
2724 plugins
: ["test-processor"],
2729 extensions
: ["js", "txt"],
2730 cwd
: path
.join(fixtureDir
, "..")
2733 engine
.addPlugin("test-processor", {
2739 postprocess(messages
) {
2746 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2748 assert
.strictEqual(report
.results
.length
, 1);
2749 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2751 it("should run processors when calling executeOnFiles with config file that specifies a processor", () => {
2752 engine
= cliEngineWithPlugins({
2753 configFile
: getFixturePath("configurations", "processors.json"),
2755 extensions
: ["js", "txt"],
2756 cwd
: path
.join(fixtureDir
, "..")
2759 const report
= engine
.executeOnFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2761 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2762 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2764 it("should run processors when calling executeOnFiles with config file that specifies preloaded processor", () => {
2765 engine
= new CLIEngine({
2767 plugins
: ["test-processor"],
2772 extensions
: ["js", "txt"],
2773 cwd
: path
.join(fixtureDir
, "..")
2776 engine
.addPlugin("test-processor", {
2780 return [text
.replace("a()", "b()")];
2782 postprocess(messages
) {
2783 messages
[0][0].ruleId
= "post-processed";
2790 const report
= engine
.executeOnFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2792 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2793 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2795 it("should run processors when calling executeOnText with config file that specifies a processor", () => {
2796 engine
= cliEngineWithPlugins({
2797 configFile
: getFixturePath("configurations", "processors.json"),
2799 extensions
: ["js", "txt"],
2803 const report
= engine
.executeOnText("function a() {console.log(\"Test\");}", "tests/fixtures/processors/test/test-processor.txt");
2805 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2806 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2808 it("should run processors when calling executeOnText with config file that specifies preloaded processor", () => {
2809 engine
= new CLIEngine({
2811 plugins
: ["test-processor"],
2816 extensions
: ["js", "txt"],
2820 engine
.addPlugin("test-processor", {
2824 return [text
.replace("a()", "b()")];
2826 postprocess(messages
) {
2827 messages
[0][0].ruleId
= "post-processed";
2834 const report
= engine
.executeOnText("function a() {console.log(\"Test\");}", "tests/fixtures/processors/test/test-processor.txt");
2836 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2837 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2840 describe("autofixing with processors", () => {
2841 const HTML_PROCESSOR
= Object
.freeze({
2843 return [text
.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
2845 postprocess(problemLists
) {
2846 return problemLists
[0].map(problem
=> {
2848 const updatedFix
= Object
.assign({}, problem
.fix
, {
2849 range
: problem
.fix
.range
.map(index
=> index
+ "<script>".length
)
2852 return Object
.assign({}, problem
, { fix
: updatedFix
});
2860 it("should run in autofix mode when using a processor that supports autofixing", () => {
2861 engine
= new CLIEngine({
2863 plugins
: ["test-processor"],
2867 extensions
: ["js", "txt"],
2872 engine
.addPlugin("test-processor", {
2874 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2878 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2880 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
2881 assert
.strictEqual(report
.results
[0].output
, "<script>foo;</script>");
2884 it("should not run in autofix mode when using a processor that does not support autofixing", () => {
2885 engine
= new CLIEngine({
2887 plugins
: ["test-processor"],
2891 extensions
: ["js", "txt"],
2896 engine
.addPlugin("test-processor", { processors
: { ".html": HTML_PROCESSOR
} });
2898 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2900 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2901 assert
.isFalse(Object
.prototype.hasOwnProperty
.call(report
.results
[0], "output"));
2904 it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", () => {
2905 engine
= new CLIEngine({
2907 plugins
: ["test-processor"],
2911 extensions
: ["js", "txt"],
2915 engine
.addPlugin("test-processor", {
2917 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2921 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2923 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2924 assert
.isFalse(Object
.prototype.hasOwnProperty
.call(report
.results
[0], "output"));
2929 describe("Patterns which match no file should throw errors.", () => {
2931 engine
= new CLIEngine({
2932 cwd
: getFixturePath("cli-engine"),
2937 it("one file", () => {
2938 assert
.throws(() => {
2939 engine
.executeOnFiles(["non-exist.js"]);
2940 }, "No files matching 'non-exist.js' were found.");
2943 it("should throw if the directory exists and is empty", () => {
2944 assert
.throws(() => {
2945 engine
.executeOnFiles(["empty"]);
2946 }, "No files matching 'empty' were found.");
2949 it("one glob pattern", () => {
2950 assert
.throws(() => {
2951 engine
.executeOnFiles(["non-exist/**/*.js"]);
2952 }, "No files matching 'non-exist/**/*.js' were found.");
2955 it("two files", () => {
2956 assert
.throws(() => {
2957 engine
.executeOnFiles(["aaa.js", "bbb.js"]);
2958 }, "No files matching 'aaa.js' were found.");
2961 it("a mix of an existing file and a non-existing file", () => {
2962 assert
.throws(() => {
2963 engine
.executeOnFiles(["console.js", "non-exist.js"]);
2964 }, "No files matching 'non-exist.js' were found.");
2968 describe("overrides", () => {
2970 engine
= new CLIEngine({
2971 cwd
: getFixturePath("cli-engine/overrides-with-dot"),
2976 it("should recognize dotfiles", () => {
2977 const ret
= engine
.executeOnFiles([".test-target.js"]);
2979 assert
.strictEqual(ret
.results
.length
, 1);
2980 assert
.strictEqual(ret
.results
[0].messages
.length
, 1);
2981 assert
.strictEqual(ret
.results
[0].messages
[0].ruleId
, "no-unused-vars");
2985 describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
2987 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
2988 cwd
: path
.join(os
.tmpdir(), "cli-engine/11510"),
2990 "no-console-error-in-overrides.json": {
2993 rules
: { "no-console": "error" }
2997 extends: "./no-console-error-in-overrides.json",
2998 rules
: { "no-console": "off" }
3000 "a.js": "console.log();"
3005 engine
= new CLIEngine({
3014 it("should not report 'no-console' error.", () => {
3015 const { results
} = engine
.executeOnFiles("a.js");
3017 assert
.strictEqual(results
.length
, 1);
3018 assert
.deepStrictEqual(results
[0].messages
, []);
3022 describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
3023 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3024 cwd
: path
.join(os
.tmpdir(), "cli-engine/11559"),
3026 "node_modules/eslint-plugin-test/index.js": `
3028 recommended: { plugins: ["test"] }
3032 meta: { schema: [{ type: "number" }] },
3033 create() { return {}; }
3039 // Import via the recommended config.
3040 extends: "plugin:test/recommended",
3042 // Has invalid option.
3043 rules
: { "test/foo": ["error", "invalid-option"] }
3045 "a.js": "console.log();"
3050 engine
= new CLIEngine({
3059 it("should throw fatal error.", () => {
3060 assert
.throws(() => {
3061 engine
.executeOnFiles("a.js");
3062 }, /invalid-option/u);
3066 describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
3068 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3069 cwd
: path
.join(os
.tmpdir(), "cli-engine/11586"),
3071 "node_modules/eslint-plugin-test/index.js": `
3074 meta: { type: "problem", fixable: "code" },
3078 if (node.name === "example") {
3082 fix: fixer => fixer.replaceText(node, "fixed")
3093 rules
: { "test/no-example": "error" }
3100 engine
= new CLIEngine({
3103 fixTypes
: ["problem"]
3112 it("should not crash.", () => {
3113 const { results
} = engine
.executeOnFiles("a.js");
3115 assert
.strictEqual(results
.length
, 1);
3116 assert
.deepStrictEqual(results
[0].messages
, []);
3117 assert
.deepStrictEqual(results
[0].output
, "fixed;");
3121 describe("multiple processors", () => {
3122 const root
= path
.join(os
.tmpdir(), "eslint/cli-engine/multiple-processors");
3123 const commonFiles
= {
3124 "node_modules/pattern-processor/index.js": fs
.readFileSync(
3125 require
.resolve("../../fixtures/processors/pattern-processor"),
3128 "node_modules/eslint-plugin-markdown/index.js": `
3129 const { defineProcessor } = require("pattern-processor");
3130 const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
3131 exports.processors = {
3132 ".md": { ...processor, supportsAutofix: true },
3133 "non-fixable": processor
3136 "node_modules/eslint-plugin-html/index.js": `
3137 const { defineProcessor } = require("pattern-processor");
3138 const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
3139 const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
3140 exports.processors = {
3141 ".html": { ...processor, supportsAutofix: true },
3142 "non-fixable": processor,
3143 "legacy": legacyProcessor
3146 "test.md": unIndent
`
3148 console
.log("hello")
3153 console
.log("hello")
3156 console
.log("hello")
3168 afterEach(() => cleanup());
3170 it("should lint only JavaScript blocks if '--ext' was not given.", async () => {
3171 const teardown
= createCustomTeardown({
3176 plugins
: ["markdown", "html"],
3177 rules
: { semi
: "error" }
3182 cleanup
= teardown
.cleanup
;
3183 await teardown
.prepare();
3184 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3186 const { results
} = engine
.executeOnFiles(["test.md"]);
3188 assert
.strictEqual(results
.length
, 1);
3189 assert
.strictEqual(results
[0].messages
.length
, 1);
3190 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3191 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3194 it("should fix only JavaScript blocks if '--ext' was not given.", async () => {
3196 const teardown
= createCustomTeardown({
3201 plugins
: ["markdown", "html"],
3202 rules
: { semi
: "error" }
3207 await teardown
.prepare();
3208 cleanup
= teardown
.cleanup
;
3209 engine
= new CLIEngine({
3210 cwd
: teardown
.getPath(),
3214 const { results
} = engine
.executeOnFiles(["test.md"]);
3216 assert
.strictEqual(results
.length
, 1);
3217 assert
.strictEqual(results
[0].messages
.length
, 0);
3218 assert
.strictEqual(results
[0].output
, unIndent
`
3220 console
.log("hello");${/* ← fixed */""}
3225 console
.log("hello")${/* ← ignored */""}
3228 console
.log("hello")${/* ← ignored */""}
3234 it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3235 const teardown
= createCustomTeardown({
3240 plugins
: ["markdown", "html"],
3241 rules
: { semi
: "error" }
3246 await teardown
.prepare();
3247 cleanup
= teardown
.cleanup
;
3248 engine
= new CLIEngine({
3249 cwd
: teardown
.getPath(),
3250 extensions
: ["js", "html"]
3253 const { results
} = engine
.executeOnFiles(["test.md"]);
3255 assert
.strictEqual(results
.length
, 1);
3256 assert
.strictEqual(results
[0].messages
.length
, 2);
3257 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3258 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3259 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3260 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3263 it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3264 const teardown
= createCustomTeardown({
3269 plugins
: ["markdown", "html"],
3270 rules
: { semi
: "error" }
3275 await teardown
.prepare();
3276 cleanup
= teardown
.cleanup
;
3277 engine
= new CLIEngine({
3278 cwd
: teardown
.getPath(),
3279 extensions
: ["js", "html"],
3283 const { results
} = engine
.executeOnFiles(["test.md"]);
3285 assert
.strictEqual(results
.length
, 1);
3286 assert
.strictEqual(results
[0].messages
.length
, 0);
3287 assert
.strictEqual(results
[0].output
, unIndent
`
3289 console
.log("hello");${/* ← fixed */""}
3294 console
.log("hello");${/* ← fixed */""}
3297 console
.log("hello")${/* ← ignored */""}
3303 it("should use overridden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", async () => {
3305 const teardown
= createCustomTeardown({
3310 plugins
: ["markdown", "html"],
3311 rules
: { semi
: "error" },
3315 processor
: "html/non-fixable" // supportsAutofix: false
3322 await teardown
.prepare();
3323 cleanup
= teardown
.cleanup
;
3324 engine
= new CLIEngine({
3325 cwd
: teardown
.getPath(),
3326 extensions
: ["js", "html"],
3330 const { results
} = engine
.executeOnFiles(["test.md"]);
3332 assert
.strictEqual(results
.length
, 1);
3333 assert
.strictEqual(results
[0].messages
.length
, 1);
3334 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS Block in HTML Block
3335 assert
.strictEqual(results
[0].messages
[0].line
, 7);
3336 assert
.strictEqual(results
[0].messages
[0].fix
, void 0);
3337 assert
.strictEqual(results
[0].output
, unIndent
`
3339 console
.log("hello");${/* ← fixed */""}
3344 console
.log("hello")${/* ← reported but not fixed */""}
3347 console
.log("hello")
3353 it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", async () => {
3355 const teardown
= createCustomTeardown({
3360 plugins
: ["markdown", "html"],
3361 rules
: { semi
: "error" },
3366 // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
3373 files
: "**/*.html/*.js",
3376 "no-console": "error"
3384 await teardown
.prepare();
3385 cleanup
= teardown
.cleanup
;
3386 engine
= new CLIEngine({
3387 cwd
: teardown
.getPath(),
3388 extensions
: ["js", "html"]
3391 const { results
} = engine
.executeOnFiles(["test.md"]);
3393 assert
.strictEqual(results
.length
, 1);
3394 assert
.strictEqual(results
[0].messages
.length
, 2);
3395 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3396 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3397 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3398 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3401 it("should use the same config as one which has 'processor' property in order to lint blocks in HTML if the processor was legacy style.", async () => {
3403 const teardown
= createCustomTeardown({
3408 plugins
: ["markdown", "html"],
3409 rules
: { semi
: "error" },
3413 processor
: "html/legacy", // this processor returns strings rather than `{text, filename}`
3416 "no-console": "error"
3420 files
: "**/*.html/*.js",
3431 await teardown
.prepare();
3432 cleanup
= teardown
.cleanup
;
3433 engine
= new CLIEngine({
3434 cwd
: teardown
.getPath(),
3435 extensions
: ["js", "html"]
3438 const { results
} = engine
.executeOnFiles(["test.md"]);
3440 assert
.strictEqual(results
.length
, 1);
3441 assert
.strictEqual(results
[0].messages
.length
, 3);
3442 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3443 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3444 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3445 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3446 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-console");
3447 assert
.strictEqual(results
[0].messages
[2].line
, 10);
3450 it("should throw an error if invalid processor was specified.", async () => {
3452 const teardown
= createCustomTeardown({
3457 plugins
: ["markdown", "html"],
3458 processor
: "markdown/unknown"
3463 await teardown
.prepare();
3464 cleanup
= teardown
.cleanup
;
3465 engine
= new CLIEngine({
3466 cwd
: teardown
.getPath()
3469 assert
.throws(() => {
3470 engine
.executeOnFiles(["test.md"]);
3471 }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
3474 it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", async () => {
3476 const teardown
= createCustomTeardown({
3481 plugins
: ["markdown", "html"],
3482 rules
: { semi
: "error" },
3486 processor
: "html/.html"
3490 processor
: "markdown/.md"
3497 await teardown
.prepare();
3498 cleanup
= teardown
.cleanup
;
3499 engine
= new CLIEngine({
3500 cwd
: teardown
.getPath()
3503 const { results
} = engine
.executeOnFiles(["test.md"]);
3505 assert
.strictEqual(results
.length
, 1);
3506 assert
.strictEqual(results
[0].messages
.length
, 2);
3507 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3508 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3509 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3510 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3514 describe("MODULE_NOT_FOUND error handling", () => {
3515 const cwd
= getFixturePath("module-not-found");
3518 engine
= new CLIEngine({ cwd
});
3521 it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", () => {
3523 engine
.executeOnText("test", "extends-js/test.js");
3525 assert
.strictEqual(err
.messageTemplate
, "extend-config-missing");
3526 assert
.deepStrictEqual(err
.messageData
, {
3527 configName
: "nonexistent-config",
3528 importerName
: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
3532 assert
.fail("Expected to throw an error");
3535 it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", () => {
3537 engine
.executeOnText("test", "extends-plugin/test.js");
3539 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3540 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3541 assert
.deepStrictEqual(err
.messageData
, {
3542 importerName
: `extends-plugin${path.sep}.eslintrc.yml`,
3543 pluginName
: "eslint-plugin-nonexistent-plugin",
3544 resolvePluginsRelativeTo
: path
.join(cwd
, "extends-plugin") // the directory of the config file.
3548 assert
.fail("Expected to throw an error");
3551 it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", () => {
3553 engine
.executeOnText("test", "plugins/test.js");
3555 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3556 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3557 assert
.deepStrictEqual(err
.messageData
, {
3558 importerName
: `plugins${path.sep}.eslintrc.yml`,
3559 pluginName
: "eslint-plugin-nonexistent-plugin",
3560 resolvePluginsRelativeTo
: path
.join(cwd
, "plugins") // the directory of the config file.
3564 assert
.fail("Expected to throw an error");
3567 it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", () => {
3569 engine
.executeOnText("test", "throw-in-config-itself/test.js");
3571 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3572 assert
.strictEqual(err
.messageTemplate
, void 0);
3575 assert
.fail("Expected to throw an error");
3578 it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", () => {
3580 engine
.executeOnText("test", "throw-in-extends-js/test.js");
3582 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3583 assert
.strictEqual(err
.messageTemplate
, void 0);
3586 assert
.fail("Expected to throw an error");
3589 it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", () => {
3591 engine
.executeOnText("test", "throw-in-extends-plugin/test.js");
3593 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3594 assert
.strictEqual(err
.messageTemplate
, void 0);
3597 assert
.fail("Expected to throw an error");
3600 it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", () => {
3602 engine
.executeOnText("test", "throw-in-plugins/test.js");
3604 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3605 assert
.strictEqual(err
.messageTemplate
, void 0);
3608 assert
.fail("Expected to throw an error");
3612 describe("with '--rulesdir' option", () => {
3614 const rootPath
= getFixturePath("cli-engine/with-rulesdir");
3616 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3619 "internal-rules/test.js": `
3620 module.exports = context => ({
3621 ExpressionStatement(node) {
3622 context.report({ node, message: "ok" })
3628 rules
: { test
: "error" }
3630 "test.js": "console.log('hello')"
3634 beforeEach(prepare
);
3638 it("should use the configured rules which are defined by '--rulesdir' option.", () => {
3640 engine
= new CLIEngine({
3642 rulePaths
: ["internal-rules"]
3644 const report
= engine
.executeOnFiles(["test.js"]);
3646 assert
.strictEqual(report
.results
.length
, 1);
3647 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
3648 assert
.strictEqual(report
.results
[0].messages
[0].message
, "ok");
3652 describe("glob pattern '[ab].js'", () => {
3653 const root
= getFixturePath("cli-engine/unmatched-glob");
3658 cleanup
= () => { };
3661 afterEach(() => cleanup());
3663 it("should match '[ab].js' if existed.", async () => {
3665 const teardown
= createCustomTeardown({
3672 ".eslintrc.yml": "root: true"
3676 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3678 await teardown
.prepare();
3679 cleanup
= teardown
.cleanup
;
3681 const { results
} = engine
.executeOnFiles(["[ab].js"]);
3682 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3684 assert
.deepStrictEqual(filenames
, ["[ab].js"]);
3687 it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", async () => {
3689 const teardown
= createCustomTeardown({
3695 ".eslintrc.yml": "root: true"
3699 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3701 await teardown
.prepare();
3702 cleanup
= teardown
.cleanup
;
3704 const { results
} = engine
.executeOnFiles(["[ab].js"]);
3705 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3707 assert
.deepStrictEqual(filenames
, ["a.js", "b.js"]);
3711 describe("with 'noInlineConfig' setting", () => {
3712 const root
= getFixturePath("cli-engine/noInlineConfig");
3717 cleanup
= () => { };
3720 afterEach(() => cleanup());
3722 it("should warn directive comments if 'noInlineConfig' was given.", async () => {
3724 const teardown
= createCustomTeardown({
3727 "test.js": "/* globals foo */",
3728 ".eslintrc.yml": "noInlineConfig: true"
3732 await teardown
.prepare();
3733 cleanup
= teardown
.cleanup
;
3734 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3736 const { results
} = engine
.executeOnFiles(["test.js"]);
3737 const messages
= results
[0].messages
;
3739 assert
.strictEqual(messages
.length
, 1);
3740 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
3743 it("should show the config file what the 'noInlineConfig' came from.", async () => {
3745 const teardown
= createCustomTeardown({
3748 "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
3749 "test.js": "/* globals foo */",
3750 ".eslintrc.yml": "extends: foo"
3754 await teardown
.prepare();
3755 cleanup
= teardown
.cleanup
;
3756 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3758 const { results
} = engine
.executeOnFiles(["test.js"]);
3759 const messages
= results
[0].messages
;
3761 assert
.strictEqual(messages
.length
, 1);
3762 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
3766 describe("with 'reportUnusedDisableDirectives' setting", () => {
3767 const root
= getFixturePath("cli-engine/reportUnusedDisableDirectives");
3772 cleanup
= () => { };
3775 afterEach(() => cleanup());
3777 it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", async () => {
3778 const teardown
= createCustomTeardown({
3781 "test.js": "/* eslint-disable eqeqeq */",
3782 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3786 await teardown
.prepare();
3787 cleanup
= teardown
.cleanup
;
3788 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3790 const { results
} = engine
.executeOnFiles(["test.js"]);
3791 const messages
= results
[0].messages
;
3793 assert
.strictEqual(messages
.length
, 1);
3794 assert
.strictEqual(messages
[0].severity
, 1);
3795 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3798 describe("the runtime option overrides config files.", () => {
3799 it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", async () => {
3800 const teardown
= createCustomTeardown({
3803 "test.js": "/* eslint-disable eqeqeq */",
3804 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3808 await teardown
.prepare();
3809 cleanup
= teardown
.cleanup
;
3811 engine
= new CLIEngine({
3812 cwd
: teardown
.getPath(),
3813 reportUnusedDisableDirectives
: "off"
3816 const { results
} = engine
.executeOnFiles(["test.js"]);
3817 const messages
= results
[0].messages
;
3819 assert
.strictEqual(messages
.length
, 0);
3822 it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", async () => {
3823 const teardown
= createCustomTeardown({
3826 "test.js": "/* eslint-disable eqeqeq */",
3827 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3831 await teardown
.prepare();
3832 cleanup
= teardown
.cleanup
;
3834 engine
= new CLIEngine({
3835 cwd
: teardown
.getPath(),
3836 reportUnusedDisableDirectives
: "error"
3839 const { results
} = engine
.executeOnFiles(["test.js"]);
3840 const messages
= results
[0].messages
;
3842 assert
.strictEqual(messages
.length
, 1);
3843 assert
.strictEqual(messages
[0].severity
, 2);
3844 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3849 describe("with 'overrides[*].extends' setting on deep locations", () => {
3850 const root
= getFixturePath("cli-engine/deeply-overrides-i-extends");
3852 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3855 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
3856 overrides: [{ files: ["*test*"], extends: "two" }]
3858 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
3859 overrides: [{ files: ["*.js"], extends: "three" }]
3861 "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
3862 rules: { "no-console": "error" }
3864 "test.js": "console.log('hello')",
3865 ".eslintrc.yml": "extends: one"
3869 beforeEach(prepare
);
3872 it("should not throw.", () => {
3873 engine
= new CLIEngine({ cwd
: getPath() });
3875 const { results
} = engine
.executeOnFiles(["test.js"]);
3876 const messages
= results
[0].messages
;
3878 assert
.strictEqual(messages
.length
, 1);
3879 assert
.strictEqual(messages
[0].ruleId
, "no-console");
3883 describe("don't ignore the entry directory.", () => {
3884 const root
= getFixturePath("cli-engine/dont-ignore-entry-dir");
3892 afterEach(async () => {
3895 const configFilePath
= path
.resolve(root
, "../.eslintrc.json");
3897 if (shell
.test("-e", configFilePath
)) {
3898 shell
.rm(configFilePath
);
3902 it("'executeOnFiles(\".\")' should not load config files from outside of \".\".", async () => {
3903 const teardown
= createCustomTeardown({
3906 "../.eslintrc.json": "BROKEN FILE",
3907 ".eslintrc.json": JSON
.stringify({ root
: true }),
3908 "index.js": "console.log(\"hello\")"
3912 await teardown
.prepare();
3913 cleanup
= teardown
.cleanup
;
3914 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3916 // Don't throw "failed to load config file" error.
3917 engine
.executeOnFiles(".");
3920 it("'executeOnFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", async () => {
3921 const teardown
= createCustomTeardown({
3924 "../.eslintrc.json": { ignorePatterns
: ["/dont-ignore-entry-dir"] },
3925 ".eslintrc.json": { root
: true },
3926 "index.js": "console.log(\"hello\")"
3930 await teardown
.prepare();
3931 cleanup
= teardown
.cleanup
;
3932 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3935 // Don't throw "file not found" error.
3936 engine
.executeOnFiles(".");
3939 it("'executeOnFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", async () => {
3940 const teardown
= createCustomTeardown({
3943 ".eslintrc.json": { ignorePatterns
: ["/subdir"] },
3944 "subdir/.eslintrc.json": { root
: true },
3945 "subdir/index.js": "console.log(\"hello\")"
3949 await teardown
.prepare();
3950 cleanup
= teardown
.cleanup
;
3951 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3953 // Don't throw "file not found" error.
3954 engine
.executeOnFiles("subdir");
3959 describe("getConfigForFile", () => {
3961 it("should return the info from Config#getConfig when called", () => {
3963 configFile
: getFixturePath("configurations", "quotes-error.json")
3965 const engine
= new CLIEngine(options
);
3966 const filePath
= getFixturePath("single-quoted.js");
3968 const actualConfig
= engine
.getConfigForFile(filePath
);
3969 const expectedConfig
= new CascadingConfigArrayFactory({ specificConfigPath
: options
.configFile
})
3970 .getConfigArrayForFile(filePath
)
3971 .extractConfig(filePath
)
3972 .toCompatibleObjectAsConfigFileContent();
3974 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3978 it("should return the config when run from within a subdir", () => {
3980 cwd
: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
3982 const engine
= new CLIEngine(options
);
3983 const filePath
= getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
3985 const actualConfig
= engine
.getConfigForFile("./.eslintrc");
3986 const expectedConfig
= new CascadingConfigArrayFactory(options
)
3987 .getConfigArrayForFile(filePath
)
3988 .extractConfig(filePath
)
3989 .toCompatibleObjectAsConfigFileContent();
3991 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3994 it("should throw an error if a directory path was given.", () => {
3995 const engine
= new CLIEngine();
3998 engine
.getConfigForFile(".");
4000 assert
.strictEqual(error
.messageTemplate
, "print-config-with-directory-path");
4003 assert
.fail("should throw an error");
4007 describe("isPathIgnored", () => {
4008 it("should check if the given path is ignored", () => {
4009 const engine
= new CLIEngine({
4010 ignorePath
: getFixturePath(".eslintignore2"),
4011 cwd
: getFixturePath()
4014 assert
.isTrue(engine
.isPathIgnored("undef.js"));
4015 assert
.isFalse(engine
.isPathIgnored("passing.js"));
4018 it("should return false if ignoring is disabled", () => {
4019 const engine
= new CLIEngine({
4021 ignorePath
: getFixturePath(".eslintignore2"),
4022 cwd
: getFixturePath()
4025 assert
.isFalse(engine
.isPathIgnored("undef.js"));
4028 // https://github.com/eslint/eslint/issues/5547
4029 it("should return true for default ignores even if ignoring is disabled", () => {
4030 const engine
= new CLIEngine({
4032 cwd
: getFixturePath("cli-engine")
4035 assert
.isTrue(engine
.isPathIgnored("node_modules/foo.js"));
4038 describe("about the default ignore patterns", () => {
4039 it("should always apply defaultPatterns if ignore option is true", () => {
4040 const cwd
= getFixturePath("ignored-paths");
4041 const engine
= new CLIEngine({ cwd
});
4043 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
4044 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
4047 it("should still apply defaultPatterns if ignore option is is false", () => {
4048 const cwd
= getFixturePath("ignored-paths");
4049 const engine
= new CLIEngine({ ignore
: false, cwd
});
4051 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
4052 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
4055 it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", () => {
4056 const cwd
= getFixturePath("ignored-paths");
4057 const engine
= new CLIEngine({ cwd
, ignorePattern
: "!/node_modules/package" });
4059 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4062 it("should allow subfolders of defaultPatterns to be unignored by ignorePath", () => {
4063 const cwd
= getFixturePath("ignored-paths");
4064 const engine
= new CLIEngine({ cwd
, ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
4066 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4069 it("should ignore dotfiles", () => {
4070 const cwd
= getFixturePath("ignored-paths");
4071 const engine
= new CLIEngine({ cwd
});
4073 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4074 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4077 it("should ignore directories beginning with a dot", () => {
4078 const cwd
= getFixturePath("ignored-paths");
4079 const engine
= new CLIEngine({ cwd
});
4081 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4082 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4085 it("should still ignore dotfiles when ignore option disabled", () => {
4086 const cwd
= getFixturePath("ignored-paths");
4087 const engine
= new CLIEngine({ ignore
: false, cwd
});
4089 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4090 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4093 it("should still ignore directories beginning with a dot when ignore option disabled", () => {
4094 const cwd
= getFixturePath("ignored-paths");
4095 const engine
= new CLIEngine({ ignore
: false, cwd
});
4097 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4098 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4101 it("should not ignore absolute paths containing '..'", () => {
4102 const cwd
= getFixturePath("ignored-paths");
4103 const engine
= new CLIEngine({ cwd
});
4105 assert(!engine
.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
4108 it("should ignore /node_modules/ relative to .eslintignore when loaded", () => {
4109 const cwd
= getFixturePath("ignored-paths");
4110 const engine
= new CLIEngine({ ignorePath
: getFixturePath("ignored-paths", ".eslintignore"), cwd
});
4112 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
4113 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
4116 it("should ignore /node_modules/ relative to cwd without an .eslintignore", () => {
4117 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4118 const engine
= new CLIEngine({ cwd
});
4120 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
4121 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
4125 describe("with no .eslintignore file", () => {
4126 it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", () => {
4127 const cwd
= getFixturePath("ignored-paths", "configurations");
4128 const engine
= new CLIEngine({ cwd
});
4130 // a .eslintignore in parent directories includes `*.js`, but don't load it.
4131 assert(!engine
.isPathIgnored("foo.js"));
4132 assert(engine
.isPathIgnored("node_modules/foo.js"));
4135 it("should return false for files outside of the cwd (with no ignore file provided)", () => {
4137 // Default ignore patterns should not inadvertently ignore files in parent directories
4138 const engine
= new CLIEngine({ cwd
: getFixturePath("ignored-paths", "no-ignore-file") });
4140 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4144 describe("with .eslintignore file or package.json file", () => {
4145 it("should load .eslintignore from cwd when explicitly passed", () => {
4146 const cwd
= getFixturePath("ignored-paths");
4147 const engine
= new CLIEngine({ cwd
});
4149 // `${cwd}/.eslintignore` includes `sampleignorepattern`.
4150 assert(engine
.isPathIgnored("sampleignorepattern"));
4153 it("should use package.json's eslintIgnore files if no specified .eslintignore file", () => {
4154 const cwd
= getFixturePath("ignored-paths", "package-json-ignore");
4155 const engine
= new CLIEngine({ cwd
});
4157 assert(engine
.isPathIgnored("hello.js"));
4158 assert(engine
.isPathIgnored("world.js"));
4161 it("should use correct message template if failed to parse package.json", () => {
4162 const cwd
= getFixturePath("ignored-paths", "broken-package-json");
4164 assert
.throw(() => {
4166 // eslint-disable-next-line no-new
4167 new CLIEngine({ cwd
});
4169 assert
.strictEqual(error
.messageTemplate
, "failed-to-read-json");
4175 it("should not use package.json's eslintIgnore files if specified .eslintignore file", () => {
4176 const cwd
= getFixturePath("ignored-paths");
4177 const engine
= new CLIEngine({ cwd
});
4180 * package.json includes `hello.js` and `world.js`.
4181 * .eslintignore includes `sampleignorepattern`.
4183 assert(!engine
.isPathIgnored("hello.js"));
4184 assert(!engine
.isPathIgnored("world.js"));
4185 assert(engine
.isPathIgnored("sampleignorepattern"));
4188 it("should error if package.json's eslintIgnore is not an array of file paths", () => {
4189 const cwd
= getFixturePath("ignored-paths", "bad-package-json-ignore");
4191 assert
.throws(() => {
4192 // eslint-disable-next-line no-new
4193 new CLIEngine({ cwd
});
4194 }, "Package.json eslintIgnore property requires an array of paths");
4198 describe("with --ignore-pattern option", () => {
4199 it("should accept a string for options.ignorePattern", () => {
4200 const cwd
= getFixturePath("ignored-paths", "ignore-pattern");
4201 const engine
= new CLIEngine({
4202 ignorePattern
: "ignore-me.txt",
4206 assert(engine
.isPathIgnored("ignore-me.txt"));
4209 it("should accept an array for options.ignorePattern", () => {
4210 const engine
= new CLIEngine({
4211 ignorePattern
: ["a", "b"],
4215 assert(engine
.isPathIgnored("a"));
4216 assert(engine
.isPathIgnored("b"));
4217 assert(!engine
.isPathIgnored("c"));
4220 it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", () => {
4221 const cwd
= getFixturePath("ignored-paths");
4222 const engine
= new CLIEngine({
4223 ignorePattern
: "not-a-file",
4227 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
4230 it("should return true for file matching an ignore pattern exactly", () => {
4231 const cwd
= getFixturePath("ignored-paths");
4232 const engine
= new CLIEngine({ ignorePattern
: "undef.js", cwd
});
4234 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4237 it("should return false for file matching an invalid ignore pattern with leading './'", () => {
4238 const cwd
= getFixturePath("ignored-paths");
4239 const engine
= new CLIEngine({ ignorePattern
: "./undef.js", cwd
});
4241 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4244 it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", () => {
4245 const cwd
= getFixturePath("ignored-paths");
4246 const engine
= new CLIEngine({ ignorePattern
: "/undef.js", cwd
});
4248 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
4251 it("should return true for file matching a child of an ignore pattern", () => {
4252 const cwd
= getFixturePath("ignored-paths");
4253 const engine
= new CLIEngine({ ignorePattern
: "ignore-pattern", cwd
});
4255 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
4258 it("should return true for file matching a grandchild of an ignore pattern", () => {
4259 const cwd
= getFixturePath("ignored-paths");
4260 const engine
= new CLIEngine({ ignorePattern
: "ignore-pattern", cwd
});
4262 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
4265 it("should return false for file not matching any ignore pattern", () => {
4266 const cwd
= getFixturePath("ignored-paths");
4267 const engine
= new CLIEngine({ ignorePattern
: "failing.js", cwd
});
4269 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
4272 it("two globstar '**' ignore pattern should ignore files in nested directories", () => {
4273 const cwd
= getFixturePath("ignored-paths");
4274 const engine
= new CLIEngine({ ignorePattern
: "**/*.js", cwd
});
4276 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4277 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
4278 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
4279 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
4280 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
4281 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
4285 describe("with --ignore-path option", () => {
4286 it("should load empty array with ignorePath set to false", () => {
4287 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4288 const engine
= new CLIEngine({ ignorePath
: false, cwd
});
4290 // a .eslintignore in parent directories includes `*.js`, but don't load it.
4291 assert(!engine
.isPathIgnored("foo.js"));
4292 assert(engine
.isPathIgnored("node_modules/foo.js"));
4295 it("initialization with ignorePath should work when cwd is a parent directory", () => {
4296 const cwd
= getFixturePath("ignored-paths");
4297 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4298 const engine
= new CLIEngine({ ignorePath
, cwd
});
4300 assert(engine
.isPathIgnored("custom-name/foo.js"));
4303 it("initialization with ignorePath should work when the file is in the cwd", () => {
4304 const cwd
= getFixturePath("ignored-paths", "custom-name");
4305 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4306 const engine
= new CLIEngine({ ignorePath
, cwd
});
4308 assert(engine
.isPathIgnored("foo.js"));
4311 it("initialization with ignorePath should work when cwd is a subdirectory", () => {
4312 const cwd
= getFixturePath("ignored-paths", "custom-name", "subdirectory");
4313 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4314 const engine
= new CLIEngine({ ignorePath
, cwd
});
4316 assert(engine
.isPathIgnored("../custom-name/foo.js"));
4319 it("initialization with invalid file should throw error", () => {
4320 const cwd
= getFixturePath("ignored-paths");
4321 const ignorePath
= getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
4323 assert
.throws(() => {
4324 // eslint-disable-next-line no-new
4325 new CLIEngine({ ignorePath
, cwd
});
4326 }, "Cannot read .eslintignore file");
4329 it("should return false for files outside of ignorePath's directory", () => {
4330 const cwd
= getFixturePath("ignored-paths");
4331 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4332 const engine
= new CLIEngine({ ignorePath
, cwd
});
4334 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4337 it("should resolve relative paths from CWD", () => {
4338 const cwd
= getFixturePath("ignored-paths", "subdir");
4339 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4340 const engine
= new CLIEngine({ ignorePath
, cwd
});
4342 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4343 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4346 it("should resolve relative paths from CWD when it's in a child directory", () => {
4347 const cwd
= getFixturePath("ignored-paths");
4348 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4349 const engine
= new CLIEngine({ ignorePath
, cwd
});
4351 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4352 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4353 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4354 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
4356 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
4359 it("should resolve relative paths from CWD when it contains negated globs", () => {
4360 const cwd
= getFixturePath("ignored-paths");
4361 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4362 const engine
= new CLIEngine({ ignorePath
, cwd
});
4364 assert(engine
.isPathIgnored("subdir/blah.txt"));
4365 assert(engine
.isPathIgnored("blah.txt"));
4366 assert(engine
.isPathIgnored("subdir/bar.txt"));
4367 assert(!engine
.isPathIgnored("bar.txt"));
4368 assert(!engine
.isPathIgnored("subdir/baz.txt"));
4369 assert(!engine
.isPathIgnored("baz.txt"));
4372 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", () => {
4373 const cwd
= getFixturePath("ignored-paths");
4374 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4375 const engine
= new CLIEngine({ ignorePath
, cwd
});
4377 assert(engine
.isPathIgnored("node_modules/blah.js"));
4380 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", () => {
4381 const cwd
= getFixturePath("ignored-paths", "subdir");
4382 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4383 const engine
= new CLIEngine({ ignorePath
, cwd
});
4385 assert(engine
.isPathIgnored("node_modules/blah.js"));
4388 it("should handle .eslintignore which contains CRLF correctly.", () => {
4389 const ignoreFileContent
= fs
.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
4391 assert(ignoreFileContent
.includes("\r"), "crlf/.eslintignore should contains CR.");
4393 const cwd
= getFixturePath("ignored-paths");
4394 const ignorePath
= getFixturePath("ignored-paths", "crlf/.eslintignore");
4395 const engine
= new CLIEngine({ ignorePath
, cwd
});
4397 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
4398 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
4399 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
4402 it("should not include comments in ignore rules", () => {
4403 const cwd
= getFixturePath("ignored-paths");
4404 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithComments");
4405 const engine
= new CLIEngine({ ignorePath
, cwd
});
4407 assert(!engine
.isPathIgnored("# should be ignored"));
4408 assert(engine
.isPathIgnored("this_one_not"));
4411 it("should ignore a non-negated pattern", () => {
4412 const cwd
= getFixturePath("ignored-paths");
4413 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4414 const engine
= new CLIEngine({ ignorePath
, cwd
});
4416 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
4419 it("should not ignore a negated pattern", () => {
4420 const cwd
= getFixturePath("ignored-paths");
4421 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4422 const engine
= new CLIEngine({ ignorePath
, cwd
});
4424 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
4428 describe("with --ignore-path option and --ignore-pattern option", () => {
4429 it("should return false for ignored file when unignored with ignore pattern", () => {
4430 const cwd
= getFixturePath("ignored-paths");
4431 const engine
= new CLIEngine({
4432 ignorePath
: getFixturePath("ignored-paths", ".eslintignore"),
4433 ignorePattern
: "!sampleignorepattern",
4437 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
4442 describe("getFormatter()", () => {
4444 it("should return a function when a bundled formatter is requested", () => {
4445 const engine
= new CLIEngine(),
4446 formatter
= engine
.getFormatter("compact");
4448 assert
.isFunction(formatter
);
4451 it("should return a function when no argument is passed", () => {
4452 const engine
= new CLIEngine(),
4453 formatter
= engine
.getFormatter();
4455 assert
.isFunction(formatter
);
4458 it("should return a function when a custom formatter is requested", () => {
4459 const engine
= new CLIEngine(),
4460 formatter
= engine
.getFormatter(getFixturePath("formatters", "simple.js"));
4462 assert
.isFunction(formatter
);
4465 it("should return a function when a custom formatter is requested, also if the path has backslashes", () => {
4466 const engine
= new CLIEngine({
4467 cwd
: path
.join(fixtureDir
, "..")
4469 formatter
= engine
.getFormatter(".\\fixtures\\formatters\\simple.js");
4471 assert
.isFunction(formatter
);
4474 it("should return a function when a formatter prefixed with eslint-formatter is requested", () => {
4475 const engine
= new CLIEngine({
4476 cwd
: getFixturePath("cli-engine")
4478 formatter
= engine
.getFormatter("bar");
4480 assert
.isFunction(formatter
);
4483 it("should return a function when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", () => {
4484 const engine
= new CLIEngine({
4485 cwd
: getFixturePath("cli-engine")
4487 formatter
= engine
.getFormatter("eslint-formatter-bar");
4489 assert
.isFunction(formatter
);
4492 it("should return a function when a formatter is requested within a scoped npm package", () => {
4493 const engine
= new CLIEngine({
4494 cwd
: getFixturePath("cli-engine")
4496 formatter
= engine
.getFormatter("@somenamespace/foo");
4498 assert
.isFunction(formatter
);
4501 it("should return a function when a formatter is requested within a scoped npm package, also when the eslint-formatter prefix is included in the format argument", () => {
4502 const engine
= new CLIEngine({
4503 cwd
: getFixturePath("cli-engine")
4505 formatter
= engine
.getFormatter("@somenamespace/eslint-formatter-foo");
4507 assert
.isFunction(formatter
);
4510 it("should return null when a customer formatter doesn't exist", () => {
4511 const engine
= new CLIEngine(),
4512 formatterPath
= getFixturePath("formatters", "doesntexist.js"),
4513 fullFormatterPath
= path
.resolve(formatterPath
);
4515 assert
.throws(() => {
4516 engine
.getFormatter(formatterPath
);
4517 }, `There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`);
4520 it("should return null when a built-in formatter doesn't exist", () => {
4521 const engine
= new CLIEngine();
4522 const fullFormatterPath
= path
.resolve(__dirname
, "../../../lib/cli-engine/formatters/special");
4524 assert
.throws(() => {
4525 engine
.getFormatter("special");
4526 }, `There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`);
4529 it("should throw if the required formatter exists but has an error", () => {
4530 const engine
= new CLIEngine(),
4531 formatterPath
= getFixturePath("formatters", "broken.js");
4533 assert
.throws(() => {
4534 engine
.getFormatter(formatterPath
);
4535 }, `There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`);
4538 it("should return null when a non-string formatter name is passed", () => {
4539 const engine
= new CLIEngine(),
4540 formatter
= engine
.getFormatter(5);
4542 assert
.isNull(formatter
);
4545 it("should return a function when called as a static function on CLIEngine", () => {
4546 const formatter
= CLIEngine
.getFormatter();
4548 assert
.isFunction(formatter
);
4551 it("should return a function when called as a static function on CLIEngine and a custom formatter is requested", () => {
4552 const formatter
= CLIEngine
.getFormatter(getFixturePath("formatters", "simple.js"));
4554 assert
.isFunction(formatter
);
4559 describe("getErrorResults()", () => {
4560 it("should report 5 error messages when looking for errors only", () => {
4562 process
.chdir(originalDir
);
4563 const engine
= new CLIEngine();
4565 const report
= engine
.executeOnText("var foo = 'bar';");
4566 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4568 assert
.lengthOf(errorResults
[0].messages
, 5);
4569 assert
.strictEqual(errorResults
[0].errorCount
, 5);
4570 assert
.strictEqual(errorResults
[0].fixableErrorCount
, 3);
4571 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4572 assert
.strictEqual(errorResults
[0].messages
[0].ruleId
, "strict");
4573 assert
.strictEqual(errorResults
[0].messages
[0].severity
, 2);
4574 assert
.strictEqual(errorResults
[0].messages
[1].ruleId
, "no-var");
4575 assert
.strictEqual(errorResults
[0].messages
[1].severity
, 2);
4576 assert
.strictEqual(errorResults
[0].messages
[2].ruleId
, "no-unused-vars");
4577 assert
.strictEqual(errorResults
[0].messages
[2].severity
, 2);
4578 assert
.strictEqual(errorResults
[0].messages
[3].ruleId
, "quotes");
4579 assert
.strictEqual(errorResults
[0].messages
[3].severity
, 2);
4580 assert
.strictEqual(errorResults
[0].messages
[4].ruleId
, "eol-last");
4581 assert
.strictEqual(errorResults
[0].messages
[4].severity
, 2);
4584 it("should not mutate passed report.results parameter", () => {
4585 process
.chdir(originalDir
);
4586 const engine
= new CLIEngine({
4587 rules
: { quotes
: [1, "double"] }
4590 const report
= engine
.executeOnText("var foo = 'bar';");
4591 const reportResultsLength
= report
.results
[0].messages
.length
;
4593 CLIEngine
.getErrorResults(report
.results
);
4595 assert
.lengthOf(report
.results
[0].messages
, reportResultsLength
);
4598 it("should report a warningCount of 0 when looking for errors only", () => {
4600 process
.chdir(originalDir
);
4601 const engine
= new CLIEngine();
4603 const report
= engine
.executeOnText("var foo = 'bar';");
4604 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4606 assert
.strictEqual(errorResults
[0].warningCount
, 0);
4607 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4610 it("should return 0 error or warning messages even when the file has warnings", () => {
4611 const engine
= new CLIEngine({
4612 ignorePath
: path
.join(fixtureDir
, ".eslintignore"),
4613 cwd
: path
.join(fixtureDir
, "..")
4616 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js", true);
4617 const errorReport
= CLIEngine
.getErrorResults(report
.results
);
4619 assert
.lengthOf(errorReport
, 0);
4620 assert
.lengthOf(report
.results
, 1);
4621 assert
.strictEqual(report
.errorCount
, 0);
4622 assert
.strictEqual(report
.warningCount
, 1);
4623 assert
.strictEqual(report
.fixableErrorCount
, 0);
4624 assert
.strictEqual(report
.fixableWarningCount
, 0);
4625 assert
.strictEqual(report
.results
[0].errorCount
, 0);
4626 assert
.strictEqual(report
.results
[0].warningCount
, 1);
4627 assert
.strictEqual(report
.fixableErrorCount
, 0);
4628 assert
.strictEqual(report
.fixableWarningCount
, 0);
4631 it("should return source code of file in the `source` property", () => {
4632 process
.chdir(originalDir
);
4633 const engine
= new CLIEngine({
4635 rules
: { quotes
: [2, "double"] }
4639 const report
= engine
.executeOnText("var foo = 'bar';");
4640 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4642 assert
.lengthOf(errorResults
[0].messages
, 1);
4643 assert
.strictEqual(errorResults
[0].source
, "var foo = 'bar';");
4646 it("should contain `output` property after fixes", () => {
4647 process
.chdir(originalDir
);
4648 const engine
= new CLIEngine({
4657 const report
= engine
.executeOnText("console.log('foo')");
4658 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4660 assert
.lengthOf(errorResults
[0].messages
, 1);
4661 assert
.strictEqual(errorResults
[0].output
, "console.log('foo');");
4665 describe("outputFixes()", () => {
4667 sinon
.verifyAndRestore();
4670 it("should call fs.writeFileSync() for each result with output", () => {
4672 writeFileSync
: () => {}
4674 localCLIEngine
= proxyquire("../../../lib/cli-engine/cli-engine", {
4690 const spy
= sinon
.spy(fakeFS
, "writeFileSync");
4692 localCLIEngine
.outputFixes(report
);
4694 assert
.strictEqual(spy
.callCount
, 2);
4695 assert
.isTrue(spy
.firstCall
.calledWithExactly("foo.js", "bar"), "First call was incorrect.");
4696 assert
.isTrue(spy
.secondCall
.calledWithExactly("bar.js", "baz"), "Second call was incorrect.");
4700 it("should call fs.writeFileSync() for each result with output and not at all for a result without output", () => {
4702 writeFileSync
: () => {}
4704 localCLIEngine
= proxyquire("../../../lib/cli-engine/cli-engine", {
4723 const spy
= sinon
.spy(fakeFS
, "writeFileSync");
4725 localCLIEngine
.outputFixes(report
);
4727 assert
.strictEqual(spy
.callCount
, 2);
4728 assert
.isTrue(spy
.firstCall
.calledWithExactly("foo.js", "bar"), "First call was incorrect.");
4729 assert
.isTrue(spy
.secondCall
.calledWithExactly("bar.js", "baz"), "Second call was incorrect.");
4735 describe("getRules()", () => {
4736 it("should expose the list of rules", () => {
4737 const engine
= new CLIEngine();
4739 assert(engine
.getRules().has("no-eval"), "no-eval is present");
4742 it("should expose the list of plugin rules", () => {
4743 const engine
= new CLIEngine({ plugins
: ["node"] });
4745 assert(engine
.getRules().has("node/no-deprecated-api"), "node/no-deprecated-api is present");
4748 it("should expose the rules of the plugin that is added by 'addPlugin'.", () => {
4749 const engine
= new CLIEngine({ plugins
: ["foo"] });
4751 engine
.addPlugin("foo", require("eslint-plugin-node"));
4753 assert(engine
.getRules().has("foo/no-deprecated-api"), "foo/no-deprecated-api is present");
4757 describe("resolveFileGlobPatterns", () => {
4760 [".", ["**/*.{js}"]],
4761 ["./", ["**/*.{js}"]],
4762 ["../", ["../**/*.{js}"]],
4764 ].forEach(([input
, expected
]) => {
4766 it(`should correctly resolve ${input} to ${expected}`, () => {
4767 const engine
= new CLIEngine();
4769 const result
= engine
.resolveFileGlobPatterns([input
]);
4771 assert
.deepStrictEqual(result
, expected
);
4776 it("should convert a directory name with no provided extensions into a glob pattern", () => {
4777 const patterns
= ["one-js-file"];
4779 cwd
: getFixturePath("glob-util")
4781 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4783 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4786 it("should not convert path with globInputPaths option false", () => {
4787 const patterns
= ["one-js-file"];
4789 cwd
: getFixturePath("glob-util"),
4790 globInputPaths
: false
4792 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4794 assert
.deepStrictEqual(result
, ["one-js-file"]);
4797 it("should convert an absolute directory name with no provided extensions into a posix glob pattern", () => {
4798 const patterns
= [getFixturePath("glob-util", "one-js-file")];
4800 cwd
: getFixturePath("glob-util")
4802 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4803 const expected
= [`${getFixturePath("glob-util", "one-js-file").replace(/\\/gu, "/")}/**/*.{js}`];
4805 assert
.deepStrictEqual(result
, expected
);
4808 it("should convert a directory name with a single provided extension into a glob pattern", () => {
4809 const patterns
= ["one-js-file"];
4811 cwd
: getFixturePath("glob-util"),
4812 extensions
: [".jsx"]
4814 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4816 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{jsx}"]);
4819 it("should convert a directory name with multiple provided extensions into a glob pattern", () => {
4820 const patterns
= ["one-js-file"];
4822 cwd
: getFixturePath("glob-util"),
4823 extensions
: [".jsx", ".js"]
4825 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4827 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{jsx,js}"]);
4830 it("should convert multiple directory names into glob patterns", () => {
4831 const patterns
= ["one-js-file", "two-js-files"];
4833 cwd
: getFixturePath("glob-util")
4835 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4837 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}", "two-js-files/**/*.{js}"]);
4840 it("should remove leading './' from glob patterns", () => {
4841 const patterns
= ["./one-js-file"];
4843 cwd
: getFixturePath("glob-util")
4845 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4847 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4850 it("should convert a directory name with a trailing '/' into a glob pattern", () => {
4851 const patterns
= ["one-js-file/"];
4853 cwd
: getFixturePath("glob-util")
4855 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4857 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4860 it("should return filenames as they are", () => {
4861 const patterns
= ["some-file.js"];
4863 cwd
: getFixturePath("glob-util")
4865 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4867 assert
.deepStrictEqual(result
, ["some-file.js"]);
4870 it("should convert backslashes into forward slashes", () => {
4871 const patterns
= ["one-js-file\\example.js"];
4873 cwd
: getFixturePath()
4875 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4877 assert
.deepStrictEqual(result
, ["one-js-file/example.js"]);
4881 describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
4883 it("should report a violation for disabling rules", () => {
4885 "alert('test'); // eslint-disable-line no-alert"
4890 allowInlineConfig
: false,
4894 "no-trailing-spaces": 0,
4900 const eslintCLI
= new CLIEngine(config
);
4902 const report
= eslintCLI
.executeOnText(code
);
4903 const messages
= report
.results
[0].messages
;
4905 assert
.strictEqual(messages
.length
, 1);
4906 assert
.strictEqual(messages
[0].ruleId
, "no-alert");
4909 it("should not report a violation by default", () => {
4911 "alert('test'); // eslint-disable-line no-alert"
4917 // allowInlineConfig: true is the default
4921 "no-trailing-spaces": 0,
4927 const eslintCLI
= new CLIEngine(config
);
4929 const report
= eslintCLI
.executeOnText(code
);
4930 const messages
= report
.results
[0].messages
;
4932 assert
.strictEqual(messages
.length
, 0);
4937 describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
4938 it("should report problems for unused eslint-disable directives", () => {
4939 const cliEngine
= new CLIEngine({ useEslintrc
: false, reportUnusedDisableDirectives
: true });
4941 assert
.deepStrictEqual(
4942 cliEngine
.executeOnText("/* eslint-disable */"),
4950 message
: "Unused eslint-disable directive (no problems were reported).",
4959 fixableErrorCount
: 0,
4960 fixableWarningCount
: 0,
4961 source
: "/* eslint-disable */"
4966 fixableErrorCount
: 0,
4967 fixableWarningCount
: 0,
4968 usedDeprecatedRules
: []
4974 describe("when retreiving version number", () => {
4975 it("should return current version number", () => {
4976 const eslintCLI
= require("../../../lib/cli-engine").CLIEngine
;
4977 const version
= eslintCLI
.version
;
4979 assert
.isString(version
);
4980 assert
.isTrue(parseInt(version
[0], 10) >= 3);
4984 describe("mutability", () => {
4985 describe("plugins", () => {
4986 it("Loading plugin in one instance doesn't mutate to another instance", () => {
4987 const filePath
= getFixturePath("single-quoted.js");
4988 const engine1
= cliEngineWithPlugins({
4989 cwd
: path
.join(fixtureDir
, ".."),
4991 plugins
: ["example"],
4992 rules
: { "example/example-rule": 1 }
4994 const engine2
= new CLIEngine({
4995 cwd
: path
.join(fixtureDir
, ".."),
4998 const fileConfig1
= engine1
.getConfigForFile(filePath
);
4999 const fileConfig2
= engine2
.getConfigForFile(filePath
);
5002 assert
.deepStrictEqual(fileConfig1
.plugins
, ["example"], "Plugin is present for engine 1");
5003 assert
.deepStrictEqual(fileConfig2
.plugins
, [], "Plugin is not present for engine 2");
5007 describe("rules", () => {
5008 it("Loading rules in one instance doesn't mutate to another instance", () => {
5009 const filePath
= getFixturePath("single-quoted.js");
5010 const engine1
= new CLIEngine({
5011 cwd
: path
.join(fixtureDir
, ".."),
5013 rules
: { "example/example-rule": 1 }
5015 const engine2
= new CLIEngine({
5016 cwd
: path
.join(fixtureDir
, ".."),
5019 const fileConfig1
= engine1
.getConfigForFile(filePath
);
5020 const fileConfig2
= engine2
.getConfigForFile(filePath
);
5023 assert
.deepStrictEqual(fileConfig1
.rules
["example/example-rule"], [1], "example is present for engine 1");
5024 assert
.isUndefined(fileConfig2
.rules
["example/example-rule"], "example is not present for engine 2");
5029 describe("with ignorePatterns config", () => {
5030 const root
= getFixturePath("cli-engine/ignore-patterns");
5032 describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
5034 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5038 ignorePatterns
: "foo.js"
5042 "subdir/foo.js": "",
5047 beforeEach(prepare
);
5050 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5051 const engine
= new CLIEngine({ cwd
: getPath() });
5053 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5054 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5057 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5058 const engine
= new CLIEngine({ cwd
: getPath() });
5060 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5061 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), false);
5064 it("'executeOnFiles()' should not verify 'foo.js'.", () => {
5065 const engine
= new CLIEngine({ cwd
: getPath() });
5066 const filePaths
= engine
.executeOnFiles("**/*.js")
5068 .map(r
=> r
.filePath
)
5071 assert
.deepStrictEqual(filePaths
, [
5072 path
.join(root
, "bar.js"),
5073 path
.join(root
, "subdir/bar.js")
5078 describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
5079 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5083 ignorePatterns
: ["foo.js", "/bar.js"]
5088 "subdir/foo.js": "",
5089 "subdir/bar.js": "",
5094 beforeEach(prepare
);
5097 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5098 const engine
= new CLIEngine({ cwd
: getPath() });
5100 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5101 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5104 it("'isPathIgnored()' should return 'true' for '/bar.js'.", () => {
5105 const engine
= new CLIEngine({ cwd
: getPath() });
5107 assert
.strictEqual(engine
.isPathIgnored("bar.js"), true);
5108 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), false);
5111 it("'executeOnFiles()' should not verify 'foo.js' and '/bar.js'.", () => {
5112 const engine
= new CLIEngine({ cwd
: getPath() });
5113 const filePaths
= engine
.executeOnFiles("**/*.js")
5115 .map(r
=> r
.filePath
)
5118 assert
.deepStrictEqual(filePaths
, [
5119 path
.join(root
, "baz.js"),
5120 path
.join(root
, "subdir/bar.js"),
5121 path
.join(root
, "subdir/baz.js")
5126 describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
5128 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5132 ignorePatterns
: "!/node_modules/foo"
5134 "node_modules/foo/index.js": "",
5135 "node_modules/foo/.dot.js": "",
5136 "node_modules/bar/index.js": "",
5141 beforeEach(prepare
);
5144 it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", () => {
5145 const engine
= new CLIEngine({ cwd
: getPath() });
5147 assert
.strictEqual(engine
.isPathIgnored("node_modules/foo/index.js"), false);
5150 it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", () => {
5151 const engine
= new CLIEngine({ cwd
: getPath() });
5153 assert
.strictEqual(engine
.isPathIgnored("node_modules/foo/.dot.js"), true);
5156 it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", () => {
5157 const engine
= new CLIEngine({ cwd
: getPath() });
5159 assert
.strictEqual(engine
.isPathIgnored("node_modules/bar/index.js"), true);
5162 it("'executeOnFiles()' should verify 'node_modules/foo/index.js'.", () => {
5163 const engine
= new CLIEngine({ cwd
: getPath() });
5164 const filePaths
= engine
.executeOnFiles("**/*.js")
5166 .map(r
=> r
.filePath
)
5169 assert
.deepStrictEqual(filePaths
, [
5170 path
.join(root
, "foo.js"),
5171 path
.join(root
, "node_modules/foo/index.js")
5176 describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
5178 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5181 ".eslintrc.js": `module.exports = ${JSON.stringify({
5182 ignorePatterns: "!.eslintrc.js"
5188 beforeEach(prepare
);
5191 it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", () => {
5192 const engine
= new CLIEngine({ cwd
: getPath() });
5194 assert
.strictEqual(engine
.isPathIgnored(".eslintrc.js"), false);
5197 it("'executeOnFiles()' should verify '.eslintrc.js'.", () => {
5198 const engine
= new CLIEngine({ cwd
: getPath() });
5199 const filePaths
= engine
.executeOnFiles("**/*.js")
5201 .map(r
=> r
.filePath
)
5204 assert
.deepStrictEqual(filePaths
, [
5205 path
.join(root
, ".eslintrc.js"),
5206 path
.join(root
, "foo.js")
5211 describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
5212 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5215 ".eslintrc.js": `module.exports = ${JSON.stringify({
5216 ignorePatterns: "!.*"
5218 ".eslintignore": ".foo*",
5224 beforeEach(prepare
);
5227 it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", () => {
5228 const engine
= new CLIEngine({ cwd
: getPath() });
5230 assert
.strictEqual(engine
.isPathIgnored(".foo.js"), true);
5233 it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", () => {
5234 const engine
= new CLIEngine({ cwd
: getPath() });
5236 assert
.strictEqual(engine
.isPathIgnored(".bar.js"), false);
5239 it("'executeOnFiles()' should not verify re-ignored '.foo.js'.", () => {
5240 const engine
= new CLIEngine({ cwd
: getPath() });
5241 const filePaths
= engine
.executeOnFiles("**/*.js")
5243 .map(r
=> r
.filePath
)
5246 assert
.deepStrictEqual(filePaths
, [
5247 path
.join(root
, ".bar.js"),
5248 path
.join(root
, ".eslintrc.js")
5253 describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
5255 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5258 ".eslintrc.js": `module.exports = ${JSON.stringify({
5259 ignorePatterns: "*.js"
5261 ".eslintignore": "!foo.js",
5267 beforeEach(prepare
);
5270 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", () => {
5271 const engine
= new CLIEngine({ cwd
: getPath() });
5273 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5276 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", () => {
5277 const engine
= new CLIEngine({ cwd
: getPath() });
5279 assert
.strictEqual(engine
.isPathIgnored("bar.js"), true);
5282 it("'executeOnFiles()' should verify unignored 'foo.js'.", () => {
5283 const engine
= new CLIEngine({ cwd
: getPath() });
5284 const filePaths
= engine
.executeOnFiles("**/*.js")
5286 .map(r
=> r
.filePath
)
5289 assert
.deepStrictEqual(filePaths
, [
5290 path
.join(root
, "foo.js")
5295 describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
5296 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5299 ".eslintrc.json": JSON
.stringify({
5300 ignorePatterns
: "foo.js"
5302 "subdir/.eslintrc.json": JSON
.stringify({
5303 ignorePatterns
: "bar.js"
5307 "subdir/foo.js": "",
5308 "subdir/bar.js": "",
5309 "subdir/subsubdir/foo.js": "",
5310 "subdir/subsubdir/bar.js": ""
5314 beforeEach(prepare
);
5317 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5318 const engine
= new CLIEngine({ cwd
: getPath() });
5320 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5321 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5322 assert
.strictEqual(engine
.isPathIgnored("subdir/subsubdir/foo.js"), true);
5325 it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", () => {
5326 const engine
= new CLIEngine({ cwd
: getPath() });
5328 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5329 assert
.strictEqual(engine
.isPathIgnored("subdir/subsubdir/bar.js"), true);
5332 it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", () => {
5333 const engine
= new CLIEngine({ cwd
: getPath() });
5335 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5338 it("'executeOnFiles()' should verify 'bar.js' in the outside of 'subdir'.", () => {
5339 const engine
= new CLIEngine({ cwd
: getPath() });
5340 const filePaths
= engine
.executeOnFiles("**/*.js")
5342 .map(r
=> r
.filePath
)
5345 assert
.deepStrictEqual(filePaths
, [
5346 path
.join(root
, "bar.js")
5351 describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
5352 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5355 ".eslintrc.json": JSON
.stringify({
5356 ignorePatterns
: "foo.js"
5358 "subdir/.eslintrc.json": JSON
.stringify({
5359 ignorePatterns
: "!foo.js"
5366 beforeEach(prepare
);
5369 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", () => {
5370 const engine
= new CLIEngine({ cwd
: getPath() });
5372 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5375 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", () => {
5376 const engine
= new CLIEngine({ cwd
: getPath() });
5378 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5381 it("'executeOnFiles()' should verify 'foo.js' in the child directory.", () => {
5382 const engine
= new CLIEngine({ cwd
: getPath() });
5383 const filePaths
= engine
.executeOnFiles("**/*.js")
5385 .map(r
=> r
.filePath
)
5388 assert
.deepStrictEqual(filePaths
, [
5389 path
.join(root
, "subdir/foo.js")
5394 describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
5395 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5398 ".eslintrc.json": {},
5399 "subdir/.eslintrc.json": {
5400 ignorePatterns
: "*.js"
5402 ".eslintignore": "!foo.js",
5404 "subdir/foo.js": "",
5409 beforeEach(prepare
);
5412 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", () => {
5413 const engine
= new CLIEngine({ cwd
: getPath() });
5415 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5416 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5419 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", () => {
5420 const engine
= new CLIEngine({ cwd
: getPath() });
5422 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5425 it("'executeOnFiles()' should verify unignored 'foo.js'.", () => {
5426 const engine
= new CLIEngine({ cwd
: getPath() });
5427 const filePaths
= engine
.executeOnFiles("**/*.js")
5429 .map(r
=> r
.filePath
)
5432 assert
.deepStrictEqual(filePaths
, [
5433 path
.join(root
, "foo.js"),
5434 path
.join(root
, "subdir/foo.js")
5439 describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
5440 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5444 ignorePatterns
: "foo.js"
5446 "subdir/.eslintrc.json": {
5448 ignorePatterns
: "bar.js"
5452 "subdir/foo.js": "",
5457 beforeEach(prepare
);
5460 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", () => {
5461 const engine
= new CLIEngine({ cwd
: getPath() });
5463 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5466 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", () => {
5467 const engine
= new CLIEngine({ cwd
: getPath() });
5469 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5472 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", () => {
5473 const engine
= new CLIEngine({ cwd
: getPath() });
5475 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5478 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", () => {
5479 const engine
= new CLIEngine({ cwd
: getPath() });
5481 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5484 it("'executeOnFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", () => {
5485 const engine
= new CLIEngine({ cwd
: getPath() });
5486 const filePaths
= engine
.executeOnFiles("**/*.js")
5488 .map(r
=> r
.filePath
)
5491 assert
.deepStrictEqual(filePaths
, [
5492 path
.join(root
, "bar.js"),
5493 path
.join(root
, "subdir/foo.js")
5498 describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
5500 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5503 ".eslintrc.json": JSON
.stringify({}),
5504 "subdir/.eslintrc.json": JSON
.stringify({
5506 ignorePatterns
: "bar.js"
5508 ".eslintignore": "foo.js",
5511 "subdir/foo.js": "",
5516 beforeEach(prepare
);
5519 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5520 const engine
= new CLIEngine({ cwd
: getPath() });
5522 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5523 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5526 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", () => {
5527 const engine
= new CLIEngine({ cwd
: getPath() });
5529 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5532 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", () => {
5533 const engine
= new CLIEngine({ cwd
: getPath() });
5535 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5538 it("'executeOnFiles()' should verify 'bar.js' in the root directory.", () => {
5539 const engine
= new CLIEngine({ cwd
: getPath() });
5540 const filePaths
= engine
.executeOnFiles("**/*.js")
5542 .map(r
=> r
.filePath
)
5545 assert
.deepStrictEqual(filePaths
, [
5546 path
.join(root
, "bar.js")
5551 describe("ignorePatterns in the shareable config should be used.", () => {
5552 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5555 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5556 ignorePatterns: "foo.js"
5558 ".eslintrc.json": JSON
.stringify({
5566 beforeEach(prepare
);
5569 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5570 const engine
= new CLIEngine({ cwd
: getPath() });
5572 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5575 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5576 const engine
= new CLIEngine({ cwd
: getPath() });
5578 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5581 it("'executeOnFiles()' should verify 'bar.js'.", () => {
5582 const engine
= new CLIEngine({ cwd
: getPath() });
5583 const filePaths
= engine
.executeOnFiles("**/*.js")
5585 .map(r
=> r
.filePath
)
5588 assert
.deepStrictEqual(filePaths
, [
5589 path
.join(root
, "bar.js")
5594 describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
5596 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5599 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5600 ignorePatterns: "/foo.js"
5602 ".eslintrc.json": JSON
.stringify({
5610 beforeEach(prepare
);
5614 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5615 const engine
= new CLIEngine({ cwd
: getPath() });
5617 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5620 it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", () => {
5621 const engine
= new CLIEngine({ cwd
: getPath() });
5623 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5626 it("'executeOnFiles()' should verify 'subdir/foo.js'.", () => {
5627 const engine
= new CLIEngine({ cwd
: getPath() });
5628 const filePaths
= engine
.executeOnFiles("**/*.js")
5630 .map(r
=> r
.filePath
)
5633 assert
.deepStrictEqual(filePaths
, [
5634 path
.join(root
, "subdir/foo.js")
5639 describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
5641 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5644 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5645 ignorePatterns: "*.js"
5647 ".eslintrc.json": JSON
.stringify({
5649 ignorePatterns
: "!bar.js"
5656 beforeEach(prepare
);
5659 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5660 const engine
= new CLIEngine({ cwd
: getPath() });
5662 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5665 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5666 const engine
= new CLIEngine({ cwd
: getPath() });
5668 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5671 it("'executeOnFiles()' should verify 'bar.js'.", () => {
5672 const engine
= new CLIEngine({ cwd
: getPath() });
5673 const filePaths
= engine
.executeOnFiles("**/*.js")
5675 .map(r
=> r
.filePath
)
5678 assert
.deepStrictEqual(filePaths
, [
5679 path
.join(root
, "bar.js")
5684 describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
5685 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5688 ".eslintrc.json": JSON
.stringify({
5689 ignorePatterns
: "*.js"
5695 beforeEach(prepare
);
5698 it("'isPathIgnored()' should return 'false' for 'foo.js'.", () => {
5699 const engine
= new CLIEngine({ cwd
: getPath(), ignore
: false });
5701 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5704 it("'executeOnFiles()' should verify 'foo.js'.", () => {
5705 const engine
= new CLIEngine({ cwd
: getPath(), ignore
: false });
5706 const filePaths
= engine
.executeOnFiles("**/*.js")
5708 .map(r
=> r
.filePath
)
5711 assert
.deepStrictEqual(filePaths
, [
5712 path
.join(root
, "foo.js")
5717 describe("ignorePatterns in overrides section is not allowed.", () => {
5719 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5722 ".eslintrc.js": `module.exports = ${JSON.stringify({
5726 ignorePatterns: "foo.js"
5734 beforeEach(prepare
);
5737 it("should throw a configuration error.", () => {
5738 assert
.throws(() => {
5739 const engine
= new CLIEngine({ cwd
: getPath() });
5741 engine
.executeOnFiles("*.js");
5742 }, "Unexpected top-level property \"overrides[0].ignorePatterns\"");
5748 describe("'overrides[].files' adds lint targets", () => {
5749 const root
= getFixturePath("cli-engine/additional-lint-targets");
5751 describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
5753 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5756 ".eslintrc.json": JSON
.stringify({
5760 excludedFiles
: "**/ignore.txt"
5764 "foo/nested/test.txt": "",
5767 "foo/ignore.txt": "",
5770 "bar/ignore.txt": "",
5777 beforeEach(prepare
);
5780 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt'.", () => {
5781 const engine
= new CLIEngine({ cwd
: getPath() });
5782 const filePaths
= engine
.executeOnFiles(".")
5784 .map(r
=> r
.filePath
)
5787 assert
.deepStrictEqual(filePaths
, [
5788 path
.join(root
, "bar/test.js"),
5789 path
.join(root
, "foo/test.js"),
5790 path
.join(root
, "foo/test.txt"),
5791 path
.join(root
, "test.js")
5795 it("'executeOnFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", () => {
5796 const engine
= new CLIEngine({ cwd
: getPath() });
5797 const filePaths
= engine
.executeOnFiles("**/*.js")
5799 .map(r
=> r
.filePath
)
5802 assert
.deepStrictEqual(filePaths
, [
5803 path
.join(root
, "bar/test.js"),
5804 path
.join(root
, "foo/test.js"),
5805 path
.join(root
, "test.js")
5810 describe("if { files: 'foo/**/*.txt' } is present,", () => {
5812 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5815 ".eslintrc.json": JSON
.stringify({
5818 files
: "foo/**/*.txt"
5822 "foo/nested/test.txt": "",
5832 beforeEach(prepare
);
5835 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5836 const engine
= new CLIEngine({ cwd
: getPath() });
5837 const filePaths
= engine
.executeOnFiles(".")
5839 .map(r
=> r
.filePath
)
5842 assert
.deepStrictEqual(filePaths
, [
5843 path
.join(root
, "bar/test.js"),
5844 path
.join(root
, "foo/nested/test.txt"),
5845 path
.join(root
, "foo/test.js"),
5846 path
.join(root
, "foo/test.txt"),
5847 path
.join(root
, "test.js")
5852 describe("if { files: 'foo/**/*' } is present,", () => {
5853 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5856 ".eslintrc.json": JSON
.stringify({
5863 "foo/nested/test.txt": "",
5873 beforeEach(prepare
);
5876 it("'executeOnFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5877 const engine
= new CLIEngine({ cwd
: getPath() });
5878 const filePaths
= engine
.executeOnFiles(".")
5880 .map(r
=> r
.filePath
)
5883 assert
.deepStrictEqual(filePaths
, [
5884 path
.join(root
, "bar/test.js"),
5885 path
.join(root
, "foo/test.js"),
5886 path
.join(root
, "test.js")
5891 describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
5892 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5895 "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
5898 files: "foo/**/*.txt"
5902 ".eslintrc.json": JSON
.stringify({
5905 "foo/nested/test.txt": "",
5915 beforeEach(prepare
);
5918 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5919 const engine
= new CLIEngine({ cwd
: getPath() });
5920 const filePaths
= engine
.executeOnFiles(".")
5922 .map(r
=> r
.filePath
)
5925 assert
.deepStrictEqual(filePaths
, [
5926 path
.join(root
, "bar/test.js"),
5927 path
.join(root
, "foo/nested/test.txt"),
5928 path
.join(root
, "foo/test.js"),
5929 path
.join(root
, "foo/test.txt"),
5930 path
.join(root
, "test.js")
5935 describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
5936 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5939 "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
5943 files: "foo/**/*.txt"
5948 ".eslintrc.json": JSON
.stringify({
5949 extends: "plugin:foo/bar"
5951 "foo/nested/test.txt": "",
5961 beforeEach(prepare
);
5964 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5965 const engine
= new CLIEngine({ cwd
: getPath() });
5966 const filePaths
= engine
.executeOnFiles(".")
5968 .map(r
=> r
.filePath
)
5971 assert
.deepStrictEqual(filePaths
, [
5972 path
.join(root
, "bar/test.js"),
5973 path
.join(root
, "foo/nested/test.txt"),
5974 path
.join(root
, "foo/test.js"),
5975 path
.join(root
, "foo/test.txt"),
5976 path
.join(root
, "test.js")
5982 describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
5983 const root
= getFixturePath("cli-engine/config-and-overrides-files");
5985 describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5986 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5989 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5999 "node_modules/myconf/foo/test.js": "a == b",
6000 "foo/test.js": "a == b"
6004 beforeEach(prepare
);
6007 it("'executeOnFiles()' with 'foo/test.js' should use the override entry.", () => {
6008 const engine
= new CLIEngine({
6009 configFile
: "node_modules/myconf/.eslintrc.json",
6014 const { results
} = engine
.executeOnFiles("foo/test.js");
6016 // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
6017 assert
.deepStrictEqual(results
, [
6020 filePath
: path
.join(root
, "foo/test.js"),
6021 fixableErrorCount
: 0,
6022 fixableWarningCount
: 0,
6029 message
: "Expected '===' and instead saw '=='.",
6030 messageId
: "unexpected",
6031 nodeType
: "BinaryExpression",
6042 it("'executeOnFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", () => {
6043 const engine
= new CLIEngine({
6044 configFile
: "node_modules/myconf/.eslintrc.json",
6049 const { results
} = engine
.executeOnFiles("node_modules/myconf/foo/test.js");
6051 // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
6052 assert
.deepStrictEqual(results
, [
6055 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
6056 fixableErrorCount
: 0,
6057 fixableWarningCount
: 0,
6065 describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6066 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6069 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6073 excludedFiles
: "foo/*.js",
6080 "node_modules/myconf/foo/test.js": "a == b",
6081 "foo/test.js": "a == b"
6085 beforeEach(prepare
);
6088 it("'executeOnFiles()' with 'foo/test.js' should NOT use the override entry.", () => {
6089 const engine
= new CLIEngine({
6090 configFile
: "node_modules/myconf/.eslintrc.json",
6095 const { results
} = engine
.executeOnFiles("foo/test.js");
6097 // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
6098 assert
.deepStrictEqual(results
, [
6101 filePath
: path
.join(root
, "foo/test.js"),
6102 fixableErrorCount
: 0,
6103 fixableWarningCount
: 0,
6110 it("'executeOnFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", () => {
6111 const engine
= new CLIEngine({
6112 configFile
: "node_modules/myconf/.eslintrc.json",
6117 const { results
} = engine
.executeOnFiles("node_modules/myconf/foo/test.js");
6119 // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
6120 assert
.deepStrictEqual(results
, [
6123 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
6124 fixableErrorCount
: 0,
6125 fixableWarningCount
: 0,
6132 message
: "Expected '===' and instead saw '=='.",
6133 messageId
: "unexpected",
6134 nodeType
: "BinaryExpression",
6146 describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6147 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6150 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6151 ignorePatterns
: ["!/node_modules/myconf", "foo/*.js"],
6156 "node_modules/myconf/foo/test.js": "a == b",
6157 "foo/test.js": "a == b"
6161 beforeEach(prepare
);
6164 it("'executeOnFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", () => {
6165 const engine
= new CLIEngine({
6166 configFile
: "node_modules/myconf/.eslintrc.json",
6170 const files
= engine
.executeOnFiles("**/*.js")
6172 .map(r
=> r
.filePath
)
6175 assert
.deepStrictEqual(files
, [
6176 path
.join(root
, "node_modules/myconf/foo/test.js")
6182 describe("plugin conflicts", () => {
6184 const root
= getFixturePath("cli-engine/plugin-conflicts-");
6187 * Verify thrown errors.
6188 * @param {() => void} f The function to run and throw.
6189 * @param {Record<string, any>} props The properties to verify.
6192 function assertThrows(f
, props
) {
6196 for (const [key
, value
] of Object
.entries(props
)) {
6197 assert
.deepStrictEqual(error
[key
], value
, key
);
6202 assert
.fail("Function should throw an error, but not.");
6205 describe("between a config file and linear extendees.", () => {
6207 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6208 cwd
: `${root}${++uid}`,
6210 "node_modules/eslint-plugin-foo/index.js": "",
6211 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6212 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6216 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6217 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6220 ".eslintrc.json": JSON
.stringify({
6228 beforeEach(prepare
);
6231 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", () => {
6232 const engine
= new CLIEngine({ cwd
: getPath() });
6234 engine
.executeOnFiles("test.js");
6238 describe("between a config file and same-depth extendees.", () => {
6239 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6240 cwd
: `${root}${++uid}`,
6242 "node_modules/eslint-plugin-foo/index.js": "",
6243 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6244 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6247 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6248 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6251 ".eslintrc.json": JSON
.stringify({
6252 extends: ["one", "two"],
6259 beforeEach(prepare
);
6262 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", () => {
6263 const engine
= new CLIEngine({ cwd
: getPath() });
6265 engine
.executeOnFiles("test.js");
6269 describe("between two config files in different directories, with single node_modules.", () => {
6270 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6271 cwd
: `${root}${++uid}`,
6273 "node_modules/eslint-plugin-foo/index.js": "",
6274 ".eslintrc.json": JSON
.stringify({
6277 "subdir/.eslintrc.json": JSON
.stringify({
6280 "subdir/test.js": ""
6284 beforeEach(prepare
);
6287 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files, but node_modules directory is unique.)", () => {
6288 const engine
= new CLIEngine({ cwd
: getPath() });
6290 engine
.executeOnFiles("subdir/test.js");
6294 describe("between two config files in different directories, with multiple node_modules.", () => {
6295 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6296 cwd
: `${root}${++uid}`,
6298 "node_modules/eslint-plugin-foo/index.js": "",
6299 ".eslintrc.json": JSON
.stringify({
6302 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6303 "subdir/.eslintrc.json": JSON
.stringify({
6306 "subdir/test.js": ""
6310 beforeEach(prepare
);
6313 it("'executeOnFiles()' should throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files.)", () => {
6314 const engine
= new CLIEngine({ cwd
: getPath() });
6317 () => engine
.executeOnFiles("subdir/test.js"),
6319 message
: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
6320 messageTemplate
: "plugin-conflict",
6325 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6326 importerName
: `subdir${path.sep}.eslintrc.json`
6329 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6330 importerName
: ".eslintrc.json"
6339 describe("between '--config' option and a regular config file, with single node_modules.", () => {
6340 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6341 cwd
: `${root}${++uid}`,
6343 "node_modules/eslint-plugin-foo/index.js": "",
6344 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6347 ".eslintrc.json": JSON
.stringify({
6354 beforeEach(prepare
);
6357 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files, but node_modules directory is unique.)", () => {
6358 const engine
= new CLIEngine({
6360 configFile
: "node_modules/mine/.eslintrc.json"
6363 engine
.executeOnFiles("test.js");
6367 describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
6368 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6369 cwd
: `${root}${++uid}`,
6371 "node_modules/eslint-plugin-foo/index.js": "",
6372 "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
6373 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6376 ".eslintrc.json": JSON
.stringify({
6383 beforeEach(prepare
);
6386 it("'executeOnFiles()' should throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files.)", () => {
6387 const engine
= new CLIEngine({
6389 configFile
: "node_modules/mine/.eslintrc.json"
6393 () => engine
.executeOnFiles("test.js"),
6395 message
: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
6396 messageTemplate
: "plugin-conflict",
6401 filePath
: path
.join(getPath(), "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
6402 importerName
: "--config"
6405 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6406 importerName
: ".eslintrc.json"
6415 describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
6416 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6417 cwd
: `${root}${++uid}`,
6419 "node_modules/eslint-plugin-foo/index.js": "",
6420 "subdir/.eslintrc.json": JSON
.stringify({
6423 "subdir/test.js": ""
6427 beforeEach(prepare
);
6430 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file, but node_modules directory is unique.)", () => {
6431 const engine
= new CLIEngine({
6436 engine
.executeOnFiles("subdir/test.js");
6440 describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
6441 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6442 cwd
: `${root}${++uid}`,
6444 "node_modules/eslint-plugin-foo/index.js": "",
6445 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6446 "subdir/.eslintrc.json": JSON
.stringify({
6449 "subdir/test.js": ""
6453 beforeEach(prepare
);
6456 it("'executeOnFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", () => {
6457 const engine
= new CLIEngine({
6463 () => engine
.executeOnFiles("subdir/test.js"),
6465 message
: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
6466 messageTemplate
: "plugin-conflict",
6471 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6472 importerName
: "CLIOptions"
6475 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6476 importerName
: `subdir${path.sep}.eslintrc.json`
6485 describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
6486 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6487 cwd
: `${root}${++uid}`,
6489 "node_modules/eslint-plugin-foo/index.js": "",
6490 ".eslintrc.json": JSON
.stringify({
6493 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6494 "subdir/.eslintrc.json": JSON
.stringify({
6497 "subdir/test.js": ""
6501 beforeEach(prepare
);
6504 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", () => {
6505 const engine
= new CLIEngine({
6507 resolvePluginsRelativeTo
: getPath()
6510 engine
.executeOnFiles("subdir/test.js");
6514 describe("between two config files with different target files.", () => {
6515 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6516 cwd
: `${root}${++uid}`,
6518 "one/node_modules/eslint-plugin-foo/index.js": "",
6519 "one/.eslintrc.json": JSON
.stringify({
6523 "two/node_modules/eslint-plugin-foo/index.js": "",
6524 "two/.eslintrc.json": JSON
.stringify({
6531 beforeEach(prepare
);
6534 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file for each target file. Not related to each other.)", () => {
6535 const engine
= new CLIEngine({ cwd
: getPath() });
6536 const { results
} = engine
.executeOnFiles("*/test.js");
6538 assert
.strictEqual(results
.length
, 2);