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 leche
= require("leche"),
16 shell
= require("shelljs"),
19 hash
= require("../../../lib/cli-engine/hash"),
20 { CascadingConfigArrayFactory
} = require("../../../lib/cli-engine/cascading-config-array-factory"),
21 { unIndent
} = require("../_utils"),
22 { defineCLIEngineWithInMemoryFileSystem
} = require("./_utils");
24 const proxyquire
= require("proxyquire").noCallThru().noPreserveCache();
25 const fCache
= require("file-entry-cache");
27 //------------------------------------------------------------------------------
29 //------------------------------------------------------------------------------
31 describe("CLIEngine", () => {
33 const examplePluginName
= "eslint-plugin-example",
34 examplePluginNameWithNamespace
= "@eslint/eslint-plugin-example",
37 "example-rule": require("../../fixtures/rules/custom-rule"),
38 "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
41 examplePreprocessorName
= "eslint-plugin-processor",
42 originalDir
= process
.cwd(),
43 fixtureDir
= path
.resolve(fs
.realpathSync(os
.tmpdir()), "eslint/fixtures");
45 /** @type {import("../../../lib/cli-engine")["CLIEngine"]} */
48 /** @type {import("../../../lib/cli-engine/cli-engine")["getCLIEngineInternalSlots"]} */
49 let getCLIEngineInternalSlots;
52 * Returns the path inside of the fixture directory.
53 * @param {...string} args file path segments.
54 * @returns {string} The path inside the fixture directory.
57 function getFixturePath(...args
) {
58 const filepath
= path
.join(fixtureDir
, ...args
);
61 return fs
.realpathSync(filepath
);
68 * Create the CLIEngine object by mocking some of the plugins
69 * @param {Object} options options for CLIEngine
70 * @returns {CLIEngine} engine object
73 function cliEngineWithPlugins(options
) {
74 const engine
= new CLIEngine(options
);
76 // load the mocked plugins
77 engine
.addPlugin(examplePluginName
, examplePlugin
);
78 engine
.addPlugin(examplePluginNameWithNamespace
, examplePlugin
);
79 engine
.addPlugin(examplePreprocessorName
, require("../../fixtures/processors/custom-processor"));
84 // copy into clean area so as not to get "infected" by this project's .eslintrc files
86 shell
.mkdir("-p", fixtureDir
);
87 shell
.cp("-r", "./tests/fixtures/.", fixtureDir
);
91 ({ CLIEngine
, getCLIEngineInternalSlots
} = require("../../../lib/cli-engine/cli-engine"));
95 shell
.rm("-r", fixtureDir
);
98 describe("new CLIEngine(options)", () => {
99 it("the default value of 'options.cwd' should be the current working directory.", () => {
100 process
.chdir(__dirname
);
102 const engine
= new CLIEngine();
103 const internalSlots
= getCLIEngineInternalSlots(engine
);
105 assert
.strictEqual(internalSlots
.options
.cwd
, __dirname
);
107 process
.chdir(originalDir
);
111 it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
112 assert
.throws(() => {
113 // eslint-disable-next-line no-new
114 new CLIEngine({ ignorePath
: fixtureDir
});
115 }, `Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`);
118 // https://github.com/eslint/eslint/issues/2380
119 it("should not modify baseConfig when format is specified", () => {
120 const customBaseConfig
= { root
: true };
122 new CLIEngine({ baseConfig
: customBaseConfig
, format
: "foo" }); // eslint-disable-line no-new
124 assert
.deepStrictEqual(customBaseConfig
, { root
: true });
128 describe("executeOnText()", () => {
132 it("should report the total and per file errors when using local cwd .eslintrc", () => {
134 engine
= new CLIEngine();
136 const report
= engine
.executeOnText("var foo = 'bar';");
138 assert
.strictEqual(report
.results
.length
, 1);
139 assert
.strictEqual(report
.errorCount
, 5);
140 assert
.strictEqual(report
.warningCount
, 0);
141 assert
.strictEqual(report
.fixableErrorCount
, 3);
142 assert
.strictEqual(report
.fixableWarningCount
, 0);
143 assert
.strictEqual(report
.results
[0].messages
.length
, 5);
144 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "strict");
145 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-var");
146 assert
.strictEqual(report
.results
[0].messages
[2].ruleId
, "no-unused-vars");
147 assert
.strictEqual(report
.results
[0].messages
[3].ruleId
, "quotes");
148 assert
.strictEqual(report
.results
[0].messages
[4].ruleId
, "eol-last");
149 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 3);
150 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
153 it("should report the total and per file warnings when using local cwd .eslintrc", () => {
155 engine
= new CLIEngine({
165 const report
= engine
.executeOnText("var foo = 'bar';");
167 assert
.strictEqual(report
.results
.length
, 1);
168 assert
.strictEqual(report
.errorCount
, 0);
169 assert
.strictEqual(report
.warningCount
, 5);
170 assert
.strictEqual(report
.fixableErrorCount
, 0);
171 assert
.strictEqual(report
.fixableWarningCount
, 3);
172 assert
.strictEqual(report
.results
[0].messages
.length
, 5);
173 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "strict");
174 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-var");
175 assert
.strictEqual(report
.results
[0].messages
[2].ruleId
, "no-unused-vars");
176 assert
.strictEqual(report
.results
[0].messages
[3].ruleId
, "quotes");
177 assert
.strictEqual(report
.results
[0].messages
[4].ruleId
, "eol-last");
178 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
179 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 3);
182 it("should report one message when using specific config file", () => {
184 engine
= new CLIEngine({
185 configFile
: "fixtures/configurations/quotes-error.json",
187 cwd
: getFixturePath("..")
190 const report
= engine
.executeOnText("var foo = 'bar';");
192 assert
.strictEqual(report
.results
.length
, 1);
193 assert
.strictEqual(report
.errorCount
, 1);
194 assert
.strictEqual(report
.warningCount
, 0);
195 assert
.strictEqual(report
.fixableErrorCount
, 1);
196 assert
.strictEqual(report
.fixableWarningCount
, 0);
197 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
198 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
199 assert
.isUndefined(report
.results
[0].messages
[0].output
);
200 assert
.strictEqual(report
.results
[0].errorCount
, 1);
201 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
202 assert
.strictEqual(report
.results
[0].warningCount
, 0);
205 it("should report the filename when passed in", () => {
207 engine
= new CLIEngine({
209 cwd
: getFixturePath()
212 const report
= engine
.executeOnText("var foo = 'bar';", "test.js");
214 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("test.js"));
217 it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", () => {
218 engine
= new CLIEngine({
219 ignorePath
: getFixturePath(".eslintignore"),
220 cwd
: getFixturePath("..")
223 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js", true);
225 assert
.strictEqual(report
.results
.length
, 1);
226 assert
.strictEqual(report
.errorCount
, 0);
227 assert
.strictEqual(report
.warningCount
, 1);
228 assert
.strictEqual(report
.fixableErrorCount
, 0);
229 assert
.strictEqual(report
.fixableWarningCount
, 0);
230 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("passing.js"));
231 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
232 assert
.strictEqual(report
.results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
233 assert
.isUndefined(report
.results
[0].messages
[0].output
);
234 assert
.strictEqual(report
.results
[0].errorCount
, 0);
235 assert
.strictEqual(report
.results
[0].warningCount
, 1);
236 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
237 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
240 it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", () => {
241 engine
= new CLIEngine({
242 ignorePath
: getFixturePath(".eslintignore"),
243 cwd
: getFixturePath("..")
246 // intentional parsing error
247 const report
= engine
.executeOnText("va r bar = foo;", "fixtures/passing.js", false);
249 // should not report anything because the file is ignored
250 assert
.strictEqual(report
.results
.length
, 0);
253 it("should suppress excluded file warnings by default", () => {
254 engine
= new CLIEngine({
255 ignorePath
: getFixturePath(".eslintignore"),
256 cwd
: getFixturePath("..")
259 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
261 // should not report anything because there are no errors
262 assert
.strictEqual(report
.results
.length
, 0);
265 it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", () => {
267 engine
= new CLIEngine({
268 ignorePath
: "fixtures/.eslintignore",
269 cwd
: getFixturePath(".."),
277 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
279 assert
.strictEqual(report
.results
.length
, 1);
280 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("passing.js"));
281 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-undef");
282 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
283 assert
.isUndefined(report
.results
[0].messages
[0].output
);
286 it("should return a message and fixed text when in fix mode", () => {
288 engine
= new CLIEngine({
295 cwd
: getFixturePath()
298 const report
= engine
.executeOnText("var bar = foo", "passing.js");
300 assert
.deepStrictEqual(report
, {
303 filePath
: getFixturePath("passing.js"),
307 fixableErrorCount
: 0,
308 fixableWarningCount
: 0,
309 output
: "var bar = foo;"
314 fixableErrorCount
: 0,
315 fixableWarningCount
: 0,
316 usedDeprecatedRules
: []
320 it("correctly autofixes semicolon-conflicting-fixes", () => {
321 engine
= new CLIEngine({
322 cwd
: path
.join(fixtureDir
, ".."),
326 const inputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.js");
327 const outputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
328 const report
= engine
.executeOnFiles([inputPath
]);
329 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
331 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
334 it("correctly autofixes return-conflicting-fixes", () => {
335 engine
= new CLIEngine({
336 cwd
: path
.join(fixtureDir
, ".."),
340 const inputPath
= getFixturePath("autofix/return-conflicting-fixes.js");
341 const outputPath
= getFixturePath("autofix/return-conflicting-fixes.expected.js");
342 const report
= engine
.executeOnFiles([inputPath
]);
343 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
345 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
348 describe("Fix Types", () => {
350 it("should throw an error when an invalid fix type is specified", () => {
351 assert
.throws(() => {
352 engine
= new CLIEngine({
353 cwd
: path
.join(fixtureDir
, ".."),
358 }, /invalid fix type/iu);
361 it("should not fix any rules when fixTypes is used without fix", () => {
362 engine
= new CLIEngine({
363 cwd
: path
.join(fixtureDir
, ".."),
369 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
370 const report
= engine
.executeOnFiles([inputPath
]);
372 assert
.isUndefined(report
.results
[0].output
);
375 it("should not fix non-style rules when fixTypes has only 'layout'", () => {
376 engine
= new CLIEngine({
377 cwd
: path
.join(fixtureDir
, ".."),
382 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
383 const outputPath
= getFixturePath("fix-types/fix-only-semi.expected.js");
384 const report
= engine
.executeOnFiles([inputPath
]);
385 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
387 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
390 it("should not fix style or problem rules when fixTypes has only 'suggestion'", () => {
391 engine
= new CLIEngine({
392 cwd
: path
.join(fixtureDir
, ".."),
395 fixTypes
: ["suggestion"]
397 const inputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
398 const outputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
399 const report
= engine
.executeOnFiles([inputPath
]);
400 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
402 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
405 it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", () => {
406 engine
= new CLIEngine({
407 cwd
: path
.join(fixtureDir
, ".."),
410 fixTypes
: ["suggestion", "layout"]
412 const inputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
413 const outputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
414 const report
= engine
.executeOnFiles([inputPath
]);
415 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
417 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
420 it("should not throw an error when a rule doesn't have a 'meta' property", () => {
421 engine
= new CLIEngine({
422 cwd
: path
.join(fixtureDir
, ".."),
425 fixTypes
: ["layout"],
426 rulePaths
: [getFixturePath("rules", "fix-types-test")]
429 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
430 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
431 const report
= engine
.executeOnFiles([inputPath
]);
432 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
434 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
437 it("should not throw an error when a rule is loaded after initialization with executeOnFiles()", () => {
438 engine
= new CLIEngine({
439 cwd
: path
.join(fixtureDir
, ".."),
444 const internalSlots
= getCLIEngineInternalSlots(engine
);
446 internalSlots
.linter
.defineRule(
448 require(getFixturePath("rules", "fix-types-test", "no-program.js"))
451 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
452 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
453 const report
= engine
.executeOnFiles([inputPath
]);
454 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
456 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
459 it("should not throw an error when a rule is loaded after initialization with executeOnText()", () => {
460 engine
= new CLIEngine({
461 cwd
: path
.join(fixtureDir
, ".."),
466 const internalSlots
= getCLIEngineInternalSlots(engine
);
468 internalSlots
.linter
.defineRule(
470 require(getFixturePath("rules", "fix-types-test", "no-program.js"))
473 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
474 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
475 const report
= engine
.executeOnText(fs
.readFileSync(inputPath
, { encoding
: "utf8" }), inputPath
);
476 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
478 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
483 it("should return a message and omit fixed text when in fix mode and fixes aren't done", () => {
485 engine
= new CLIEngine({
492 cwd
: getFixturePath()
495 const report
= engine
.executeOnText("var bar = foo", "passing.js");
497 assert
.deepStrictEqual(report
, {
500 filePath
: getFixturePath("passing.js"),
506 message
: "'foo' is not defined.",
511 nodeType
: "Identifier"
516 fixableErrorCount
: 0,
517 fixableWarningCount
: 0,
518 source
: "var bar = foo"
523 fixableErrorCount
: 0,
524 fixableWarningCount
: 0,
525 usedDeprecatedRules
: []
529 it("should not delete code if there is a syntax error after trying to autofix.", () => {
530 engine
= cliEngineWithPlugins({
533 plugins
: ["example"],
535 "example/make-syntax-error": "error"
538 cwd
: getFixturePath()
541 const report
= engine
.executeOnText("var bar = foo", "test.js");
543 assert
.deepStrictEqual(report
, {
546 filePath
: getFixturePath("test.js"),
552 message
: "Parsing error: Unexpected token is",
559 fixableErrorCount
: 0,
560 fixableWarningCount
: 0,
561 output
: "var bar = foothis is a syntax error."
566 fixableErrorCount
: 0,
567 fixableWarningCount
: 0,
568 usedDeprecatedRules
: []
572 it("should not crash even if there are any syntax error since the first time.", () => {
573 engine
= new CLIEngine({
577 "example/make-syntax-error": "error"
580 cwd
: getFixturePath()
583 const report
= engine
.executeOnText("var bar =", "test.js");
585 assert
.deepStrictEqual(report
, {
588 filePath
: getFixturePath("test.js"),
594 message
: "Parsing error: Unexpected token",
601 fixableErrorCount
: 0,
602 fixableWarningCount
: 0,
608 fixableErrorCount
: 0,
609 fixableWarningCount
: 0,
610 usedDeprecatedRules
: []
614 it("should return source code of file in `source` property when errors are present", () => {
615 engine
= new CLIEngine({
620 const report
= engine
.executeOnText("var foo = 'bar'");
622 assert
.strictEqual(report
.results
[0].source
, "var foo = 'bar'");
625 it("should return source code of file in `source` property when warnings are present", () => {
626 engine
= new CLIEngine({
631 const report
= engine
.executeOnText("var foo = 'bar'");
633 assert
.strictEqual(report
.results
[0].source
, "var foo = 'bar'");
637 it("should not return a `source` property when no errors or warnings are present", () => {
638 engine
= new CLIEngine({
643 const report
= engine
.executeOnText("var foo = 'bar';");
645 assert
.lengthOf(report
.results
[0].messages
, 0);
646 assert
.isUndefined(report
.results
[0].source
);
649 it("should not return a `source` property when fixes are applied", () => {
650 engine
= new CLIEngine({
659 const report
= engine
.executeOnText("var msg = 'hi' + foo\n");
661 assert
.isUndefined(report
.results
[0].source
);
662 assert
.strictEqual(report
.results
[0].output
, "var msg = 'hi' + foo;\n");
665 it("should return a `source` property when a parsing error has occurred", () => {
666 engine
= new CLIEngine({
671 const report
= engine
.executeOnText("var bar = foothis is a syntax error.\n return bar;");
673 assert
.deepStrictEqual(report
, {
682 message
: "Parsing error: Unexpected token is",
689 fixableErrorCount
: 0,
690 fixableWarningCount
: 0,
691 source
: "var bar = foothis is a syntax error.\n return bar;"
696 fixableErrorCount
: 0,
697 fixableWarningCount
: 0,
698 usedDeprecatedRules
: []
702 // https://github.com/eslint/eslint/issues/5547
703 it("should respect default ignore rules, even with --no-ignore", () => {
705 engine
= new CLIEngine({
706 cwd
: getFixturePath(),
710 const report
= engine
.executeOnText("var bar = foo;", "node_modules/passing.js", true);
711 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
713 assert
.strictEqual(report
.results
.length
, 1);
714 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("node_modules/passing.js"));
715 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
718 // @scope for @scope/eslint-plugin
719 describe("(plugin shorthand)", () => {
720 const Module
= require("module");
721 let originalFindPath
= null;
723 /* eslint-disable no-underscore-dangle */
725 originalFindPath
= Module
._findPath
;
726 Module
._findPath = function(id
, ...otherArgs
) {
727 if (id
=== "@scope/eslint-plugin") {
728 return path
.resolve(__dirname
, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
730 return originalFindPath
.call(this, id
, ...otherArgs
);
734 Module
._findPath
= originalFindPath
;
736 /* eslint-enable no-underscore-dangle */
738 it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
739 engine
= new CLIEngine({ cwd
: getFixturePath("plugin-shorthand/basic") });
740 const report
= engine
.executeOnText("var x = 0", "index.js").results
[0];
742 assert
.strictEqual(report
.filePath
, getFixturePath("plugin-shorthand/basic/index.js"));
743 assert
.strictEqual(report
.messages
[0].ruleId
, "@scope/rule");
744 assert
.strictEqual(report
.messages
[0].message
, "OK");
747 it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
748 engine
= new CLIEngine({ cwd
: getFixturePath("plugin-shorthand/extends") });
749 const report
= engine
.executeOnText("var x = 0", "index.js").results
[0];
751 assert
.strictEqual(report
.filePath
, getFixturePath("plugin-shorthand/extends/index.js"));
752 assert
.strictEqual(report
.messages
[0].ruleId
, "@scope/rule");
753 assert
.strictEqual(report
.messages
[0].message
, "OK");
756 it("should warn when deprecated rules are found in a config", () => {
757 engine
= new CLIEngine({
760 configFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
763 const report
= engine
.executeOnText("foo");
765 assert
.deepStrictEqual(
766 report
.usedDeprecatedRules
,
767 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
772 describe("executeOnFiles()", () => {
774 /** @type {InstanceType<import("../../../lib/cli-engine")["CLIEngine"]>} */
777 it("should use correct parser when custom parser is specified", () => {
779 engine
= new CLIEngine({
784 const filePath
= path
.resolve(__dirname
, "../../fixtures/configurations/parser/custom.js");
785 const report
= engine
.executeOnFiles([filePath
]);
787 assert
.strictEqual(report
.results
.length
, 1);
788 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
789 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Parsing error: Boom!");
793 it("should report zero messages when given a config file and a valid file", () => {
795 engine
= new CLIEngine({
797 configFile
: ".eslintrc.js"
800 const report
= engine
.executeOnFiles(["lib/**/cli*.js"]);
802 assert
.strictEqual(report
.results
.length
, 2);
803 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
804 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
807 it("should handle multiple patterns with overlapping files", () => {
809 engine
= new CLIEngine({
811 configFile
: ".eslintrc.js"
814 const report
= engine
.executeOnFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
816 assert
.strictEqual(report
.results
.length
, 2);
817 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
818 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
821 it("should report zero messages when given a config file and a valid file and espree as parser", () => {
823 engine
= new CLIEngine({
829 const report
= engine
.executeOnFiles(["lib/cli.js"]);
831 assert
.strictEqual(report
.results
.length
, 1);
832 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
835 it("should report zero messages when given a config file and a valid file and esprima as parser", () => {
837 engine
= new CLIEngine({
842 const report
= engine
.executeOnFiles(["lib/cli.js"]);
844 assert
.strictEqual(report
.results
.length
, 1);
845 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
848 it("should throw an error when given a config file and a valid file and invalid parser", () => {
850 engine
= new CLIEngine({
855 assert
.throws(() => engine
.executeOnFiles(["lib/cli.js"]), "Cannot find module 'test11'");
858 it("should report zero messages when given a directory with a .js2 file", () => {
860 engine
= new CLIEngine({
861 cwd
: path
.join(fixtureDir
, ".."),
865 const report
= engine
.executeOnFiles([getFixturePath("files/foo.js2")]);
867 assert
.strictEqual(report
.results
.length
, 1);
868 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
871 it("should report zero messages when given a directory with a .js and a .js2 file", () => {
873 engine
= new CLIEngine({
874 extensions
: [".js", ".js2"],
876 cwd
: getFixturePath("..")
879 const report
= engine
.executeOnFiles(["fixtures/files/"]);
881 assert
.strictEqual(report
.results
.length
, 2);
882 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
883 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
886 it("should report zero messages when given a '**' pattern with a .js and a .js2 file", () => {
888 engine
= new CLIEngine({
889 extensions
: [".js", ".js2"],
891 cwd
: path
.join(fixtureDir
, "..")
894 const report
= engine
.executeOnFiles(["fixtures/files/*"]);
896 assert
.strictEqual(report
.results
.length
, 2);
897 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
898 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
901 it("should resolve globs when 'globInputPaths' option is true", () => {
902 engine
= new CLIEngine({
903 extensions
: [".js", ".js2"],
905 cwd
: getFixturePath("..")
908 const report
= engine
.executeOnFiles(["fixtures/files/*"]);
910 assert
.strictEqual(report
.results
.length
, 2);
911 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
912 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
915 it("should not resolve globs when 'globInputPaths' option is false", () => {
916 engine
= new CLIEngine({
917 extensions
: [".js", ".js2"],
919 cwd
: getFixturePath(".."),
920 globInputPaths
: false
923 assert
.throws(() => {
924 engine
.executeOnFiles(["fixtures/files/*"]);
925 }, "No files matching 'fixtures/files/*' were found (glob was disabled).");
928 it("should report on all files passed explicitly, even if ignored by default", () => {
930 engine
= new CLIEngine({
931 cwd
: getFixturePath("cli-engine")
934 const report
= engine
.executeOnFiles(["node_modules/foo.js"]);
935 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
937 assert
.strictEqual(report
.results
.length
, 1);
938 assert
.strictEqual(report
.results
[0].errorCount
, 0);
939 assert
.strictEqual(report
.results
[0].warningCount
, 1);
940 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
941 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
942 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
945 it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", () => {
947 engine
= new CLIEngine({
948 cwd
: getFixturePath("cli-engine"),
950 quotes
: [2, "single"]
954 const report
= engine
.executeOnFiles(["hidden/.hiddenfolder/*.js"]);
956 assert
.strictEqual(report
.results
.length
, 1);
957 assert
.strictEqual(report
.results
[0].errorCount
, 1);
958 assert
.strictEqual(report
.results
[0].warningCount
, 0);
959 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
960 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
963 it("should not check default ignored files without --no-ignore flag", () => {
965 engine
= new CLIEngine({
966 cwd
: getFixturePath("cli-engine")
969 assert
.throws(() => {
970 engine
.executeOnFiles(["node_modules"]);
971 }, "All files matched by 'node_modules' are ignored.");
974 // https://github.com/eslint/eslint/issues/5547
975 it("should not check node_modules files even with --no-ignore flag", () => {
977 engine
= new CLIEngine({
978 cwd
: getFixturePath("cli-engine"),
982 assert
.throws(() => {
983 engine
.executeOnFiles(["node_modules"]);
984 }, "All files matched by 'node_modules' are ignored.");
987 it("should not check .hidden files if they are passed explicitly without --no-ignore flag", () => {
989 engine
= new CLIEngine({
990 cwd
: getFixturePath(".."),
993 quotes
: [2, "single"]
997 const report
= engine
.executeOnFiles(["fixtures/files/.bar.js"]);
998 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1000 assert
.strictEqual(report
.results
.length
, 1);
1001 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1002 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1003 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1004 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1005 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1008 // https://github.com/eslint/eslint/issues/12873
1009 it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", () => {
1010 engine
= new CLIEngine({
1011 cwd
: getFixturePath("cli-engine"),
1014 quotes
: [2, "single"]
1018 const report
= engine
.executeOnFiles(["hidden/.hiddenfolder/double-quotes.js"]);
1019 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1021 assert
.strictEqual(report
.results
.length
, 1);
1022 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1023 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1024 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1025 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1026 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1029 it("should check .hidden files if they are passed explicitly with --no-ignore flag", () => {
1031 engine
= new CLIEngine({
1032 cwd
: getFixturePath(".."),
1036 quotes
: [2, "single"]
1040 const report
= engine
.executeOnFiles(["fixtures/files/.bar.js"]);
1042 assert
.strictEqual(report
.results
.length
, 1);
1043 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1044 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1045 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1046 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1047 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1050 it("should check .hidden files if they are unignored with an --ignore-pattern", () => {
1052 engine
= new CLIEngine({
1053 cwd
: getFixturePath("cli-engine"),
1056 ignorePattern
: "!.hidden*",
1058 quotes
: [2, "single"]
1062 const report
= engine
.executeOnFiles(["hidden/"]);
1064 assert
.strictEqual(report
.results
.length
, 1);
1065 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1066 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1067 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1068 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1069 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1072 it("should report zero messages when given a pattern with a .js and a .js2 file", () => {
1074 engine
= new CLIEngine({
1075 extensions
: [".js", ".js2"],
1077 cwd
: path
.join(fixtureDir
, "..")
1080 const report
= engine
.executeOnFiles(["fixtures/files/*.?s*"]);
1082 assert
.strictEqual(report
.results
.length
, 2);
1083 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1084 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
1087 it("should return one error message when given a config with rules with options and severity level set to error", () => {
1089 engine
= new CLIEngine({
1090 cwd
: getFixturePath("configurations"),
1091 configFile
: getFixturePath("configurations", "quotes-error.json")
1093 const report
= engine
.executeOnFiles([getFixturePath("single-quoted.js")]);
1095 assert
.strictEqual(report
.results
.length
, 1);
1096 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1097 assert
.strictEqual(report
.errorCount
, 1);
1098 assert
.strictEqual(report
.warningCount
, 0);
1099 assert
.strictEqual(report
.fixableErrorCount
, 1);
1100 assert
.strictEqual(report
.fixableWarningCount
, 0);
1101 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1102 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1103 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1104 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1105 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1106 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1109 it("should return 3 messages when given a config file and a directory of 3 valid files", () => {
1111 engine
= new CLIEngine({
1112 cwd
: path
.join(fixtureDir
, ".."),
1113 configFile
: getFixturePath("configurations", "semi-error.json")
1116 const report
= engine
.executeOnFiles([getFixturePath("formatters")]);
1118 assert
.strictEqual(report
.results
.length
, 3);
1119 assert
.strictEqual(report
.errorCount
, 0);
1120 assert
.strictEqual(report
.warningCount
, 0);
1121 assert
.strictEqual(report
.fixableErrorCount
, 0);
1122 assert
.strictEqual(report
.fixableWarningCount
, 0);
1123 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1124 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
1125 assert
.strictEqual(report
.results
[2].messages
.length
, 0);
1126 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1127 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1128 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1129 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1130 assert
.strictEqual(report
.results
[1].errorCount
, 0);
1131 assert
.strictEqual(report
.results
[1].warningCount
, 0);
1132 assert
.strictEqual(report
.results
[1].fixableErrorCount
, 0);
1133 assert
.strictEqual(report
.results
[1].fixableWarningCount
, 0);
1134 assert
.strictEqual(report
.results
[2].errorCount
, 0);
1135 assert
.strictEqual(report
.results
[2].warningCount
, 0);
1136 assert
.strictEqual(report
.results
[2].fixableErrorCount
, 0);
1137 assert
.strictEqual(report
.results
[2].fixableWarningCount
, 0);
1141 it("should return the total number of errors when given multiple files", () => {
1143 engine
= new CLIEngine({
1144 cwd
: path
.join(fixtureDir
, ".."),
1145 configFile
: getFixturePath("configurations", "single-quotes-error.json")
1148 const report
= engine
.executeOnFiles([getFixturePath("formatters")]);
1150 assert
.strictEqual(report
.errorCount
, 6);
1151 assert
.strictEqual(report
.warningCount
, 0);
1152 assert
.strictEqual(report
.fixableErrorCount
, 6);
1153 assert
.strictEqual(report
.fixableWarningCount
, 0);
1154 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1155 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1156 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1157 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1158 assert
.strictEqual(report
.results
[1].errorCount
, 3);
1159 assert
.strictEqual(report
.results
[1].warningCount
, 0);
1160 assert
.strictEqual(report
.results
[1].fixableErrorCount
, 3);
1161 assert
.strictEqual(report
.results
[1].fixableWarningCount
, 0);
1162 assert
.strictEqual(report
.results
[2].errorCount
, 3);
1163 assert
.strictEqual(report
.results
[2].warningCount
, 0);
1164 assert
.strictEqual(report
.results
[2].fixableErrorCount
, 3);
1165 assert
.strictEqual(report
.results
[2].fixableWarningCount
, 0);
1168 it("should process when file is given by not specifying extensions", () => {
1170 engine
= new CLIEngine({
1172 cwd
: path
.join(fixtureDir
, "..")
1175 const report
= engine
.executeOnFiles(["fixtures/files/foo.js2"]);
1177 assert
.strictEqual(report
.results
.length
, 1);
1178 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1181 it("should return zero messages when given a config with environment set to browser", () => {
1183 engine
= new CLIEngine({
1184 cwd
: path
.join(fixtureDir
, ".."),
1185 configFile
: getFixturePath("configurations", "env-browser.json")
1188 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1190 assert
.strictEqual(report
.results
.length
, 1);
1191 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1194 it("should return zero messages when given an option to set environment to browser", () => {
1196 engine
= new CLIEngine({
1197 cwd
: path
.join(fixtureDir
, ".."),
1205 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1207 assert
.strictEqual(report
.results
.length
, 1);
1208 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1211 it("should return zero messages when given a config with environment set to Node.js", () => {
1213 engine
= new CLIEngine({
1214 cwd
: path
.join(fixtureDir
, ".."),
1215 configFile
: getFixturePath("configurations", "env-node.json")
1218 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-node.js"))]);
1220 assert
.strictEqual(report
.results
.length
, 1);
1221 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1224 it("should not return results from previous call when calling more than once", () => {
1226 engine
= new CLIEngine({
1227 cwd
: path
.join(fixtureDir
, ".."),
1234 const failFilePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1235 const passFilePath
= fs
.realpathSync(getFixturePath("passing.js"));
1237 let report
= engine
.executeOnFiles([failFilePath
]);
1239 assert
.strictEqual(report
.results
.length
, 1);
1240 assert
.strictEqual(report
.results
[0].filePath
, failFilePath
);
1241 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1242 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "semi");
1243 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1245 report
= engine
.executeOnFiles([passFilePath
]);
1246 assert
.strictEqual(report
.results
.length
, 1);
1247 assert
.strictEqual(report
.results
[0].filePath
, passFilePath
);
1248 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1252 it("should throw an error when given a directory with all eslint excluded files in the directory", () => {
1254 engine
= new CLIEngine({
1255 ignorePath
: getFixturePath(".eslintignore")
1258 assert
.throws(() => {
1259 engine
.executeOnFiles([getFixturePath("./cli-engine/")]);
1260 }, `All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`);
1263 it("should throw an error when all given files are ignored", () => {
1265 assert
.throws(() => {
1266 engine
.executeOnFiles(["tests/fixtures/cli-engine/"]);
1267 }, "All files matched by 'tests/fixtures/cli-engine/' are ignored.");
1270 it("should throw an error when all given files are ignored even with a `./` prefix", () => {
1271 engine
= new CLIEngine({
1272 ignorePath
: getFixturePath(".eslintignore")
1275 assert
.throws(() => {
1276 engine
.executeOnFiles(["./tests/fixtures/cli-engine/"]);
1277 }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
1280 // https://github.com/eslint/eslint/issues/3788
1281 it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", () => {
1282 engine
= new CLIEngine({
1283 ignorePath
: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
1286 quotes
: [2, "double"]
1288 cwd
: getFixturePath("cli-engine", "nested_node_modules")
1291 const report
= engine
.executeOnFiles(["."]);
1293 assert
.strictEqual(report
.results
.length
, 1);
1294 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1295 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1296 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1297 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1300 // https://github.com/eslint/eslint/issues/3812
1301 it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", () => {
1302 engine
= new CLIEngine({
1303 ignorePath
: getFixturePath("cli-engine/.eslintignore2"),
1306 quotes
: [2, "double"]
1310 assert
.throws(() => {
1311 engine
.executeOnFiles(["./tests/fixtures/cli-engine/"]);
1312 }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
1315 it("should throw an error when all given files are ignored via ignore-pattern", () => {
1316 engine
= new CLIEngine({
1317 ignorePattern
: "tests/fixtures/single-quoted.js"
1320 assert
.throws(() => {
1321 engine
.executeOnFiles(["tests/fixtures/*-quoted.js"]);
1322 }, "All files matched by 'tests/fixtures/*-quoted.js' are ignored.");
1325 it("should return a warning when an explicitly given file is ignored", () => {
1326 engine
= new CLIEngine({
1327 ignorePath
: getFixturePath(".eslintignore"),
1328 cwd
: getFixturePath()
1331 const filePath
= getFixturePath("passing.js");
1333 const report
= engine
.executeOnFiles([filePath
]);
1335 assert
.strictEqual(report
.results
.length
, 1);
1336 assert
.strictEqual(report
.errorCount
, 0);
1337 assert
.strictEqual(report
.warningCount
, 1);
1338 assert
.strictEqual(report
.fixableErrorCount
, 0);
1339 assert
.strictEqual(report
.fixableWarningCount
, 0);
1340 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1341 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1342 assert
.strictEqual(report
.results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
1343 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1344 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1345 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1346 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1349 it("should return two messages when given a file in excluded files list while ignore is off", () => {
1351 engine
= new CLIEngine({
1352 ignorePath
: getFixturePath(".eslintignore"),
1359 const filePath
= fs
.realpathSync(getFixturePath("undef.js"));
1361 const report
= engine
.executeOnFiles([filePath
]);
1363 assert
.strictEqual(report
.results
.length
, 1);
1364 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1365 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-undef");
1366 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1367 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-undef");
1368 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 2);
1371 it("should return zero messages when executing a file with a shebang", () => {
1373 engine
= new CLIEngine({
1377 const report
= engine
.executeOnFiles([getFixturePath("shebang.js")]);
1379 assert
.strictEqual(report
.results
.length
, 1);
1380 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1383 it("should give a warning when loading a custom rule that doesn't exist", () => {
1385 engine
= new CLIEngine({
1387 rulesPaths
: [getFixturePath("rules", "dir1")],
1388 configFile
: getFixturePath("rules", "missing-rule.json")
1390 const report
= engine
.executeOnFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1392 assert
.strictEqual(report
.results
.length
, 1);
1393 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1394 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "missing-rule");
1395 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1396 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Definition for rule 'missing-rule' was not found.");
1401 it("should throw an error when loading a bad custom rule", () => {
1403 engine
= new CLIEngine({
1405 rulePaths
: [getFixturePath("rules", "wrong")],
1406 configFile
: getFixturePath("rules", "eslint.json")
1410 assert
.throws(() => {
1411 engine
.executeOnFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1412 }, /Error while loading rule 'custom-rule'/u);
1415 it("should return one message when a custom rule matches a file", () => {
1417 engine
= new CLIEngine({
1420 rulePaths
: [getFixturePath("rules/")],
1421 configFile
: getFixturePath("rules", "eslint.json")
1424 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1426 const report
= engine
.executeOnFiles([filePath
]);
1428 assert
.strictEqual(report
.results
.length
, 1);
1429 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1430 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1431 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "custom-rule");
1432 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1435 it("should load custom rule from the provided cwd", () => {
1436 const cwd
= path
.resolve(getFixturePath("rules"));
1438 engine
= new CLIEngine({
1442 configFile
: "eslint.json"
1445 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1447 const report
= engine
.executeOnFiles([filePath
]);
1449 assert
.strictEqual(report
.results
.length
, 1);
1450 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1451 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1452 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "custom-rule");
1453 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1456 it("should return messages when multiple custom rules match a file", () => {
1458 engine
= new CLIEngine({
1461 getFixturePath("rules", "dir1"),
1462 getFixturePath("rules", "dir2")
1464 configFile
: getFixturePath("rules", "multi-rulesdirs.json")
1467 const filePath
= fs
.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.js"));
1469 const report
= engine
.executeOnFiles([filePath
]);
1471 assert
.strictEqual(report
.results
.length
, 1);
1472 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1473 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1474 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-literals");
1475 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1476 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-strings");
1477 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 2);
1480 it("should return zero messages when executing without useEslintrc flag", () => {
1482 engine
= new CLIEngine({
1487 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1489 const report
= engine
.executeOnFiles([filePath
]);
1491 assert
.strictEqual(report
.results
.length
, 1);
1492 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1493 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1496 it("should return zero messages when executing without useEslintrc flag in Node.js environment", () => {
1498 engine
= new CLIEngine({
1504 const filePath
= fs
.realpathSync(getFixturePath("process-exit.js"));
1506 const report
= engine
.executeOnFiles([filePath
]);
1508 assert
.strictEqual(report
.results
.length
, 1);
1509 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1510 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1513 it("should return zero messages when executing with base-config flag set to false", () => {
1515 engine
= new CLIEngine({
1521 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1523 const report
= engine
.executeOnFiles([filePath
]);
1525 assert
.strictEqual(report
.results
.length
, 1);
1526 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1527 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1530 it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", () => {
1532 engine
= new CLIEngine({
1538 const filePath
= fs
.realpathSync(getFixturePath("eslintrc", "quotes.js"));
1540 const report
= engine
.executeOnFiles([filePath
]);
1542 assert
.strictEqual(report
.results
.length
, 1);
1543 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1544 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1547 it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", () => {
1549 engine
= new CLIEngine({
1555 const filePath
= fs
.realpathSync(getFixturePath("packagejson", "quotes.js"));
1557 const report
= engine
.executeOnFiles([filePath
]);
1559 assert
.strictEqual(report
.results
.length
, 1);
1560 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1561 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1564 it("should warn when deprecated rules are configured", () => {
1565 engine
= new CLIEngine({
1567 configFile
: ".eslintrc.js",
1575 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1577 assert
.sameDeepMembers(
1578 report
.usedDeprecatedRules
,
1580 { ruleId
: "indent-legacy", replacedBy
: ["indent"] },
1581 { ruleId
: "require-jsdoc", replacedBy
: [] },
1582 { ruleId
: "valid-jsdoc", replacedBy
: [] }
1587 it("should not warn when deprecated rules are not configured", () => {
1588 engine
= new CLIEngine({
1590 configFile
: ".eslintrc.js",
1591 rules
: { indent
: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
1594 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1596 assert
.deepStrictEqual(report
.usedDeprecatedRules
, []);
1599 it("should warn when deprecated rules are found in a config", () => {
1600 engine
= new CLIEngine({
1602 configFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
1606 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1608 assert
.deepStrictEqual(
1609 report
.usedDeprecatedRules
,
1610 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
1614 describe("Fix Mode", () => {
1616 it("should return fixed text on multiple files when in fix mode", () => {
1619 * Converts CRLF to LF in output.
1620 * This is a workaround for git's autocrlf option on Windows.
1621 * @param {Object} result A result object to convert.
1624 function convertCRLF(result
) {
1625 if (result
&& result
.output
) {
1626 result
.output
= result
.output
.replace(/\r\n/gu, "\n");
1630 engine
= new CLIEngine({
1631 cwd
: path
.join(fixtureDir
, ".."),
1636 quotes
: [2, "double"],
1639 "space-infix-ops": 2
1643 const report
= engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1645 report
.results
.forEach(convertCRLF
);
1646 assert
.deepStrictEqual(report
.results
, [
1648 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/multipass.js")),
1652 fixableErrorCount
: 0,
1653 fixableWarningCount
: 0,
1654 output
: "true ? \"yes\" : \"no\";\n"
1657 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/ok.js")),
1661 fixableErrorCount
: 0,
1662 fixableWarningCount
: 0
1665 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes-semi-eqeqeq.js")),
1672 message
: "Expected '===' and instead saw '=='.",
1673 messageId
: "unexpected",
1674 nodeType
: "BinaryExpression",
1681 fixableErrorCount
: 0,
1682 fixableWarningCount
: 0,
1683 output
: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n"
1686 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes.js")),
1694 message
: "'foo' is not defined.",
1695 nodeType
: "Identifier",
1702 fixableErrorCount
: 0,
1703 fixableWarningCount
: 0,
1704 output
: "var msg = \"hi\" + foo;\n"
1707 assert
.strictEqual(report
.errorCount
, 2);
1708 assert
.strictEqual(report
.warningCount
, 0);
1709 assert
.strictEqual(report
.fixableErrorCount
, 0);
1710 assert
.strictEqual(report
.fixableWarningCount
, 0);
1713 it("should run autofix even if files are cached without autofix results", () => {
1714 const baseOptions
= {
1715 cwd
: path
.join(fixtureDir
, ".."),
1719 quotes
: [2, "double"],
1722 "space-infix-ops": 2
1726 engine
= new CLIEngine(Object
.assign({}, baseOptions
, { cache
: true, fix
: false }));
1728 // Do initial lint run and populate the cache file
1729 engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1731 engine
= new CLIEngine(Object
.assign({}, baseOptions
, { cache
: true, fix
: true }));
1733 const report
= engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1735 assert
.ok(report
.results
.some(result
=> result
.output
));
1740 // These tests have to do with https://github.com/eslint/eslint/issues/963
1742 describe("configuration hierarchy", () => {
1744 // Default configuration - blank
1745 it("should return zero messages when executing with no .eslintrc", () => {
1747 engine
= new CLIEngine({
1748 cwd
: path
.join(fixtureDir
, ".."),
1752 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1754 assert
.strictEqual(report
.results
.length
, 1);
1755 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1758 // No default configuration rules - conf/environments.js (/*eslint-env node*/)
1759 it("should return zero messages when executing with no .eslintrc in the Node.js environment", () => {
1761 engine
= new CLIEngine({
1762 cwd
: path
.join(fixtureDir
, ".."),
1767 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
1769 assert
.strictEqual(report
.results
.length
, 1);
1770 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1773 // Project configuration - first level .eslintrc
1774 it("should return zero messages when executing with .eslintrc in the Node.js environment", () => {
1776 engine
= new CLIEngine({
1777 cwd
: path
.join(fixtureDir
, "..")
1780 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1782 assert
.strictEqual(report
.results
.length
, 1);
1783 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1786 // Project configuration - first level .eslintrc
1787 it("should return zero messages when executing with .eslintrc in the Node.js environment", () => {
1789 engine
= new CLIEngine({
1790 cwd
: path
.join(fixtureDir
, "..")
1793 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1795 assert
.strictEqual(report
.results
.length
, 1);
1796 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1799 // Project configuration - first level .eslintrc
1800 it("should return one message when executing with .eslintrc", () => {
1802 engine
= new CLIEngine({
1803 cwd
: path
.join(fixtureDir
, "..")
1806 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1808 assert
.strictEqual(report
.results
.length
, 1);
1809 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1810 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1811 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1814 // Project configuration - second level .eslintrc
1815 it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", () => {
1817 engine
= new CLIEngine({
1818 cwd
: path
.join(fixtureDir
, "..")
1821 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1823 assert
.strictEqual(report
.results
.length
, 1);
1824 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1825 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1826 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1829 // Project configuration - third level .eslintrc
1830 it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", () => {
1832 engine
= new CLIEngine({
1833 cwd
: path
.join(fixtureDir
, "..")
1836 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
1838 assert
.strictEqual(report
.results
.length
, 1);
1839 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1840 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1841 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1844 // Project configuration - first level package.json
1845 it("should return one message when executing with package.json", () => {
1847 engine
= new CLIEngine({
1848 cwd
: path
.join(fixtureDir
, "..")
1851 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
1853 assert
.strictEqual(report
.results
.length
, 1);
1854 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1855 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1856 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1859 // Project configuration - second level package.json
1860 it("should return zero messages when executing with local package.json that overrides parent package.json", () => {
1862 engine
= new CLIEngine({
1863 cwd
: path
.join(fixtureDir
, "..")
1866 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
1868 assert
.strictEqual(report
.results
.length
, 1);
1869 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1872 // Project configuration - third level package.json
1873 it("should return one message when executing with local package.json that overrides parent and grandparent package.json", () => {
1875 engine
= new CLIEngine({
1876 cwd
: path
.join(fixtureDir
, "..")
1879 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
1881 assert
.strictEqual(report
.results
.length
, 1);
1882 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1883 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1884 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1887 // Project configuration - .eslintrc overrides package.json in same directory
1888 it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", () => {
1890 engine
= new CLIEngine({
1891 cwd
: path
.join(fixtureDir
, "..")
1894 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
1896 assert
.strictEqual(report
.results
.length
, 1);
1897 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1898 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1899 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1902 // Command line configuration - --config with first level .eslintrc
1903 it("should return two messages when executing with config file that adds to local .eslintrc", () => {
1905 engine
= new CLIEngine({
1906 cwd
: path
.join(fixtureDir
, ".."),
1907 configFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1910 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1912 assert
.strictEqual(report
.results
.length
, 1);
1913 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1914 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1915 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1916 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "semi");
1917 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 1);
1920 // Command line configuration - --config with first level .eslintrc
1921 it("should return no messages when executing with config file that overrides local .eslintrc", () => {
1923 engine
= new CLIEngine({
1924 cwd
: path
.join(fixtureDir
, ".."),
1925 configFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1928 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1930 assert
.strictEqual(report
.results
.length
, 1);
1931 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1934 // Command line configuration - --config with second level .eslintrc
1935 it("should return two messages when executing with config file that adds to local and parent .eslintrc", () => {
1937 engine
= new CLIEngine({
1938 cwd
: path
.join(fixtureDir
, ".."),
1939 configFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1942 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1944 assert
.strictEqual(report
.results
.length
, 1);
1945 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1946 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1947 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1948 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "semi");
1949 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 1);
1952 // Command line configuration - --config with second level .eslintrc
1953 it("should return one message when executing with config file that overrides local and parent .eslintrc", () => {
1955 engine
= new CLIEngine({
1956 cwd
: path
.join(fixtureDir
, ".."),
1957 configFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml")
1960 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1962 assert
.strictEqual(report
.results
.length
, 1);
1963 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1964 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1965 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1968 // Command line configuration - --config with first level .eslintrc
1969 it("should return no messages when executing with config file that overrides local .eslintrc", () => {
1971 engine
= new CLIEngine({
1972 cwd
: path
.join(fixtureDir
, ".."),
1973 configFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1976 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1978 assert
.strictEqual(report
.results
.length
, 1);
1979 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1982 // Command line configuration - --rule with --config and first level .eslintrc
1983 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", () => {
1985 engine
= new CLIEngine({
1986 cwd
: path
.join(fixtureDir
, ".."),
1987 configFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
1989 quotes
: [1, "double"]
1993 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1995 assert
.strictEqual(report
.results
.length
, 1);
1996 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1997 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1998 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2001 // Command line configuration - --rule with --config and first level .eslintrc
2002 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", () => {
2004 engine
= new CLIEngine({
2005 cwd
: path
.join(fixtureDir
, ".."),
2006 configFile
: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
2008 quotes
: [1, "double"]
2012 const report
= engine
.executeOnFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
2014 assert
.strictEqual(report
.results
.length
, 1);
2015 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2016 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2017 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2022 describe("plugins", () => {
2023 it("should return two messages when executing with config file that specifies a plugin", () => {
2024 engine
= cliEngineWithPlugins({
2025 cwd
: path
.join(fixtureDir
, ".."),
2026 configFile
: getFixturePath("configurations", "plugins-with-prefix.json"),
2030 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
2032 assert
.strictEqual(report
.results
.length
, 1);
2033 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2034 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2037 it("should return two messages when executing with config file that specifies a plugin with namespace", () => {
2038 engine
= cliEngineWithPlugins({
2039 cwd
: path
.join(fixtureDir
, ".."),
2040 configFile
: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
2044 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2046 assert
.strictEqual(report
.results
.length
, 1);
2047 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2048 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2051 it("should return two messages when executing with config file that specifies a plugin without prefix", () => {
2052 engine
= cliEngineWithPlugins({
2053 cwd
: path
.join(fixtureDir
, ".."),
2054 configFile
: getFixturePath("configurations", "plugins-without-prefix.json"),
2058 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2060 assert
.strictEqual(report
.results
.length
, 1);
2061 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2062 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2065 it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", () => {
2066 engine
= cliEngineWithPlugins({
2067 cwd
: path
.join(fixtureDir
, ".."),
2068 configFile
: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
2072 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2074 assert
.strictEqual(report
.results
.length
, 1);
2075 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2076 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2079 it("should return two messages when executing with cli option that specifies a plugin", () => {
2080 engine
= cliEngineWithPlugins({
2081 cwd
: path
.join(fixtureDir
, ".."),
2083 plugins
: ["example"],
2084 rules
: { "example/example-rule": 1 }
2087 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2089 assert
.strictEqual(report
.results
.length
, 1);
2090 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2091 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2094 it("should return two messages when executing with cli option that specifies preloaded plugin", () => {
2095 engine
= new CLIEngine({
2096 cwd
: path
.join(fixtureDir
, ".."),
2099 rules
: { "test/example-rule": 1 }
2102 engine
.addPlugin("eslint-plugin-test", { rules
: { "example-rule": require("../../fixtures/rules/custom-rule") } });
2104 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2106 assert
.strictEqual(report
.results
.length
, 1);
2107 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2108 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "test/example-rule");
2111 it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", () => {
2112 engine
= new CLIEngine({
2113 resolvePluginsRelativeTo
: getFixturePath("plugins"),
2115 plugins
: ["with-rules"],
2116 rules
: { "with-rules/rule1": "error" }
2121 const report
= engine
.executeOnText("foo");
2123 assert
.strictEqual(report
.results
.length
, 1);
2124 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2125 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "with-rules/rule1");
2126 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Rule report from plugin");
2130 describe("cache", () => {
2133 * helper method to delete a file without caring about exceptions
2134 * @param {string} filePath The file path
2137 function doDelete(filePath
) {
2139 fs
.unlinkSync(filePath
);
2143 * we don't care if the file didn't exist, since our
2144 * intention was to remove the file
2150 * helper method to delete the cache files created during testing
2153 function deleteCache() {
2154 doDelete(path
.resolve(".eslintcache"));
2155 doDelete(path
.resolve(".cache/custom-cache"));
2167 describe("when the cacheFile is a directory or looks like a directory", () => {
2170 * helper method to delete the cache files created during testing
2173 function deleteCacheDir() {
2175 fs
.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
2179 * we don't care if the file didn't exist, since our
2180 * intention was to remove the file
2192 it("should create the cache file inside the provided directory", () => {
2193 assert
.isFalse(shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2195 engine
= new CLIEngine({
2198 // specifying cache true the cache will be created
2200 cacheFile
: "./tmp/.cacheFileDir/",
2209 const file
= getFixturePath("cache/src", "test-file.js");
2211 engine
.executeOnFiles([file
]);
2213 assert
.isTrue(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2219 it("should create the cache file inside the provided directory using the cacheLocation option", () => {
2220 assert
.isFalse(shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2222 engine
= new CLIEngine({
2225 // specifying cache true the cache will be created
2227 cacheLocation
: "./tmp/.cacheFileDir/",
2236 const file
= getFixturePath("cache/src", "test-file.js");
2238 engine
.executeOnFiles([file
]);
2240 assert
.isTrue(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2245 it("should create the cache file inside cwd when no cacheLocation provided", () => {
2246 const cwd
= path
.resolve(getFixturePath("cli-engine"));
2248 engine
= new CLIEngine({
2259 const file
= getFixturePath("cli-engine", "console.js");
2261 engine
.executeOnFiles([file
]);
2263 assert
.isTrue(shell
.test("-f", path
.resolve(cwd
, ".eslintcache")), "the cache for eslint was created at provided cwd");
2266 it("should invalidate the cache if the configuration changed between executions", () => {
2267 assert
.isFalse(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2269 engine
= new CLIEngine({
2272 // specifying cache true the cache will be created
2282 let spy
= sinon
.spy(fs
, "readFileSync");
2284 let file
= getFixturePath("cache/src", "test-file.js");
2286 file
= fs
.realpathSync(file
);
2288 const result
= engine
.executeOnFiles([file
]);
2290 assert
.strictEqual(result
.errorCount
+ result
.warningCount
, 0, "the file passed without errors or warnings");
2291 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2292 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2297 engine
= new CLIEngine({
2300 // specifying cache true the cache will be created
2311 spy
= sinon
.spy(fs
, "readFileSync");
2313 const cachedResult
= engine
.executeOnFiles([file
]);
2315 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed because the config changed");
2316 assert
.strictEqual(cachedResult
.errorCount
, 1, "since configuration changed the cache was not used an one error was reported");
2317 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2320 it("should remember the files from a previous run and do not operate on them if not changed", () => {
2322 assert
.isFalse(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2324 engine
= new CLIEngine({
2327 // specifying cache true the cache will be created
2337 let spy
= sinon
.spy(fs
, "readFileSync");
2339 let file
= getFixturePath("cache/src", "test-file.js");
2341 file
= fs
.realpathSync(file
);
2343 const result
= engine
.executeOnFiles([file
]);
2345 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2346 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2351 engine
= new CLIEngine({
2354 // specifying cache true the cache will be created
2365 spy
= sinon
.spy(fs
, "readFileSync");
2367 const cachedResult
= engine
.executeOnFiles([file
]);
2369 assert
.deepStrictEqual(result
, cachedResult
, "the result is the same regardless of using cache or not");
2371 // assert the file was not processed because the cache was used
2372 assert
.isFalse(spy
.calledWith(file
), "the file was not loaded because it used the cache");
2375 it("should remember the files from a previous run and do not operate on then if not changed", () => {
2377 const cacheFile
= getFixturePath(".eslintcache");
2378 const cliEngineOptions
= {
2381 // specifying cache true the cache will be created
2389 cwd
: path
.join(fixtureDir
, "..")
2392 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint does not exist");
2394 engine
= new CLIEngine(cliEngineOptions
);
2396 let file
= getFixturePath("cache/src", "test-file.js");
2398 file
= fs
.realpathSync(file
);
2400 engine
.executeOnFiles([file
]);
2402 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint was created");
2404 cliEngineOptions
.cache
= false;
2405 engine
= new CLIEngine(cliEngineOptions
);
2407 engine
.executeOnFiles([file
]);
2409 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint was deleted since last run did not used the cache");
2412 it("should store in the cache a file that failed the test", () => {
2414 const cacheFile
= getFixturePath(".eslintcache");
2416 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint does not exist");
2418 engine
= new CLIEngine({
2419 cwd
: path
.join(fixtureDir
, ".."),
2422 // specifying cache true the cache will be created
2432 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2433 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2435 const result
= engine
.executeOnFiles([badFile
, goodFile
]);
2437 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint was created");
2439 const fileCache
= fCache
.createFromFile(cacheFile
);
2440 const { cache
} = fileCache
;
2442 assert
.isTrue(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2444 assert
.isTrue(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2446 const cachedResult
= engine
.executeOnFiles([badFile
, goodFile
]);
2448 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2451 it("should not contain in the cache a file that was deleted", () => {
2453 const cacheFile
= getFixturePath(".eslintcache");
2455 doDelete(cacheFile
);
2457 engine
= new CLIEngine({
2458 cwd
: path
.join(fixtureDir
, ".."),
2461 // specifying cache true the cache will be created
2471 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2472 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2473 const toBeDeletedFile
= fs
.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
2475 engine
.executeOnFiles([badFile
, goodFile
, toBeDeletedFile
]);
2477 const fileCache
= fCache
.createFromFile(cacheFile
);
2478 let { cache
} = fileCache
;
2480 assert
.isTrue(typeof cache
.getKey(toBeDeletedFile
) === "object", "the entry for the file to be deleted is in the cache");
2482 // delete the file from the file system
2483 fs
.unlinkSync(toBeDeletedFile
);
2486 * file-entry-cache@2.0.0 will remove from the cache deleted files
2487 * even when they were not part of the array of files to be analyzed
2489 engine
.executeOnFiles([badFile
, goodFile
]);
2491 cache
= JSON
.parse(fs
.readFileSync(cacheFile
));
2493 assert
.isTrue(typeof cache
[toBeDeletedFile
] === "undefined", "the entry for the file to be deleted is not in the cache");
2496 it("should contain files that were not visited in the cache provided they still exist", () => {
2498 const cacheFile
= getFixturePath(".eslintcache");
2500 doDelete(cacheFile
);
2502 engine
= new CLIEngine({
2503 cwd
: path
.join(fixtureDir
, ".."),
2506 // specifying cache true the cache will be created
2516 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2517 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2518 const testFile2
= fs
.realpathSync(getFixturePath("cache/src", "test-file2.js"));
2520 engine
.executeOnFiles([badFile
, goodFile
, testFile2
]);
2522 let fileCache
= fCache
.createFromFile(cacheFile
);
2523 let { cache
} = fileCache
;
2525 assert
.isTrue(typeof cache
.getKey(testFile2
) === "object", "the entry for the test-file2 is in the cache");
2528 * we pass a different set of files minus test-file2
2529 * previous version of file-entry-cache would remove the non visited
2530 * entries. 2.0.0 version will keep them unless they don't exist
2532 engine
.executeOnFiles([badFile
, goodFile
]);
2534 fileCache
= fCache
.createFromFile(cacheFile
);
2535 cache
= fileCache
.cache
;
2537 assert
.isTrue(typeof cache
.getKey(testFile2
) === "object", "the entry for the test-file2 is in the cache");
2540 it("should not delete cache when executing on text", () => {
2541 const cacheFile
= getFixturePath(".eslintcache");
2543 engine
= new CLIEngine({
2544 cwd
: path
.join(fixtureDir
, ".."),
2554 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2556 engine
.executeOnText("var foo = 'bar';");
2558 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2561 it("should not delete cache when executing on text with a provided filename", () => {
2562 const cacheFile
= getFixturePath(".eslintcache");
2564 engine
= new CLIEngine({
2565 cwd
: path
.join(fixtureDir
, ".."),
2575 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2577 engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
2579 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2582 it("should not delete cache when executing on files with --cache flag", () => {
2583 const cacheFile
= getFixturePath(".eslintcache");
2585 engine
= new CLIEngine({
2586 cwd
: path
.join(fixtureDir
, ".."),
2597 const file
= getFixturePath("cli-engine", "console.js");
2599 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2601 engine
.executeOnFiles([file
]);
2603 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2606 it("should delete cache when executing on files without --cache flag", () => {
2607 const cacheFile
= getFixturePath(".eslintcache");
2609 engine
= new CLIEngine({
2610 cwd
: path
.join(fixtureDir
, ".."),
2620 const file
= getFixturePath("cli-engine", "console.js");
2622 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2624 engine
.executeOnFiles([file
]);
2626 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint has been deleted");
2629 describe("cacheFile", () => {
2630 it("should use the specified cache file", () => {
2631 const customCacheFile
= path
.resolve(".cache/custom-cache");
2633 assert
.isFalse(shell
.test("-f", customCacheFile
), "the cache for eslint does not exist");
2635 engine
= new CLIEngine({
2638 // specify a custom cache file
2639 cacheFile
: customCacheFile
,
2641 // specifying cache true the cache will be created
2648 cwd
: path
.join(fixtureDir
, "..")
2651 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2652 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2654 const result
= engine
.executeOnFiles([badFile
, goodFile
]);
2656 assert
.isTrue(shell
.test("-f", customCacheFile
), "the cache for eslint was created");
2658 const fileCache
= fCache
.createFromFile(customCacheFile
);
2659 const { cache
} = fileCache
;
2661 assert
.isTrue(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2663 assert
.isTrue(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2665 const cachedResult
= engine
.executeOnFiles([badFile
, goodFile
]);
2667 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2672 describe("processors", () => {
2673 it("should return two messages when executing with config file that specifies a processor", () => {
2674 engine
= cliEngineWithPlugins({
2675 configFile
: getFixturePath("configurations", "processors.json"),
2677 extensions
: ["js", "txt"],
2678 cwd
: path
.join(fixtureDir
, "..")
2681 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2683 assert
.strictEqual(report
.results
.length
, 1);
2684 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2686 it("should return two messages when executing with config file that specifies preloaded processor", () => {
2687 engine
= new CLIEngine({
2689 plugins
: ["test-processor"],
2694 extensions
: ["js", "txt"],
2695 cwd
: path
.join(fixtureDir
, "..")
2698 engine
.addPlugin("test-processor", {
2704 postprocess(messages
) {
2711 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2713 assert
.strictEqual(report
.results
.length
, 1);
2714 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2716 it("should run processors when calling executeOnFiles with config file that specifies a processor", () => {
2717 engine
= cliEngineWithPlugins({
2718 configFile
: getFixturePath("configurations", "processors.json"),
2720 extensions
: ["js", "txt"],
2721 cwd
: path
.join(fixtureDir
, "..")
2724 const report
= engine
.executeOnFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2726 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2727 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2729 it("should run processors when calling executeOnFiles with config file that specifies preloaded processor", () => {
2730 engine
= new CLIEngine({
2732 plugins
: ["test-processor"],
2737 extensions
: ["js", "txt"],
2738 cwd
: path
.join(fixtureDir
, "..")
2741 engine
.addPlugin("test-processor", {
2745 return [text
.replace("a()", "b()")];
2747 postprocess(messages
) {
2748 messages
[0][0].ruleId
= "post-processed";
2755 const report
= engine
.executeOnFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2757 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2758 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2760 it("should run processors when calling executeOnText with config file that specifies a processor", () => {
2761 engine
= cliEngineWithPlugins({
2762 configFile
: getFixturePath("configurations", "processors.json"),
2764 extensions
: ["js", "txt"],
2768 const report
= engine
.executeOnText("function a() {console.log(\"Test\");}", "tests/fixtures/processors/test/test-processor.txt");
2770 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2771 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2773 it("should run processors when calling executeOnText with config file that specifies preloaded processor", () => {
2774 engine
= new CLIEngine({
2776 plugins
: ["test-processor"],
2781 extensions
: ["js", "txt"],
2785 engine
.addPlugin("test-processor", {
2789 return [text
.replace("a()", "b()")];
2791 postprocess(messages
) {
2792 messages
[0][0].ruleId
= "post-processed";
2799 const report
= engine
.executeOnText("function a() {console.log(\"Test\");}", "tests/fixtures/processors/test/test-processor.txt");
2801 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2802 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2805 describe("autofixing with processors", () => {
2806 const HTML_PROCESSOR
= Object
.freeze({
2808 return [text
.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
2810 postprocess(problemLists
) {
2811 return problemLists
[0].map(problem
=> {
2813 const updatedFix
= Object
.assign({}, problem
.fix
, {
2814 range
: problem
.fix
.range
.map(index
=> index
+ "<script>".length
)
2817 return Object
.assign({}, problem
, { fix
: updatedFix
});
2825 it("should run in autofix mode when using a processor that supports autofixing", () => {
2826 engine
= new CLIEngine({
2828 plugins
: ["test-processor"],
2832 extensions
: ["js", "txt"],
2837 engine
.addPlugin("test-processor", {
2839 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2843 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2845 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
2846 assert
.strictEqual(report
.results
[0].output
, "<script>foo;</script>");
2849 it("should not run in autofix mode when using a processor that does not support autofixing", () => {
2850 engine
= new CLIEngine({
2852 plugins
: ["test-processor"],
2856 extensions
: ["js", "txt"],
2861 engine
.addPlugin("test-processor", { processors
: { ".html": HTML_PROCESSOR
} });
2863 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2865 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2866 assert
.isFalse(Object
.prototype.hasOwnProperty
.call(report
.results
[0], "output"));
2869 it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", () => {
2870 engine
= new CLIEngine({
2872 plugins
: ["test-processor"],
2876 extensions
: ["js", "txt"],
2880 engine
.addPlugin("test-processor", {
2882 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2886 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2888 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2889 assert
.isFalse(Object
.prototype.hasOwnProperty
.call(report
.results
[0], "output"));
2894 describe("Patterns which match no file should throw errors.", () => {
2896 engine
= new CLIEngine({
2897 cwd
: getFixturePath("cli-engine"),
2902 it("one file", () => {
2903 assert
.throws(() => {
2904 engine
.executeOnFiles(["non-exist.js"]);
2905 }, "No files matching 'non-exist.js' were found.");
2908 it("should throw if the directory exists and is empty", () => {
2909 assert
.throws(() => {
2910 engine
.executeOnFiles(["empty"]);
2911 }, "No files matching 'empty' were found.");
2914 it("one glob pattern", () => {
2915 assert
.throws(() => {
2916 engine
.executeOnFiles(["non-exist/**/*.js"]);
2917 }, "No files matching 'non-exist/**/*.js' were found.");
2920 it("two files", () => {
2921 assert
.throws(() => {
2922 engine
.executeOnFiles(["aaa.js", "bbb.js"]);
2923 }, "No files matching 'aaa.js' were found.");
2926 it("a mix of an existing file and a non-existing file", () => {
2927 assert
.throws(() => {
2928 engine
.executeOnFiles(["console.js", "non-exist.js"]);
2929 }, "No files matching 'non-exist.js' were found.");
2933 describe("overrides", () => {
2935 engine
= new CLIEngine({
2936 cwd
: getFixturePath("cli-engine/overrides-with-dot"),
2941 it("should recognize dotfiles", () => {
2942 const ret
= engine
.executeOnFiles([".test-target.js"]);
2944 assert
.strictEqual(ret
.results
.length
, 1);
2945 assert
.strictEqual(ret
.results
[0].messages
.length
, 1);
2946 assert
.strictEqual(ret
.results
[0].messages
[0].ruleId
, "no-unused-vars");
2950 describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
2952 ({ CLIEngine
} = defineCLIEngineWithInMemoryFileSystem({
2953 cwd
: () => path
.join(os
.tmpdir(), "cli-engine/11510"),
2955 "no-console-error-in-overrides.json": JSON
.stringify({
2958 rules
: { "no-console": "error" }
2961 ".eslintrc.json": JSON
.stringify({
2962 extends: "./no-console-error-in-overrides.json",
2963 rules
: { "no-console": "off" }
2965 "a.js": "console.log();"
2968 engine
= new CLIEngine();
2971 it("should not report 'no-console' error.", () => {
2972 const { results
} = engine
.executeOnFiles("a.js");
2974 assert
.strictEqual(results
.length
, 1);
2975 assert
.deepStrictEqual(results
[0].messages
, []);
2979 describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
2981 ({ CLIEngine
} = defineCLIEngineWithInMemoryFileSystem({
2982 cwd
: () => path
.join(os
.tmpdir(), "cli-engine/11559"),
2984 "node_modules/eslint-plugin-test/index.js": `
2986 recommended: { plugins: ["test"] }
2990 meta: { schema: [{ type: "number" }] },
2991 create() { return {}; }
2995 ".eslintrc.json": JSON
.stringify({
2997 // Import via the recommended config.
2998 extends: "plugin:test/recommended",
3000 // Has invalid option.
3001 rules
: { "test/foo": ["error", "invalid-option"] }
3003 "a.js": "console.log();"
3006 engine
= new CLIEngine();
3009 it("should throw fatal error.", () => {
3010 assert
.throws(() => {
3011 engine
.executeOnFiles("a.js");
3012 }, /invalid-option/u);
3016 describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
3018 ({ CLIEngine
} = defineCLIEngineWithInMemoryFileSystem({
3019 cwd
: () => path
.join(os
.tmpdir(), "cli-engine/11586"),
3021 "node_modules/eslint-plugin-test/index.js": `
3024 meta: { type: "problem", fixable: "code" },
3028 if (node.name === "example") {
3032 fix: fixer => fixer.replaceText(node, "fixed")
3041 ".eslintrc.json": JSON
.stringify({
3043 rules
: { "test/no-example": "error" }
3048 engine
= new CLIEngine({ fix
: true, fixTypes
: ["problem"] });
3051 it("should not crash.", () => {
3052 const { results
} = engine
.executeOnFiles("a.js");
3054 assert
.strictEqual(results
.length
, 1);
3055 assert
.deepStrictEqual(results
[0].messages
, []);
3056 assert
.deepStrictEqual(results
[0].output
, "fixed;");
3060 describe("multiple processors", () => {
3061 const root
= path
.join(os
.tmpdir(), "eslint/cli-engine/multiple-processors");
3062 const commonFiles
= {
3063 "node_modules/pattern-processor/index.js": fs
.readFileSync(
3064 require
.resolve("../../fixtures/processors/pattern-processor"),
3067 "node_modules/eslint-plugin-markdown/index.js": `
3068 const { defineProcessor } = require("pattern-processor");
3069 const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
3070 exports.processors = {
3071 ".md": { ...processor, supportsAutofix: true },
3072 "non-fixable": processor
3075 "node_modules/eslint-plugin-html/index.js": `
3076 const { defineProcessor } = require("pattern-processor");
3077 const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
3078 const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
3079 exports.processors = {
3080 ".html": { ...processor, supportsAutofix: true },
3081 "non-fixable": processor,
3082 "legacy": legacyProcessor
3085 "test.md": unIndent
`
3087 console
.log("hello")
3092 console
.log("hello")
3095 console
.log("hello")
3101 it("should lint only JavaScript blocks if '--ext' was not given.", () => {
3102 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3106 ".eslintrc.json": JSON
.stringify({
3107 plugins
: ["markdown", "html"],
3108 rules
: { semi
: "error" }
3112 engine
= new CLIEngine({ cwd
: root
});
3114 const { results
} = engine
.executeOnFiles(["test.md"]);
3116 assert
.strictEqual(results
.length
, 1);
3117 assert
.strictEqual(results
[0].messages
.length
, 1);
3118 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3119 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3122 it("should fix only JavaScript blocks if '--ext' was not given.", () => {
3123 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3127 ".eslintrc.json": JSON
.stringify({
3128 plugins
: ["markdown", "html"],
3129 rules
: { semi
: "error" }
3133 engine
= new CLIEngine({ cwd
: root
, fix
: true });
3135 const { results
} = engine
.executeOnFiles(["test.md"]);
3137 assert
.strictEqual(results
.length
, 1);
3138 assert
.strictEqual(results
[0].messages
.length
, 0);
3139 assert
.strictEqual(results
[0].output
, unIndent
`
3141 console
.log("hello");${/* ← fixed */""}
3146 console
.log("hello")${/* ← ignored */""}
3149 console
.log("hello")${/* ← ignored */""}
3155 it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", () => {
3156 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3160 ".eslintrc.json": JSON
.stringify({
3161 plugins
: ["markdown", "html"],
3162 rules
: { semi
: "error" }
3166 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"] });
3168 const { results
} = engine
.executeOnFiles(["test.md"]);
3170 assert
.strictEqual(results
.length
, 1);
3171 assert
.strictEqual(results
[0].messages
.length
, 2);
3172 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3173 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3174 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3175 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3178 it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", () => {
3179 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3183 ".eslintrc.json": JSON
.stringify({
3184 plugins
: ["markdown", "html"],
3185 rules
: { semi
: "error" }
3189 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"], fix
: true });
3191 const { results
} = engine
.executeOnFiles(["test.md"]);
3193 assert
.strictEqual(results
.length
, 1);
3194 assert
.strictEqual(results
[0].messages
.length
, 0);
3195 assert
.strictEqual(results
[0].output
, unIndent
`
3197 console
.log("hello");${/* ← fixed */""}
3202 console
.log("hello");${/* ← fixed */""}
3205 console
.log("hello")${/* ← ignored */""}
3211 it("should use overriden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", () => {
3212 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3216 ".eslintrc.json": JSON
.stringify({
3217 plugins
: ["markdown", "html"],
3218 rules
: { semi
: "error" },
3222 processor
: "html/non-fixable" // supportsAutofix: false
3228 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"], fix
: true });
3230 const { results
} = engine
.executeOnFiles(["test.md"]);
3232 assert
.strictEqual(results
.length
, 1);
3233 assert
.strictEqual(results
[0].messages
.length
, 1);
3234 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS Block in HTML Block
3235 assert
.strictEqual(results
[0].messages
[0].line
, 7);
3236 assert
.strictEqual(results
[0].messages
[0].fix
, void 0);
3237 assert
.strictEqual(results
[0].output
, unIndent
`
3239 console
.log("hello");${/* ← fixed */""}
3244 console
.log("hello")${/* ← reported but not fixed */""}
3247 console
.log("hello")
3253 it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", () => {
3254 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3258 ".eslintrc.json": JSON
.stringify({
3259 plugins
: ["markdown", "html"],
3260 rules
: { semi
: "error" },
3265 // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
3272 files
: "**/*.html/*.js",
3275 "no-console": "error"
3282 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"] });
3284 const { results
} = engine
.executeOnFiles(["test.md"]);
3286 assert
.strictEqual(results
.length
, 1);
3287 assert
.strictEqual(results
[0].messages
.length
, 2);
3288 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3289 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3290 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3291 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3294 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.", () => {
3295 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3299 ".eslintrc.json": JSON
.stringify({
3300 plugins
: ["markdown", "html"],
3301 rules
: { semi
: "error" },
3305 processor
: "html/legacy", // this processor returns strings rather than `{text, filename}`
3308 "no-console": "error"
3312 files
: "**/*.html/*.js",
3322 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"] });
3324 const { results
} = engine
.executeOnFiles(["test.md"]);
3326 assert
.strictEqual(results
.length
, 1);
3327 assert
.strictEqual(results
[0].messages
.length
, 3);
3328 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3329 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3330 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3331 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3332 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-console");
3333 assert
.strictEqual(results
[0].messages
[2].line
, 10);
3336 it("should throw an error if invalid processor was specified.", () => {
3337 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3341 ".eslintrc.json": JSON
.stringify({
3342 plugins
: ["markdown", "html"],
3343 processor
: "markdown/unknown"
3347 engine
= new CLIEngine({ cwd
: root
});
3349 assert
.throws(() => {
3350 engine
.executeOnFiles(["test.md"]);
3351 }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
3354 it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", () => {
3355 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3359 ".eslintrc.json": JSON
.stringify({
3360 plugins
: ["markdown", "html"],
3361 rules
: { semi
: "error" },
3365 processor
: "html/.html"
3369 processor
: "markdown/.md"
3375 engine
= new CLIEngine({ cwd
: root
});
3377 const { results
} = engine
.executeOnFiles(["test.md"]);
3379 assert
.strictEqual(results
.length
, 1);
3380 assert
.strictEqual(results
[0].messages
.length
, 2);
3381 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3382 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3383 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3384 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3388 describe("MODULE_NOT_FOUND error handling", () => {
3389 const cwd
= getFixturePath("module-not-found");
3392 engine
= new CLIEngine({ cwd
});
3395 it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", () => {
3397 engine
.executeOnText("test", "extends-js/test.js");
3399 assert
.strictEqual(err
.messageTemplate
, "extend-config-missing");
3400 assert
.deepStrictEqual(err
.messageData
, {
3401 configName
: "nonexistent-config",
3402 importerName
: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
3406 assert
.fail("Expected to throw an error");
3409 it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", () => {
3411 engine
.executeOnText("test", "extends-plugin/test.js");
3413 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3414 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3415 assert
.deepStrictEqual(err
.messageData
, {
3416 importerName
: `extends-plugin${path.sep}.eslintrc.yml`,
3417 pluginName
: "eslint-plugin-nonexistent-plugin",
3418 resolvePluginsRelativeTo
: path
.join(cwd
, "extends-plugin") // the directory of the config file.
3422 assert
.fail("Expected to throw an error");
3425 it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", () => {
3427 engine
.executeOnText("test", "plugins/test.js");
3429 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3430 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3431 assert
.deepStrictEqual(err
.messageData
, {
3432 importerName
: `plugins${path.sep}.eslintrc.yml`,
3433 pluginName
: "eslint-plugin-nonexistent-plugin",
3434 resolvePluginsRelativeTo
: path
.join(cwd
, "plugins") // the directory of the config file.
3438 assert
.fail("Expected to throw an error");
3441 it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", () => {
3443 engine
.executeOnText("test", "throw-in-config-itself/test.js");
3445 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3446 assert
.strictEqual(err
.messageTemplate
, void 0);
3449 assert
.fail("Expected to throw an error");
3452 it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", () => {
3454 engine
.executeOnText("test", "throw-in-extends-js/test.js");
3456 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3457 assert
.strictEqual(err
.messageTemplate
, void 0);
3460 assert
.fail("Expected to throw an error");
3463 it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", () => {
3465 engine
.executeOnText("test", "throw-in-extends-plugin/test.js");
3467 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3468 assert
.strictEqual(err
.messageTemplate
, void 0);
3471 assert
.fail("Expected to throw an error");
3474 it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", () => {
3476 engine
.executeOnText("test", "throw-in-plugins/test.js");
3478 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3479 assert
.strictEqual(err
.messageTemplate
, void 0);
3482 assert
.fail("Expected to throw an error");
3486 describe("with '--rulesdir' option", () => {
3487 it("should use the configured rules which are defined by '--rulesdir' option.", () => {
3488 const rootPath
= getFixturePath("cli-engine/with-rulesdir");
3489 const StubbedCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3490 cwd
: () => rootPath
,
3492 "internal-rules/test.js": `
3493 module.exports = context => ({
3494 ExpressionStatement(node) {
3495 context.report({ node, message: "ok" })
3499 ".eslintrc.json": JSON
.stringify({
3501 rules
: { test
: "error" }
3503 "test.js": "console.log('hello')"
3507 engine
= new StubbedCLIEngine({
3508 rulePaths
: ["internal-rules"]
3510 const report
= engine
.executeOnFiles(["test.js"]);
3512 assert
.strictEqual(report
.results
.length
, 1);
3513 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
3514 assert
.strictEqual(report
.results
[0].messages
[0].message
, "ok");
3518 describe("glob pattern '[ab].js'", () => {
3519 const root
= getFixturePath("cli-engine/unmatched-glob");
3521 it("should match '[ab].js' if existed.", () => {
3522 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3529 ".eslintrc.yml": "root: true"
3532 engine
= new CLIEngine();
3534 const { results
} = engine
.executeOnFiles(["[ab].js"]);
3535 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3537 assert
.deepStrictEqual(filenames
, ["[ab].js"]);
3540 it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", () => {
3541 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3547 ".eslintrc.yml": "root: true"
3550 engine
= new CLIEngine();
3552 const { results
} = engine
.executeOnFiles(["[ab].js"]);
3553 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3555 assert
.deepStrictEqual(filenames
, ["a.js", "b.js"]);
3559 describe("with 'noInlineConfig' setting", () => {
3560 const root
= getFixturePath("cli-engine/noInlineConfig");
3562 it("should warn directive comments if 'noInlineConfig' was given.", () => {
3563 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3566 "test.js": "/* globals foo */",
3567 ".eslintrc.yml": "noInlineConfig: true"
3570 engine
= new CLIEngine();
3572 const { results
} = engine
.executeOnFiles(["test.js"]);
3573 const messages
= results
[0].messages
;
3575 assert
.strictEqual(messages
.length
, 1);
3576 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
3579 it("should show the config file what the 'noInlineConfig' came from.", () => {
3580 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3583 "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
3584 "test.js": "/* globals foo */",
3585 ".eslintrc.yml": "extends: foo"
3588 engine
= new CLIEngine();
3590 const { results
} = engine
.executeOnFiles(["test.js"]);
3591 const messages
= results
[0].messages
;
3593 assert
.strictEqual(messages
.length
, 1);
3594 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
3598 describe("with 'reportUnusedDisableDirectives' setting", () => {
3599 const root
= getFixturePath("cli-engine/reportUnusedDisableDirectives");
3601 it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", () => {
3602 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3605 "test.js": "/* eslint-disable eqeqeq */",
3606 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3609 engine
= new CLIEngine();
3611 const { results
} = engine
.executeOnFiles(["test.js"]);
3612 const messages
= results
[0].messages
;
3614 assert
.strictEqual(messages
.length
, 1);
3615 assert
.strictEqual(messages
[0].severity
, 1);
3616 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3619 describe("the runtime option overrides config files.", () => {
3620 it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", () => {
3621 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3624 "test.js": "/* eslint-disable eqeqeq */",
3625 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3628 engine
= new CLIEngine({ reportUnusedDisableDirectives
: "off" });
3630 const { results
} = engine
.executeOnFiles(["test.js"]);
3631 const messages
= results
[0].messages
;
3633 assert
.strictEqual(messages
.length
, 0);
3636 it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", () => {
3637 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3640 "test.js": "/* eslint-disable eqeqeq */",
3641 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3644 engine
= new CLIEngine({ reportUnusedDisableDirectives
: "error" });
3646 const { results
} = engine
.executeOnFiles(["test.js"]);
3647 const messages
= results
[0].messages
;
3649 assert
.strictEqual(messages
.length
, 1);
3650 assert
.strictEqual(messages
[0].severity
, 2);
3651 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3656 describe("with 'overrides[*].extends' setting on deep locations", () => {
3657 const root
= getFixturePath("cli-engine/deeply-overrides-i-extends");
3659 it("should not throw.", () => {
3660 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3663 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
3664 overrides: [{ files: ["*test*"], extends: "two" }]
3666 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
3667 overrides: [{ files: ["*.js"], extends: "three" }]
3669 "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
3670 rules: { "no-console": "error" }
3672 "test.js": "console.log('hello')",
3673 ".eslintrc.yml": "extends: one"
3676 engine
= new CLIEngine();
3678 const { results
} = engine
.executeOnFiles(["test.js"]);
3679 const messages
= results
[0].messages
;
3681 assert
.strictEqual(messages
.length
, 1);
3682 assert
.strictEqual(messages
[0].ruleId
, "no-console");
3686 describe("don't ignore the entry directory.", () => {
3687 const root
= getFixturePath("cli-engine/dont-ignore-entry-dir");
3689 it("'executeOnFiles(\".\")' should not load config files from outside of \".\".", () => {
3690 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3693 "../.eslintrc.json": "BROKEN FILE",
3694 ".eslintrc.json": JSON
.stringify({ root
: true }),
3695 "index.js": "console.log(\"hello\")"
3698 engine
= new CLIEngine();
3700 // Don't throw "failed to load config file" error.
3701 engine
.executeOnFiles(".");
3704 it("'executeOnFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", () => {
3705 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3708 "../.eslintrc.json": JSON
.stringify({ ignorePatterns
: ["/dont-ignore-entry-dir"] }),
3709 ".eslintrc.json": JSON
.stringify({ root
: true }),
3710 "index.js": "console.log(\"hello\")"
3713 engine
= new CLIEngine();
3715 // Don't throw "file not found" error.
3716 engine
.executeOnFiles(".");
3719 it("'executeOnFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", () => {
3720 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3723 ".eslintrc.json": JSON
.stringify({ ignorePatterns
: ["/subdir"] }),
3724 "subdir/.eslintrc.json": JSON
.stringify({ root
: true }),
3725 "subdir/index.js": "console.log(\"hello\")"
3728 engine
= new CLIEngine();
3730 // Don't throw "file not found" error.
3731 engine
.executeOnFiles("subdir");
3736 describe("getConfigForFile", () => {
3738 it("should return the info from Config#getConfig when called", () => {
3740 configFile
: getFixturePath("configurations", "quotes-error.json")
3742 const engine
= new CLIEngine(options
);
3743 const filePath
= getFixturePath("single-quoted.js");
3745 const actualConfig
= engine
.getConfigForFile(filePath
);
3746 const expectedConfig
= new CascadingConfigArrayFactory({ specificConfigPath
: options
.configFile
})
3747 .getConfigArrayForFile(filePath
)
3748 .extractConfig(filePath
)
3749 .toCompatibleObjectAsConfigFileContent();
3751 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3755 it("should return the config when run from within a subdir", () => {
3757 cwd
: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
3759 const engine
= new CLIEngine(options
);
3760 const filePath
= getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
3762 const actualConfig
= engine
.getConfigForFile("./.eslintrc");
3763 const expectedConfig
= new CascadingConfigArrayFactory(options
)
3764 .getConfigArrayForFile(filePath
)
3765 .extractConfig(filePath
)
3766 .toCompatibleObjectAsConfigFileContent();
3768 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3771 it("should throw an error if a directory path was given.", () => {
3772 const engine
= new CLIEngine();
3775 engine
.getConfigForFile(".");
3777 assert
.strictEqual(error
.messageTemplate
, "print-config-with-directory-path");
3780 assert
.fail("should throw an error");
3784 describe("isPathIgnored", () => {
3785 it("should check if the given path is ignored", () => {
3786 const engine
= new CLIEngine({
3787 ignorePath
: getFixturePath(".eslintignore2"),
3788 cwd
: getFixturePath()
3791 assert
.isTrue(engine
.isPathIgnored("undef.js"));
3792 assert
.isFalse(engine
.isPathIgnored("passing.js"));
3795 it("should return false if ignoring is disabled", () => {
3796 const engine
= new CLIEngine({
3798 ignorePath
: getFixturePath(".eslintignore2"),
3799 cwd
: getFixturePath()
3802 assert
.isFalse(engine
.isPathIgnored("undef.js"));
3805 // https://github.com/eslint/eslint/issues/5547
3806 it("should return true for default ignores even if ignoring is disabled", () => {
3807 const engine
= new CLIEngine({
3809 cwd
: getFixturePath("cli-engine")
3812 assert
.isTrue(engine
.isPathIgnored("node_modules/foo.js"));
3815 describe("about the default ignore patterns", () => {
3816 it("should always apply defaultPatterns if ignore option is true", () => {
3817 const cwd
= getFixturePath("ignored-paths");
3818 const engine
= new CLIEngine({ cwd
});
3820 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
3821 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
3824 it("should still apply defaultPatterns if ignore option is is false", () => {
3825 const cwd
= getFixturePath("ignored-paths");
3826 const engine
= new CLIEngine({ ignore
: false, cwd
});
3828 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
3829 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
3832 it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", () => {
3833 const cwd
= getFixturePath("ignored-paths");
3834 const engine
= new CLIEngine({ cwd
, ignorePattern
: "!/node_modules/package" });
3836 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
3839 it("should allow subfolders of defaultPatterns to be unignored by ignorePath", () => {
3840 const cwd
= getFixturePath("ignored-paths");
3841 const engine
= new CLIEngine({ cwd
, ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
3843 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
3846 it("should ignore dotfiles", () => {
3847 const cwd
= getFixturePath("ignored-paths");
3848 const engine
= new CLIEngine({ cwd
});
3850 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
3851 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
3854 it("should ignore directories beginning with a dot", () => {
3855 const cwd
= getFixturePath("ignored-paths");
3856 const engine
= new CLIEngine({ cwd
});
3858 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
3859 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
3862 it("should still ignore dotfiles when ignore option disabled", () => {
3863 const cwd
= getFixturePath("ignored-paths");
3864 const engine
= new CLIEngine({ ignore
: false, cwd
});
3866 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
3867 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
3870 it("should still ignore directories beginning with a dot when ignore option disabled", () => {
3871 const cwd
= getFixturePath("ignored-paths");
3872 const engine
= new CLIEngine({ ignore
: false, cwd
});
3874 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
3875 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
3878 it("should not ignore absolute paths containing '..'", () => {
3879 const cwd
= getFixturePath("ignored-paths");
3880 const engine
= new CLIEngine({ cwd
});
3882 assert(!engine
.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
3885 it("should ignore /node_modules/ relative to .eslintignore when loaded", () => {
3886 const cwd
= getFixturePath("ignored-paths");
3887 const engine
= new CLIEngine({ ignorePath
: getFixturePath("ignored-paths", ".eslintignore"), cwd
});
3889 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
3890 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
3893 it("should ignore /node_modules/ relative to cwd without an .eslintignore", () => {
3894 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
3895 const engine
= new CLIEngine({ cwd
});
3897 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
3898 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
3902 describe("with no .eslintignore file", () => {
3903 it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", () => {
3904 const cwd
= getFixturePath("ignored-paths", "configurations");
3905 const engine
= new CLIEngine({ cwd
});
3907 // a .eslintignore in parent directories includes `*.js`, but don't load it.
3908 assert(!engine
.isPathIgnored("foo.js"));
3909 assert(engine
.isPathIgnored("node_modules/foo.js"));
3912 it("should return false for files outside of the cwd (with no ignore file provided)", () => {
3914 // Default ignore patterns should not inadvertently ignore files in parent directories
3915 const engine
= new CLIEngine({ cwd
: getFixturePath("ignored-paths", "no-ignore-file") });
3917 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
3921 describe("with .eslintignore file or package.json file", () => {
3922 it("should load .eslintignore from cwd when explicitly passed", () => {
3923 const cwd
= getFixturePath("ignored-paths");
3924 const engine
= new CLIEngine({ cwd
});
3926 // `${cwd}/.eslintignore` includes `sampleignorepattern`.
3927 assert(engine
.isPathIgnored("sampleignorepattern"));
3930 it("should use package.json's eslintIgnore files if no specified .eslintignore file", () => {
3931 const cwd
= getFixturePath("ignored-paths", "package-json-ignore");
3932 const engine
= new CLIEngine({ cwd
});
3934 assert(engine
.isPathIgnored("hello.js"));
3935 assert(engine
.isPathIgnored("world.js"));
3938 it("should use correct message template if failed to parse package.json", () => {
3939 const cwd
= getFixturePath("ignored-paths", "broken-package-json");
3941 assert
.throw(() => {
3943 // eslint-disable-next-line no-new
3944 new CLIEngine({ cwd
});
3946 assert
.strictEqual(error
.messageTemplate
, "failed-to-read-json");
3952 it("should not use package.json's eslintIgnore files if specified .eslintignore file", () => {
3953 const cwd
= getFixturePath("ignored-paths");
3954 const engine
= new CLIEngine({ cwd
});
3957 * package.json includes `hello.js` and `world.js`.
3958 * .eslintignore includes `sampleignorepattern`.
3960 assert(!engine
.isPathIgnored("hello.js"));
3961 assert(!engine
.isPathIgnored("world.js"));
3962 assert(engine
.isPathIgnored("sampleignorepattern"));
3965 it("should error if package.json's eslintIgnore is not an array of file paths", () => {
3966 const cwd
= getFixturePath("ignored-paths", "bad-package-json-ignore");
3968 assert
.throws(() => {
3969 // eslint-disable-next-line no-new
3970 new CLIEngine({ cwd
});
3971 }, "Package.json eslintIgnore property requires an array of paths");
3975 describe("with --ignore-pattern option", () => {
3976 it("should accept a string for options.ignorePattern", () => {
3977 const cwd
= getFixturePath("ignored-paths", "ignore-pattern");
3978 const engine
= new CLIEngine({
3979 ignorePattern
: "ignore-me.txt",
3983 assert(engine
.isPathIgnored("ignore-me.txt"));
3986 it("should accept an array for options.ignorePattern", () => {
3987 const engine
= new CLIEngine({
3988 ignorePattern
: ["a", "b"],
3992 assert(engine
.isPathIgnored("a"));
3993 assert(engine
.isPathIgnored("b"));
3994 assert(!engine
.isPathIgnored("c"));
3997 it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", () => {
3998 const cwd
= getFixturePath("ignored-paths");
3999 const engine
= new CLIEngine({
4000 ignorePattern
: "not-a-file",
4004 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
4007 it("should return true for file matching an ignore pattern exactly", () => {
4008 const cwd
= getFixturePath("ignored-paths");
4009 const engine
= new CLIEngine({ ignorePattern
: "undef.js", cwd
});
4011 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4014 it("should return false for file matching an invalid ignore pattern with leading './'", () => {
4015 const cwd
= getFixturePath("ignored-paths");
4016 const engine
= new CLIEngine({ ignorePattern
: "./undef.js", cwd
});
4018 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4021 it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", () => {
4022 const cwd
= getFixturePath("ignored-paths");
4023 const engine
= new CLIEngine({ ignorePattern
: "/undef.js", cwd
});
4025 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
4028 it("should return true for file matching a child of an ignore pattern", () => {
4029 const cwd
= getFixturePath("ignored-paths");
4030 const engine
= new CLIEngine({ ignorePattern
: "ignore-pattern", cwd
});
4032 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
4035 it("should return true for file matching a grandchild of an ignore pattern", () => {
4036 const cwd
= getFixturePath("ignored-paths");
4037 const engine
= new CLIEngine({ ignorePattern
: "ignore-pattern", cwd
});
4039 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
4042 it("should return false for file not matching any ignore pattern", () => {
4043 const cwd
= getFixturePath("ignored-paths");
4044 const engine
= new CLIEngine({ ignorePattern
: "failing.js", cwd
});
4046 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
4049 it("two globstar '**' ignore pattern should ignore files in nested directories", () => {
4050 const cwd
= getFixturePath("ignored-paths");
4051 const engine
= new CLIEngine({ ignorePattern
: "**/*.js", cwd
});
4053 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4054 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
4055 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
4056 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
4057 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
4058 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
4062 describe("with --ignore-path option", () => {
4063 it("should load empty array with ignorePath set to false", () => {
4064 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4065 const engine
= new CLIEngine({ ignorePath
: false, cwd
});
4067 // a .eslintignore in parent directories includes `*.js`, but don't load it.
4068 assert(!engine
.isPathIgnored("foo.js"));
4069 assert(engine
.isPathIgnored("node_modules/foo.js"));
4072 it("initialization with ignorePath should work when cwd is a parent directory", () => {
4073 const cwd
= getFixturePath("ignored-paths");
4074 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4075 const engine
= new CLIEngine({ ignorePath
, cwd
});
4077 assert(engine
.isPathIgnored("custom-name/foo.js"));
4080 it("initialization with ignorePath should work when the file is in the cwd", () => {
4081 const cwd
= getFixturePath("ignored-paths", "custom-name");
4082 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4083 const engine
= new CLIEngine({ ignorePath
, cwd
});
4085 assert(engine
.isPathIgnored("foo.js"));
4088 it("initialization with ignorePath should work when cwd is a subdirectory", () => {
4089 const cwd
= getFixturePath("ignored-paths", "custom-name", "subdirectory");
4090 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4091 const engine
= new CLIEngine({ ignorePath
, cwd
});
4093 assert(engine
.isPathIgnored("../custom-name/foo.js"));
4096 it("initialization with invalid file should throw error", () => {
4097 const cwd
= getFixturePath("ignored-paths");
4098 const ignorePath
= getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
4100 assert
.throws(() => {
4101 // eslint-disable-next-line no-new
4102 new CLIEngine({ ignorePath
, cwd
});
4103 }, "Cannot read .eslintignore file");
4106 it("should return false for files outside of ignorePath's directory", () => {
4107 const cwd
= getFixturePath("ignored-paths");
4108 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4109 const engine
= new CLIEngine({ ignorePath
, cwd
});
4111 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4114 it("should resolve relative paths from CWD", () => {
4115 const cwd
= getFixturePath("ignored-paths", "subdir");
4116 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4117 const engine
= new CLIEngine({ ignorePath
, cwd
});
4119 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4120 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4123 it("should resolve relative paths from CWD when it's in a child directory", () => {
4124 const cwd
= getFixturePath("ignored-paths");
4125 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4126 const engine
= new CLIEngine({ ignorePath
, cwd
});
4128 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4129 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4130 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4131 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
4133 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
4136 it("should resolve relative paths from CWD when it contains negated globs", () => {
4137 const cwd
= getFixturePath("ignored-paths");
4138 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4139 const engine
= new CLIEngine({ ignorePath
, cwd
});
4141 assert(engine
.isPathIgnored("subdir/blah.txt"));
4142 assert(engine
.isPathIgnored("blah.txt"));
4143 assert(engine
.isPathIgnored("subdir/bar.txt"));
4144 assert(!engine
.isPathIgnored("bar.txt"));
4145 assert(!engine
.isPathIgnored("subdir/baz.txt"));
4146 assert(!engine
.isPathIgnored("baz.txt"));
4149 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", () => {
4150 const cwd
= getFixturePath("ignored-paths");
4151 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4152 const engine
= new CLIEngine({ ignorePath
, cwd
});
4154 assert(engine
.isPathIgnored("node_modules/blah.js"));
4157 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", () => {
4158 const cwd
= getFixturePath("ignored-paths", "subdir");
4159 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4160 const engine
= new CLIEngine({ ignorePath
, cwd
});
4162 assert(engine
.isPathIgnored("node_modules/blah.js"));
4165 it("should handle .eslintignore which contains CRLF correctly.", () => {
4166 const ignoreFileContent
= fs
.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
4168 assert(ignoreFileContent
.includes("\r"), "crlf/.eslintignore should contains CR.");
4170 const cwd
= getFixturePath("ignored-paths");
4171 const ignorePath
= getFixturePath("ignored-paths", "crlf/.eslintignore");
4172 const engine
= new CLIEngine({ ignorePath
, cwd
});
4174 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
4175 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
4176 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
4179 it("should not include comments in ignore rules", () => {
4180 const cwd
= getFixturePath("ignored-paths");
4181 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithComments");
4182 const engine
= new CLIEngine({ ignorePath
, cwd
});
4184 assert(!engine
.isPathIgnored("# should be ignored"));
4185 assert(engine
.isPathIgnored("this_one_not"));
4188 it("should ignore a non-negated pattern", () => {
4189 const cwd
= getFixturePath("ignored-paths");
4190 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4191 const engine
= new CLIEngine({ ignorePath
, cwd
});
4193 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
4196 it("should not ignore a negated pattern", () => {
4197 const cwd
= getFixturePath("ignored-paths");
4198 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4199 const engine
= new CLIEngine({ ignorePath
, cwd
});
4201 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
4205 describe("with --ignore-path option and --ignore-pattern option", () => {
4206 it("should return false for ignored file when unignored with ignore pattern", () => {
4207 const cwd
= getFixturePath("ignored-paths");
4208 const engine
= new CLIEngine({
4209 ignorePath
: getFixturePath("ignored-paths", ".eslintignore"),
4210 ignorePattern
: "!sampleignorepattern",
4214 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
4219 describe("getFormatter()", () => {
4221 it("should return a function when a bundled formatter is requested", () => {
4222 const engine
= new CLIEngine(),
4223 formatter
= engine
.getFormatter("compact");
4225 assert
.isFunction(formatter
);
4228 it("should return a function when no argument is passed", () => {
4229 const engine
= new CLIEngine(),
4230 formatter
= engine
.getFormatter();
4232 assert
.isFunction(formatter
);
4235 it("should return a function when a custom formatter is requested", () => {
4236 const engine
= new CLIEngine(),
4237 formatter
= engine
.getFormatter(getFixturePath("formatters", "simple.js"));
4239 assert
.isFunction(formatter
);
4242 it("should return a function when a custom formatter is requested, also if the path has backslashes", () => {
4243 const engine
= new CLIEngine({
4244 cwd
: path
.join(fixtureDir
, "..")
4246 formatter
= engine
.getFormatter(".\\fixtures\\formatters\\simple.js");
4248 assert
.isFunction(formatter
);
4251 it("should return a function when a formatter prefixed with eslint-formatter is requested", () => {
4252 const engine
= new CLIEngine({
4253 cwd
: getFixturePath("cli-engine")
4255 formatter
= engine
.getFormatter("bar");
4257 assert
.isFunction(formatter
);
4260 it("should return a function when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", () => {
4261 const engine
= new CLIEngine({
4262 cwd
: getFixturePath("cli-engine")
4264 formatter
= engine
.getFormatter("eslint-formatter-bar");
4266 assert
.isFunction(formatter
);
4269 it("should return a function when a formatter is requested within a scoped npm package", () => {
4270 const engine
= new CLIEngine({
4271 cwd
: getFixturePath("cli-engine")
4273 formatter
= engine
.getFormatter("@somenamespace/foo");
4275 assert
.isFunction(formatter
);
4278 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", () => {
4279 const engine
= new CLIEngine({
4280 cwd
: getFixturePath("cli-engine")
4282 formatter
= engine
.getFormatter("@somenamespace/eslint-formatter-foo");
4284 assert
.isFunction(formatter
);
4287 it("should return null when a customer formatter doesn't exist", () => {
4288 const engine
= new CLIEngine(),
4289 formatterPath
= getFixturePath("formatters", "doesntexist.js"),
4290 fullFormatterPath
= path
.resolve(formatterPath
);
4292 assert
.throws(() => {
4293 engine
.getFormatter(formatterPath
);
4294 }, `There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`);
4297 it("should return null when a built-in formatter doesn't exist", () => {
4298 const engine
= new CLIEngine();
4299 const fullFormatterPath
= path
.resolve(__dirname
, "../../../lib/cli-engine/formatters/special");
4301 assert
.throws(() => {
4302 engine
.getFormatter("special");
4303 }, `There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`);
4306 it("should throw if the required formatter exists but has an error", () => {
4307 const engine
= new CLIEngine(),
4308 formatterPath
= getFixturePath("formatters", "broken.js");
4310 assert
.throws(() => {
4311 engine
.getFormatter(formatterPath
);
4312 }, `There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`);
4315 it("should return null when a non-string formatter name is passed", () => {
4316 const engine
= new CLIEngine(),
4317 formatter
= engine
.getFormatter(5);
4319 assert
.isNull(formatter
);
4322 it("should return a function when called as a static function on CLIEngine", () => {
4323 const formatter
= CLIEngine
.getFormatter();
4325 assert
.isFunction(formatter
);
4328 it("should return a function when called as a static function on CLIEngine and a custom formatter is requested", () => {
4329 const formatter
= CLIEngine
.getFormatter(getFixturePath("formatters", "simple.js"));
4331 assert
.isFunction(formatter
);
4336 describe("getErrorResults()", () => {
4337 it("should report 5 error messages when looking for errors only", () => {
4339 process
.chdir(originalDir
);
4340 const engine
= new CLIEngine();
4342 const report
= engine
.executeOnText("var foo = 'bar';");
4343 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4345 assert
.lengthOf(errorResults
[0].messages
, 5);
4346 assert
.strictEqual(errorResults
[0].errorCount
, 5);
4347 assert
.strictEqual(errorResults
[0].fixableErrorCount
, 3);
4348 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4349 assert
.strictEqual(errorResults
[0].messages
[0].ruleId
, "strict");
4350 assert
.strictEqual(errorResults
[0].messages
[0].severity
, 2);
4351 assert
.strictEqual(errorResults
[0].messages
[1].ruleId
, "no-var");
4352 assert
.strictEqual(errorResults
[0].messages
[1].severity
, 2);
4353 assert
.strictEqual(errorResults
[0].messages
[2].ruleId
, "no-unused-vars");
4354 assert
.strictEqual(errorResults
[0].messages
[2].severity
, 2);
4355 assert
.strictEqual(errorResults
[0].messages
[3].ruleId
, "quotes");
4356 assert
.strictEqual(errorResults
[0].messages
[3].severity
, 2);
4357 assert
.strictEqual(errorResults
[0].messages
[4].ruleId
, "eol-last");
4358 assert
.strictEqual(errorResults
[0].messages
[4].severity
, 2);
4361 it("should not mutate passed report.results parameter", () => {
4362 process
.chdir(originalDir
);
4363 const engine
= new CLIEngine({
4364 rules
: { quotes
: [1, "double"] }
4367 const report
= engine
.executeOnText("var foo = 'bar';");
4368 const reportResultsLength
= report
.results
[0].messages
.length
;
4370 CLIEngine
.getErrorResults(report
.results
);
4372 assert
.lengthOf(report
.results
[0].messages
, reportResultsLength
);
4375 it("should report a warningCount of 0 when looking for errors only", () => {
4377 process
.chdir(originalDir
);
4378 const engine
= new CLIEngine();
4380 const report
= engine
.executeOnText("var foo = 'bar';");
4381 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4383 assert
.strictEqual(errorResults
[0].warningCount
, 0);
4384 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4387 it("should return 0 error or warning messages even when the file has warnings", () => {
4388 const engine
= new CLIEngine({
4389 ignorePath
: path
.join(fixtureDir
, ".eslintignore"),
4390 cwd
: path
.join(fixtureDir
, "..")
4393 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js", true);
4394 const errorReport
= CLIEngine
.getErrorResults(report
.results
);
4396 assert
.lengthOf(errorReport
, 0);
4397 assert
.lengthOf(report
.results
, 1);
4398 assert
.strictEqual(report
.errorCount
, 0);
4399 assert
.strictEqual(report
.warningCount
, 1);
4400 assert
.strictEqual(report
.fixableErrorCount
, 0);
4401 assert
.strictEqual(report
.fixableWarningCount
, 0);
4402 assert
.strictEqual(report
.results
[0].errorCount
, 0);
4403 assert
.strictEqual(report
.results
[0].warningCount
, 1);
4404 assert
.strictEqual(report
.fixableErrorCount
, 0);
4405 assert
.strictEqual(report
.fixableWarningCount
, 0);
4408 it("should return source code of file in the `source` property", () => {
4409 process
.chdir(originalDir
);
4410 const engine
= new CLIEngine({
4412 rules
: { quotes
: [2, "double"] }
4416 const report
= engine
.executeOnText("var foo = 'bar';");
4417 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4419 assert
.lengthOf(errorResults
[0].messages
, 1);
4420 assert
.strictEqual(errorResults
[0].source
, "var foo = 'bar';");
4423 it("should contain `output` property after fixes", () => {
4424 process
.chdir(originalDir
);
4425 const engine
= new CLIEngine({
4434 const report
= engine
.executeOnText("console.log('foo')");
4435 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4437 assert
.lengthOf(errorResults
[0].messages
, 1);
4438 assert
.strictEqual(errorResults
[0].output
, "console.log('foo');");
4442 describe("outputFixes()", () => {
4444 sinon
.verifyAndRestore();
4447 it("should call fs.writeFileSync() for each result with output", () => {
4448 const fakeFS
= leche
.fake(fs
),
4449 localCLIEngine
= proxyquire("../../../lib/cli-engine/cli-engine", {
4465 fakeFS
.writeFileSync = function() {};
4466 const spy
= sinon
.spy(fakeFS
, "writeFileSync");
4468 localCLIEngine
.outputFixes(report
);
4470 assert
.strictEqual(spy
.callCount
, 2);
4471 assert
.isTrue(spy
.firstCall
.calledWithExactly("foo.js", "bar"), "First call was incorrect.");
4472 assert
.isTrue(spy
.secondCall
.calledWithExactly("bar.js", "baz"), "Second call was incorrect.");
4476 it("should call fs.writeFileSync() for each result with output and not at all for a result without output", () => {
4477 const fakeFS
= leche
.fake(fs
),
4478 localCLIEngine
= proxyquire("../../../lib/cli-engine/cli-engine", {
4497 fakeFS
.writeFileSync = function() {};
4498 const spy
= sinon
.spy(fakeFS
, "writeFileSync");
4500 localCLIEngine
.outputFixes(report
);
4502 assert
.strictEqual(spy
.callCount
, 2);
4503 assert
.isTrue(spy
.firstCall
.calledWithExactly("foo.js", "bar"), "First call was incorrect.");
4504 assert
.isTrue(spy
.secondCall
.calledWithExactly("bar.js", "baz"), "Second call was incorrect.");
4510 describe("getRules()", () => {
4511 it("should expose the list of rules", () => {
4512 const engine
= new CLIEngine();
4514 assert(engine
.getRules().has("no-eval"), "no-eval is present");
4517 it("should expose the list of plugin rules", () => {
4518 const engine
= new CLIEngine({ plugins
: ["node"] });
4520 assert(engine
.getRules().has("node/no-deprecated-api"), "node/no-deprecated-api is present");
4523 it("should expose the rules of the plugin that is added by 'addPlugin'.", () => {
4524 const engine
= new CLIEngine({ plugins
: ["foo"] });
4526 engine
.addPlugin("foo", require("eslint-plugin-node"));
4528 assert(engine
.getRules().has("foo/no-deprecated-api"), "foo/no-deprecated-api is present");
4532 describe("resolveFileGlobPatterns", () => {
4535 [".", ["**/*.{js}"]],
4536 ["./", ["**/*.{js}"]],
4537 ["../", ["../**/*.{js}"]],
4539 ], (input
, expected
) => {
4541 it(`should correctly resolve ${input} to ${expected}`, () => {
4542 const engine
= new CLIEngine();
4544 const result
= engine
.resolveFileGlobPatterns([input
]);
4546 assert
.deepStrictEqual(result
, expected
);
4551 it("should convert a directory name with no provided extensions into a glob pattern", () => {
4552 const patterns
= ["one-js-file"];
4554 cwd
: getFixturePath("glob-util")
4556 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4558 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4561 it("should not convert path with globInputPaths option false", () => {
4562 const patterns
= ["one-js-file"];
4564 cwd
: getFixturePath("glob-util"),
4565 globInputPaths
: false
4567 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4569 assert
.deepStrictEqual(result
, ["one-js-file"]);
4572 it("should convert an absolute directory name with no provided extensions into a posix glob pattern", () => {
4573 const patterns
= [getFixturePath("glob-util", "one-js-file")];
4575 cwd
: getFixturePath("glob-util")
4577 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4578 const expected
= [`${getFixturePath("glob-util", "one-js-file").replace(/\\/gu, "/")}/**/*.{js}`];
4580 assert
.deepStrictEqual(result
, expected
);
4583 it("should convert a directory name with a single provided extension into a glob pattern", () => {
4584 const patterns
= ["one-js-file"];
4586 cwd
: getFixturePath("glob-util"),
4587 extensions
: [".jsx"]
4589 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4591 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{jsx}"]);
4594 it("should convert a directory name with multiple provided extensions into a glob pattern", () => {
4595 const patterns
= ["one-js-file"];
4597 cwd
: getFixturePath("glob-util"),
4598 extensions
: [".jsx", ".js"]
4600 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4602 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{jsx,js}"]);
4605 it("should convert multiple directory names into glob patterns", () => {
4606 const patterns
= ["one-js-file", "two-js-files"];
4608 cwd
: getFixturePath("glob-util")
4610 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4612 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}", "two-js-files/**/*.{js}"]);
4615 it("should remove leading './' from glob patterns", () => {
4616 const patterns
= ["./one-js-file"];
4618 cwd
: getFixturePath("glob-util")
4620 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4622 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4625 it("should convert a directory name with a trailing '/' into a glob pattern", () => {
4626 const patterns
= ["one-js-file/"];
4628 cwd
: getFixturePath("glob-util")
4630 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4632 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4635 it("should return filenames as they are", () => {
4636 const patterns
= ["some-file.js"];
4638 cwd
: getFixturePath("glob-util")
4640 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4642 assert
.deepStrictEqual(result
, ["some-file.js"]);
4645 it("should convert backslashes into forward slashes", () => {
4646 const patterns
= ["one-js-file\\example.js"];
4648 cwd
: getFixturePath()
4650 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4652 assert
.deepStrictEqual(result
, ["one-js-file/example.js"]);
4656 describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
4658 it("should report a violation for disabling rules", () => {
4660 "alert('test'); // eslint-disable-line no-alert"
4665 allowInlineConfig
: false,
4669 "no-trailing-spaces": 0,
4675 const eslintCLI
= new CLIEngine(config
);
4677 const report
= eslintCLI
.executeOnText(code
);
4678 const messages
= report
.results
[0].messages
;
4680 assert
.strictEqual(messages
.length
, 1);
4681 assert
.strictEqual(messages
[0].ruleId
, "no-alert");
4684 it("should not report a violation by default", () => {
4686 "alert('test'); // eslint-disable-line no-alert"
4692 // allowInlineConfig: true is the default
4696 "no-trailing-spaces": 0,
4702 const eslintCLI
= new CLIEngine(config
);
4704 const report
= eslintCLI
.executeOnText(code
);
4705 const messages
= report
.results
[0].messages
;
4707 assert
.strictEqual(messages
.length
, 0);
4712 describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
4713 it("should report problems for unused eslint-disable directives", () => {
4714 const cliEngine
= new CLIEngine({ useEslintrc
: false, reportUnusedDisableDirectives
: true });
4716 assert
.deepStrictEqual(
4717 cliEngine
.executeOnText("/* eslint-disable */"),
4725 message
: "Unused eslint-disable directive (no problems were reported).",
4734 fixableErrorCount
: 0,
4735 fixableWarningCount
: 0,
4736 source
: "/* eslint-disable */"
4741 fixableErrorCount
: 0,
4742 fixableWarningCount
: 0,
4743 usedDeprecatedRules
: []
4749 describe("when retreiving version number", () => {
4750 it("should return current version number", () => {
4751 const eslintCLI
= require("../../../lib/cli-engine").CLIEngine
;
4752 const version
= eslintCLI
.version
;
4754 assert
.isString(version
);
4755 assert
.isTrue(parseInt(version
[0], 10) >= 3);
4759 describe("mutability", () => {
4760 describe("plugins", () => {
4761 it("Loading plugin in one instance doesn't mutate to another instance", () => {
4762 const filePath
= getFixturePath("single-quoted.js");
4763 const engine1
= cliEngineWithPlugins({
4764 cwd
: path
.join(fixtureDir
, ".."),
4766 plugins
: ["example"],
4767 rules
: { "example/example-rule": 1 }
4769 const engine2
= new CLIEngine({
4770 cwd
: path
.join(fixtureDir
, ".."),
4773 const fileConfig1
= engine1
.getConfigForFile(filePath
);
4774 const fileConfig2
= engine2
.getConfigForFile(filePath
);
4777 assert
.deepStrictEqual(fileConfig1
.plugins
, ["example"], "Plugin is present for engine 1");
4778 assert
.deepStrictEqual(fileConfig2
.plugins
, [], "Plugin is not present for engine 2");
4782 describe("rules", () => {
4783 it("Loading rules in one instance doesn't mutate to another instance", () => {
4784 const filePath
= getFixturePath("single-quoted.js");
4785 const engine1
= new CLIEngine({
4786 cwd
: path
.join(fixtureDir
, ".."),
4788 rules
: { "example/example-rule": 1 }
4790 const engine2
= new CLIEngine({
4791 cwd
: path
.join(fixtureDir
, ".."),
4794 const fileConfig1
= engine1
.getConfigForFile(filePath
);
4795 const fileConfig2
= engine2
.getConfigForFile(filePath
);
4798 assert
.deepStrictEqual(fileConfig1
.rules
["example/example-rule"], [1], "example is present for engine 1");
4799 assert
.isUndefined(fileConfig2
.rules
["example/example-rule"], "example is not present for engine 2");
4804 describe("with ignorePatterns config", () => {
4805 const root
= getFixturePath("cli-engine/ignore-patterns");
4807 /** @type {typeof CLIEngine} */
4808 let InMemoryCLIEngine
;
4810 describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
4812 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4815 ".eslintrc.json": JSON
.stringify({
4816 ignorePatterns
: "foo.js"
4820 "subdir/foo.js": "",
4826 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
4827 const engine
= new InMemoryCLIEngine();
4829 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
4830 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
4833 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
4834 const engine
= new InMemoryCLIEngine();
4836 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
4837 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), false);
4840 it("'executeOnFiles()' should not verify 'foo.js'.", () => {
4841 const engine
= new InMemoryCLIEngine();
4842 const filePaths
= engine
.executeOnFiles("**/*.js")
4844 .map(r
=> r
.filePath
)
4847 assert
.deepStrictEqual(filePaths
, [
4848 path
.join(root
, "bar.js"),
4849 path
.join(root
, "subdir/bar.js")
4854 describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
4856 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4859 ".eslintrc.json": JSON
.stringify({
4860 ignorePatterns
: ["foo.js", "/bar.js"]
4865 "subdir/foo.js": "",
4866 "subdir/bar.js": "",
4872 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
4873 const engine
= new InMemoryCLIEngine();
4875 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
4876 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
4879 it("'isPathIgnored()' should return 'true' for '/bar.js'.", () => {
4880 const engine
= new InMemoryCLIEngine();
4882 assert
.strictEqual(engine
.isPathIgnored("bar.js"), true);
4883 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), false);
4886 it("'executeOnFiles()' should not verify 'foo.js' and '/bar.js'.", () => {
4887 const engine
= new InMemoryCLIEngine();
4888 const filePaths
= engine
.executeOnFiles("**/*.js")
4890 .map(r
=> r
.filePath
)
4893 assert
.deepStrictEqual(filePaths
, [
4894 path
.join(root
, "baz.js"),
4895 path
.join(root
, "subdir/bar.js"),
4896 path
.join(root
, "subdir/baz.js")
4901 describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
4903 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4906 ".eslintrc.json": JSON
.stringify({
4907 ignorePatterns
: "!/node_modules/foo"
4909 "node_modules/foo/index.js": "",
4910 "node_modules/foo/.dot.js": "",
4911 "node_modules/bar/index.js": "",
4917 it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", () => {
4918 const engine
= new InMemoryCLIEngine();
4920 assert
.strictEqual(engine
.isPathIgnored("node_modules/foo/index.js"), false);
4923 it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", () => {
4924 const engine
= new InMemoryCLIEngine();
4926 assert
.strictEqual(engine
.isPathIgnored("node_modules/foo/.dot.js"), true);
4929 it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", () => {
4930 const engine
= new InMemoryCLIEngine();
4932 assert
.strictEqual(engine
.isPathIgnored("node_modules/bar/index.js"), true);
4935 it("'executeOnFiles()' should verify 'node_modules/foo/index.js'.", () => {
4936 const engine
= new InMemoryCLIEngine();
4937 const filePaths
= engine
.executeOnFiles("**/*.js")
4939 .map(r
=> r
.filePath
)
4942 assert
.deepStrictEqual(filePaths
, [
4943 path
.join(root
, "foo.js"),
4944 path
.join(root
, "node_modules/foo/index.js")
4949 describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
4951 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4954 ".eslintrc.js": `module.exports = ${JSON.stringify({
4955 ignorePatterns: "!.eslintrc.js"
4962 it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", () => {
4963 const engine
= new InMemoryCLIEngine();
4965 assert
.strictEqual(engine
.isPathIgnored(".eslintrc.js"), false);
4968 it("'executeOnFiles()' should verify '.eslintrc.js'.", () => {
4969 const engine
= new InMemoryCLIEngine();
4970 const filePaths
= engine
.executeOnFiles("**/*.js")
4972 .map(r
=> r
.filePath
)
4975 assert
.deepStrictEqual(filePaths
, [
4976 path
.join(root
, ".eslintrc.js"),
4977 path
.join(root
, "foo.js")
4982 describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
4984 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4987 ".eslintrc.js": `module.exports = ${JSON.stringify({
4988 ignorePatterns: "!.*"
4990 ".eslintignore": ".foo*",
4997 it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", () => {
4998 const engine
= new InMemoryCLIEngine();
5000 assert
.strictEqual(engine
.isPathIgnored(".foo.js"), true);
5003 it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", () => {
5004 const engine
= new InMemoryCLIEngine();
5006 assert
.strictEqual(engine
.isPathIgnored(".bar.js"), false);
5009 it("'executeOnFiles()' should not verify re-ignored '.foo.js'.", () => {
5010 const engine
= new InMemoryCLIEngine();
5011 const filePaths
= engine
.executeOnFiles("**/*.js")
5013 .map(r
=> r
.filePath
)
5016 assert
.deepStrictEqual(filePaths
, [
5017 path
.join(root
, ".bar.js"),
5018 path
.join(root
, ".eslintrc.js")
5023 describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
5025 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5028 ".eslintrc.js": `module.exports = ${JSON.stringify({
5029 ignorePatterns: "*.js"
5031 ".eslintignore": "!foo.js",
5038 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", () => {
5039 const engine
= new InMemoryCLIEngine();
5041 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5044 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", () => {
5045 const engine
= new InMemoryCLIEngine();
5047 assert
.strictEqual(engine
.isPathIgnored("bar.js"), true);
5050 it("'executeOnFiles()' should verify unignored 'foo.js'.", () => {
5051 const engine
= new InMemoryCLIEngine();
5052 const filePaths
= engine
.executeOnFiles("**/*.js")
5054 .map(r
=> r
.filePath
)
5057 assert
.deepStrictEqual(filePaths
, [
5058 path
.join(root
, "foo.js")
5063 describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
5065 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5068 ".eslintrc.json": JSON
.stringify({
5069 ignorePatterns
: "foo.js"
5071 "subdir/.eslintrc.json": JSON
.stringify({
5072 ignorePatterns
: "bar.js"
5076 "subdir/foo.js": "",
5077 "subdir/bar.js": "",
5078 "subdir/subsubdir/foo.js": "",
5079 "subdir/subsubdir/bar.js": ""
5084 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5085 const engine
= new InMemoryCLIEngine();
5087 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5088 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5089 assert
.strictEqual(engine
.isPathIgnored("subdir/subsubdir/foo.js"), true);
5092 it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", () => {
5093 const engine
= new InMemoryCLIEngine();
5095 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5096 assert
.strictEqual(engine
.isPathIgnored("subdir/subsubdir/bar.js"), true);
5099 it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", () => {
5100 const engine
= new InMemoryCLIEngine();
5102 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5105 it("'executeOnFiles()' should verify 'bar.js' in the outside of 'subdir'.", () => {
5106 const engine
= new InMemoryCLIEngine();
5107 const filePaths
= engine
.executeOnFiles("**/*.js")
5109 .map(r
=> r
.filePath
)
5112 assert
.deepStrictEqual(filePaths
, [
5113 path
.join(root
, "bar.js")
5118 describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
5120 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5123 ".eslintrc.json": JSON
.stringify({
5124 ignorePatterns
: "foo.js"
5126 "subdir/.eslintrc.json": JSON
.stringify({
5127 ignorePatterns
: "!foo.js"
5135 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", () => {
5136 const engine
= new InMemoryCLIEngine();
5138 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5141 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", () => {
5142 const engine
= new InMemoryCLIEngine();
5144 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5147 it("'executeOnFiles()' should verify 'foo.js' in the child directory.", () => {
5148 const engine
= new InMemoryCLIEngine();
5149 const filePaths
= engine
.executeOnFiles("**/*.js")
5151 .map(r
=> r
.filePath
)
5154 assert
.deepStrictEqual(filePaths
, [
5155 path
.join(root
, "subdir/foo.js")
5160 describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
5162 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5165 ".eslintrc.json": JSON
.stringify({}),
5166 "subdir/.eslintrc.json": JSON
.stringify({
5167 ignorePatterns
: "*.js"
5169 ".eslintignore": "!foo.js",
5171 "subdir/foo.js": "",
5177 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", () => {
5178 const engine
= new InMemoryCLIEngine();
5180 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5181 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5184 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", () => {
5185 const engine
= new InMemoryCLIEngine();
5187 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5190 it("'executeOnFiles()' should verify unignored 'foo.js'.", () => {
5191 const engine
= new InMemoryCLIEngine();
5192 const filePaths
= engine
.executeOnFiles("**/*.js")
5194 .map(r
=> r
.filePath
)
5197 assert
.deepStrictEqual(filePaths
, [
5198 path
.join(root
, "foo.js"),
5199 path
.join(root
, "subdir/foo.js")
5204 describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
5206 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5209 ".eslintrc.json": JSON
.stringify({
5210 ignorePatterns
: "foo.js"
5212 "subdir/.eslintrc.json": JSON
.stringify({
5214 ignorePatterns
: "bar.js"
5218 "subdir/foo.js": "",
5224 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", () => {
5225 const engine
= new InMemoryCLIEngine();
5227 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5230 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", () => {
5231 const engine
= new InMemoryCLIEngine();
5233 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5236 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", () => {
5237 const engine
= new InMemoryCLIEngine();
5239 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5242 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", () => {
5243 const engine
= new InMemoryCLIEngine();
5245 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5248 it("'executeOnFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", () => {
5249 const engine
= new InMemoryCLIEngine();
5250 const filePaths
= engine
.executeOnFiles("**/*.js")
5252 .map(r
=> r
.filePath
)
5255 assert
.deepStrictEqual(filePaths
, [
5256 path
.join(root
, "bar.js"),
5257 path
.join(root
, "subdir/foo.js")
5262 describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
5264 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5267 ".eslintrc.json": JSON
.stringify({}),
5268 "subdir/.eslintrc.json": JSON
.stringify({
5270 ignorePatterns
: "bar.js"
5272 ".eslintignore": "foo.js",
5275 "subdir/foo.js": "",
5281 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5282 const engine
= new InMemoryCLIEngine();
5284 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5285 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5288 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", () => {
5289 const engine
= new InMemoryCLIEngine();
5291 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5294 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", () => {
5295 const engine
= new InMemoryCLIEngine();
5297 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5300 it("'executeOnFiles()' should verify 'bar.js' in the root directory.", () => {
5301 const engine
= new InMemoryCLIEngine();
5302 const filePaths
= engine
.executeOnFiles("**/*.js")
5304 .map(r
=> r
.filePath
)
5307 assert
.deepStrictEqual(filePaths
, [
5308 path
.join(root
, "bar.js")
5313 describe("ignorePatterns in the shareable config should be used.", () => {
5315 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5318 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5319 ignorePatterns: "foo.js"
5321 ".eslintrc.json": JSON
.stringify({
5330 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5331 const engine
= new InMemoryCLIEngine();
5333 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5336 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5337 const engine
= new InMemoryCLIEngine();
5339 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5342 it("'executeOnFiles()' should verify 'bar.js'.", () => {
5343 const engine
= new InMemoryCLIEngine();
5344 const filePaths
= engine
.executeOnFiles("**/*.js")
5346 .map(r
=> r
.filePath
)
5349 assert
.deepStrictEqual(filePaths
, [
5350 path
.join(root
, "bar.js")
5355 describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
5357 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5360 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5361 ignorePatterns: "/foo.js"
5363 ".eslintrc.json": JSON
.stringify({
5372 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5373 const engine
= new InMemoryCLIEngine();
5375 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5378 it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", () => {
5379 const engine
= new InMemoryCLIEngine();
5381 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5384 it("'executeOnFiles()' should verify 'subdir/foo.js'.", () => {
5385 const engine
= new InMemoryCLIEngine();
5386 const filePaths
= engine
.executeOnFiles("**/*.js")
5388 .map(r
=> r
.filePath
)
5391 assert
.deepStrictEqual(filePaths
, [
5392 path
.join(root
, "subdir/foo.js")
5397 describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
5399 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5402 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5403 ignorePatterns: "*.js"
5405 ".eslintrc.json": JSON
.stringify({
5407 ignorePatterns
: "!bar.js"
5415 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5416 const engine
= new InMemoryCLIEngine();
5418 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5421 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5422 const engine
= new InMemoryCLIEngine();
5424 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5427 it("'executeOnFiles()' should verify 'bar.js'.", () => {
5428 const engine
= new InMemoryCLIEngine();
5429 const filePaths
= engine
.executeOnFiles("**/*.js")
5431 .map(r
=> r
.filePath
)
5434 assert
.deepStrictEqual(filePaths
, [
5435 path
.join(root
, "bar.js")
5440 describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
5442 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5445 ".eslintrc.json": JSON
.stringify({
5446 ignorePatterns
: "*.js"
5453 it("'isPathIgnored()' should return 'false' for 'foo.js'.", () => {
5454 const engine
= new InMemoryCLIEngine({ ignore
: false });
5456 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5459 it("'executeOnFiles()' should verify 'foo.js'.", () => {
5460 const engine
= new InMemoryCLIEngine({ ignore
: false });
5461 const filePaths
= engine
.executeOnFiles("**/*.js")
5463 .map(r
=> r
.filePath
)
5466 assert
.deepStrictEqual(filePaths
, [
5467 path
.join(root
, "foo.js")
5472 describe("ignorePatterns in overrides section is not allowed.", () => {
5474 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5477 ".eslintrc.js": `module.exports = ${JSON.stringify({
5481 ignorePatterns: "foo.js"
5490 it("should throw a configuration error.", () => {
5491 assert
.throws(() => {
5492 const engine
= new InMemoryCLIEngine();
5494 engine
.executeOnFiles("*.js");
5495 }, "Unexpected top-level property \"overrides[0].ignorePatterns\"");
5501 describe("'overrides[].files' adds lint targets", () => {
5502 const root
= getFixturePath("cli-engine/additional-lint-targets");
5503 let InMemoryCLIEngine
;
5505 describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
5507 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5510 ".eslintrc.json": JSON
.stringify({
5514 excludedFiles
: "**/ignore.txt"
5518 "foo/nested/test.txt": "",
5521 "foo/ignore.txt": "",
5524 "bar/ignore.txt": "",
5532 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt'.", () => {
5533 const engine
= new InMemoryCLIEngine();
5534 const filePaths
= engine
.executeOnFiles(".")
5536 .map(r
=> r
.filePath
)
5539 assert
.deepStrictEqual(filePaths
, [
5540 path
.join(root
, "bar/test.js"),
5541 path
.join(root
, "foo/test.js"),
5542 path
.join(root
, "foo/test.txt"),
5543 path
.join(root
, "test.js")
5547 it("'executeOnFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", () => {
5548 const engine
= new InMemoryCLIEngine();
5549 const filePaths
= engine
.executeOnFiles("**/*.js")
5551 .map(r
=> r
.filePath
)
5554 assert
.deepStrictEqual(filePaths
, [
5555 path
.join(root
, "bar/test.js"),
5556 path
.join(root
, "foo/test.js"),
5557 path
.join(root
, "test.js")
5562 describe("if { files: 'foo/**/*.txt' } is present,", () => {
5564 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5567 ".eslintrc.json": JSON
.stringify({
5570 files
: "foo/**/*.txt"
5574 "foo/nested/test.txt": "",
5585 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5586 const engine
= new InMemoryCLIEngine();
5587 const filePaths
= engine
.executeOnFiles(".")
5589 .map(r
=> r
.filePath
)
5592 assert
.deepStrictEqual(filePaths
, [
5593 path
.join(root
, "bar/test.js"),
5594 path
.join(root
, "foo/nested/test.txt"),
5595 path
.join(root
, "foo/test.js"),
5596 path
.join(root
, "foo/test.txt"),
5597 path
.join(root
, "test.js")
5602 describe("if { files: 'foo/**/*' } is present,", () => {
5604 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5607 ".eslintrc.json": JSON
.stringify({
5614 "foo/nested/test.txt": "",
5625 it("'executeOnFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5626 const engine
= new InMemoryCLIEngine();
5627 const filePaths
= engine
.executeOnFiles(".")
5629 .map(r
=> r
.filePath
)
5632 assert
.deepStrictEqual(filePaths
, [
5633 path
.join(root
, "bar/test.js"),
5634 path
.join(root
, "foo/test.js"),
5635 path
.join(root
, "test.js")
5640 describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
5642 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5645 "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
5648 files: "foo/**/*.txt"
5652 ".eslintrc.json": JSON
.stringify({
5655 "foo/nested/test.txt": "",
5666 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5667 const engine
= new InMemoryCLIEngine();
5668 const filePaths
= engine
.executeOnFiles(".")
5670 .map(r
=> r
.filePath
)
5673 assert
.deepStrictEqual(filePaths
, [
5674 path
.join(root
, "bar/test.js"),
5675 path
.join(root
, "foo/nested/test.txt"),
5676 path
.join(root
, "foo/test.js"),
5677 path
.join(root
, "foo/test.txt"),
5678 path
.join(root
, "test.js")
5683 describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
5685 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5688 "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
5692 files: "foo/**/*.txt"
5697 ".eslintrc.json": JSON
.stringify({
5698 extends: "plugin:foo/bar"
5700 "foo/nested/test.txt": "",
5711 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5712 const engine
= new InMemoryCLIEngine();
5713 const filePaths
= engine
.executeOnFiles(".")
5715 .map(r
=> r
.filePath
)
5718 assert
.deepStrictEqual(filePaths
, [
5719 path
.join(root
, "bar/test.js"),
5720 path
.join(root
, "foo/nested/test.txt"),
5721 path
.join(root
, "foo/test.js"),
5722 path
.join(root
, "foo/test.txt"),
5723 path
.join(root
, "test.js")
5729 describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
5730 const root
= getFixturePath("cli-engine/config-and-overrides-files");
5732 /** @type {CLIEngine} */
5733 let InMemoryCLIEngine
;
5735 describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5737 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5740 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5750 "node_modules/myconf/foo/test.js": "a == b",
5751 "foo/test.js": "a == b"
5756 it("'executeOnFiles()' with 'foo/test.js' should use the override entry.", () => {
5757 const engine
= new InMemoryCLIEngine({
5758 configFile
: "node_modules/myconf/.eslintrc.json",
5763 const { results
} = engine
.executeOnFiles("foo/test.js");
5765 // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
5766 assert
.deepStrictEqual(results
, [
5769 filePath
: path
.join(root
, "foo/test.js"),
5770 fixableErrorCount
: 0,
5771 fixableWarningCount
: 0,
5778 message
: "Expected '===' and instead saw '=='.",
5779 messageId
: "unexpected",
5780 nodeType
: "BinaryExpression",
5791 it("'executeOnFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", () => {
5792 const engine
= new InMemoryCLIEngine({
5793 configFile
: "node_modules/myconf/.eslintrc.json",
5798 const { results
} = engine
.executeOnFiles("node_modules/myconf/foo/test.js");
5800 // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
5801 assert
.deepStrictEqual(results
, [
5804 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
5805 fixableErrorCount
: 0,
5806 fixableWarningCount
: 0,
5814 describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5816 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5819 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5823 excludedFiles
: "foo/*.js",
5830 "node_modules/myconf/foo/test.js": "a == b",
5831 "foo/test.js": "a == b"
5836 it("'executeOnFiles()' with 'foo/test.js' should NOT use the override entry.", () => {
5837 const engine
= new InMemoryCLIEngine({
5838 configFile
: "node_modules/myconf/.eslintrc.json",
5843 const { results
} = engine
.executeOnFiles("foo/test.js");
5845 // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
5846 assert
.deepStrictEqual(results
, [
5849 filePath
: path
.join(root
, "foo/test.js"),
5850 fixableErrorCount
: 0,
5851 fixableWarningCount
: 0,
5858 it("'executeOnFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", () => {
5859 const engine
= new InMemoryCLIEngine({
5860 configFile
: "node_modules/myconf/.eslintrc.json",
5865 const { results
} = engine
.executeOnFiles("node_modules/myconf/foo/test.js");
5867 // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
5868 assert
.deepStrictEqual(results
, [
5871 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
5872 fixableErrorCount
: 0,
5873 fixableWarningCount
: 0,
5880 message
: "Expected '===' and instead saw '=='.",
5881 messageId
: "unexpected",
5882 nodeType
: "BinaryExpression",
5894 describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5896 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5899 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5900 ignorePatterns
: ["!/node_modules/myconf", "foo/*.js"],
5905 "node_modules/myconf/foo/test.js": "a == b",
5906 "foo/test.js": "a == b"
5911 it("'executeOnFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", () => {
5912 const engine
= new InMemoryCLIEngine({
5913 configFile
: "node_modules/myconf/.eslintrc.json",
5917 const files
= engine
.executeOnFiles("**/*.js")
5919 .map(r
=> r
.filePath
)
5922 assert
.deepStrictEqual(files
, [
5923 path
.join(root
, "node_modules/myconf/foo/test.js")
5929 describe("plugin conflicts", () => {
5934 root
= getFixturePath(`cli-engine/plugin-conflicts-${++uid}`);
5937 /** @type {typeof CLIEngine} */
5938 let InMemoryCLIEngine
;
5941 * Verify thrown errors.
5942 * @param {() => void} f The function to run and throw.
5943 * @param {Record<string, any>} props The properties to verify.
5946 function assertThrows(f
, props
) {
5950 for (const [key
, value
] of Object
.entries(props
)) {
5951 assert
.deepStrictEqual(error
[key
], value
, key
);
5956 assert
.fail("Function should throw an error, but not.");
5959 describe("between a config file and linear extendees.", () => {
5961 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5964 "node_modules/eslint-plugin-foo/index.js": "",
5965 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
5966 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5970 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
5971 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
5974 ".eslintrc.json": JSON
.stringify({
5983 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", () => {
5984 const engine
= new InMemoryCLIEngine({ cwd
: root
});
5986 engine
.executeOnFiles("test.js");
5990 describe("between a config file and same-depth extendees.", () => {
5992 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5995 "node_modules/eslint-plugin-foo/index.js": "",
5996 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
5997 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6000 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6001 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6004 ".eslintrc.json": JSON
.stringify({
6005 extends: ["one", "two"],
6013 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", () => {
6014 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6016 engine
.executeOnFiles("test.js");
6020 describe("between two config files in different directories, with single node_modules.", () => {
6022 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6025 "node_modules/eslint-plugin-foo/index.js": "",
6026 ".eslintrc.json": JSON
.stringify({
6029 "subdir/.eslintrc.json": JSON
.stringify({
6032 "subdir/test.js": ""
6037 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.)", () => {
6038 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6040 engine
.executeOnFiles("subdir/test.js");
6044 describe("between two config files in different directories, with multiple node_modules.", () => {
6046 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6049 "node_modules/eslint-plugin-foo/index.js": "",
6050 ".eslintrc.json": JSON
.stringify({
6053 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6054 "subdir/.eslintrc.json": JSON
.stringify({
6057 "subdir/test.js": ""
6062 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.)", () => {
6063 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6066 () => engine
.executeOnFiles("subdir/test.js"),
6068 message
: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
6069 messageTemplate
: "plugin-conflict",
6074 filePath
: path
.join(root
, "subdir/node_modules/eslint-plugin-foo/index.js"),
6075 importerName
: `subdir${path.sep}.eslintrc.json`
6078 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
6079 importerName
: ".eslintrc.json"
6088 describe("between '--config' option and a regular config file, with single node_modules.", () => {
6090 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6093 "node_modules/eslint-plugin-foo/index.js": "",
6094 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6097 ".eslintrc.json": JSON
.stringify({
6105 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.)", () => {
6106 const engine
= new InMemoryCLIEngine({
6108 configFile
: "node_modules/mine/.eslintrc.json"
6111 engine
.executeOnFiles("test.js");
6115 describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
6117 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6120 "node_modules/eslint-plugin-foo/index.js": "",
6121 "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
6122 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6125 ".eslintrc.json": JSON
.stringify({
6133 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.)", () => {
6134 const engine
= new InMemoryCLIEngine({
6136 configFile
: "node_modules/mine/.eslintrc.json"
6140 () => engine
.executeOnFiles("test.js"),
6142 message
: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
6143 messageTemplate
: "plugin-conflict",
6148 filePath
: path
.join(root
, "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
6149 importerName
: "--config"
6152 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
6153 importerName
: ".eslintrc.json"
6162 describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
6164 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6167 "node_modules/eslint-plugin-foo/index.js": "",
6168 "subdir/.eslintrc.json": JSON
.stringify({
6171 "subdir/test.js": ""
6176 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.)", () => {
6177 const engine
= new InMemoryCLIEngine({
6182 engine
.executeOnFiles("subdir/test.js");
6186 describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
6188 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6191 "node_modules/eslint-plugin-foo/index.js": "",
6192 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6193 "subdir/.eslintrc.json": JSON
.stringify({
6196 "subdir/test.js": ""
6201 it("'executeOnFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", () => {
6202 const engine
= new InMemoryCLIEngine({
6208 () => engine
.executeOnFiles("subdir/test.js"),
6210 message
: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
6211 messageTemplate
: "plugin-conflict",
6216 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
6217 importerName
: "CLIOptions"
6220 filePath
: path
.join(root
, "subdir/node_modules/eslint-plugin-foo/index.js"),
6221 importerName
: `subdir${path.sep}.eslintrc.json`
6230 describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
6232 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6235 "node_modules/eslint-plugin-foo/index.js": "",
6236 ".eslintrc.json": JSON
.stringify({
6239 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6240 "subdir/.eslintrc.json": JSON
.stringify({
6243 "subdir/test.js": ""
6248 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", () => {
6249 const engine
= new InMemoryCLIEngine({
6251 resolvePluginsRelativeTo
: root
6254 engine
.executeOnFiles("subdir/test.js");
6258 describe("between two config files with different target files.", () => {
6260 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6263 "one/node_modules/eslint-plugin-foo/index.js": "",
6264 "one/.eslintrc.json": JSON
.stringify({
6268 "two/node_modules/eslint-plugin-foo/index.js": "",
6269 "two/.eslintrc.json": JSON
.stringify({
6277 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.)", () => {
6278 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6279 const { results
} = engine
.executeOnFiles("*/test.js");
6281 assert
.strictEqual(results
.length
, 2);