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
, defineCLIEngineWithInMemoryFileSystem
} = require("../../_utils");
23 const proxyquire
= require("proxyquire").noCallThru().noPreserveCache();
24 const fCache
= require("file-entry-cache");
26 //------------------------------------------------------------------------------
28 //------------------------------------------------------------------------------
30 describe("CLIEngine", () => {
32 const examplePluginName
= "eslint-plugin-example",
33 examplePluginNameWithNamespace
= "@eslint/eslint-plugin-example",
36 "example-rule": require("../../fixtures/rules/custom-rule"),
37 "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
40 examplePreprocessorName
= "eslint-plugin-processor",
41 originalDir
= process
.cwd(),
42 fixtureDir
= path
.resolve(fs
.realpathSync(os
.tmpdir()), "eslint/fixtures");
44 /** @type {import("../../../lib/cli-engine")["CLIEngine"]} */
47 /** @type {import("../../../lib/cli-engine/cli-engine")["getCLIEngineInternalSlots"]} */
48 let getCLIEngineInternalSlots;
51 * Returns the path inside of the fixture directory.
52 * @param {...string} args file path segments.
53 * @returns {string} The path inside the fixture directory.
56 function getFixturePath(...args
) {
57 const filepath
= path
.join(fixtureDir
, ...args
);
60 return fs
.realpathSync(filepath
);
67 * Create the CLIEngine object by mocking some of the plugins
68 * @param {Object} options options for CLIEngine
69 * @returns {CLIEngine} engine object
72 function cliEngineWithPlugins(options
) {
73 const engine
= new CLIEngine(options
);
75 // load the mocked plugins
76 engine
.addPlugin(examplePluginName
, examplePlugin
);
77 engine
.addPlugin(examplePluginNameWithNamespace
, examplePlugin
);
78 engine
.addPlugin(examplePreprocessorName
, require("../../fixtures/processors/custom-processor"));
83 // copy into clean area so as not to get "infected" by this project's .eslintrc files
85 shell
.mkdir("-p", fixtureDir
);
86 shell
.cp("-r", "./tests/fixtures/.", fixtureDir
);
90 ({ CLIEngine
, getCLIEngineInternalSlots
} = require("../../../lib/cli-engine/cli-engine"));
94 shell
.rm("-r", fixtureDir
);
97 describe("new CLIEngine(options)", () => {
98 it("the default value of 'options.cwd' should be the current working directory.", () => {
99 process
.chdir(__dirname
);
101 const engine
= new CLIEngine();
102 const internalSlots
= getCLIEngineInternalSlots(engine
);
104 assert
.strictEqual(internalSlots
.options
.cwd
, __dirname
);
106 process
.chdir(originalDir
);
110 it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
111 assert
.throws(() => {
112 // eslint-disable-next-line no-new
113 new CLIEngine({ ignorePath
: fixtureDir
});
114 }, `Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`);
117 // https://github.com/eslint/eslint/issues/2380
118 it("should not modify baseConfig when format is specified", () => {
119 const customBaseConfig
= { root
: true };
121 new CLIEngine({ baseConfig
: customBaseConfig
, format
: "foo" }); // eslint-disable-line no-new
123 assert
.deepStrictEqual(customBaseConfig
, { root
: true });
127 describe("executeOnText()", () => {
131 it("should report the total and per file errors when using local cwd .eslintrc", () => {
133 engine
= new CLIEngine();
135 const report
= engine
.executeOnText("var foo = 'bar';");
137 assert
.strictEqual(report
.results
.length
, 1);
138 assert
.strictEqual(report
.errorCount
, 5);
139 assert
.strictEqual(report
.warningCount
, 0);
140 assert
.strictEqual(report
.fixableErrorCount
, 3);
141 assert
.strictEqual(report
.fixableWarningCount
, 0);
142 assert
.strictEqual(report
.results
[0].messages
.length
, 5);
143 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "strict");
144 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-var");
145 assert
.strictEqual(report
.results
[0].messages
[2].ruleId
, "no-unused-vars");
146 assert
.strictEqual(report
.results
[0].messages
[3].ruleId
, "quotes");
147 assert
.strictEqual(report
.results
[0].messages
[4].ruleId
, "eol-last");
148 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 3);
149 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
152 it("should report the total and per file warnings when using local cwd .eslintrc", () => {
154 engine
= new CLIEngine({
164 const report
= engine
.executeOnText("var foo = 'bar';");
166 assert
.strictEqual(report
.results
.length
, 1);
167 assert
.strictEqual(report
.errorCount
, 0);
168 assert
.strictEqual(report
.warningCount
, 5);
169 assert
.strictEqual(report
.fixableErrorCount
, 0);
170 assert
.strictEqual(report
.fixableWarningCount
, 3);
171 assert
.strictEqual(report
.results
[0].messages
.length
, 5);
172 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "strict");
173 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-var");
174 assert
.strictEqual(report
.results
[0].messages
[2].ruleId
, "no-unused-vars");
175 assert
.strictEqual(report
.results
[0].messages
[3].ruleId
, "quotes");
176 assert
.strictEqual(report
.results
[0].messages
[4].ruleId
, "eol-last");
177 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
178 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 3);
181 it("should report one message when using specific config file", () => {
183 engine
= new CLIEngine({
184 configFile
: "fixtures/configurations/quotes-error.json",
186 cwd
: getFixturePath("..")
189 const report
= engine
.executeOnText("var foo = 'bar';");
191 assert
.strictEqual(report
.results
.length
, 1);
192 assert
.strictEqual(report
.errorCount
, 1);
193 assert
.strictEqual(report
.warningCount
, 0);
194 assert
.strictEqual(report
.fixableErrorCount
, 1);
195 assert
.strictEqual(report
.fixableWarningCount
, 0);
196 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
197 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
198 assert
.isUndefined(report
.results
[0].messages
[0].output
);
199 assert
.strictEqual(report
.results
[0].errorCount
, 1);
200 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
201 assert
.strictEqual(report
.results
[0].warningCount
, 0);
204 it("should report the filename when passed in", () => {
206 engine
= new CLIEngine({
208 cwd
: getFixturePath()
211 const report
= engine
.executeOnText("var foo = 'bar';", "test.js");
213 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("test.js"));
216 it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", () => {
217 engine
= new CLIEngine({
218 ignorePath
: getFixturePath(".eslintignore"),
219 cwd
: getFixturePath("..")
222 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js", true);
224 assert
.strictEqual(report
.results
.length
, 1);
225 assert
.strictEqual(report
.errorCount
, 0);
226 assert
.strictEqual(report
.warningCount
, 1);
227 assert
.strictEqual(report
.fixableErrorCount
, 0);
228 assert
.strictEqual(report
.fixableWarningCount
, 0);
229 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("passing.js"));
230 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
231 assert
.strictEqual(report
.results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
232 assert
.isUndefined(report
.results
[0].messages
[0].output
);
233 assert
.strictEqual(report
.results
[0].errorCount
, 0);
234 assert
.strictEqual(report
.results
[0].warningCount
, 1);
235 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
236 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
239 it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", () => {
240 engine
= new CLIEngine({
241 ignorePath
: getFixturePath(".eslintignore"),
242 cwd
: getFixturePath("..")
245 // intentional parsing error
246 const report
= engine
.executeOnText("va r bar = foo;", "fixtures/passing.js", false);
248 // should not report anything because the file is ignored
249 assert
.strictEqual(report
.results
.length
, 0);
252 it("should suppress excluded file warnings by default", () => {
253 engine
= new CLIEngine({
254 ignorePath
: getFixturePath(".eslintignore"),
255 cwd
: getFixturePath("..")
258 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
260 // should not report anything because there are no errors
261 assert
.strictEqual(report
.results
.length
, 0);
264 it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", () => {
266 engine
= new CLIEngine({
267 ignorePath
: "fixtures/.eslintignore",
268 cwd
: getFixturePath(".."),
276 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
278 assert
.strictEqual(report
.results
.length
, 1);
279 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("passing.js"));
280 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-undef");
281 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
282 assert
.isUndefined(report
.results
[0].messages
[0].output
);
285 it("should return a message and fixed text when in fix mode", () => {
287 engine
= new CLIEngine({
294 cwd
: getFixturePath()
297 const report
= engine
.executeOnText("var bar = foo", "passing.js");
299 assert
.deepStrictEqual(report
, {
302 filePath
: getFixturePath("passing.js"),
306 fixableErrorCount
: 0,
307 fixableWarningCount
: 0,
308 output
: "var bar = foo;"
313 fixableErrorCount
: 0,
314 fixableWarningCount
: 0,
315 usedDeprecatedRules
: []
319 it("correctly autofixes semicolon-conflicting-fixes", () => {
320 engine
= new CLIEngine({
321 cwd
: path
.join(fixtureDir
, ".."),
325 const inputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.js");
326 const outputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
327 const report
= engine
.executeOnFiles([inputPath
]);
328 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
330 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
333 it("correctly autofixes return-conflicting-fixes", () => {
334 engine
= new CLIEngine({
335 cwd
: path
.join(fixtureDir
, ".."),
339 const inputPath
= getFixturePath("autofix/return-conflicting-fixes.js");
340 const outputPath
= getFixturePath("autofix/return-conflicting-fixes.expected.js");
341 const report
= engine
.executeOnFiles([inputPath
]);
342 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
344 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
347 describe("Fix Types", () => {
349 it("should throw an error when an invalid fix type is specified", () => {
350 assert
.throws(() => {
351 engine
= new CLIEngine({
352 cwd
: path
.join(fixtureDir
, ".."),
357 }, /invalid fix type/iu);
360 it("should not fix any rules when fixTypes is used without fix", () => {
361 engine
= new CLIEngine({
362 cwd
: path
.join(fixtureDir
, ".."),
368 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
369 const report
= engine
.executeOnFiles([inputPath
]);
371 assert
.isUndefined(report
.results
[0].output
);
374 it("should not fix non-style rules when fixTypes has only 'layout'", () => {
375 engine
= new CLIEngine({
376 cwd
: path
.join(fixtureDir
, ".."),
381 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
382 const outputPath
= getFixturePath("fix-types/fix-only-semi.expected.js");
383 const report
= engine
.executeOnFiles([inputPath
]);
384 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
386 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
389 it("should not fix style or problem rules when fixTypes has only 'suggestion'", () => {
390 engine
= new CLIEngine({
391 cwd
: path
.join(fixtureDir
, ".."),
394 fixTypes
: ["suggestion"]
396 const inputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
397 const outputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
398 const report
= engine
.executeOnFiles([inputPath
]);
399 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
401 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
404 it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", () => {
405 engine
= new CLIEngine({
406 cwd
: path
.join(fixtureDir
, ".."),
409 fixTypes
: ["suggestion", "layout"]
411 const inputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
412 const outputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
413 const report
= engine
.executeOnFiles([inputPath
]);
414 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
416 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
419 it("should not throw an error when a rule doesn't have a 'meta' property", () => {
420 engine
= new CLIEngine({
421 cwd
: path
.join(fixtureDir
, ".."),
424 fixTypes
: ["layout"],
425 rulePaths
: [getFixturePath("rules", "fix-types-test")]
428 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
429 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
430 const report
= engine
.executeOnFiles([inputPath
]);
431 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
433 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
436 it("should not throw an error when a rule is loaded after initialization with executeOnFiles()", () => {
437 engine
= new CLIEngine({
438 cwd
: path
.join(fixtureDir
, ".."),
443 const internalSlots
= getCLIEngineInternalSlots(engine
);
445 internalSlots
.linter
.defineRule(
447 require(getFixturePath("rules", "fix-types-test", "no-program.js"))
450 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
451 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
452 const report
= engine
.executeOnFiles([inputPath
]);
453 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
455 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
458 it("should not throw an error when a rule is loaded after initialization with executeOnText()", () => {
459 engine
= new CLIEngine({
460 cwd
: path
.join(fixtureDir
, ".."),
465 const internalSlots
= getCLIEngineInternalSlots(engine
);
467 internalSlots
.linter
.defineRule(
469 require(getFixturePath("rules", "fix-types-test", "no-program.js"))
472 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
473 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
474 const report
= engine
.executeOnText(fs
.readFileSync(inputPath
, { encoding
: "utf8" }), inputPath
);
475 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
477 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
482 it("should return a message and omit fixed text when in fix mode and fixes aren't done", () => {
484 engine
= new CLIEngine({
491 cwd
: getFixturePath()
494 const report
= engine
.executeOnText("var bar = foo", "passing.js");
496 assert
.deepStrictEqual(report
, {
499 filePath
: getFixturePath("passing.js"),
505 message
: "'foo' is not defined.",
510 nodeType
: "Identifier"
515 fixableErrorCount
: 0,
516 fixableWarningCount
: 0,
517 source
: "var bar = foo"
522 fixableErrorCount
: 0,
523 fixableWarningCount
: 0,
524 usedDeprecatedRules
: []
528 it("should not delete code if there is a syntax error after trying to autofix.", () => {
529 engine
= cliEngineWithPlugins({
532 plugins
: ["example"],
534 "example/make-syntax-error": "error"
537 cwd
: getFixturePath()
540 const report
= engine
.executeOnText("var bar = foo", "test.js");
542 assert
.deepStrictEqual(report
, {
545 filePath
: getFixturePath("test.js"),
551 message
: "Parsing error: Unexpected token is",
558 fixableErrorCount
: 0,
559 fixableWarningCount
: 0,
560 output
: "var bar = foothis is a syntax error."
565 fixableErrorCount
: 0,
566 fixableWarningCount
: 0,
567 usedDeprecatedRules
: []
571 it("should not crash even if there are any syntax error since the first time.", () => {
572 engine
= new CLIEngine({
576 "example/make-syntax-error": "error"
579 cwd
: getFixturePath()
582 const report
= engine
.executeOnText("var bar =", "test.js");
584 assert
.deepStrictEqual(report
, {
587 filePath
: getFixturePath("test.js"),
593 message
: "Parsing error: Unexpected token",
600 fixableErrorCount
: 0,
601 fixableWarningCount
: 0,
607 fixableErrorCount
: 0,
608 fixableWarningCount
: 0,
609 usedDeprecatedRules
: []
613 it("should return source code of file in `source` property when errors are present", () => {
614 engine
= new CLIEngine({
619 const report
= engine
.executeOnText("var foo = 'bar'");
621 assert
.strictEqual(report
.results
[0].source
, "var foo = 'bar'");
624 it("should return source code of file in `source` property when warnings are present", () => {
625 engine
= new CLIEngine({
630 const report
= engine
.executeOnText("var foo = 'bar'");
632 assert
.strictEqual(report
.results
[0].source
, "var foo = 'bar'");
636 it("should not return a `source` property when no errors or warnings are present", () => {
637 engine
= new CLIEngine({
642 const report
= engine
.executeOnText("var foo = 'bar';");
644 assert
.lengthOf(report
.results
[0].messages
, 0);
645 assert
.isUndefined(report
.results
[0].source
);
648 it("should not return a `source` property when fixes are applied", () => {
649 engine
= new CLIEngine({
658 const report
= engine
.executeOnText("var msg = 'hi' + foo\n");
660 assert
.isUndefined(report
.results
[0].source
);
661 assert
.strictEqual(report
.results
[0].output
, "var msg = 'hi' + foo;\n");
664 it("should return a `source` property when a parsing error has occurred", () => {
665 engine
= new CLIEngine({
670 const report
= engine
.executeOnText("var bar = foothis is a syntax error.\n return bar;");
672 assert
.deepStrictEqual(report
, {
681 message
: "Parsing error: Unexpected token is",
688 fixableErrorCount
: 0,
689 fixableWarningCount
: 0,
690 source
: "var bar = foothis is a syntax error.\n return bar;"
695 fixableErrorCount
: 0,
696 fixableWarningCount
: 0,
697 usedDeprecatedRules
: []
701 // https://github.com/eslint/eslint/issues/5547
702 it("should respect default ignore rules, even with --no-ignore", () => {
704 engine
= new CLIEngine({
705 cwd
: getFixturePath(),
709 const report
= engine
.executeOnText("var bar = foo;", "node_modules/passing.js", true);
710 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
712 assert
.strictEqual(report
.results
.length
, 1);
713 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("node_modules/passing.js"));
714 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
717 // @scope for @scope/eslint-plugin
718 describe("(plugin shorthand)", () => {
719 const Module
= require("module");
720 let originalFindPath
= null;
722 /* eslint-disable no-underscore-dangle */
724 originalFindPath
= Module
._findPath
;
725 Module
._findPath = function(id
, ...otherArgs
) {
726 if (id
=== "@scope/eslint-plugin") {
727 return path
.resolve(__dirname
, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
729 return originalFindPath
.call(this, id
, ...otherArgs
);
733 Module
._findPath
= originalFindPath
;
735 /* eslint-enable no-underscore-dangle */
737 it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
738 engine
= new CLIEngine({ cwd
: getFixturePath("plugin-shorthand/basic") });
739 const report
= engine
.executeOnText("var x = 0", "index.js").results
[0];
741 assert
.strictEqual(report
.filePath
, getFixturePath("plugin-shorthand/basic/index.js"));
742 assert
.strictEqual(report
.messages
[0].ruleId
, "@scope/rule");
743 assert
.strictEqual(report
.messages
[0].message
, "OK");
746 it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
747 engine
= new CLIEngine({ cwd
: getFixturePath("plugin-shorthand/extends") });
748 const report
= engine
.executeOnText("var x = 0", "index.js").results
[0];
750 assert
.strictEqual(report
.filePath
, getFixturePath("plugin-shorthand/extends/index.js"));
751 assert
.strictEqual(report
.messages
[0].ruleId
, "@scope/rule");
752 assert
.strictEqual(report
.messages
[0].message
, "OK");
755 it("should warn when deprecated rules are found in a config", () => {
756 engine
= new CLIEngine({
759 configFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
762 const report
= engine
.executeOnText("foo");
764 assert
.deepStrictEqual(
765 report
.usedDeprecatedRules
,
766 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
771 describe("executeOnFiles()", () => {
773 /** @type {InstanceType<import("../../../lib/cli-engine")["CLIEngine"]>} */
776 it("should use correct parser when custom parser is specified", () => {
778 engine
= new CLIEngine({
783 const filePath
= path
.resolve(__dirname
, "../../fixtures/configurations/parser/custom.js");
784 const report
= engine
.executeOnFiles([filePath
]);
786 assert
.strictEqual(report
.results
.length
, 1);
787 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
788 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Parsing error: Boom!");
792 it("should report zero messages when given a config file and a valid file", () => {
794 engine
= new CLIEngine({
796 configFile
: ".eslintrc.js"
799 const report
= engine
.executeOnFiles(["lib/**/cli*.js"]);
801 assert
.strictEqual(report
.results
.length
, 2);
802 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
803 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
806 it("should handle multiple patterns with overlapping files", () => {
808 engine
= new CLIEngine({
810 configFile
: ".eslintrc.js"
813 const report
= engine
.executeOnFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
815 assert
.strictEqual(report
.results
.length
, 2);
816 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
817 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
820 it("should report zero messages when given a config file and a valid file and espree as parser", () => {
822 engine
= new CLIEngine({
830 const report
= engine
.executeOnFiles(["lib/cli.js"]);
832 assert
.strictEqual(report
.results
.length
, 1);
833 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
836 it("should report zero messages when given a config file and a valid file and esprima as parser", () => {
838 engine
= new CLIEngine({
843 const report
= engine
.executeOnFiles(["lib/cli.js"]);
845 assert
.strictEqual(report
.results
.length
, 1);
846 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
849 it("should throw an error when given a config file and a valid file and invalid parser", () => {
851 engine
= new CLIEngine({
856 assert
.throws(() => engine
.executeOnFiles(["lib/cli.js"]), "Cannot find module 'test11'");
859 it("should report zero messages when given a directory with a .js2 file", () => {
861 engine
= new CLIEngine({
862 cwd
: path
.join(fixtureDir
, ".."),
866 const report
= engine
.executeOnFiles([getFixturePath("files/foo.js2")]);
868 assert
.strictEqual(report
.results
.length
, 1);
869 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
872 it("should fall back to defaults when extensions is set to an empty array", () => {
874 engine
= new CLIEngine({
875 cwd
: getFixturePath("configurations"),
876 configFile
: getFixturePath("configurations", "quotes-error.json"),
879 const report
= engine
.executeOnFiles([getFixturePath("single-quoted.js")]);
881 assert
.strictEqual(report
.results
.length
, 1);
882 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
883 assert
.strictEqual(report
.errorCount
, 1);
884 assert
.strictEqual(report
.warningCount
, 0);
885 assert
.strictEqual(report
.fixableErrorCount
, 1);
886 assert
.strictEqual(report
.fixableWarningCount
, 0);
887 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
888 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
889 assert
.strictEqual(report
.results
[0].errorCount
, 1);
890 assert
.strictEqual(report
.results
[0].warningCount
, 0);
891 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
892 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
895 it("should report zero messages when given a directory with a .js and a .js2 file", () => {
897 engine
= new CLIEngine({
898 extensions
: [".js", ".js2"],
900 cwd
: getFixturePath("..")
903 const report
= engine
.executeOnFiles(["fixtures/files/"]);
905 assert
.strictEqual(report
.results
.length
, 2);
906 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
907 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
910 it("should report zero messages when given a '**' pattern with a .js and a .js2 file", () => {
912 engine
= new CLIEngine({
913 extensions
: [".js", ".js2"],
915 cwd
: path
.join(fixtureDir
, "..")
918 const report
= engine
.executeOnFiles(["fixtures/files/*"]);
920 assert
.strictEqual(report
.results
.length
, 2);
921 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
922 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
925 it("should resolve globs when 'globInputPaths' option is true", () => {
926 engine
= new CLIEngine({
927 extensions
: [".js", ".js2"],
929 cwd
: getFixturePath("..")
932 const report
= engine
.executeOnFiles(["fixtures/files/*"]);
934 assert
.strictEqual(report
.results
.length
, 2);
935 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
936 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
939 it("should not resolve globs when 'globInputPaths' option is false", () => {
940 engine
= new CLIEngine({
941 extensions
: [".js", ".js2"],
943 cwd
: getFixturePath(".."),
944 globInputPaths
: false
947 assert
.throws(() => {
948 engine
.executeOnFiles(["fixtures/files/*"]);
949 }, "No files matching 'fixtures/files/*' were found (glob was disabled).");
952 it("should report on all files passed explicitly, even if ignored by default", () => {
954 engine
= new CLIEngine({
955 cwd
: getFixturePath("cli-engine")
958 const report
= engine
.executeOnFiles(["node_modules/foo.js"]);
959 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
961 assert
.strictEqual(report
.results
.length
, 1);
962 assert
.strictEqual(report
.results
[0].errorCount
, 0);
963 assert
.strictEqual(report
.results
[0].warningCount
, 1);
964 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
965 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
966 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
969 it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", () => {
971 engine
= new CLIEngine({
972 cwd
: getFixturePath("cli-engine"),
974 quotes
: [2, "single"]
978 const report
= engine
.executeOnFiles(["hidden/.hiddenfolder/*.js"]);
980 assert
.strictEqual(report
.results
.length
, 1);
981 assert
.strictEqual(report
.results
[0].errorCount
, 1);
982 assert
.strictEqual(report
.results
[0].warningCount
, 0);
983 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
984 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
987 it("should not check default ignored files without --no-ignore flag", () => {
989 engine
= new CLIEngine({
990 cwd
: getFixturePath("cli-engine")
993 assert
.throws(() => {
994 engine
.executeOnFiles(["node_modules"]);
995 }, "All files matched by 'node_modules' are ignored.");
998 // https://github.com/eslint/eslint/issues/5547
999 it("should not check node_modules files even with --no-ignore flag", () => {
1001 engine
= new CLIEngine({
1002 cwd
: getFixturePath("cli-engine"),
1006 assert
.throws(() => {
1007 engine
.executeOnFiles(["node_modules"]);
1008 }, "All files matched by 'node_modules' are ignored.");
1011 it("should not check .hidden files if they are passed explicitly without --no-ignore flag", () => {
1013 engine
= new CLIEngine({
1014 cwd
: getFixturePath(".."),
1017 quotes
: [2, "single"]
1021 const report
= engine
.executeOnFiles(["fixtures/files/.bar.js"]);
1022 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1024 assert
.strictEqual(report
.results
.length
, 1);
1025 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1026 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1027 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1028 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1029 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1032 // https://github.com/eslint/eslint/issues/12873
1033 it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", () => {
1034 engine
= new CLIEngine({
1035 cwd
: getFixturePath("cli-engine"),
1038 quotes
: [2, "single"]
1042 const report
= engine
.executeOnFiles(["hidden/.hiddenfolder/double-quotes.js"]);
1043 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1045 assert
.strictEqual(report
.results
.length
, 1);
1046 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1047 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1048 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1049 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1050 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1053 it("should check .hidden files if they are passed explicitly with --no-ignore flag", () => {
1055 engine
= new CLIEngine({
1056 cwd
: getFixturePath(".."),
1060 quotes
: [2, "single"]
1064 const report
= engine
.executeOnFiles(["fixtures/files/.bar.js"]);
1066 assert
.strictEqual(report
.results
.length
, 1);
1067 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1068 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1069 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1070 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1071 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1074 it("should check .hidden files if they are unignored with an --ignore-pattern", () => {
1076 engine
= new CLIEngine({
1077 cwd
: getFixturePath("cli-engine"),
1080 ignorePattern
: "!.hidden*",
1082 quotes
: [2, "single"]
1086 const report
= engine
.executeOnFiles(["hidden/"]);
1088 assert
.strictEqual(report
.results
.length
, 1);
1089 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1090 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1091 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1092 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1093 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1096 it("should report zero messages when given a pattern with a .js and a .js2 file", () => {
1098 engine
= new CLIEngine({
1099 extensions
: [".js", ".js2"],
1101 cwd
: path
.join(fixtureDir
, "..")
1104 const report
= engine
.executeOnFiles(["fixtures/files/*.?s*"]);
1106 assert
.strictEqual(report
.results
.length
, 2);
1107 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1108 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
1111 it("should return one error message when given a config with rules with options and severity level set to error", () => {
1113 engine
= new CLIEngine({
1114 cwd
: getFixturePath("configurations"),
1115 configFile
: getFixturePath("configurations", "quotes-error.json")
1117 const report
= engine
.executeOnFiles([getFixturePath("single-quoted.js")]);
1119 assert
.strictEqual(report
.results
.length
, 1);
1120 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1121 assert
.strictEqual(report
.errorCount
, 1);
1122 assert
.strictEqual(report
.warningCount
, 0);
1123 assert
.strictEqual(report
.fixableErrorCount
, 1);
1124 assert
.strictEqual(report
.fixableWarningCount
, 0);
1125 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1126 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1127 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1128 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1129 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1130 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1133 it("should return 3 messages when given a config file and a directory of 3 valid files", () => {
1135 engine
= new CLIEngine({
1136 cwd
: path
.join(fixtureDir
, ".."),
1137 configFile
: getFixturePath("configurations", "semi-error.json")
1140 const report
= engine
.executeOnFiles([getFixturePath("formatters")]);
1142 assert
.strictEqual(report
.results
.length
, 3);
1143 assert
.strictEqual(report
.errorCount
, 0);
1144 assert
.strictEqual(report
.warningCount
, 0);
1145 assert
.strictEqual(report
.fixableErrorCount
, 0);
1146 assert
.strictEqual(report
.fixableWarningCount
, 0);
1147 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1148 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
1149 assert
.strictEqual(report
.results
[2].messages
.length
, 0);
1150 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1151 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1152 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1153 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1154 assert
.strictEqual(report
.results
[1].errorCount
, 0);
1155 assert
.strictEqual(report
.results
[1].warningCount
, 0);
1156 assert
.strictEqual(report
.results
[1].fixableErrorCount
, 0);
1157 assert
.strictEqual(report
.results
[1].fixableWarningCount
, 0);
1158 assert
.strictEqual(report
.results
[2].errorCount
, 0);
1159 assert
.strictEqual(report
.results
[2].warningCount
, 0);
1160 assert
.strictEqual(report
.results
[2].fixableErrorCount
, 0);
1161 assert
.strictEqual(report
.results
[2].fixableWarningCount
, 0);
1165 it("should return the total number of errors when given multiple files", () => {
1167 engine
= new CLIEngine({
1168 cwd
: path
.join(fixtureDir
, ".."),
1169 configFile
: getFixturePath("configurations", "single-quotes-error.json")
1172 const report
= engine
.executeOnFiles([getFixturePath("formatters")]);
1174 assert
.strictEqual(report
.errorCount
, 6);
1175 assert
.strictEqual(report
.warningCount
, 0);
1176 assert
.strictEqual(report
.fixableErrorCount
, 6);
1177 assert
.strictEqual(report
.fixableWarningCount
, 0);
1178 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1179 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1180 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1181 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1182 assert
.strictEqual(report
.results
[1].errorCount
, 3);
1183 assert
.strictEqual(report
.results
[1].warningCount
, 0);
1184 assert
.strictEqual(report
.results
[1].fixableErrorCount
, 3);
1185 assert
.strictEqual(report
.results
[1].fixableWarningCount
, 0);
1186 assert
.strictEqual(report
.results
[2].errorCount
, 3);
1187 assert
.strictEqual(report
.results
[2].warningCount
, 0);
1188 assert
.strictEqual(report
.results
[2].fixableErrorCount
, 3);
1189 assert
.strictEqual(report
.results
[2].fixableWarningCount
, 0);
1192 it("should process when file is given by not specifying extensions", () => {
1194 engine
= new CLIEngine({
1196 cwd
: path
.join(fixtureDir
, "..")
1199 const report
= engine
.executeOnFiles(["fixtures/files/foo.js2"]);
1201 assert
.strictEqual(report
.results
.length
, 1);
1202 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1205 it("should return zero messages when given a config with environment set to browser", () => {
1207 engine
= new CLIEngine({
1208 cwd
: path
.join(fixtureDir
, ".."),
1209 configFile
: getFixturePath("configurations", "env-browser.json")
1212 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1214 assert
.strictEqual(report
.results
.length
, 1);
1215 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1218 it("should return zero messages when given an option to set environment to browser", () => {
1220 engine
= new CLIEngine({
1221 cwd
: path
.join(fixtureDir
, ".."),
1229 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1231 assert
.strictEqual(report
.results
.length
, 1);
1232 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1235 it("should return zero messages when given a config with environment set to Node.js", () => {
1237 engine
= new CLIEngine({
1238 cwd
: path
.join(fixtureDir
, ".."),
1239 configFile
: getFixturePath("configurations", "env-node.json")
1242 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-node.js"))]);
1244 assert
.strictEqual(report
.results
.length
, 1);
1245 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1248 it("should not return results from previous call when calling more than once", () => {
1250 engine
= new CLIEngine({
1251 cwd
: path
.join(fixtureDir
, ".."),
1258 const failFilePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1259 const passFilePath
= fs
.realpathSync(getFixturePath("passing.js"));
1261 let report
= engine
.executeOnFiles([failFilePath
]);
1263 assert
.strictEqual(report
.results
.length
, 1);
1264 assert
.strictEqual(report
.results
[0].filePath
, failFilePath
);
1265 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1266 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "semi");
1267 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1269 report
= engine
.executeOnFiles([passFilePath
]);
1270 assert
.strictEqual(report
.results
.length
, 1);
1271 assert
.strictEqual(report
.results
[0].filePath
, passFilePath
);
1272 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1276 it("should throw an error when given a directory with all eslint excluded files in the directory", () => {
1278 engine
= new CLIEngine({
1279 ignorePath
: getFixturePath(".eslintignore")
1282 assert
.throws(() => {
1283 engine
.executeOnFiles([getFixturePath("./cli-engine/")]);
1284 }, `All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`);
1287 it("should throw an error when all given files are ignored", () => {
1289 assert
.throws(() => {
1290 engine
.executeOnFiles(["tests/fixtures/cli-engine/"]);
1291 }, "All files matched by 'tests/fixtures/cli-engine/' are ignored.");
1294 it("should throw an error when all given files are ignored even with a `./` prefix", () => {
1295 engine
= new CLIEngine({
1296 ignorePath
: getFixturePath(".eslintignore")
1299 assert
.throws(() => {
1300 engine
.executeOnFiles(["./tests/fixtures/cli-engine/"]);
1301 }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
1304 // https://github.com/eslint/eslint/issues/3788
1305 it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", () => {
1306 engine
= new CLIEngine({
1307 ignorePath
: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
1310 quotes
: [2, "double"]
1312 cwd
: getFixturePath("cli-engine", "nested_node_modules")
1315 const report
= engine
.executeOnFiles(["."]);
1317 assert
.strictEqual(report
.results
.length
, 1);
1318 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1319 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1320 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1321 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1324 // https://github.com/eslint/eslint/issues/3812
1325 it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", () => {
1326 engine
= new CLIEngine({
1327 ignorePath
: getFixturePath("cli-engine/.eslintignore2"),
1330 quotes
: [2, "double"]
1334 assert
.throws(() => {
1335 engine
.executeOnFiles(["./tests/fixtures/cli-engine/"]);
1336 }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
1339 it("should throw an error when all given files are ignored via ignore-pattern", () => {
1340 engine
= new CLIEngine({
1341 ignorePattern
: "tests/fixtures/single-quoted.js"
1344 assert
.throws(() => {
1345 engine
.executeOnFiles(["tests/fixtures/*-quoted.js"]);
1346 }, "All files matched by 'tests/fixtures/*-quoted.js' are ignored.");
1349 it("should return a warning when an explicitly given file is ignored", () => {
1350 engine
= new CLIEngine({
1351 ignorePath
: getFixturePath(".eslintignore"),
1352 cwd
: getFixturePath()
1355 const filePath
= getFixturePath("passing.js");
1357 const report
= engine
.executeOnFiles([filePath
]);
1359 assert
.strictEqual(report
.results
.length
, 1);
1360 assert
.strictEqual(report
.errorCount
, 0);
1361 assert
.strictEqual(report
.warningCount
, 1);
1362 assert
.strictEqual(report
.fixableErrorCount
, 0);
1363 assert
.strictEqual(report
.fixableWarningCount
, 0);
1364 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1365 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1366 assert
.strictEqual(report
.results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
1367 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1368 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1369 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1370 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1373 it("should return two messages when given a file in excluded files list while ignore is off", () => {
1375 engine
= new CLIEngine({
1376 ignorePath
: getFixturePath(".eslintignore"),
1383 const filePath
= fs
.realpathSync(getFixturePath("undef.js"));
1385 const report
= engine
.executeOnFiles([filePath
]);
1387 assert
.strictEqual(report
.results
.length
, 1);
1388 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1389 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-undef");
1390 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1391 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-undef");
1392 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 2);
1395 it("should return zero messages when executing a file with a shebang", () => {
1397 engine
= new CLIEngine({
1401 const report
= engine
.executeOnFiles([getFixturePath("shebang.js")]);
1403 assert
.strictEqual(report
.results
.length
, 1);
1404 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1407 it("should give a warning when loading a custom rule that doesn't exist", () => {
1409 engine
= new CLIEngine({
1411 rulesPaths
: [getFixturePath("rules", "dir1")],
1412 configFile
: getFixturePath("rules", "missing-rule.json")
1414 const report
= engine
.executeOnFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1416 assert
.strictEqual(report
.results
.length
, 1);
1417 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1418 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "missing-rule");
1419 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1420 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Definition for rule 'missing-rule' was not found.");
1425 it("should throw an error when loading a bad custom rule", () => {
1427 engine
= new CLIEngine({
1429 rulePaths
: [getFixturePath("rules", "wrong")],
1430 configFile
: getFixturePath("rules", "eslint.json")
1434 assert
.throws(() => {
1435 engine
.executeOnFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1436 }, /Error while loading rule 'custom-rule'/u);
1439 it("should return one message when a custom rule matches a file", () => {
1441 engine
= new CLIEngine({
1444 rulePaths
: [getFixturePath("rules/")],
1445 configFile
: getFixturePath("rules", "eslint.json")
1448 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1450 const report
= engine
.executeOnFiles([filePath
]);
1452 assert
.strictEqual(report
.results
.length
, 1);
1453 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1454 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1455 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "custom-rule");
1456 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1459 it("should load custom rule from the provided cwd", () => {
1460 const cwd
= path
.resolve(getFixturePath("rules"));
1462 engine
= new CLIEngine({
1466 configFile
: "eslint.json"
1469 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1471 const report
= engine
.executeOnFiles([filePath
]);
1473 assert
.strictEqual(report
.results
.length
, 1);
1474 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1475 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1476 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "custom-rule");
1477 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1480 it("should return messages when multiple custom rules match a file", () => {
1482 engine
= new CLIEngine({
1485 getFixturePath("rules", "dir1"),
1486 getFixturePath("rules", "dir2")
1488 configFile
: getFixturePath("rules", "multi-rulesdirs.json")
1491 const filePath
= fs
.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.js"));
1493 const report
= engine
.executeOnFiles([filePath
]);
1495 assert
.strictEqual(report
.results
.length
, 1);
1496 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1497 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1498 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-literals");
1499 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1500 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-strings");
1501 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 2);
1504 it("should return zero messages when executing without useEslintrc flag", () => {
1506 engine
= new CLIEngine({
1511 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1513 const report
= engine
.executeOnFiles([filePath
]);
1515 assert
.strictEqual(report
.results
.length
, 1);
1516 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1517 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1520 it("should return zero messages when executing without useEslintrc flag in Node.js environment", () => {
1522 engine
= new CLIEngine({
1528 const filePath
= fs
.realpathSync(getFixturePath("process-exit.js"));
1530 const report
= engine
.executeOnFiles([filePath
]);
1532 assert
.strictEqual(report
.results
.length
, 1);
1533 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1534 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1537 it("should return zero messages when executing with base-config flag set to false", () => {
1539 engine
= new CLIEngine({
1545 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1547 const report
= engine
.executeOnFiles([filePath
]);
1549 assert
.strictEqual(report
.results
.length
, 1);
1550 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1551 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1554 it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", () => {
1556 engine
= new CLIEngine({
1562 const filePath
= fs
.realpathSync(getFixturePath("eslintrc", "quotes.js"));
1564 const report
= engine
.executeOnFiles([filePath
]);
1566 assert
.strictEqual(report
.results
.length
, 1);
1567 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1568 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1571 it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", () => {
1573 engine
= new CLIEngine({
1579 const filePath
= fs
.realpathSync(getFixturePath("packagejson", "quotes.js"));
1581 const report
= engine
.executeOnFiles([filePath
]);
1583 assert
.strictEqual(report
.results
.length
, 1);
1584 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1585 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1588 it("should warn when deprecated rules are configured", () => {
1589 engine
= new CLIEngine({
1591 configFile
: ".eslintrc.js",
1599 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1601 assert
.sameDeepMembers(
1602 report
.usedDeprecatedRules
,
1604 { ruleId
: "indent-legacy", replacedBy
: ["indent"] },
1605 { ruleId
: "require-jsdoc", replacedBy
: [] },
1606 { ruleId
: "valid-jsdoc", replacedBy
: [] }
1611 it("should not warn when deprecated rules are not configured", () => {
1612 engine
= new CLIEngine({
1614 configFile
: ".eslintrc.js",
1615 rules
: { indent
: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
1618 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1620 assert
.deepStrictEqual(report
.usedDeprecatedRules
, []);
1623 it("should warn when deprecated rules are found in a config", () => {
1624 engine
= new CLIEngine({
1626 configFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
1630 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1632 assert
.deepStrictEqual(
1633 report
.usedDeprecatedRules
,
1634 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
1638 describe("Fix Mode", () => {
1640 it("should return fixed text on multiple files when in fix mode", () => {
1643 * Converts CRLF to LF in output.
1644 * This is a workaround for git's autocrlf option on Windows.
1645 * @param {Object} result A result object to convert.
1648 function convertCRLF(result
) {
1649 if (result
&& result
.output
) {
1650 result
.output
= result
.output
.replace(/\r\n/gu, "\n");
1654 engine
= new CLIEngine({
1655 cwd
: path
.join(fixtureDir
, ".."),
1660 quotes
: [2, "double"],
1663 "space-infix-ops": 2
1667 const report
= engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1669 report
.results
.forEach(convertCRLF
);
1670 assert
.deepStrictEqual(report
.results
, [
1672 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/multipass.js")),
1676 fixableErrorCount
: 0,
1677 fixableWarningCount
: 0,
1678 output
: "true ? \"yes\" : \"no\";\n"
1681 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/ok.js")),
1685 fixableErrorCount
: 0,
1686 fixableWarningCount
: 0
1689 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes-semi-eqeqeq.js")),
1696 message
: "Expected '===' and instead saw '=='.",
1697 messageId
: "unexpected",
1698 nodeType
: "BinaryExpression",
1705 fixableErrorCount
: 0,
1706 fixableWarningCount
: 0,
1707 output
: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n"
1710 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes.js")),
1718 message
: "'foo' is not defined.",
1719 nodeType
: "Identifier",
1726 fixableErrorCount
: 0,
1727 fixableWarningCount
: 0,
1728 output
: "var msg = \"hi\" + foo;\n"
1731 assert
.strictEqual(report
.errorCount
, 2);
1732 assert
.strictEqual(report
.warningCount
, 0);
1733 assert
.strictEqual(report
.fixableErrorCount
, 0);
1734 assert
.strictEqual(report
.fixableWarningCount
, 0);
1737 it("should run autofix even if files are cached without autofix results", () => {
1738 const baseOptions
= {
1739 cwd
: path
.join(fixtureDir
, ".."),
1743 quotes
: [2, "double"],
1746 "space-infix-ops": 2
1750 engine
= new CLIEngine(Object
.assign({}, baseOptions
, { cache
: true, fix
: false }));
1752 // Do initial lint run and populate the cache file
1753 engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1755 engine
= new CLIEngine(Object
.assign({}, baseOptions
, { cache
: true, fix
: true }));
1757 const report
= engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1759 assert
.ok(report
.results
.some(result
=> result
.output
));
1764 // These tests have to do with https://github.com/eslint/eslint/issues/963
1766 describe("configuration hierarchy", () => {
1768 // Default configuration - blank
1769 it("should return zero messages when executing with no .eslintrc", () => {
1771 engine
= new CLIEngine({
1772 cwd
: path
.join(fixtureDir
, ".."),
1776 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1778 assert
.strictEqual(report
.results
.length
, 1);
1779 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1782 // No default configuration rules - conf/environments.js (/*eslint-env node*/)
1783 it("should return zero messages when executing with no .eslintrc in the Node.js environment", () => {
1785 engine
= new CLIEngine({
1786 cwd
: path
.join(fixtureDir
, ".."),
1791 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
1793 assert
.strictEqual(report
.results
.length
, 1);
1794 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1797 // Project configuration - first level .eslintrc
1798 it("should return zero messages when executing with .eslintrc in the Node.js environment", () => {
1800 engine
= new CLIEngine({
1801 cwd
: path
.join(fixtureDir
, "..")
1804 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1806 assert
.strictEqual(report
.results
.length
, 1);
1807 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1810 // Project configuration - first level .eslintrc
1811 it("should return zero messages when executing with .eslintrc in the Node.js environment", () => {
1813 engine
= new CLIEngine({
1814 cwd
: path
.join(fixtureDir
, "..")
1817 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1819 assert
.strictEqual(report
.results
.length
, 1);
1820 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1823 // Project configuration - first level .eslintrc
1824 it("should return one message when executing with .eslintrc", () => {
1826 engine
= new CLIEngine({
1827 cwd
: path
.join(fixtureDir
, "..")
1830 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1832 assert
.strictEqual(report
.results
.length
, 1);
1833 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1834 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1835 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1838 // Project configuration - second level .eslintrc
1839 it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", () => {
1841 engine
= new CLIEngine({
1842 cwd
: path
.join(fixtureDir
, "..")
1845 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1847 assert
.strictEqual(report
.results
.length
, 1);
1848 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1849 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1850 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1853 // Project configuration - third level .eslintrc
1854 it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", () => {
1856 engine
= new CLIEngine({
1857 cwd
: path
.join(fixtureDir
, "..")
1860 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
1862 assert
.strictEqual(report
.results
.length
, 1);
1863 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1864 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1865 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1868 // Project configuration - first level package.json
1869 it("should return one message when executing with package.json", () => {
1871 engine
= new CLIEngine({
1872 cwd
: path
.join(fixtureDir
, "..")
1875 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
1877 assert
.strictEqual(report
.results
.length
, 1);
1878 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1879 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1880 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1883 // Project configuration - second level package.json
1884 it("should return zero messages when executing with local package.json that overrides parent package.json", () => {
1886 engine
= new CLIEngine({
1887 cwd
: path
.join(fixtureDir
, "..")
1890 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
1892 assert
.strictEqual(report
.results
.length
, 1);
1893 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1896 // Project configuration - third level package.json
1897 it("should return one message when executing with local package.json that overrides parent and grandparent package.json", () => {
1899 engine
= new CLIEngine({
1900 cwd
: path
.join(fixtureDir
, "..")
1903 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
1905 assert
.strictEqual(report
.results
.length
, 1);
1906 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1907 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1908 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1911 // Project configuration - .eslintrc overrides package.json in same directory
1912 it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", () => {
1914 engine
= new CLIEngine({
1915 cwd
: path
.join(fixtureDir
, "..")
1918 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
1920 assert
.strictEqual(report
.results
.length
, 1);
1921 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1922 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1923 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1926 // Command line configuration - --config with first level .eslintrc
1927 it("should return two messages when executing with config file that adds to local .eslintrc", () => {
1929 engine
= new CLIEngine({
1930 cwd
: path
.join(fixtureDir
, ".."),
1931 configFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1934 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1936 assert
.strictEqual(report
.results
.length
, 1);
1937 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1938 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1939 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1940 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "semi");
1941 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 1);
1944 // Command line configuration - --config with first level .eslintrc
1945 it("should return no messages when executing with config file that overrides local .eslintrc", () => {
1947 engine
= new CLIEngine({
1948 cwd
: path
.join(fixtureDir
, ".."),
1949 configFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1952 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1954 assert
.strictEqual(report
.results
.length
, 1);
1955 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1958 // Command line configuration - --config with second level .eslintrc
1959 it("should return two messages when executing with config file that adds to local and parent .eslintrc", () => {
1961 engine
= new CLIEngine({
1962 cwd
: path
.join(fixtureDir
, ".."),
1963 configFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1966 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1968 assert
.strictEqual(report
.results
.length
, 1);
1969 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1970 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1971 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1972 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "semi");
1973 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 1);
1976 // Command line configuration - --config with second level .eslintrc
1977 it("should return one message when executing with config file that overrides local and parent .eslintrc", () => {
1979 engine
= new CLIEngine({
1980 cwd
: path
.join(fixtureDir
, ".."),
1981 configFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml")
1984 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1986 assert
.strictEqual(report
.results
.length
, 1);
1987 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1988 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1989 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1992 // Command line configuration - --config with first level .eslintrc
1993 it("should return no messages when executing with config file that overrides local .eslintrc", () => {
1995 engine
= new CLIEngine({
1996 cwd
: path
.join(fixtureDir
, ".."),
1997 configFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
2000 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2002 assert
.strictEqual(report
.results
.length
, 1);
2003 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
2006 // Command line configuration - --rule with --config and first level .eslintrc
2007 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", () => {
2009 engine
= new CLIEngine({
2010 cwd
: path
.join(fixtureDir
, ".."),
2011 configFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
2013 quotes
: [1, "double"]
2017 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2019 assert
.strictEqual(report
.results
.length
, 1);
2020 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2021 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2022 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2025 // Command line configuration - --rule with --config and first level .eslintrc
2026 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", () => {
2028 engine
= new CLIEngine({
2029 cwd
: path
.join(fixtureDir
, ".."),
2030 configFile
: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
2032 quotes
: [1, "double"]
2036 const report
= engine
.executeOnFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
2038 assert
.strictEqual(report
.results
.length
, 1);
2039 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2040 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2041 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2046 describe("plugins", () => {
2047 it("should return two messages when executing with config file that specifies a plugin", () => {
2048 engine
= cliEngineWithPlugins({
2049 cwd
: path
.join(fixtureDir
, ".."),
2050 configFile
: getFixturePath("configurations", "plugins-with-prefix.json"),
2054 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
2056 assert
.strictEqual(report
.results
.length
, 1);
2057 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2058 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2061 it("should return two messages when executing with config file that specifies a plugin with namespace", () => {
2062 engine
= cliEngineWithPlugins({
2063 cwd
: path
.join(fixtureDir
, ".."),
2064 configFile
: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
2068 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2070 assert
.strictEqual(report
.results
.length
, 1);
2071 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2072 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2075 it("should return two messages when executing with config file that specifies a plugin without prefix", () => {
2076 engine
= cliEngineWithPlugins({
2077 cwd
: path
.join(fixtureDir
, ".."),
2078 configFile
: getFixturePath("configurations", "plugins-without-prefix.json"),
2082 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2084 assert
.strictEqual(report
.results
.length
, 1);
2085 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2086 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2089 it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", () => {
2090 engine
= cliEngineWithPlugins({
2091 cwd
: path
.join(fixtureDir
, ".."),
2092 configFile
: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
2096 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2098 assert
.strictEqual(report
.results
.length
, 1);
2099 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2100 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2103 it("should return two messages when executing with cli option that specifies a plugin", () => {
2104 engine
= cliEngineWithPlugins({
2105 cwd
: path
.join(fixtureDir
, ".."),
2107 plugins
: ["example"],
2108 rules
: { "example/example-rule": 1 }
2111 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2113 assert
.strictEqual(report
.results
.length
, 1);
2114 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2115 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2118 it("should return two messages when executing with cli option that specifies preloaded plugin", () => {
2119 engine
= new CLIEngine({
2120 cwd
: path
.join(fixtureDir
, ".."),
2123 rules
: { "test/example-rule": 1 }
2126 engine
.addPlugin("eslint-plugin-test", { rules
: { "example-rule": require("../../fixtures/rules/custom-rule") } });
2128 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2130 assert
.strictEqual(report
.results
.length
, 1);
2131 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2132 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "test/example-rule");
2135 it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", () => {
2136 engine
= new CLIEngine({
2137 resolvePluginsRelativeTo
: getFixturePath("plugins"),
2139 plugins
: ["with-rules"],
2140 rules
: { "with-rules/rule1": "error" }
2145 const report
= engine
.executeOnText("foo");
2147 assert
.strictEqual(report
.results
.length
, 1);
2148 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2149 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "with-rules/rule1");
2150 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Rule report from plugin");
2154 describe("cache", () => {
2157 * helper method to delete a file without caring about exceptions
2158 * @param {string} filePath The file path
2161 function doDelete(filePath
) {
2163 fs
.unlinkSync(filePath
);
2167 * we don't care if the file didn't exist, since our
2168 * intention was to remove the file
2174 * helper method to delete the cache files created during testing
2177 function deleteCache() {
2178 doDelete(path
.resolve(".eslintcache"));
2179 doDelete(path
.resolve(".cache/custom-cache"));
2191 describe("when the cacheFile is a directory or looks like a directory", () => {
2194 * helper method to delete the cache files created during testing
2197 function deleteCacheDir() {
2199 fs
.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
2203 * we don't care if the file didn't exist, since our
2204 * intention was to remove the file
2216 it("should create the cache file inside the provided directory", () => {
2217 assert
.isFalse(shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2219 engine
= new CLIEngine({
2222 // specifying cache true the cache will be created
2224 cacheFile
: "./tmp/.cacheFileDir/",
2233 const file
= getFixturePath("cache/src", "test-file.js");
2235 engine
.executeOnFiles([file
]);
2237 assert
.isTrue(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2243 it("should create the cache file inside the provided directory using the cacheLocation option", () => {
2244 assert
.isFalse(shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2246 engine
= new CLIEngine({
2249 // specifying cache true the cache will be created
2251 cacheLocation
: "./tmp/.cacheFileDir/",
2260 const file
= getFixturePath("cache/src", "test-file.js");
2262 engine
.executeOnFiles([file
]);
2264 assert
.isTrue(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2269 it("should create the cache file inside cwd when no cacheLocation provided", () => {
2270 const cwd
= path
.resolve(getFixturePath("cli-engine"));
2272 engine
= new CLIEngine({
2283 const file
= getFixturePath("cli-engine", "console.js");
2285 engine
.executeOnFiles([file
]);
2287 assert
.isTrue(shell
.test("-f", path
.resolve(cwd
, ".eslintcache")), "the cache for eslint was created at provided cwd");
2290 it("should invalidate the cache if the configuration changed between executions", () => {
2291 assert
.isFalse(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2293 engine
= new CLIEngine({
2296 // specifying cache true the cache will be created
2306 let spy
= sinon
.spy(fs
, "readFileSync");
2308 let file
= getFixturePath("cache/src", "test-file.js");
2310 file
= fs
.realpathSync(file
);
2312 const result
= engine
.executeOnFiles([file
]);
2314 assert
.strictEqual(result
.errorCount
+ result
.warningCount
, 0, "the file passed without errors or warnings");
2315 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2316 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2321 engine
= new CLIEngine({
2324 // specifying cache true the cache will be created
2335 spy
= sinon
.spy(fs
, "readFileSync");
2337 const cachedResult
= engine
.executeOnFiles([file
]);
2339 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed because the config changed");
2340 assert
.strictEqual(cachedResult
.errorCount
, 1, "since configuration changed the cache was not used an one error was reported");
2341 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2344 it("should remember the files from a previous run and do not operate on them if not changed", () => {
2346 assert
.isFalse(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2348 engine
= new CLIEngine({
2351 // specifying cache true the cache will be created
2361 let spy
= sinon
.spy(fs
, "readFileSync");
2363 let file
= getFixturePath("cache/src", "test-file.js");
2365 file
= fs
.realpathSync(file
);
2367 const result
= engine
.executeOnFiles([file
]);
2369 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2370 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2375 engine
= new CLIEngine({
2378 // specifying cache true the cache will be created
2389 spy
= sinon
.spy(fs
, "readFileSync");
2391 const cachedResult
= engine
.executeOnFiles([file
]);
2393 assert
.deepStrictEqual(result
, cachedResult
, "the result is the same regardless of using cache or not");
2395 // assert the file was not processed because the cache was used
2396 assert
.isFalse(spy
.calledWith(file
), "the file was not loaded because it used the cache");
2399 it("should remember the files from a previous run and do not operate on then if not changed", () => {
2401 const cacheFile
= getFixturePath(".eslintcache");
2402 const cliEngineOptions
= {
2405 // specifying cache true the cache will be created
2413 cwd
: path
.join(fixtureDir
, "..")
2416 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint does not exist");
2418 engine
= new CLIEngine(cliEngineOptions
);
2420 let file
= getFixturePath("cache/src", "test-file.js");
2422 file
= fs
.realpathSync(file
);
2424 engine
.executeOnFiles([file
]);
2426 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint was created");
2428 cliEngineOptions
.cache
= false;
2429 engine
= new CLIEngine(cliEngineOptions
);
2431 engine
.executeOnFiles([file
]);
2433 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint was deleted since last run did not used the cache");
2436 it("should store in the cache a file that failed the test", () => {
2438 const cacheFile
= getFixturePath(".eslintcache");
2440 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint does not exist");
2442 engine
= new CLIEngine({
2443 cwd
: path
.join(fixtureDir
, ".."),
2446 // specifying cache true the cache will be created
2456 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2457 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2459 const result
= engine
.executeOnFiles([badFile
, goodFile
]);
2461 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint was created");
2463 const fileCache
= fCache
.createFromFile(cacheFile
);
2464 const { cache
} = fileCache
;
2466 assert
.isTrue(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2468 assert
.isTrue(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2470 const cachedResult
= engine
.executeOnFiles([badFile
, goodFile
]);
2472 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2475 it("should not contain in the cache a file that was deleted", () => {
2477 const cacheFile
= getFixturePath(".eslintcache");
2479 doDelete(cacheFile
);
2481 engine
= new CLIEngine({
2482 cwd
: path
.join(fixtureDir
, ".."),
2485 // specifying cache true the cache will be created
2495 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2496 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2497 const toBeDeletedFile
= fs
.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
2499 engine
.executeOnFiles([badFile
, goodFile
, toBeDeletedFile
]);
2501 const fileCache
= fCache
.createFromFile(cacheFile
);
2502 let { cache
} = fileCache
;
2504 assert
.isTrue(typeof cache
.getKey(toBeDeletedFile
) === "object", "the entry for the file to be deleted is in the cache");
2506 // delete the file from the file system
2507 fs
.unlinkSync(toBeDeletedFile
);
2510 * file-entry-cache@2.0.0 will remove from the cache deleted files
2511 * even when they were not part of the array of files to be analyzed
2513 engine
.executeOnFiles([badFile
, goodFile
]);
2515 cache
= JSON
.parse(fs
.readFileSync(cacheFile
));
2517 assert
.isTrue(typeof cache
[toBeDeletedFile
] === "undefined", "the entry for the file to be deleted is not in the cache");
2520 it("should contain files that were not visited in the cache provided they still exist", () => {
2522 const cacheFile
= getFixturePath(".eslintcache");
2524 doDelete(cacheFile
);
2526 engine
= new CLIEngine({
2527 cwd
: path
.join(fixtureDir
, ".."),
2530 // specifying cache true the cache will be created
2540 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2541 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2542 const testFile2
= fs
.realpathSync(getFixturePath("cache/src", "test-file2.js"));
2544 engine
.executeOnFiles([badFile
, goodFile
, testFile2
]);
2546 let fileCache
= fCache
.createFromFile(cacheFile
);
2547 let { cache
} = fileCache
;
2549 assert
.isTrue(typeof cache
.getKey(testFile2
) === "object", "the entry for the test-file2 is in the cache");
2552 * we pass a different set of files minus test-file2
2553 * previous version of file-entry-cache would remove the non visited
2554 * entries. 2.0.0 version will keep them unless they don't exist
2556 engine
.executeOnFiles([badFile
, goodFile
]);
2558 fileCache
= fCache
.createFromFile(cacheFile
);
2559 cache
= fileCache
.cache
;
2561 assert
.isTrue(typeof cache
.getKey(testFile2
) === "object", "the entry for the test-file2 is in the cache");
2564 it("should not delete cache when executing on text", () => {
2565 const cacheFile
= getFixturePath(".eslintcache");
2567 engine
= new CLIEngine({
2568 cwd
: path
.join(fixtureDir
, ".."),
2578 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2580 engine
.executeOnText("var foo = 'bar';");
2582 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2585 it("should not delete cache when executing on text with a provided filename", () => {
2586 const cacheFile
= getFixturePath(".eslintcache");
2588 engine
= new CLIEngine({
2589 cwd
: path
.join(fixtureDir
, ".."),
2599 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2601 engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
2603 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2606 it("should not delete cache when executing on files with --cache flag", () => {
2607 const cacheFile
= getFixturePath(".eslintcache");
2609 engine
= new CLIEngine({
2610 cwd
: path
.join(fixtureDir
, ".."),
2621 const file
= getFixturePath("cli-engine", "console.js");
2623 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2625 engine
.executeOnFiles([file
]);
2627 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2630 it("should delete cache when executing on files without --cache flag", () => {
2631 const cacheFile
= getFixturePath(".eslintcache");
2633 engine
= new CLIEngine({
2634 cwd
: path
.join(fixtureDir
, ".."),
2644 const file
= getFixturePath("cli-engine", "console.js");
2646 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2648 engine
.executeOnFiles([file
]);
2650 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint has been deleted");
2653 describe("cacheFile", () => {
2654 it("should use the specified cache file", () => {
2655 const customCacheFile
= path
.resolve(".cache/custom-cache");
2657 assert
.isFalse(shell
.test("-f", customCacheFile
), "the cache for eslint does not exist");
2659 engine
= new CLIEngine({
2662 // specify a custom cache file
2663 cacheFile
: customCacheFile
,
2665 // specifying cache true the cache will be created
2672 cwd
: path
.join(fixtureDir
, "..")
2675 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2676 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2678 const result
= engine
.executeOnFiles([badFile
, goodFile
]);
2680 assert
.isTrue(shell
.test("-f", customCacheFile
), "the cache for eslint was created");
2682 const fileCache
= fCache
.createFromFile(customCacheFile
);
2683 const { cache
} = fileCache
;
2685 assert
.isTrue(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2687 assert
.isTrue(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2689 const cachedResult
= engine
.executeOnFiles([badFile
, goodFile
]);
2691 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2696 describe("processors", () => {
2697 it("should return two messages when executing with config file that specifies a processor", () => {
2698 engine
= cliEngineWithPlugins({
2699 configFile
: getFixturePath("configurations", "processors.json"),
2701 extensions
: ["js", "txt"],
2702 cwd
: path
.join(fixtureDir
, "..")
2705 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2707 assert
.strictEqual(report
.results
.length
, 1);
2708 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2710 it("should return two messages when executing with config file that specifies preloaded processor", () => {
2711 engine
= new CLIEngine({
2713 plugins
: ["test-processor"],
2718 extensions
: ["js", "txt"],
2719 cwd
: path
.join(fixtureDir
, "..")
2722 engine
.addPlugin("test-processor", {
2728 postprocess(messages
) {
2735 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2737 assert
.strictEqual(report
.results
.length
, 1);
2738 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2740 it("should run processors when calling executeOnFiles with config file that specifies a processor", () => {
2741 engine
= cliEngineWithPlugins({
2742 configFile
: getFixturePath("configurations", "processors.json"),
2744 extensions
: ["js", "txt"],
2745 cwd
: path
.join(fixtureDir
, "..")
2748 const report
= engine
.executeOnFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2750 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2751 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2753 it("should run processors when calling executeOnFiles with config file that specifies preloaded processor", () => {
2754 engine
= new CLIEngine({
2756 plugins
: ["test-processor"],
2761 extensions
: ["js", "txt"],
2762 cwd
: path
.join(fixtureDir
, "..")
2765 engine
.addPlugin("test-processor", {
2769 return [text
.replace("a()", "b()")];
2771 postprocess(messages
) {
2772 messages
[0][0].ruleId
= "post-processed";
2779 const report
= engine
.executeOnFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2781 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2782 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2784 it("should run processors when calling executeOnText with config file that specifies a processor", () => {
2785 engine
= cliEngineWithPlugins({
2786 configFile
: getFixturePath("configurations", "processors.json"),
2788 extensions
: ["js", "txt"],
2792 const report
= engine
.executeOnText("function a() {console.log(\"Test\");}", "tests/fixtures/processors/test/test-processor.txt");
2794 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2795 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2797 it("should run processors when calling executeOnText with config file that specifies preloaded processor", () => {
2798 engine
= new CLIEngine({
2800 plugins
: ["test-processor"],
2805 extensions
: ["js", "txt"],
2809 engine
.addPlugin("test-processor", {
2813 return [text
.replace("a()", "b()")];
2815 postprocess(messages
) {
2816 messages
[0][0].ruleId
= "post-processed";
2823 const report
= engine
.executeOnText("function a() {console.log(\"Test\");}", "tests/fixtures/processors/test/test-processor.txt");
2825 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
2826 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
2829 describe("autofixing with processors", () => {
2830 const HTML_PROCESSOR
= Object
.freeze({
2832 return [text
.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
2834 postprocess(problemLists
) {
2835 return problemLists
[0].map(problem
=> {
2837 const updatedFix
= Object
.assign({}, problem
.fix
, {
2838 range
: problem
.fix
.range
.map(index
=> index
+ "<script>".length
)
2841 return Object
.assign({}, problem
, { fix
: updatedFix
});
2849 it("should run in autofix mode when using a processor that supports autofixing", () => {
2850 engine
= new CLIEngine({
2852 plugins
: ["test-processor"],
2856 extensions
: ["js", "txt"],
2861 engine
.addPlugin("test-processor", {
2863 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2867 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2869 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
2870 assert
.strictEqual(report
.results
[0].output
, "<script>foo;</script>");
2873 it("should not run in autofix mode when using a processor that does not support autofixing", () => {
2874 engine
= new CLIEngine({
2876 plugins
: ["test-processor"],
2880 extensions
: ["js", "txt"],
2885 engine
.addPlugin("test-processor", { processors
: { ".html": HTML_PROCESSOR
} });
2887 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2889 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2890 assert
.isFalse(Object
.prototype.hasOwnProperty
.call(report
.results
[0], "output"));
2893 it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", () => {
2894 engine
= new CLIEngine({
2896 plugins
: ["test-processor"],
2900 extensions
: ["js", "txt"],
2904 engine
.addPlugin("test-processor", {
2906 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2910 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
2912 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2913 assert
.isFalse(Object
.prototype.hasOwnProperty
.call(report
.results
[0], "output"));
2918 describe("Patterns which match no file should throw errors.", () => {
2920 engine
= new CLIEngine({
2921 cwd
: getFixturePath("cli-engine"),
2926 it("one file", () => {
2927 assert
.throws(() => {
2928 engine
.executeOnFiles(["non-exist.js"]);
2929 }, "No files matching 'non-exist.js' were found.");
2932 it("should throw if the directory exists and is empty", () => {
2933 assert
.throws(() => {
2934 engine
.executeOnFiles(["empty"]);
2935 }, "No files matching 'empty' were found.");
2938 it("one glob pattern", () => {
2939 assert
.throws(() => {
2940 engine
.executeOnFiles(["non-exist/**/*.js"]);
2941 }, "No files matching 'non-exist/**/*.js' were found.");
2944 it("two files", () => {
2945 assert
.throws(() => {
2946 engine
.executeOnFiles(["aaa.js", "bbb.js"]);
2947 }, "No files matching 'aaa.js' were found.");
2950 it("a mix of an existing file and a non-existing file", () => {
2951 assert
.throws(() => {
2952 engine
.executeOnFiles(["console.js", "non-exist.js"]);
2953 }, "No files matching 'non-exist.js' were found.");
2957 describe("overrides", () => {
2959 engine
= new CLIEngine({
2960 cwd
: getFixturePath("cli-engine/overrides-with-dot"),
2965 it("should recognize dotfiles", () => {
2966 const ret
= engine
.executeOnFiles([".test-target.js"]);
2968 assert
.strictEqual(ret
.results
.length
, 1);
2969 assert
.strictEqual(ret
.results
[0].messages
.length
, 1);
2970 assert
.strictEqual(ret
.results
[0].messages
[0].ruleId
, "no-unused-vars");
2974 describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
2976 ({ CLIEngine
} = defineCLIEngineWithInMemoryFileSystem({
2977 cwd
: () => path
.join(os
.tmpdir(), "cli-engine/11510"),
2979 "no-console-error-in-overrides.json": JSON
.stringify({
2982 rules
: { "no-console": "error" }
2985 ".eslintrc.json": JSON
.stringify({
2986 extends: "./no-console-error-in-overrides.json",
2987 rules
: { "no-console": "off" }
2989 "a.js": "console.log();"
2992 engine
= new CLIEngine();
2995 it("should not report 'no-console' error.", () => {
2996 const { results
} = engine
.executeOnFiles("a.js");
2998 assert
.strictEqual(results
.length
, 1);
2999 assert
.deepStrictEqual(results
[0].messages
, []);
3003 describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
3005 ({ CLIEngine
} = defineCLIEngineWithInMemoryFileSystem({
3006 cwd
: () => path
.join(os
.tmpdir(), "cli-engine/11559"),
3008 "node_modules/eslint-plugin-test/index.js": `
3010 recommended: { plugins: ["test"] }
3014 meta: { schema: [{ type: "number" }] },
3015 create() { return {}; }
3019 ".eslintrc.json": JSON
.stringify({
3021 // Import via the recommended config.
3022 extends: "plugin:test/recommended",
3024 // Has invalid option.
3025 rules
: { "test/foo": ["error", "invalid-option"] }
3027 "a.js": "console.log();"
3030 engine
= new CLIEngine();
3033 it("should throw fatal error.", () => {
3034 assert
.throws(() => {
3035 engine
.executeOnFiles("a.js");
3036 }, /invalid-option/u);
3040 describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
3042 ({ CLIEngine
} = defineCLIEngineWithInMemoryFileSystem({
3043 cwd
: () => path
.join(os
.tmpdir(), "cli-engine/11586"),
3045 "node_modules/eslint-plugin-test/index.js": `
3048 meta: { type: "problem", fixable: "code" },
3052 if (node.name === "example") {
3056 fix: fixer => fixer.replaceText(node, "fixed")
3065 ".eslintrc.json": JSON
.stringify({
3067 rules
: { "test/no-example": "error" }
3072 engine
= new CLIEngine({ fix
: true, fixTypes
: ["problem"] });
3075 it("should not crash.", () => {
3076 const { results
} = engine
.executeOnFiles("a.js");
3078 assert
.strictEqual(results
.length
, 1);
3079 assert
.deepStrictEqual(results
[0].messages
, []);
3080 assert
.deepStrictEqual(results
[0].output
, "fixed;");
3084 describe("multiple processors", () => {
3085 const root
= path
.join(os
.tmpdir(), "eslint/cli-engine/multiple-processors");
3086 const commonFiles
= {
3087 "node_modules/pattern-processor/index.js": fs
.readFileSync(
3088 require
.resolve("../../fixtures/processors/pattern-processor"),
3091 "node_modules/eslint-plugin-markdown/index.js": `
3092 const { defineProcessor } = require("pattern-processor");
3093 const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
3094 exports.processors = {
3095 ".md": { ...processor, supportsAutofix: true },
3096 "non-fixable": processor
3099 "node_modules/eslint-plugin-html/index.js": `
3100 const { defineProcessor } = require("pattern-processor");
3101 const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
3102 const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
3103 exports.processors = {
3104 ".html": { ...processor, supportsAutofix: true },
3105 "non-fixable": processor,
3106 "legacy": legacyProcessor
3109 "test.md": unIndent
`
3111 console
.log("hello")
3116 console
.log("hello")
3119 console
.log("hello")
3125 it("should lint only JavaScript blocks if '--ext' was not given.", () => {
3126 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3130 ".eslintrc.json": JSON
.stringify({
3131 plugins
: ["markdown", "html"],
3132 rules
: { semi
: "error" }
3136 engine
= new CLIEngine({ cwd
: root
});
3138 const { results
} = engine
.executeOnFiles(["test.md"]);
3140 assert
.strictEqual(results
.length
, 1);
3141 assert
.strictEqual(results
[0].messages
.length
, 1);
3142 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3143 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3146 it("should fix only JavaScript blocks if '--ext' was not given.", () => {
3147 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3151 ".eslintrc.json": JSON
.stringify({
3152 plugins
: ["markdown", "html"],
3153 rules
: { semi
: "error" }
3157 engine
= new CLIEngine({ cwd
: root
, fix
: true });
3159 const { results
} = engine
.executeOnFiles(["test.md"]);
3161 assert
.strictEqual(results
.length
, 1);
3162 assert
.strictEqual(results
[0].messages
.length
, 0);
3163 assert
.strictEqual(results
[0].output
, unIndent
`
3165 console
.log("hello");${/* ← fixed */""}
3170 console
.log("hello")${/* ← ignored */""}
3173 console
.log("hello")${/* ← ignored */""}
3179 it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", () => {
3180 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3184 ".eslintrc.json": JSON
.stringify({
3185 plugins
: ["markdown", "html"],
3186 rules
: { semi
: "error" }
3190 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"] });
3192 const { results
} = engine
.executeOnFiles(["test.md"]);
3194 assert
.strictEqual(results
.length
, 1);
3195 assert
.strictEqual(results
[0].messages
.length
, 2);
3196 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3197 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3198 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3199 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3202 it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", () => {
3203 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3207 ".eslintrc.json": JSON
.stringify({
3208 plugins
: ["markdown", "html"],
3209 rules
: { semi
: "error" }
3213 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"], fix
: true });
3215 const { results
} = engine
.executeOnFiles(["test.md"]);
3217 assert
.strictEqual(results
.length
, 1);
3218 assert
.strictEqual(results
[0].messages
.length
, 0);
3219 assert
.strictEqual(results
[0].output
, unIndent
`
3221 console
.log("hello");${/* ← fixed */""}
3226 console
.log("hello");${/* ← fixed */""}
3229 console
.log("hello")${/* ← ignored */""}
3235 it("should use overridden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", () => {
3236 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3240 ".eslintrc.json": JSON
.stringify({
3241 plugins
: ["markdown", "html"],
3242 rules
: { semi
: "error" },
3246 processor
: "html/non-fixable" // supportsAutofix: false
3252 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"], fix
: true });
3254 const { results
} = engine
.executeOnFiles(["test.md"]);
3256 assert
.strictEqual(results
.length
, 1);
3257 assert
.strictEqual(results
[0].messages
.length
, 1);
3258 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS Block in HTML Block
3259 assert
.strictEqual(results
[0].messages
[0].line
, 7);
3260 assert
.strictEqual(results
[0].messages
[0].fix
, void 0);
3261 assert
.strictEqual(results
[0].output
, unIndent
`
3263 console
.log("hello");${/* ← fixed */""}
3268 console
.log("hello")${/* ← reported but not fixed */""}
3271 console
.log("hello")
3277 it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", () => {
3278 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3282 ".eslintrc.json": JSON
.stringify({
3283 plugins
: ["markdown", "html"],
3284 rules
: { semi
: "error" },
3289 // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
3296 files
: "**/*.html/*.js",
3299 "no-console": "error"
3306 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"] });
3308 const { results
} = engine
.executeOnFiles(["test.md"]);
3310 assert
.strictEqual(results
.length
, 1);
3311 assert
.strictEqual(results
[0].messages
.length
, 2);
3312 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3313 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3314 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3315 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3318 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.", () => {
3319 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3323 ".eslintrc.json": JSON
.stringify({
3324 plugins
: ["markdown", "html"],
3325 rules
: { semi
: "error" },
3329 processor
: "html/legacy", // this processor returns strings rather than `{text, filename}`
3332 "no-console": "error"
3336 files
: "**/*.html/*.js",
3346 engine
= new CLIEngine({ cwd
: root
, extensions
: ["js", "html"] });
3348 const { results
} = engine
.executeOnFiles(["test.md"]);
3350 assert
.strictEqual(results
.length
, 1);
3351 assert
.strictEqual(results
[0].messages
.length
, 3);
3352 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3353 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3354 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3355 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3356 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-console");
3357 assert
.strictEqual(results
[0].messages
[2].line
, 10);
3360 it("should throw an error if invalid processor was specified.", () => {
3361 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3365 ".eslintrc.json": JSON
.stringify({
3366 plugins
: ["markdown", "html"],
3367 processor
: "markdown/unknown"
3371 engine
= new CLIEngine({ cwd
: root
});
3373 assert
.throws(() => {
3374 engine
.executeOnFiles(["test.md"]);
3375 }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
3378 it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", () => {
3379 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3383 ".eslintrc.json": JSON
.stringify({
3384 plugins
: ["markdown", "html"],
3385 rules
: { semi
: "error" },
3389 processor
: "html/.html"
3393 processor
: "markdown/.md"
3399 engine
= new CLIEngine({ cwd
: root
});
3401 const { results
} = engine
.executeOnFiles(["test.md"]);
3403 assert
.strictEqual(results
.length
, 1);
3404 assert
.strictEqual(results
[0].messages
.length
, 2);
3405 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3406 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3407 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3408 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3412 describe("MODULE_NOT_FOUND error handling", () => {
3413 const cwd
= getFixturePath("module-not-found");
3416 engine
= new CLIEngine({ cwd
});
3419 it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", () => {
3421 engine
.executeOnText("test", "extends-js/test.js");
3423 assert
.strictEqual(err
.messageTemplate
, "extend-config-missing");
3424 assert
.deepStrictEqual(err
.messageData
, {
3425 configName
: "nonexistent-config",
3426 importerName
: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
3430 assert
.fail("Expected to throw an error");
3433 it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", () => {
3435 engine
.executeOnText("test", "extends-plugin/test.js");
3437 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3438 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3439 assert
.deepStrictEqual(err
.messageData
, {
3440 importerName
: `extends-plugin${path.sep}.eslintrc.yml`,
3441 pluginName
: "eslint-plugin-nonexistent-plugin",
3442 resolvePluginsRelativeTo
: path
.join(cwd
, "extends-plugin") // the directory of the config file.
3446 assert
.fail("Expected to throw an error");
3449 it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", () => {
3451 engine
.executeOnText("test", "plugins/test.js");
3453 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3454 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3455 assert
.deepStrictEqual(err
.messageData
, {
3456 importerName
: `plugins${path.sep}.eslintrc.yml`,
3457 pluginName
: "eslint-plugin-nonexistent-plugin",
3458 resolvePluginsRelativeTo
: path
.join(cwd
, "plugins") // the directory of the config file.
3462 assert
.fail("Expected to throw an error");
3465 it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", () => {
3467 engine
.executeOnText("test", "throw-in-config-itself/test.js");
3469 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3470 assert
.strictEqual(err
.messageTemplate
, void 0);
3473 assert
.fail("Expected to throw an error");
3476 it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", () => {
3478 engine
.executeOnText("test", "throw-in-extends-js/test.js");
3480 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3481 assert
.strictEqual(err
.messageTemplate
, void 0);
3484 assert
.fail("Expected to throw an error");
3487 it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", () => {
3489 engine
.executeOnText("test", "throw-in-extends-plugin/test.js");
3491 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3492 assert
.strictEqual(err
.messageTemplate
, void 0);
3495 assert
.fail("Expected to throw an error");
3498 it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", () => {
3500 engine
.executeOnText("test", "throw-in-plugins/test.js");
3502 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3503 assert
.strictEqual(err
.messageTemplate
, void 0);
3506 assert
.fail("Expected to throw an error");
3510 describe("with '--rulesdir' option", () => {
3511 it("should use the configured rules which are defined by '--rulesdir' option.", () => {
3512 const rootPath
= getFixturePath("cli-engine/with-rulesdir");
3513 const StubbedCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3514 cwd
: () => rootPath
,
3516 "internal-rules/test.js": `
3517 module.exports = context => ({
3518 ExpressionStatement(node) {
3519 context.report({ node, message: "ok" })
3523 ".eslintrc.json": JSON
.stringify({
3525 rules
: { test
: "error" }
3527 "test.js": "console.log('hello')"
3531 engine
= new StubbedCLIEngine({
3532 rulePaths
: ["internal-rules"]
3534 const report
= engine
.executeOnFiles(["test.js"]);
3536 assert
.strictEqual(report
.results
.length
, 1);
3537 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
3538 assert
.strictEqual(report
.results
[0].messages
[0].message
, "ok");
3542 describe("glob pattern '[ab].js'", () => {
3543 const root
= getFixturePath("cli-engine/unmatched-glob");
3545 it("should match '[ab].js' if existed.", () => {
3546 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3553 ".eslintrc.yml": "root: true"
3556 engine
= new CLIEngine();
3558 const { results
} = engine
.executeOnFiles(["[ab].js"]);
3559 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3561 assert
.deepStrictEqual(filenames
, ["[ab].js"]);
3564 it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", () => {
3565 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3571 ".eslintrc.yml": "root: true"
3574 engine
= new CLIEngine();
3576 const { results
} = engine
.executeOnFiles(["[ab].js"]);
3577 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3579 assert
.deepStrictEqual(filenames
, ["a.js", "b.js"]);
3583 describe("with 'noInlineConfig' setting", () => {
3584 const root
= getFixturePath("cli-engine/noInlineConfig");
3586 it("should warn directive comments if 'noInlineConfig' was given.", () => {
3587 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3590 "test.js": "/* globals foo */",
3591 ".eslintrc.yml": "noInlineConfig: true"
3594 engine
= new CLIEngine();
3596 const { results
} = engine
.executeOnFiles(["test.js"]);
3597 const messages
= results
[0].messages
;
3599 assert
.strictEqual(messages
.length
, 1);
3600 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
3603 it("should show the config file what the 'noInlineConfig' came from.", () => {
3604 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3607 "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
3608 "test.js": "/* globals foo */",
3609 ".eslintrc.yml": "extends: foo"
3612 engine
= new CLIEngine();
3614 const { results
} = engine
.executeOnFiles(["test.js"]);
3615 const messages
= results
[0].messages
;
3617 assert
.strictEqual(messages
.length
, 1);
3618 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
3622 describe("with 'reportUnusedDisableDirectives' setting", () => {
3623 const root
= getFixturePath("cli-engine/reportUnusedDisableDirectives");
3625 it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", () => {
3626 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3629 "test.js": "/* eslint-disable eqeqeq */",
3630 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3633 engine
= new CLIEngine();
3635 const { results
} = engine
.executeOnFiles(["test.js"]);
3636 const messages
= results
[0].messages
;
3638 assert
.strictEqual(messages
.length
, 1);
3639 assert
.strictEqual(messages
[0].severity
, 1);
3640 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3643 describe("the runtime option overrides config files.", () => {
3644 it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", () => {
3645 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3648 "test.js": "/* eslint-disable eqeqeq */",
3649 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3652 engine
= new CLIEngine({ reportUnusedDisableDirectives
: "off" });
3654 const { results
} = engine
.executeOnFiles(["test.js"]);
3655 const messages
= results
[0].messages
;
3657 assert
.strictEqual(messages
.length
, 0);
3660 it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", () => {
3661 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3664 "test.js": "/* eslint-disable eqeqeq */",
3665 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3668 engine
= new CLIEngine({ reportUnusedDisableDirectives
: "error" });
3670 const { results
} = engine
.executeOnFiles(["test.js"]);
3671 const messages
= results
[0].messages
;
3673 assert
.strictEqual(messages
.length
, 1);
3674 assert
.strictEqual(messages
[0].severity
, 2);
3675 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3680 describe("with 'overrides[*].extends' setting on deep locations", () => {
3681 const root
= getFixturePath("cli-engine/deeply-overrides-i-extends");
3683 it("should not throw.", () => {
3684 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3687 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
3688 overrides: [{ files: ["*test*"], extends: "two" }]
3690 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
3691 overrides: [{ files: ["*.js"], extends: "three" }]
3693 "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
3694 rules: { "no-console": "error" }
3696 "test.js": "console.log('hello')",
3697 ".eslintrc.yml": "extends: one"
3700 engine
= new CLIEngine();
3702 const { results
} = engine
.executeOnFiles(["test.js"]);
3703 const messages
= results
[0].messages
;
3705 assert
.strictEqual(messages
.length
, 1);
3706 assert
.strictEqual(messages
[0].ruleId
, "no-console");
3710 describe("don't ignore the entry directory.", () => {
3711 const root
= getFixturePath("cli-engine/dont-ignore-entry-dir");
3713 it("'executeOnFiles(\".\")' should not load config files from outside of \".\".", () => {
3714 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3717 "../.eslintrc.json": "BROKEN FILE",
3718 ".eslintrc.json": JSON
.stringify({ root
: true }),
3719 "index.js": "console.log(\"hello\")"
3722 engine
= new CLIEngine();
3724 // Don't throw "failed to load config file" error.
3725 engine
.executeOnFiles(".");
3728 it("'executeOnFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", () => {
3729 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3732 "../.eslintrc.json": JSON
.stringify({ ignorePatterns
: ["/dont-ignore-entry-dir"] }),
3733 ".eslintrc.json": JSON
.stringify({ root
: true }),
3734 "index.js": "console.log(\"hello\")"
3737 engine
= new CLIEngine();
3739 // Don't throw "file not found" error.
3740 engine
.executeOnFiles(".");
3743 it("'executeOnFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", () => {
3744 CLIEngine
= defineCLIEngineWithInMemoryFileSystem({
3747 ".eslintrc.json": JSON
.stringify({ ignorePatterns
: ["/subdir"] }),
3748 "subdir/.eslintrc.json": JSON
.stringify({ root
: true }),
3749 "subdir/index.js": "console.log(\"hello\")"
3752 engine
= new CLIEngine();
3754 // Don't throw "file not found" error.
3755 engine
.executeOnFiles("subdir");
3760 describe("getConfigForFile", () => {
3762 it("should return the info from Config#getConfig when called", () => {
3764 configFile
: getFixturePath("configurations", "quotes-error.json")
3766 const engine
= new CLIEngine(options
);
3767 const filePath
= getFixturePath("single-quoted.js");
3769 const actualConfig
= engine
.getConfigForFile(filePath
);
3770 const expectedConfig
= new CascadingConfigArrayFactory({ specificConfigPath
: options
.configFile
})
3771 .getConfigArrayForFile(filePath
)
3772 .extractConfig(filePath
)
3773 .toCompatibleObjectAsConfigFileContent();
3775 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3779 it("should return the config when run from within a subdir", () => {
3781 cwd
: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
3783 const engine
= new CLIEngine(options
);
3784 const filePath
= getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
3786 const actualConfig
= engine
.getConfigForFile("./.eslintrc");
3787 const expectedConfig
= new CascadingConfigArrayFactory(options
)
3788 .getConfigArrayForFile(filePath
)
3789 .extractConfig(filePath
)
3790 .toCompatibleObjectAsConfigFileContent();
3792 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3795 it("should throw an error if a directory path was given.", () => {
3796 const engine
= new CLIEngine();
3799 engine
.getConfigForFile(".");
3801 assert
.strictEqual(error
.messageTemplate
, "print-config-with-directory-path");
3804 assert
.fail("should throw an error");
3808 describe("isPathIgnored", () => {
3809 it("should check if the given path is ignored", () => {
3810 const engine
= new CLIEngine({
3811 ignorePath
: getFixturePath(".eslintignore2"),
3812 cwd
: getFixturePath()
3815 assert
.isTrue(engine
.isPathIgnored("undef.js"));
3816 assert
.isFalse(engine
.isPathIgnored("passing.js"));
3819 it("should return false if ignoring is disabled", () => {
3820 const engine
= new CLIEngine({
3822 ignorePath
: getFixturePath(".eslintignore2"),
3823 cwd
: getFixturePath()
3826 assert
.isFalse(engine
.isPathIgnored("undef.js"));
3829 // https://github.com/eslint/eslint/issues/5547
3830 it("should return true for default ignores even if ignoring is disabled", () => {
3831 const engine
= new CLIEngine({
3833 cwd
: getFixturePath("cli-engine")
3836 assert
.isTrue(engine
.isPathIgnored("node_modules/foo.js"));
3839 describe("about the default ignore patterns", () => {
3840 it("should always apply defaultPatterns if ignore option is true", () => {
3841 const cwd
= getFixturePath("ignored-paths");
3842 const engine
= new CLIEngine({ cwd
});
3844 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
3845 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
3848 it("should still apply defaultPatterns if ignore option is is false", () => {
3849 const cwd
= getFixturePath("ignored-paths");
3850 const engine
= new CLIEngine({ ignore
: false, cwd
});
3852 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
3853 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
3856 it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", () => {
3857 const cwd
= getFixturePath("ignored-paths");
3858 const engine
= new CLIEngine({ cwd
, ignorePattern
: "!/node_modules/package" });
3860 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
3863 it("should allow subfolders of defaultPatterns to be unignored by ignorePath", () => {
3864 const cwd
= getFixturePath("ignored-paths");
3865 const engine
= new CLIEngine({ cwd
, ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
3867 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
3870 it("should ignore dotfiles", () => {
3871 const cwd
= getFixturePath("ignored-paths");
3872 const engine
= new CLIEngine({ cwd
});
3874 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
3875 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
3878 it("should ignore directories beginning with a dot", () => {
3879 const cwd
= getFixturePath("ignored-paths");
3880 const engine
= new CLIEngine({ cwd
});
3882 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
3883 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
3886 it("should still ignore dotfiles when ignore option disabled", () => {
3887 const cwd
= getFixturePath("ignored-paths");
3888 const engine
= new CLIEngine({ ignore
: false, cwd
});
3890 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
3891 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
3894 it("should still ignore directories beginning with a dot when ignore option disabled", () => {
3895 const cwd
= getFixturePath("ignored-paths");
3896 const engine
= new CLIEngine({ ignore
: false, cwd
});
3898 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
3899 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
3902 it("should not ignore absolute paths containing '..'", () => {
3903 const cwd
= getFixturePath("ignored-paths");
3904 const engine
= new CLIEngine({ cwd
});
3906 assert(!engine
.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
3909 it("should ignore /node_modules/ relative to .eslintignore when loaded", () => {
3910 const cwd
= getFixturePath("ignored-paths");
3911 const engine
= new CLIEngine({ ignorePath
: getFixturePath("ignored-paths", ".eslintignore"), cwd
});
3913 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
3914 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
3917 it("should ignore /node_modules/ relative to cwd without an .eslintignore", () => {
3918 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
3919 const engine
= new CLIEngine({ cwd
});
3921 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
3922 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
3926 describe("with no .eslintignore file", () => {
3927 it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", () => {
3928 const cwd
= getFixturePath("ignored-paths", "configurations");
3929 const engine
= new CLIEngine({ cwd
});
3931 // a .eslintignore in parent directories includes `*.js`, but don't load it.
3932 assert(!engine
.isPathIgnored("foo.js"));
3933 assert(engine
.isPathIgnored("node_modules/foo.js"));
3936 it("should return false for files outside of the cwd (with no ignore file provided)", () => {
3938 // Default ignore patterns should not inadvertently ignore files in parent directories
3939 const engine
= new CLIEngine({ cwd
: getFixturePath("ignored-paths", "no-ignore-file") });
3941 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
3945 describe("with .eslintignore file or package.json file", () => {
3946 it("should load .eslintignore from cwd when explicitly passed", () => {
3947 const cwd
= getFixturePath("ignored-paths");
3948 const engine
= new CLIEngine({ cwd
});
3950 // `${cwd}/.eslintignore` includes `sampleignorepattern`.
3951 assert(engine
.isPathIgnored("sampleignorepattern"));
3954 it("should use package.json's eslintIgnore files if no specified .eslintignore file", () => {
3955 const cwd
= getFixturePath("ignored-paths", "package-json-ignore");
3956 const engine
= new CLIEngine({ cwd
});
3958 assert(engine
.isPathIgnored("hello.js"));
3959 assert(engine
.isPathIgnored("world.js"));
3962 it("should use correct message template if failed to parse package.json", () => {
3963 const cwd
= getFixturePath("ignored-paths", "broken-package-json");
3965 assert
.throw(() => {
3967 // eslint-disable-next-line no-new
3968 new CLIEngine({ cwd
});
3970 assert
.strictEqual(error
.messageTemplate
, "failed-to-read-json");
3976 it("should not use package.json's eslintIgnore files if specified .eslintignore file", () => {
3977 const cwd
= getFixturePath("ignored-paths");
3978 const engine
= new CLIEngine({ cwd
});
3981 * package.json includes `hello.js` and `world.js`.
3982 * .eslintignore includes `sampleignorepattern`.
3984 assert(!engine
.isPathIgnored("hello.js"));
3985 assert(!engine
.isPathIgnored("world.js"));
3986 assert(engine
.isPathIgnored("sampleignorepattern"));
3989 it("should error if package.json's eslintIgnore is not an array of file paths", () => {
3990 const cwd
= getFixturePath("ignored-paths", "bad-package-json-ignore");
3992 assert
.throws(() => {
3993 // eslint-disable-next-line no-new
3994 new CLIEngine({ cwd
});
3995 }, "Package.json eslintIgnore property requires an array of paths");
3999 describe("with --ignore-pattern option", () => {
4000 it("should accept a string for options.ignorePattern", () => {
4001 const cwd
= getFixturePath("ignored-paths", "ignore-pattern");
4002 const engine
= new CLIEngine({
4003 ignorePattern
: "ignore-me.txt",
4007 assert(engine
.isPathIgnored("ignore-me.txt"));
4010 it("should accept an array for options.ignorePattern", () => {
4011 const engine
= new CLIEngine({
4012 ignorePattern
: ["a", "b"],
4016 assert(engine
.isPathIgnored("a"));
4017 assert(engine
.isPathIgnored("b"));
4018 assert(!engine
.isPathIgnored("c"));
4021 it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", () => {
4022 const cwd
= getFixturePath("ignored-paths");
4023 const engine
= new CLIEngine({
4024 ignorePattern
: "not-a-file",
4028 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
4031 it("should return true for file matching an ignore pattern exactly", () => {
4032 const cwd
= getFixturePath("ignored-paths");
4033 const engine
= new CLIEngine({ ignorePattern
: "undef.js", cwd
});
4035 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4038 it("should return false for file matching an invalid ignore pattern with leading './'", () => {
4039 const cwd
= getFixturePath("ignored-paths");
4040 const engine
= new CLIEngine({ ignorePattern
: "./undef.js", cwd
});
4042 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4045 it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", () => {
4046 const cwd
= getFixturePath("ignored-paths");
4047 const engine
= new CLIEngine({ ignorePattern
: "/undef.js", cwd
});
4049 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
4052 it("should return true for file matching a child of an ignore pattern", () => {
4053 const cwd
= getFixturePath("ignored-paths");
4054 const engine
= new CLIEngine({ ignorePattern
: "ignore-pattern", cwd
});
4056 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
4059 it("should return true for file matching a grandchild of an ignore pattern", () => {
4060 const cwd
= getFixturePath("ignored-paths");
4061 const engine
= new CLIEngine({ ignorePattern
: "ignore-pattern", cwd
});
4063 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
4066 it("should return false for file not matching any ignore pattern", () => {
4067 const cwd
= getFixturePath("ignored-paths");
4068 const engine
= new CLIEngine({ ignorePattern
: "failing.js", cwd
});
4070 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
4073 it("two globstar '**' ignore pattern should ignore files in nested directories", () => {
4074 const cwd
= getFixturePath("ignored-paths");
4075 const engine
= new CLIEngine({ ignorePattern
: "**/*.js", cwd
});
4077 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4078 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
4079 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
4080 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
4081 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
4082 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
4086 describe("with --ignore-path option", () => {
4087 it("should load empty array with ignorePath set to false", () => {
4088 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4089 const engine
= new CLIEngine({ ignorePath
: false, cwd
});
4091 // a .eslintignore in parent directories includes `*.js`, but don't load it.
4092 assert(!engine
.isPathIgnored("foo.js"));
4093 assert(engine
.isPathIgnored("node_modules/foo.js"));
4096 it("initialization with ignorePath should work when cwd is a parent directory", () => {
4097 const cwd
= getFixturePath("ignored-paths");
4098 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4099 const engine
= new CLIEngine({ ignorePath
, cwd
});
4101 assert(engine
.isPathIgnored("custom-name/foo.js"));
4104 it("initialization with ignorePath should work when the file is in the cwd", () => {
4105 const cwd
= getFixturePath("ignored-paths", "custom-name");
4106 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4107 const engine
= new CLIEngine({ ignorePath
, cwd
});
4109 assert(engine
.isPathIgnored("foo.js"));
4112 it("initialization with ignorePath should work when cwd is a subdirectory", () => {
4113 const cwd
= getFixturePath("ignored-paths", "custom-name", "subdirectory");
4114 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4115 const engine
= new CLIEngine({ ignorePath
, cwd
});
4117 assert(engine
.isPathIgnored("../custom-name/foo.js"));
4120 it("initialization with invalid file should throw error", () => {
4121 const cwd
= getFixturePath("ignored-paths");
4122 const ignorePath
= getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
4124 assert
.throws(() => {
4125 // eslint-disable-next-line no-new
4126 new CLIEngine({ ignorePath
, cwd
});
4127 }, "Cannot read .eslintignore file");
4130 it("should return false for files outside of ignorePath's directory", () => {
4131 const cwd
= getFixturePath("ignored-paths");
4132 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4133 const engine
= new CLIEngine({ ignorePath
, cwd
});
4135 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4138 it("should resolve relative paths from CWD", () => {
4139 const cwd
= getFixturePath("ignored-paths", "subdir");
4140 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4141 const engine
= new CLIEngine({ ignorePath
, cwd
});
4143 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4144 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4147 it("should resolve relative paths from CWD when it's in a child directory", () => {
4148 const cwd
= getFixturePath("ignored-paths");
4149 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4150 const engine
= new CLIEngine({ ignorePath
, cwd
});
4152 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4153 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4154 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4155 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
4157 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
4160 it("should resolve relative paths from CWD when it contains negated globs", () => {
4161 const cwd
= getFixturePath("ignored-paths");
4162 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4163 const engine
= new CLIEngine({ ignorePath
, cwd
});
4165 assert(engine
.isPathIgnored("subdir/blah.txt"));
4166 assert(engine
.isPathIgnored("blah.txt"));
4167 assert(engine
.isPathIgnored("subdir/bar.txt"));
4168 assert(!engine
.isPathIgnored("bar.txt"));
4169 assert(!engine
.isPathIgnored("subdir/baz.txt"));
4170 assert(!engine
.isPathIgnored("baz.txt"));
4173 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", () => {
4174 const cwd
= getFixturePath("ignored-paths");
4175 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4176 const engine
= new CLIEngine({ ignorePath
, cwd
});
4178 assert(engine
.isPathIgnored("node_modules/blah.js"));
4181 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", () => {
4182 const cwd
= getFixturePath("ignored-paths", "subdir");
4183 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4184 const engine
= new CLIEngine({ ignorePath
, cwd
});
4186 assert(engine
.isPathIgnored("node_modules/blah.js"));
4189 it("should handle .eslintignore which contains CRLF correctly.", () => {
4190 const ignoreFileContent
= fs
.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
4192 assert(ignoreFileContent
.includes("\r"), "crlf/.eslintignore should contains CR.");
4194 const cwd
= getFixturePath("ignored-paths");
4195 const ignorePath
= getFixturePath("ignored-paths", "crlf/.eslintignore");
4196 const engine
= new CLIEngine({ ignorePath
, cwd
});
4198 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
4199 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
4200 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
4203 it("should not include comments in ignore rules", () => {
4204 const cwd
= getFixturePath("ignored-paths");
4205 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithComments");
4206 const engine
= new CLIEngine({ ignorePath
, cwd
});
4208 assert(!engine
.isPathIgnored("# should be ignored"));
4209 assert(engine
.isPathIgnored("this_one_not"));
4212 it("should ignore a non-negated pattern", () => {
4213 const cwd
= getFixturePath("ignored-paths");
4214 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4215 const engine
= new CLIEngine({ ignorePath
, cwd
});
4217 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
4220 it("should not ignore a negated pattern", () => {
4221 const cwd
= getFixturePath("ignored-paths");
4222 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4223 const engine
= new CLIEngine({ ignorePath
, cwd
});
4225 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
4229 describe("with --ignore-path option and --ignore-pattern option", () => {
4230 it("should return false for ignored file when unignored with ignore pattern", () => {
4231 const cwd
= getFixturePath("ignored-paths");
4232 const engine
= new CLIEngine({
4233 ignorePath
: getFixturePath("ignored-paths", ".eslintignore"),
4234 ignorePattern
: "!sampleignorepattern",
4238 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
4243 describe("getFormatter()", () => {
4245 it("should return a function when a bundled formatter is requested", () => {
4246 const engine
= new CLIEngine(),
4247 formatter
= engine
.getFormatter("compact");
4249 assert
.isFunction(formatter
);
4252 it("should return a function when no argument is passed", () => {
4253 const engine
= new CLIEngine(),
4254 formatter
= engine
.getFormatter();
4256 assert
.isFunction(formatter
);
4259 it("should return a function when a custom formatter is requested", () => {
4260 const engine
= new CLIEngine(),
4261 formatter
= engine
.getFormatter(getFixturePath("formatters", "simple.js"));
4263 assert
.isFunction(formatter
);
4266 it("should return a function when a custom formatter is requested, also if the path has backslashes", () => {
4267 const engine
= new CLIEngine({
4268 cwd
: path
.join(fixtureDir
, "..")
4270 formatter
= engine
.getFormatter(".\\fixtures\\formatters\\simple.js");
4272 assert
.isFunction(formatter
);
4275 it("should return a function when a formatter prefixed with eslint-formatter is requested", () => {
4276 const engine
= new CLIEngine({
4277 cwd
: getFixturePath("cli-engine")
4279 formatter
= engine
.getFormatter("bar");
4281 assert
.isFunction(formatter
);
4284 it("should return a function when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", () => {
4285 const engine
= new CLIEngine({
4286 cwd
: getFixturePath("cli-engine")
4288 formatter
= engine
.getFormatter("eslint-formatter-bar");
4290 assert
.isFunction(formatter
);
4293 it("should return a function when a formatter is requested within a scoped npm package", () => {
4294 const engine
= new CLIEngine({
4295 cwd
: getFixturePath("cli-engine")
4297 formatter
= engine
.getFormatter("@somenamespace/foo");
4299 assert
.isFunction(formatter
);
4302 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", () => {
4303 const engine
= new CLIEngine({
4304 cwd
: getFixturePath("cli-engine")
4306 formatter
= engine
.getFormatter("@somenamespace/eslint-formatter-foo");
4308 assert
.isFunction(formatter
);
4311 it("should return null when a customer formatter doesn't exist", () => {
4312 const engine
= new CLIEngine(),
4313 formatterPath
= getFixturePath("formatters", "doesntexist.js"),
4314 fullFormatterPath
= path
.resolve(formatterPath
);
4316 assert
.throws(() => {
4317 engine
.getFormatter(formatterPath
);
4318 }, `There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`);
4321 it("should return null when a built-in formatter doesn't exist", () => {
4322 const engine
= new CLIEngine();
4323 const fullFormatterPath
= path
.resolve(__dirname
, "../../../lib/cli-engine/formatters/special");
4325 assert
.throws(() => {
4326 engine
.getFormatter("special");
4327 }, `There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`);
4330 it("should throw if the required formatter exists but has an error", () => {
4331 const engine
= new CLIEngine(),
4332 formatterPath
= getFixturePath("formatters", "broken.js");
4334 assert
.throws(() => {
4335 engine
.getFormatter(formatterPath
);
4336 }, `There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`);
4339 it("should return null when a non-string formatter name is passed", () => {
4340 const engine
= new CLIEngine(),
4341 formatter
= engine
.getFormatter(5);
4343 assert
.isNull(formatter
);
4346 it("should return a function when called as a static function on CLIEngine", () => {
4347 const formatter
= CLIEngine
.getFormatter();
4349 assert
.isFunction(formatter
);
4352 it("should return a function when called as a static function on CLIEngine and a custom formatter is requested", () => {
4353 const formatter
= CLIEngine
.getFormatter(getFixturePath("formatters", "simple.js"));
4355 assert
.isFunction(formatter
);
4360 describe("getErrorResults()", () => {
4361 it("should report 5 error messages when looking for errors only", () => {
4363 process
.chdir(originalDir
);
4364 const engine
= new CLIEngine();
4366 const report
= engine
.executeOnText("var foo = 'bar';");
4367 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4369 assert
.lengthOf(errorResults
[0].messages
, 5);
4370 assert
.strictEqual(errorResults
[0].errorCount
, 5);
4371 assert
.strictEqual(errorResults
[0].fixableErrorCount
, 3);
4372 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4373 assert
.strictEqual(errorResults
[0].messages
[0].ruleId
, "strict");
4374 assert
.strictEqual(errorResults
[0].messages
[0].severity
, 2);
4375 assert
.strictEqual(errorResults
[0].messages
[1].ruleId
, "no-var");
4376 assert
.strictEqual(errorResults
[0].messages
[1].severity
, 2);
4377 assert
.strictEqual(errorResults
[0].messages
[2].ruleId
, "no-unused-vars");
4378 assert
.strictEqual(errorResults
[0].messages
[2].severity
, 2);
4379 assert
.strictEqual(errorResults
[0].messages
[3].ruleId
, "quotes");
4380 assert
.strictEqual(errorResults
[0].messages
[3].severity
, 2);
4381 assert
.strictEqual(errorResults
[0].messages
[4].ruleId
, "eol-last");
4382 assert
.strictEqual(errorResults
[0].messages
[4].severity
, 2);
4385 it("should not mutate passed report.results parameter", () => {
4386 process
.chdir(originalDir
);
4387 const engine
= new CLIEngine({
4388 rules
: { quotes
: [1, "double"] }
4391 const report
= engine
.executeOnText("var foo = 'bar';");
4392 const reportResultsLength
= report
.results
[0].messages
.length
;
4394 CLIEngine
.getErrorResults(report
.results
);
4396 assert
.lengthOf(report
.results
[0].messages
, reportResultsLength
);
4399 it("should report a warningCount of 0 when looking for errors only", () => {
4401 process
.chdir(originalDir
);
4402 const engine
= new CLIEngine();
4404 const report
= engine
.executeOnText("var foo = 'bar';");
4405 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4407 assert
.strictEqual(errorResults
[0].warningCount
, 0);
4408 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4411 it("should return 0 error or warning messages even when the file has warnings", () => {
4412 const engine
= new CLIEngine({
4413 ignorePath
: path
.join(fixtureDir
, ".eslintignore"),
4414 cwd
: path
.join(fixtureDir
, "..")
4417 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js", true);
4418 const errorReport
= CLIEngine
.getErrorResults(report
.results
);
4420 assert
.lengthOf(errorReport
, 0);
4421 assert
.lengthOf(report
.results
, 1);
4422 assert
.strictEqual(report
.errorCount
, 0);
4423 assert
.strictEqual(report
.warningCount
, 1);
4424 assert
.strictEqual(report
.fixableErrorCount
, 0);
4425 assert
.strictEqual(report
.fixableWarningCount
, 0);
4426 assert
.strictEqual(report
.results
[0].errorCount
, 0);
4427 assert
.strictEqual(report
.results
[0].warningCount
, 1);
4428 assert
.strictEqual(report
.fixableErrorCount
, 0);
4429 assert
.strictEqual(report
.fixableWarningCount
, 0);
4432 it("should return source code of file in the `source` property", () => {
4433 process
.chdir(originalDir
);
4434 const engine
= new CLIEngine({
4436 rules
: { quotes
: [2, "double"] }
4440 const report
= engine
.executeOnText("var foo = 'bar';");
4441 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4443 assert
.lengthOf(errorResults
[0].messages
, 1);
4444 assert
.strictEqual(errorResults
[0].source
, "var foo = 'bar';");
4447 it("should contain `output` property after fixes", () => {
4448 process
.chdir(originalDir
);
4449 const engine
= new CLIEngine({
4458 const report
= engine
.executeOnText("console.log('foo')");
4459 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4461 assert
.lengthOf(errorResults
[0].messages
, 1);
4462 assert
.strictEqual(errorResults
[0].output
, "console.log('foo');");
4466 describe("outputFixes()", () => {
4468 sinon
.verifyAndRestore();
4471 it("should call fs.writeFileSync() for each result with output", () => {
4472 const fakeFS
= leche
.fake(fs
),
4473 localCLIEngine
= proxyquire("../../../lib/cli-engine/cli-engine", {
4489 fakeFS
.writeFileSync = function() {};
4490 const spy
= sinon
.spy(fakeFS
, "writeFileSync");
4492 localCLIEngine
.outputFixes(report
);
4494 assert
.strictEqual(spy
.callCount
, 2);
4495 assert
.isTrue(spy
.firstCall
.calledWithExactly("foo.js", "bar"), "First call was incorrect.");
4496 assert
.isTrue(spy
.secondCall
.calledWithExactly("bar.js", "baz"), "Second call was incorrect.");
4500 it("should call fs.writeFileSync() for each result with output and not at all for a result without output", () => {
4501 const fakeFS
= leche
.fake(fs
),
4502 localCLIEngine
= proxyquire("../../../lib/cli-engine/cli-engine", {
4521 fakeFS
.writeFileSync = function() {};
4522 const spy
= sinon
.spy(fakeFS
, "writeFileSync");
4524 localCLIEngine
.outputFixes(report
);
4526 assert
.strictEqual(spy
.callCount
, 2);
4527 assert
.isTrue(spy
.firstCall
.calledWithExactly("foo.js", "bar"), "First call was incorrect.");
4528 assert
.isTrue(spy
.secondCall
.calledWithExactly("bar.js", "baz"), "Second call was incorrect.");
4534 describe("getRules()", () => {
4535 it("should expose the list of rules", () => {
4536 const engine
= new CLIEngine();
4538 assert(engine
.getRules().has("no-eval"), "no-eval is present");
4541 it("should expose the list of plugin rules", () => {
4542 const engine
= new CLIEngine({ plugins
: ["node"] });
4544 assert(engine
.getRules().has("node/no-deprecated-api"), "node/no-deprecated-api is present");
4547 it("should expose the rules of the plugin that is added by 'addPlugin'.", () => {
4548 const engine
= new CLIEngine({ plugins
: ["foo"] });
4550 engine
.addPlugin("foo", require("eslint-plugin-node"));
4552 assert(engine
.getRules().has("foo/no-deprecated-api"), "foo/no-deprecated-api is present");
4556 describe("resolveFileGlobPatterns", () => {
4559 [".", ["**/*.{js}"]],
4560 ["./", ["**/*.{js}"]],
4561 ["../", ["../**/*.{js}"]],
4563 ], (input
, expected
) => {
4565 it(`should correctly resolve ${input} to ${expected}`, () => {
4566 const engine
= new CLIEngine();
4568 const result
= engine
.resolveFileGlobPatterns([input
]);
4570 assert
.deepStrictEqual(result
, expected
);
4575 it("should convert a directory name with no provided extensions into a glob pattern", () => {
4576 const patterns
= ["one-js-file"];
4578 cwd
: getFixturePath("glob-util")
4580 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4582 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4585 it("should not convert path with globInputPaths option false", () => {
4586 const patterns
= ["one-js-file"];
4588 cwd
: getFixturePath("glob-util"),
4589 globInputPaths
: false
4591 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4593 assert
.deepStrictEqual(result
, ["one-js-file"]);
4596 it("should convert an absolute directory name with no provided extensions into a posix glob pattern", () => {
4597 const patterns
= [getFixturePath("glob-util", "one-js-file")];
4599 cwd
: getFixturePath("glob-util")
4601 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4602 const expected
= [`${getFixturePath("glob-util", "one-js-file").replace(/\\/gu, "/")}/**/*.{js}`];
4604 assert
.deepStrictEqual(result
, expected
);
4607 it("should convert a directory name with a single provided extension into a glob pattern", () => {
4608 const patterns
= ["one-js-file"];
4610 cwd
: getFixturePath("glob-util"),
4611 extensions
: [".jsx"]
4613 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4615 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{jsx}"]);
4618 it("should convert a directory name with multiple provided extensions into a glob pattern", () => {
4619 const patterns
= ["one-js-file"];
4621 cwd
: getFixturePath("glob-util"),
4622 extensions
: [".jsx", ".js"]
4624 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4626 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{jsx,js}"]);
4629 it("should convert multiple directory names into glob patterns", () => {
4630 const patterns
= ["one-js-file", "two-js-files"];
4632 cwd
: getFixturePath("glob-util")
4634 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4636 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}", "two-js-files/**/*.{js}"]);
4639 it("should remove leading './' from glob patterns", () => {
4640 const patterns
= ["./one-js-file"];
4642 cwd
: getFixturePath("glob-util")
4644 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4646 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4649 it("should convert a directory name with a trailing '/' into a glob pattern", () => {
4650 const patterns
= ["one-js-file/"];
4652 cwd
: getFixturePath("glob-util")
4654 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4656 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
4659 it("should return filenames as they are", () => {
4660 const patterns
= ["some-file.js"];
4662 cwd
: getFixturePath("glob-util")
4664 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4666 assert
.deepStrictEqual(result
, ["some-file.js"]);
4669 it("should convert backslashes into forward slashes", () => {
4670 const patterns
= ["one-js-file\\example.js"];
4672 cwd
: getFixturePath()
4674 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
4676 assert
.deepStrictEqual(result
, ["one-js-file/example.js"]);
4680 describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
4682 it("should report a violation for disabling rules", () => {
4684 "alert('test'); // eslint-disable-line no-alert"
4689 allowInlineConfig
: false,
4693 "no-trailing-spaces": 0,
4699 const eslintCLI
= new CLIEngine(config
);
4701 const report
= eslintCLI
.executeOnText(code
);
4702 const messages
= report
.results
[0].messages
;
4704 assert
.strictEqual(messages
.length
, 1);
4705 assert
.strictEqual(messages
[0].ruleId
, "no-alert");
4708 it("should not report a violation by default", () => {
4710 "alert('test'); // eslint-disable-line no-alert"
4716 // allowInlineConfig: true is the default
4720 "no-trailing-spaces": 0,
4726 const eslintCLI
= new CLIEngine(config
);
4728 const report
= eslintCLI
.executeOnText(code
);
4729 const messages
= report
.results
[0].messages
;
4731 assert
.strictEqual(messages
.length
, 0);
4736 describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
4737 it("should report problems for unused eslint-disable directives", () => {
4738 const cliEngine
= new CLIEngine({ useEslintrc
: false, reportUnusedDisableDirectives
: true });
4740 assert
.deepStrictEqual(
4741 cliEngine
.executeOnText("/* eslint-disable */"),
4749 message
: "Unused eslint-disable directive (no problems were reported).",
4758 fixableErrorCount
: 0,
4759 fixableWarningCount
: 0,
4760 source
: "/* eslint-disable */"
4765 fixableErrorCount
: 0,
4766 fixableWarningCount
: 0,
4767 usedDeprecatedRules
: []
4773 describe("when retreiving version number", () => {
4774 it("should return current version number", () => {
4775 const eslintCLI
= require("../../../lib/cli-engine").CLIEngine
;
4776 const version
= eslintCLI
.version
;
4778 assert
.isString(version
);
4779 assert
.isTrue(parseInt(version
[0], 10) >= 3);
4783 describe("mutability", () => {
4784 describe("plugins", () => {
4785 it("Loading plugin in one instance doesn't mutate to another instance", () => {
4786 const filePath
= getFixturePath("single-quoted.js");
4787 const engine1
= cliEngineWithPlugins({
4788 cwd
: path
.join(fixtureDir
, ".."),
4790 plugins
: ["example"],
4791 rules
: { "example/example-rule": 1 }
4793 const engine2
= new CLIEngine({
4794 cwd
: path
.join(fixtureDir
, ".."),
4797 const fileConfig1
= engine1
.getConfigForFile(filePath
);
4798 const fileConfig2
= engine2
.getConfigForFile(filePath
);
4801 assert
.deepStrictEqual(fileConfig1
.plugins
, ["example"], "Plugin is present for engine 1");
4802 assert
.deepStrictEqual(fileConfig2
.plugins
, [], "Plugin is not present for engine 2");
4806 describe("rules", () => {
4807 it("Loading rules in one instance doesn't mutate to another instance", () => {
4808 const filePath
= getFixturePath("single-quoted.js");
4809 const engine1
= new CLIEngine({
4810 cwd
: path
.join(fixtureDir
, ".."),
4812 rules
: { "example/example-rule": 1 }
4814 const engine2
= new CLIEngine({
4815 cwd
: path
.join(fixtureDir
, ".."),
4818 const fileConfig1
= engine1
.getConfigForFile(filePath
);
4819 const fileConfig2
= engine2
.getConfigForFile(filePath
);
4822 assert
.deepStrictEqual(fileConfig1
.rules
["example/example-rule"], [1], "example is present for engine 1");
4823 assert
.isUndefined(fileConfig2
.rules
["example/example-rule"], "example is not present for engine 2");
4828 describe("with ignorePatterns config", () => {
4829 const root
= getFixturePath("cli-engine/ignore-patterns");
4831 /** @type {typeof CLIEngine} */
4832 let InMemoryCLIEngine
;
4834 describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
4836 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4839 ".eslintrc.json": JSON
.stringify({
4840 ignorePatterns
: "foo.js"
4844 "subdir/foo.js": "",
4850 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
4851 const engine
= new InMemoryCLIEngine();
4853 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
4854 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
4857 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
4858 const engine
= new InMemoryCLIEngine();
4860 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
4861 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), false);
4864 it("'executeOnFiles()' should not verify 'foo.js'.", () => {
4865 const engine
= new InMemoryCLIEngine();
4866 const filePaths
= engine
.executeOnFiles("**/*.js")
4868 .map(r
=> r
.filePath
)
4871 assert
.deepStrictEqual(filePaths
, [
4872 path
.join(root
, "bar.js"),
4873 path
.join(root
, "subdir/bar.js")
4878 describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
4880 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4883 ".eslintrc.json": JSON
.stringify({
4884 ignorePatterns
: ["foo.js", "/bar.js"]
4889 "subdir/foo.js": "",
4890 "subdir/bar.js": "",
4896 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
4897 const engine
= new InMemoryCLIEngine();
4899 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
4900 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
4903 it("'isPathIgnored()' should return 'true' for '/bar.js'.", () => {
4904 const engine
= new InMemoryCLIEngine();
4906 assert
.strictEqual(engine
.isPathIgnored("bar.js"), true);
4907 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), false);
4910 it("'executeOnFiles()' should not verify 'foo.js' and '/bar.js'.", () => {
4911 const engine
= new InMemoryCLIEngine();
4912 const filePaths
= engine
.executeOnFiles("**/*.js")
4914 .map(r
=> r
.filePath
)
4917 assert
.deepStrictEqual(filePaths
, [
4918 path
.join(root
, "baz.js"),
4919 path
.join(root
, "subdir/bar.js"),
4920 path
.join(root
, "subdir/baz.js")
4925 describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
4927 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4930 ".eslintrc.json": JSON
.stringify({
4931 ignorePatterns
: "!/node_modules/foo"
4933 "node_modules/foo/index.js": "",
4934 "node_modules/foo/.dot.js": "",
4935 "node_modules/bar/index.js": "",
4941 it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", () => {
4942 const engine
= new InMemoryCLIEngine();
4944 assert
.strictEqual(engine
.isPathIgnored("node_modules/foo/index.js"), false);
4947 it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", () => {
4948 const engine
= new InMemoryCLIEngine();
4950 assert
.strictEqual(engine
.isPathIgnored("node_modules/foo/.dot.js"), true);
4953 it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", () => {
4954 const engine
= new InMemoryCLIEngine();
4956 assert
.strictEqual(engine
.isPathIgnored("node_modules/bar/index.js"), true);
4959 it("'executeOnFiles()' should verify 'node_modules/foo/index.js'.", () => {
4960 const engine
= new InMemoryCLIEngine();
4961 const filePaths
= engine
.executeOnFiles("**/*.js")
4963 .map(r
=> r
.filePath
)
4966 assert
.deepStrictEqual(filePaths
, [
4967 path
.join(root
, "foo.js"),
4968 path
.join(root
, "node_modules/foo/index.js")
4973 describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
4975 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
4978 ".eslintrc.js": `module.exports = ${JSON.stringify({
4979 ignorePatterns: "!.eslintrc.js"
4986 it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", () => {
4987 const engine
= new InMemoryCLIEngine();
4989 assert
.strictEqual(engine
.isPathIgnored(".eslintrc.js"), false);
4992 it("'executeOnFiles()' should verify '.eslintrc.js'.", () => {
4993 const engine
= new InMemoryCLIEngine();
4994 const filePaths
= engine
.executeOnFiles("**/*.js")
4996 .map(r
=> r
.filePath
)
4999 assert
.deepStrictEqual(filePaths
, [
5000 path
.join(root
, ".eslintrc.js"),
5001 path
.join(root
, "foo.js")
5006 describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
5008 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5011 ".eslintrc.js": `module.exports = ${JSON.stringify({
5012 ignorePatterns: "!.*"
5014 ".eslintignore": ".foo*",
5021 it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", () => {
5022 const engine
= new InMemoryCLIEngine();
5024 assert
.strictEqual(engine
.isPathIgnored(".foo.js"), true);
5027 it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", () => {
5028 const engine
= new InMemoryCLIEngine();
5030 assert
.strictEqual(engine
.isPathIgnored(".bar.js"), false);
5033 it("'executeOnFiles()' should not verify re-ignored '.foo.js'.", () => {
5034 const engine
= new InMemoryCLIEngine();
5035 const filePaths
= engine
.executeOnFiles("**/*.js")
5037 .map(r
=> r
.filePath
)
5040 assert
.deepStrictEqual(filePaths
, [
5041 path
.join(root
, ".bar.js"),
5042 path
.join(root
, ".eslintrc.js")
5047 describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
5049 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5052 ".eslintrc.js": `module.exports = ${JSON.stringify({
5053 ignorePatterns: "*.js"
5055 ".eslintignore": "!foo.js",
5062 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", () => {
5063 const engine
= new InMemoryCLIEngine();
5065 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5068 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", () => {
5069 const engine
= new InMemoryCLIEngine();
5071 assert
.strictEqual(engine
.isPathIgnored("bar.js"), true);
5074 it("'executeOnFiles()' should verify unignored 'foo.js'.", () => {
5075 const engine
= new InMemoryCLIEngine();
5076 const filePaths
= engine
.executeOnFiles("**/*.js")
5078 .map(r
=> r
.filePath
)
5081 assert
.deepStrictEqual(filePaths
, [
5082 path
.join(root
, "foo.js")
5087 describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
5089 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5092 ".eslintrc.json": JSON
.stringify({
5093 ignorePatterns
: "foo.js"
5095 "subdir/.eslintrc.json": JSON
.stringify({
5096 ignorePatterns
: "bar.js"
5100 "subdir/foo.js": "",
5101 "subdir/bar.js": "",
5102 "subdir/subsubdir/foo.js": "",
5103 "subdir/subsubdir/bar.js": ""
5108 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5109 const engine
= new InMemoryCLIEngine();
5111 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5112 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5113 assert
.strictEqual(engine
.isPathIgnored("subdir/subsubdir/foo.js"), true);
5116 it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", () => {
5117 const engine
= new InMemoryCLIEngine();
5119 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5120 assert
.strictEqual(engine
.isPathIgnored("subdir/subsubdir/bar.js"), true);
5123 it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", () => {
5124 const engine
= new InMemoryCLIEngine();
5126 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5129 it("'executeOnFiles()' should verify 'bar.js' in the outside of 'subdir'.", () => {
5130 const engine
= new InMemoryCLIEngine();
5131 const filePaths
= engine
.executeOnFiles("**/*.js")
5133 .map(r
=> r
.filePath
)
5136 assert
.deepStrictEqual(filePaths
, [
5137 path
.join(root
, "bar.js")
5142 describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
5144 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5147 ".eslintrc.json": JSON
.stringify({
5148 ignorePatterns
: "foo.js"
5150 "subdir/.eslintrc.json": JSON
.stringify({
5151 ignorePatterns
: "!foo.js"
5159 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", () => {
5160 const engine
= new InMemoryCLIEngine();
5162 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5165 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", () => {
5166 const engine
= new InMemoryCLIEngine();
5168 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5171 it("'executeOnFiles()' should verify 'foo.js' in the child directory.", () => {
5172 const engine
= new InMemoryCLIEngine();
5173 const filePaths
= engine
.executeOnFiles("**/*.js")
5175 .map(r
=> r
.filePath
)
5178 assert
.deepStrictEqual(filePaths
, [
5179 path
.join(root
, "subdir/foo.js")
5184 describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
5186 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5189 ".eslintrc.json": JSON
.stringify({}),
5190 "subdir/.eslintrc.json": JSON
.stringify({
5191 ignorePatterns
: "*.js"
5193 ".eslintignore": "!foo.js",
5195 "subdir/foo.js": "",
5201 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", () => {
5202 const engine
= new InMemoryCLIEngine();
5204 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5205 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5208 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", () => {
5209 const engine
= new InMemoryCLIEngine();
5211 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5214 it("'executeOnFiles()' should verify unignored 'foo.js'.", () => {
5215 const engine
= new InMemoryCLIEngine();
5216 const filePaths
= engine
.executeOnFiles("**/*.js")
5218 .map(r
=> r
.filePath
)
5221 assert
.deepStrictEqual(filePaths
, [
5222 path
.join(root
, "foo.js"),
5223 path
.join(root
, "subdir/foo.js")
5228 describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
5230 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5233 ".eslintrc.json": JSON
.stringify({
5234 ignorePatterns
: "foo.js"
5236 "subdir/.eslintrc.json": JSON
.stringify({
5238 ignorePatterns
: "bar.js"
5242 "subdir/foo.js": "",
5248 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", () => {
5249 const engine
= new InMemoryCLIEngine();
5251 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5254 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", () => {
5255 const engine
= new InMemoryCLIEngine();
5257 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5260 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", () => {
5261 const engine
= new InMemoryCLIEngine();
5263 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5266 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", () => {
5267 const engine
= new InMemoryCLIEngine();
5269 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5272 it("'executeOnFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", () => {
5273 const engine
= new InMemoryCLIEngine();
5274 const filePaths
= engine
.executeOnFiles("**/*.js")
5276 .map(r
=> r
.filePath
)
5279 assert
.deepStrictEqual(filePaths
, [
5280 path
.join(root
, "bar.js"),
5281 path
.join(root
, "subdir/foo.js")
5286 describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
5288 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5291 ".eslintrc.json": JSON
.stringify({}),
5292 "subdir/.eslintrc.json": JSON
.stringify({
5294 ignorePatterns
: "bar.js"
5296 ".eslintignore": "foo.js",
5299 "subdir/foo.js": "",
5305 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5306 const engine
= new InMemoryCLIEngine();
5308 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5309 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5312 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", () => {
5313 const engine
= new InMemoryCLIEngine();
5315 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5318 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", () => {
5319 const engine
= new InMemoryCLIEngine();
5321 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5324 it("'executeOnFiles()' should verify 'bar.js' in the root directory.", () => {
5325 const engine
= new InMemoryCLIEngine();
5326 const filePaths
= engine
.executeOnFiles("**/*.js")
5328 .map(r
=> r
.filePath
)
5331 assert
.deepStrictEqual(filePaths
, [
5332 path
.join(root
, "bar.js")
5337 describe("ignorePatterns in the shareable config should be used.", () => {
5339 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5342 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5343 ignorePatterns: "foo.js"
5345 ".eslintrc.json": JSON
.stringify({
5354 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5355 const engine
= new InMemoryCLIEngine();
5357 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5360 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5361 const engine
= new InMemoryCLIEngine();
5363 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5366 it("'executeOnFiles()' should verify 'bar.js'.", () => {
5367 const engine
= new InMemoryCLIEngine();
5368 const filePaths
= engine
.executeOnFiles("**/*.js")
5370 .map(r
=> r
.filePath
)
5373 assert
.deepStrictEqual(filePaths
, [
5374 path
.join(root
, "bar.js")
5379 describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
5381 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5384 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5385 ignorePatterns: "/foo.js"
5387 ".eslintrc.json": JSON
.stringify({
5396 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5397 const engine
= new InMemoryCLIEngine();
5399 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5402 it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", () => {
5403 const engine
= new InMemoryCLIEngine();
5405 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5408 it("'executeOnFiles()' should verify 'subdir/foo.js'.", () => {
5409 const engine
= new InMemoryCLIEngine();
5410 const filePaths
= engine
.executeOnFiles("**/*.js")
5412 .map(r
=> r
.filePath
)
5415 assert
.deepStrictEqual(filePaths
, [
5416 path
.join(root
, "subdir/foo.js")
5421 describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
5423 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5426 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5427 ignorePatterns: "*.js"
5429 ".eslintrc.json": JSON
.stringify({
5431 ignorePatterns
: "!bar.js"
5439 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5440 const engine
= new InMemoryCLIEngine();
5442 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5445 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5446 const engine
= new InMemoryCLIEngine();
5448 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5451 it("'executeOnFiles()' should verify 'bar.js'.", () => {
5452 const engine
= new InMemoryCLIEngine();
5453 const filePaths
= engine
.executeOnFiles("**/*.js")
5455 .map(r
=> r
.filePath
)
5458 assert
.deepStrictEqual(filePaths
, [
5459 path
.join(root
, "bar.js")
5464 describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
5466 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5469 ".eslintrc.json": JSON
.stringify({
5470 ignorePatterns
: "*.js"
5477 it("'isPathIgnored()' should return 'false' for 'foo.js'.", () => {
5478 const engine
= new InMemoryCLIEngine({ ignore
: false });
5480 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5483 it("'executeOnFiles()' should verify 'foo.js'.", () => {
5484 const engine
= new InMemoryCLIEngine({ ignore
: false });
5485 const filePaths
= engine
.executeOnFiles("**/*.js")
5487 .map(r
=> r
.filePath
)
5490 assert
.deepStrictEqual(filePaths
, [
5491 path
.join(root
, "foo.js")
5496 describe("ignorePatterns in overrides section is not allowed.", () => {
5498 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5501 ".eslintrc.js": `module.exports = ${JSON.stringify({
5505 ignorePatterns: "foo.js"
5514 it("should throw a configuration error.", () => {
5515 assert
.throws(() => {
5516 const engine
= new InMemoryCLIEngine();
5518 engine
.executeOnFiles("*.js");
5519 }, "Unexpected top-level property \"overrides[0].ignorePatterns\"");
5525 describe("'overrides[].files' adds lint targets", () => {
5526 const root
= getFixturePath("cli-engine/additional-lint-targets");
5527 let InMemoryCLIEngine
;
5529 describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
5531 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5534 ".eslintrc.json": JSON
.stringify({
5538 excludedFiles
: "**/ignore.txt"
5542 "foo/nested/test.txt": "",
5545 "foo/ignore.txt": "",
5548 "bar/ignore.txt": "",
5556 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt'.", () => {
5557 const engine
= new InMemoryCLIEngine();
5558 const filePaths
= engine
.executeOnFiles(".")
5560 .map(r
=> r
.filePath
)
5563 assert
.deepStrictEqual(filePaths
, [
5564 path
.join(root
, "bar/test.js"),
5565 path
.join(root
, "foo/test.js"),
5566 path
.join(root
, "foo/test.txt"),
5567 path
.join(root
, "test.js")
5571 it("'executeOnFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", () => {
5572 const engine
= new InMemoryCLIEngine();
5573 const filePaths
= engine
.executeOnFiles("**/*.js")
5575 .map(r
=> r
.filePath
)
5578 assert
.deepStrictEqual(filePaths
, [
5579 path
.join(root
, "bar/test.js"),
5580 path
.join(root
, "foo/test.js"),
5581 path
.join(root
, "test.js")
5586 describe("if { files: 'foo/**/*.txt' } is present,", () => {
5588 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5591 ".eslintrc.json": JSON
.stringify({
5594 files
: "foo/**/*.txt"
5598 "foo/nested/test.txt": "",
5609 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5610 const engine
= new InMemoryCLIEngine();
5611 const filePaths
= engine
.executeOnFiles(".")
5613 .map(r
=> r
.filePath
)
5616 assert
.deepStrictEqual(filePaths
, [
5617 path
.join(root
, "bar/test.js"),
5618 path
.join(root
, "foo/nested/test.txt"),
5619 path
.join(root
, "foo/test.js"),
5620 path
.join(root
, "foo/test.txt"),
5621 path
.join(root
, "test.js")
5626 describe("if { files: 'foo/**/*' } is present,", () => {
5628 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5631 ".eslintrc.json": JSON
.stringify({
5638 "foo/nested/test.txt": "",
5649 it("'executeOnFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5650 const engine
= new InMemoryCLIEngine();
5651 const filePaths
= engine
.executeOnFiles(".")
5653 .map(r
=> r
.filePath
)
5656 assert
.deepStrictEqual(filePaths
, [
5657 path
.join(root
, "bar/test.js"),
5658 path
.join(root
, "foo/test.js"),
5659 path
.join(root
, "test.js")
5664 describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
5666 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5669 "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
5672 files: "foo/**/*.txt"
5676 ".eslintrc.json": JSON
.stringify({
5679 "foo/nested/test.txt": "",
5690 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5691 const engine
= new InMemoryCLIEngine();
5692 const filePaths
= engine
.executeOnFiles(".")
5694 .map(r
=> r
.filePath
)
5697 assert
.deepStrictEqual(filePaths
, [
5698 path
.join(root
, "bar/test.js"),
5699 path
.join(root
, "foo/nested/test.txt"),
5700 path
.join(root
, "foo/test.js"),
5701 path
.join(root
, "foo/test.txt"),
5702 path
.join(root
, "test.js")
5707 describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
5709 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5712 "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
5716 files: "foo/**/*.txt"
5721 ".eslintrc.json": JSON
.stringify({
5722 extends: "plugin:foo/bar"
5724 "foo/nested/test.txt": "",
5735 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
5736 const engine
= new InMemoryCLIEngine();
5737 const filePaths
= engine
.executeOnFiles(".")
5739 .map(r
=> r
.filePath
)
5742 assert
.deepStrictEqual(filePaths
, [
5743 path
.join(root
, "bar/test.js"),
5744 path
.join(root
, "foo/nested/test.txt"),
5745 path
.join(root
, "foo/test.js"),
5746 path
.join(root
, "foo/test.txt"),
5747 path
.join(root
, "test.js")
5753 describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
5754 const root
= getFixturePath("cli-engine/config-and-overrides-files");
5756 /** @type {CLIEngine} */
5757 let InMemoryCLIEngine
;
5759 describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5761 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5764 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5774 "node_modules/myconf/foo/test.js": "a == b",
5775 "foo/test.js": "a == b"
5780 it("'executeOnFiles()' with 'foo/test.js' should use the override entry.", () => {
5781 const engine
= new InMemoryCLIEngine({
5782 configFile
: "node_modules/myconf/.eslintrc.json",
5787 const { results
} = engine
.executeOnFiles("foo/test.js");
5789 // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
5790 assert
.deepStrictEqual(results
, [
5793 filePath
: path
.join(root
, "foo/test.js"),
5794 fixableErrorCount
: 0,
5795 fixableWarningCount
: 0,
5802 message
: "Expected '===' and instead saw '=='.",
5803 messageId
: "unexpected",
5804 nodeType
: "BinaryExpression",
5815 it("'executeOnFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", () => {
5816 const engine
= new InMemoryCLIEngine({
5817 configFile
: "node_modules/myconf/.eslintrc.json",
5822 const { results
} = engine
.executeOnFiles("node_modules/myconf/foo/test.js");
5824 // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
5825 assert
.deepStrictEqual(results
, [
5828 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
5829 fixableErrorCount
: 0,
5830 fixableWarningCount
: 0,
5838 describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5840 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5843 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5847 excludedFiles
: "foo/*.js",
5854 "node_modules/myconf/foo/test.js": "a == b",
5855 "foo/test.js": "a == b"
5860 it("'executeOnFiles()' with 'foo/test.js' should NOT use the override entry.", () => {
5861 const engine
= new InMemoryCLIEngine({
5862 configFile
: "node_modules/myconf/.eslintrc.json",
5867 const { results
} = engine
.executeOnFiles("foo/test.js");
5869 // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
5870 assert
.deepStrictEqual(results
, [
5873 filePath
: path
.join(root
, "foo/test.js"),
5874 fixableErrorCount
: 0,
5875 fixableWarningCount
: 0,
5882 it("'executeOnFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", () => {
5883 const engine
= new InMemoryCLIEngine({
5884 configFile
: "node_modules/myconf/.eslintrc.json",
5889 const { results
} = engine
.executeOnFiles("node_modules/myconf/foo/test.js");
5891 // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
5892 assert
.deepStrictEqual(results
, [
5895 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
5896 fixableErrorCount
: 0,
5897 fixableWarningCount
: 0,
5904 message
: "Expected '===' and instead saw '=='.",
5905 messageId
: "unexpected",
5906 nodeType
: "BinaryExpression",
5918 describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5920 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5923 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5924 ignorePatterns
: ["!/node_modules/myconf", "foo/*.js"],
5929 "node_modules/myconf/foo/test.js": "a == b",
5930 "foo/test.js": "a == b"
5935 it("'executeOnFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", () => {
5936 const engine
= new InMemoryCLIEngine({
5937 configFile
: "node_modules/myconf/.eslintrc.json",
5941 const files
= engine
.executeOnFiles("**/*.js")
5943 .map(r
=> r
.filePath
)
5946 assert
.deepStrictEqual(files
, [
5947 path
.join(root
, "node_modules/myconf/foo/test.js")
5953 describe("plugin conflicts", () => {
5958 root
= getFixturePath(`cli-engine/plugin-conflicts-${++uid}`);
5961 /** @type {typeof CLIEngine} */
5962 let InMemoryCLIEngine
;
5965 * Verify thrown errors.
5966 * @param {() => void} f The function to run and throw.
5967 * @param {Record<string, any>} props The properties to verify.
5970 function assertThrows(f
, props
) {
5974 for (const [key
, value
] of Object
.entries(props
)) {
5975 assert
.deepStrictEqual(error
[key
], value
, key
);
5980 assert
.fail("Function should throw an error, but not.");
5983 describe("between a config file and linear extendees.", () => {
5985 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
5988 "node_modules/eslint-plugin-foo/index.js": "",
5989 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
5990 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5994 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
5995 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
5998 ".eslintrc.json": JSON
.stringify({
6007 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", () => {
6008 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6010 engine
.executeOnFiles("test.js");
6014 describe("between a config file and same-depth extendees.", () => {
6016 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6019 "node_modules/eslint-plugin-foo/index.js": "",
6020 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6021 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6024 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6025 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6028 ".eslintrc.json": JSON
.stringify({
6029 extends: ["one", "two"],
6037 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", () => {
6038 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6040 engine
.executeOnFiles("test.js");
6044 describe("between two config files in different directories, with single node_modules.", () => {
6046 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6049 "node_modules/eslint-plugin-foo/index.js": "",
6050 ".eslintrc.json": JSON
.stringify({
6053 "subdir/.eslintrc.json": JSON
.stringify({
6056 "subdir/test.js": ""
6061 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.)", () => {
6062 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6064 engine
.executeOnFiles("subdir/test.js");
6068 describe("between two config files in different directories, with multiple node_modules.", () => {
6070 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6073 "node_modules/eslint-plugin-foo/index.js": "",
6074 ".eslintrc.json": JSON
.stringify({
6077 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6078 "subdir/.eslintrc.json": JSON
.stringify({
6081 "subdir/test.js": ""
6086 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.)", () => {
6087 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6090 () => engine
.executeOnFiles("subdir/test.js"),
6092 message
: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
6093 messageTemplate
: "plugin-conflict",
6098 filePath
: path
.join(root
, "subdir/node_modules/eslint-plugin-foo/index.js"),
6099 importerName
: `subdir${path.sep}.eslintrc.json`
6102 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
6103 importerName
: ".eslintrc.json"
6112 describe("between '--config' option and a regular config file, with single node_modules.", () => {
6114 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6117 "node_modules/eslint-plugin-foo/index.js": "",
6118 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6121 ".eslintrc.json": JSON
.stringify({
6129 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.)", () => {
6130 const engine
= new InMemoryCLIEngine({
6132 configFile
: "node_modules/mine/.eslintrc.json"
6135 engine
.executeOnFiles("test.js");
6139 describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
6141 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6144 "node_modules/eslint-plugin-foo/index.js": "",
6145 "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
6146 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6149 ".eslintrc.json": JSON
.stringify({
6157 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.)", () => {
6158 const engine
= new InMemoryCLIEngine({
6160 configFile
: "node_modules/mine/.eslintrc.json"
6164 () => engine
.executeOnFiles("test.js"),
6166 message
: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
6167 messageTemplate
: "plugin-conflict",
6172 filePath
: path
.join(root
, "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
6173 importerName
: "--config"
6176 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
6177 importerName
: ".eslintrc.json"
6186 describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
6188 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6191 "node_modules/eslint-plugin-foo/index.js": "",
6192 "subdir/.eslintrc.json": JSON
.stringify({
6195 "subdir/test.js": ""
6200 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.)", () => {
6201 const engine
= new InMemoryCLIEngine({
6206 engine
.executeOnFiles("subdir/test.js");
6210 describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
6212 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6215 "node_modules/eslint-plugin-foo/index.js": "",
6216 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6217 "subdir/.eslintrc.json": JSON
.stringify({
6220 "subdir/test.js": ""
6225 it("'executeOnFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", () => {
6226 const engine
= new InMemoryCLIEngine({
6232 () => engine
.executeOnFiles("subdir/test.js"),
6234 message
: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
6235 messageTemplate
: "plugin-conflict",
6240 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
6241 importerName
: "CLIOptions"
6244 filePath
: path
.join(root
, "subdir/node_modules/eslint-plugin-foo/index.js"),
6245 importerName
: `subdir${path.sep}.eslintrc.json`
6254 describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
6256 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6259 "node_modules/eslint-plugin-foo/index.js": "",
6260 ".eslintrc.json": JSON
.stringify({
6263 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6264 "subdir/.eslintrc.json": JSON
.stringify({
6267 "subdir/test.js": ""
6272 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", () => {
6273 const engine
= new InMemoryCLIEngine({
6275 resolvePluginsRelativeTo
: root
6278 engine
.executeOnFiles("subdir/test.js");
6282 describe("between two config files with different target files.", () => {
6284 InMemoryCLIEngine
= defineCLIEngineWithInMemoryFileSystem({
6287 "one/node_modules/eslint-plugin-foo/index.js": "",
6288 "one/.eslintrc.json": JSON
.stringify({
6292 "two/node_modules/eslint-plugin-foo/index.js": "",
6293 "two/.eslintrc.json": JSON
.stringify({
6301 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.)", () => {
6302 const engine
= new InMemoryCLIEngine({ cwd
: root
});
6303 const { results
} = engine
.executeOnFiles("*/test.js");
6305 assert
.strictEqual(results
.length
, 2);