2 * @fileoverview Tests for CLIEngine.
3 * @author Nicholas C. Zakas
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const assert
= require("chai").assert
,
13 path
= require("path"),
14 sinon
= require("sinon"),
15 shell
= require("shelljs"),
18 hash
= require("../../../lib/cli-engine/hash"),
21 CascadingConfigArrayFactory
23 } = require("@eslint/eslintrc"),
24 { unIndent
, createCustomTeardown
} = require("../../_utils");
26 const proxyquire
= require("proxyquire").noCallThru().noPreserveCache();
27 const fCache
= require("file-entry-cache");
29 //------------------------------------------------------------------------------
31 //------------------------------------------------------------------------------
33 describe("CLIEngine", () => {
35 const examplePluginName
= "eslint-plugin-example",
36 examplePluginNameWithNamespace
= "@eslint/eslint-plugin-example",
39 "example-rule": require("../../fixtures/rules/custom-rule"),
40 "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
43 examplePreprocessorName
= "eslint-plugin-processor",
44 originalDir
= process
.cwd(),
45 fixtureDir
= path
.resolve(fs
.realpathSync(os
.tmpdir()), "eslint/fixtures");
47 /** @type {import("../../../lib/cli-engine").CLIEngine} */
50 /** @type {import("../../../lib/cli-engine/cli-engine").getCLIEngineInternalSlots} */
51 let getCLIEngineInternalSlots;
54 * Returns the path inside of the fixture directory.
55 * @param {...string} args file path segments.
56 * @returns {string} The path inside the fixture directory.
59 function getFixturePath(...args
) {
60 const filepath
= path
.join(fixtureDir
, ...args
);
63 return fs
.realpathSync(filepath
);
70 * Create the CLIEngine object by mocking some of the plugins
71 * @param {Object} options options for CLIEngine
72 * @returns {CLIEngine} engine object
75 function cliEngineWithPlugins(options
) {
76 return new CLIEngine(options
, {
78 [examplePluginName
]: examplePlugin
,
79 [examplePluginNameWithNamespace
]: examplePlugin
,
80 [examplePreprocessorName
]: require("../../fixtures/processors/custom-processor")
85 // copy into clean area so as not to get "infected" by this project's .eslintrc files
89 * GitHub Actions Windows and macOS runners occasionally exhibit
90 * extremely slow filesystem operations, during which copying fixtures
91 * exceeds the default test timeout, so raise it just for this hook.
92 * Mocha uses `this` to set timeouts on an individual hook level.
94 this.timeout(60 * 1000); // eslint-disable-line no-invalid-this -- Mocha API
95 shell
.mkdir("-p", fixtureDir
);
96 shell
.cp("-r", "./tests/fixtures/.", fixtureDir
);
100 ({ CLIEngine
, getCLIEngineInternalSlots
} = require("../../../lib/cli-engine/cli-engine"));
104 shell
.rm("-r", fixtureDir
);
107 describe("new CLIEngine(options)", () => {
108 it("the default value of 'options.cwd' should be the current working directory.", () => {
109 process
.chdir(__dirname
);
111 const engine
= new CLIEngine();
112 const internalSlots
= getCLIEngineInternalSlots(engine
);
114 assert
.strictEqual(internalSlots
.options
.cwd
, __dirname
);
116 process
.chdir(originalDir
);
120 it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
121 assert
.throws(() => {
122 // eslint-disable-next-line no-new -- Testing synchronous throwing
123 new CLIEngine({ ignorePath
: fixtureDir
});
124 }, `Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`);
127 // https://github.com/eslint/eslint/issues/2380
128 it("should not modify baseConfig when format is specified", () => {
129 const customBaseConfig
= { root
: true };
131 new CLIEngine({ baseConfig
: customBaseConfig
, format
: "foo" }); // eslint-disable-line no-new -- Test side effects
133 assert
.deepStrictEqual(customBaseConfig
, { root
: true });
137 describe("executeOnText()", () => {
141 it("should report the total and per file errors when using local cwd .eslintrc", () => {
143 engine
= new CLIEngine();
145 const report
= engine
.executeOnText("var foo = 'bar';");
147 assert
.strictEqual(report
.results
.length
, 1);
148 assert
.strictEqual(report
.errorCount
, 5);
149 assert
.strictEqual(report
.warningCount
, 0);
150 assert
.strictEqual(report
.fatalErrorCount
, 0);
151 assert
.strictEqual(report
.fixableErrorCount
, 3);
152 assert
.strictEqual(report
.fixableWarningCount
, 0);
153 assert
.strictEqual(report
.results
[0].messages
.length
, 5);
154 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "strict");
155 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-var");
156 assert
.strictEqual(report
.results
[0].messages
[2].ruleId
, "no-unused-vars");
157 assert
.strictEqual(report
.results
[0].messages
[3].ruleId
, "quotes");
158 assert
.strictEqual(report
.results
[0].messages
[4].ruleId
, "eol-last");
159 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 3);
160 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
161 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
164 it("should report the total and per file warnings when using local cwd .eslintrc", () => {
166 engine
= new CLIEngine({
176 const report
= engine
.executeOnText("var foo = 'bar';");
178 assert
.strictEqual(report
.results
.length
, 1);
179 assert
.strictEqual(report
.errorCount
, 0);
180 assert
.strictEqual(report
.warningCount
, 5);
181 assert
.strictEqual(report
.fixableErrorCount
, 0);
182 assert
.strictEqual(report
.fixableWarningCount
, 3);
183 assert
.strictEqual(report
.results
[0].messages
.length
, 5);
184 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "strict");
185 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-var");
186 assert
.strictEqual(report
.results
[0].messages
[2].ruleId
, "no-unused-vars");
187 assert
.strictEqual(report
.results
[0].messages
[3].ruleId
, "quotes");
188 assert
.strictEqual(report
.results
[0].messages
[4].ruleId
, "eol-last");
189 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
190 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 3);
191 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
194 it("should report one message when using specific config file", () => {
196 engine
= new CLIEngine({
197 configFile
: "fixtures/configurations/quotes-error.json",
199 cwd
: getFixturePath("..")
202 const report
= engine
.executeOnText("var foo = 'bar';");
204 assert
.strictEqual(report
.results
.length
, 1);
205 assert
.strictEqual(report
.errorCount
, 1);
206 assert
.strictEqual(report
.warningCount
, 0);
207 assert
.strictEqual(report
.fixableErrorCount
, 1);
208 assert
.strictEqual(report
.fixableWarningCount
, 0);
209 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
210 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
211 assert
.isUndefined(report
.results
[0].messages
[0].output
);
212 assert
.strictEqual(report
.results
[0].errorCount
, 1);
213 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
214 assert
.strictEqual(report
.results
[0].warningCount
, 0);
215 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
218 it("should report the filename when passed in", () => {
220 engine
= new CLIEngine({
222 cwd
: getFixturePath()
225 const report
= engine
.executeOnText("var foo = 'bar';", "test.js");
227 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("test.js"));
228 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
231 it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", () => {
232 engine
= new CLIEngine({
233 ignorePath
: getFixturePath(".eslintignore"),
234 cwd
: getFixturePath("..")
237 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js", true);
239 assert
.strictEqual(report
.results
.length
, 1);
240 assert
.strictEqual(report
.errorCount
, 0);
241 assert
.strictEqual(report
.warningCount
, 1);
242 assert
.strictEqual(report
.fatalErrorCount
, 0);
243 assert
.strictEqual(report
.fixableErrorCount
, 0);
244 assert
.strictEqual(report
.fixableWarningCount
, 0);
245 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("passing.js"));
246 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
247 assert
.strictEqual(report
.results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
248 assert
.isUndefined(report
.results
[0].messages
[0].output
);
249 assert
.strictEqual(report
.results
[0].errorCount
, 0);
250 assert
.strictEqual(report
.results
[0].warningCount
, 1);
251 assert
.strictEqual(report
.results
[0].fatalErrorCount
, 0);
252 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
253 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
254 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
257 it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", () => {
258 engine
= new CLIEngine({
259 ignorePath
: getFixturePath(".eslintignore"),
260 cwd
: getFixturePath("..")
263 // intentional parsing error
264 const report
= engine
.executeOnText("va r bar = foo;", "fixtures/passing.js", false);
266 // should not report anything because the file is ignored
267 assert
.strictEqual(report
.results
.length
, 0);
270 it("should suppress excluded file warnings by default", () => {
271 engine
= new CLIEngine({
272 ignorePath
: getFixturePath(".eslintignore"),
273 cwd
: getFixturePath("..")
276 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
278 // should not report anything because there are no errors
279 assert
.strictEqual(report
.results
.length
, 0);
282 it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", () => {
284 engine
= new CLIEngine({
285 ignorePath
: "fixtures/.eslintignore",
286 cwd
: getFixturePath(".."),
294 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
296 assert
.strictEqual(report
.results
.length
, 1);
297 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("passing.js"));
298 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-undef");
299 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
300 assert
.isUndefined(report
.results
[0].messages
[0].output
);
301 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
304 it("should return a message and fixed text when in fix mode", () => {
306 engine
= new CLIEngine({
313 cwd
: getFixturePath()
316 const report
= engine
.executeOnText("var bar = foo", "passing.js");
318 assert
.deepStrictEqual(report
, {
321 filePath
: getFixturePath("passing.js"),
323 suppressedMessages
: [],
327 fixableErrorCount
: 0,
328 fixableWarningCount
: 0,
329 output
: "var bar = foo;"
335 fixableErrorCount
: 0,
336 fixableWarningCount
: 0,
337 usedDeprecatedRules
: []
341 it("correctly autofixes semicolon-conflicting-fixes", () => {
342 engine
= new CLIEngine({
343 cwd
: path
.join(fixtureDir
, ".."),
347 const inputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.js");
348 const outputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
349 const report
= engine
.executeOnFiles([inputPath
]);
350 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
352 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
353 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
356 it("correctly autofixes return-conflicting-fixes", () => {
357 engine
= new CLIEngine({
358 cwd
: path
.join(fixtureDir
, ".."),
362 const inputPath
= getFixturePath("autofix/return-conflicting-fixes.js");
363 const outputPath
= getFixturePath("autofix/return-conflicting-fixes.expected.js");
364 const report
= engine
.executeOnFiles([inputPath
]);
365 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
367 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
368 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
371 describe("Fix Types", () => {
373 it("should throw an error when an invalid fix type is specified", () => {
374 assert
.throws(() => {
375 engine
= new CLIEngine({
376 cwd
: path
.join(fixtureDir
, ".."),
381 }, /invalid fix type/iu);
384 it("should not fix any rules when fixTypes is used without fix", () => {
385 engine
= new CLIEngine({
386 cwd
: path
.join(fixtureDir
, ".."),
392 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
393 const report
= engine
.executeOnFiles([inputPath
]);
395 assert
.isUndefined(report
.results
[0].output
);
398 it("should not fix non-style rules when fixTypes has only 'layout'", () => {
399 engine
= new CLIEngine({
400 cwd
: path
.join(fixtureDir
, ".."),
405 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
406 const outputPath
= getFixturePath("fix-types/fix-only-semi.expected.js");
407 const report
= engine
.executeOnFiles([inputPath
]);
408 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
410 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
413 it("should not fix style or problem rules when fixTypes has only 'suggestion'", () => {
414 engine
= new CLIEngine({
415 cwd
: path
.join(fixtureDir
, ".."),
418 fixTypes
: ["suggestion"]
420 const inputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
421 const outputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
422 const report
= engine
.executeOnFiles([inputPath
]);
423 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
425 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
428 it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", () => {
429 engine
= new CLIEngine({
430 cwd
: path
.join(fixtureDir
, ".."),
433 fixTypes
: ["suggestion", "layout"]
435 const inputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
436 const outputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
437 const report
= engine
.executeOnFiles([inputPath
]);
438 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
440 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
443 it("should not throw an error when a rule doesn't have a 'meta' property", () => {
444 engine
= new CLIEngine({
445 cwd
: path
.join(fixtureDir
, ".."),
448 fixTypes
: ["layout"],
449 rulePaths
: [getFixturePath("rules", "fix-types-test")]
452 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
453 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
454 const report
= engine
.executeOnFiles([inputPath
]);
455 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
457 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
460 it("should not throw an error when a rule is loaded after initialization with executeOnFiles()", () => {
461 engine
= new CLIEngine({
462 cwd
: path
.join(fixtureDir
, ".."),
467 const internalSlots
= getCLIEngineInternalSlots(engine
);
469 internalSlots
.linter
.defineRule(
471 require(getFixturePath("rules", "fix-types-test", "no-program.js"))
474 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
475 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
476 const report
= engine
.executeOnFiles([inputPath
]);
477 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
479 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
482 it("should not throw an error when a rule is loaded after initialization with executeOnText()", () => {
483 engine
= new CLIEngine({
484 cwd
: path
.join(fixtureDir
, ".."),
489 const internalSlots
= getCLIEngineInternalSlots(engine
);
491 internalSlots
.linter
.defineRule(
493 require(getFixturePath("rules", "fix-types-test", "no-program.js"))
496 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
497 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
498 const report
= engine
.executeOnText(fs
.readFileSync(inputPath
, { encoding
: "utf8" }), inputPath
);
499 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
501 assert
.strictEqual(report
.results
[0].output
, expectedOutput
);
506 it("should return a message and omit fixed text when in fix mode and fixes aren't done", () => {
508 engine
= new CLIEngine({
515 cwd
: getFixturePath()
518 const report
= engine
.executeOnText("var bar = foo", "passing.js");
520 assert
.deepStrictEqual(report
, {
523 filePath
: getFixturePath("passing.js"),
529 message
: "'foo' is not defined.",
534 nodeType
: "Identifier"
537 suppressedMessages
: [],
541 fixableErrorCount
: 0,
542 fixableWarningCount
: 0,
543 source
: "var bar = foo"
549 fixableErrorCount
: 0,
550 fixableWarningCount
: 0,
551 usedDeprecatedRules
: []
555 it("should not delete code if there is a syntax error after trying to autofix.", () => {
556 engine
= cliEngineWithPlugins({
559 plugins
: ["example"],
561 "example/make-syntax-error": "error"
564 cwd
: getFixturePath()
567 const report
= engine
.executeOnText("var bar = foo", "test.js");
569 assert
.deepStrictEqual(report
, {
572 filePath
: getFixturePath("test.js"),
578 message
: "Parsing error: Unexpected token is",
583 suppressedMessages
: [],
587 fixableErrorCount
: 0,
588 fixableWarningCount
: 0,
589 output
: "var bar = foothis is a syntax error."
595 fixableErrorCount
: 0,
596 fixableWarningCount
: 0,
597 usedDeprecatedRules
: []
601 it("should not crash even if there are any syntax error since the first time.", () => {
602 engine
= new CLIEngine({
606 "example/make-syntax-error": "error"
609 cwd
: getFixturePath()
612 const report
= engine
.executeOnText("var bar =", "test.js");
614 assert
.deepStrictEqual(report
, {
617 filePath
: getFixturePath("test.js"),
623 message
: "Parsing error: Unexpected token",
628 suppressedMessages
: [],
632 fixableErrorCount
: 0,
633 fixableWarningCount
: 0,
640 fixableErrorCount
: 0,
641 fixableWarningCount
: 0,
642 usedDeprecatedRules
: []
646 it("should return source code of file in `source` property when errors are present", () => {
647 engine
= new CLIEngine({
652 const report
= engine
.executeOnText("var foo = 'bar'");
654 assert
.strictEqual(report
.results
[0].source
, "var foo = 'bar'");
657 it("should return source code of file in `source` property when warnings are present", () => {
658 engine
= new CLIEngine({
663 const report
= engine
.executeOnText("var foo = 'bar'");
665 assert
.strictEqual(report
.results
[0].source
, "var foo = 'bar'");
669 it("should not return a `source` property when no errors or warnings are present", () => {
670 engine
= new CLIEngine({
675 const report
= engine
.executeOnText("var foo = 'bar';");
677 assert
.lengthOf(report
.results
[0].messages
, 0);
678 assert
.isUndefined(report
.results
[0].source
);
681 it("should not return a `source` property when fixes are applied", () => {
682 engine
= new CLIEngine({
691 const report
= engine
.executeOnText("var msg = 'hi' + foo\n");
693 assert
.isUndefined(report
.results
[0].source
);
694 assert
.strictEqual(report
.results
[0].output
, "var msg = 'hi' + foo;\n");
697 it("should return a `source` property when a parsing error has occurred", () => {
698 engine
= new CLIEngine({
703 const report
= engine
.executeOnText("var bar = foothis is a syntax error.\n return bar;");
705 assert
.deepStrictEqual(report
, {
714 message
: "Parsing error: Unexpected token is",
719 suppressedMessages
: [],
723 fixableErrorCount
: 0,
724 fixableWarningCount
: 0,
725 source
: "var bar = foothis is a syntax error.\n return bar;"
731 fixableErrorCount
: 0,
732 fixableWarningCount
: 0,
733 usedDeprecatedRules
: []
737 // https://github.com/eslint/eslint/issues/5547
738 it("should respect default ignore rules, even with --no-ignore", () => {
740 engine
= new CLIEngine({
741 cwd
: getFixturePath(),
745 const report
= engine
.executeOnText("var bar = foo;", "node_modules/passing.js", true);
746 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
748 assert
.strictEqual(report
.results
.length
, 1);
749 assert
.strictEqual(report
.results
[0].filePath
, getFixturePath("node_modules/passing.js"));
750 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
751 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
754 // @scope for @scope/eslint-plugin
755 describe("(plugin shorthand)", () => {
756 const Module
= require("module");
757 let originalFindPath
= null;
759 /* eslint-disable no-underscore-dangle -- Private Node API overriding */
761 originalFindPath
= Module
._findPath
;
762 Module
._findPath = function(id
, ...otherArgs
) {
763 if (id
=== "@scope/eslint-plugin") {
764 return path
.resolve(__dirname
, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
766 return originalFindPath
.call(this, id
, ...otherArgs
);
770 Module
._findPath
= originalFindPath
;
772 /* eslint-enable no-underscore-dangle -- Private Node API overriding */
774 it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
775 engine
= new CLIEngine({ cwd
: getFixturePath("plugin-shorthand/basic") });
776 const report
= engine
.executeOnText("var x = 0", "index.js").results
[0];
778 assert
.strictEqual(report
.filePath
, getFixturePath("plugin-shorthand/basic/index.js"));
779 assert
.strictEqual(report
.messages
[0].ruleId
, "@scope/rule");
780 assert
.strictEqual(report
.messages
[0].message
, "OK");
781 assert
.strictEqual(report
.suppressedMessages
.length
, 0);
784 it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", () => {
785 engine
= new CLIEngine({ cwd
: getFixturePath("plugin-shorthand/extends") });
786 const report
= engine
.executeOnText("var x = 0", "index.js").results
[0];
788 assert
.strictEqual(report
.filePath
, getFixturePath("plugin-shorthand/extends/index.js"));
789 assert
.strictEqual(report
.messages
[0].ruleId
, "@scope/rule");
790 assert
.strictEqual(report
.messages
[0].message
, "OK");
791 assert
.strictEqual(report
.suppressedMessages
.length
, 0);
794 it("should warn when deprecated rules are found in a config", () => {
795 engine
= new CLIEngine({
798 configFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
801 const report
= engine
.executeOnText("foo");
803 assert
.deepStrictEqual(
804 report
.usedDeprecatedRules
,
805 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
807 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
811 describe("executeOnFiles()", () => {
813 /** @type {InstanceType<import("../../../lib/cli-engine").CLIEngine>} */
816 it("should use correct parser when custom parser is specified", () => {
818 engine
= new CLIEngine({
823 const filePath
= path
.resolve(__dirname
, "../../fixtures/configurations/parser/custom.js");
824 const report
= engine
.executeOnFiles([filePath
]);
826 assert
.strictEqual(report
.results
.length
, 1);
827 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
828 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Parsing error: Boom!");
829 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
832 it("should report zero messages when given a config file and a valid file", () => {
834 engine
= new CLIEngine({
836 configFile
: ".eslintrc.js"
839 const report
= engine
.executeOnFiles(["lib/**/cli*.js"]);
841 assert
.strictEqual(report
.results
.length
, 2);
842 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
843 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
844 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
847 it("should handle multiple patterns with overlapping files", () => {
849 engine
= new CLIEngine({
851 configFile
: ".eslintrc.js"
854 const report
= engine
.executeOnFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
856 assert
.strictEqual(report
.results
.length
, 2);
857 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
858 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
859 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
860 assert
.strictEqual(report
.results
[1].suppressedMessages
.length
, 0);
863 it("should report zero messages when given a config file and a valid file and espree as parser", () => {
865 engine
= new CLIEngine({
873 const report
= engine
.executeOnFiles(["lib/cli.js"]);
875 assert
.strictEqual(report
.results
.length
, 1);
876 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
877 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
880 it("should report zero messages when given a config file and a valid file and esprima as parser", () => {
882 engine
= new CLIEngine({
887 const report
= engine
.executeOnFiles(["lib/cli.js"]);
889 assert
.strictEqual(report
.results
.length
, 1);
890 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
891 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
894 it("should throw an error when given a config file and a valid file and invalid parser", () => {
896 engine
= new CLIEngine({
901 assert
.throws(() => engine
.executeOnFiles(["lib/cli.js"]), "Cannot find module 'test11'");
904 it("should report zero messages when given a directory with a .js2 file", () => {
906 engine
= new CLIEngine({
907 cwd
: path
.join(fixtureDir
, ".."),
911 const report
= engine
.executeOnFiles([getFixturePath("files/foo.js2")]);
913 assert
.strictEqual(report
.results
.length
, 1);
914 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
915 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
918 it("should fall back to defaults when extensions is set to an empty array", () => {
920 engine
= new CLIEngine({
921 cwd
: getFixturePath("configurations"),
922 configFile
: getFixturePath("configurations", "quotes-error.json"),
925 const report
= engine
.executeOnFiles([getFixturePath("single-quoted.js")]);
927 assert
.strictEqual(report
.results
.length
, 1);
928 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
929 assert
.strictEqual(report
.errorCount
, 1);
930 assert
.strictEqual(report
.warningCount
, 0);
931 assert
.strictEqual(report
.fixableErrorCount
, 1);
932 assert
.strictEqual(report
.fixableWarningCount
, 0);
933 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
934 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
935 assert
.strictEqual(report
.results
[0].errorCount
, 1);
936 assert
.strictEqual(report
.results
[0].warningCount
, 0);
937 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
938 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
939 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
942 it("should report zero messages when given a directory with a .js and a .js2 file", () => {
944 engine
= new CLIEngine({
945 extensions
: [".js", ".js2"],
947 cwd
: getFixturePath("..")
950 const report
= engine
.executeOnFiles(["fixtures/files/"]);
952 assert
.strictEqual(report
.results
.length
, 2);
953 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
954 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
955 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
958 it("should report zero messages when given a '**' pattern with a .js and a .js2 file", () => {
960 engine
= new CLIEngine({
961 extensions
: [".js", ".js2"],
963 cwd
: path
.join(fixtureDir
, "..")
966 const report
= engine
.executeOnFiles(["fixtures/files/*"]);
968 assert
.strictEqual(report
.results
.length
, 2);
969 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
970 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
971 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
974 it("should resolve globs when 'globInputPaths' option is true", () => {
975 engine
= new CLIEngine({
976 extensions
: [".js", ".js2"],
978 cwd
: getFixturePath("..")
981 const report
= engine
.executeOnFiles(["fixtures/files/*"]);
983 assert
.strictEqual(report
.results
.length
, 2);
984 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
985 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
986 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
989 it("should not resolve globs when 'globInputPaths' option is false", () => {
990 engine
= new CLIEngine({
991 extensions
: [".js", ".js2"],
993 cwd
: getFixturePath(".."),
994 globInputPaths
: false
997 assert
.throws(() => {
998 engine
.executeOnFiles(["fixtures/files/*"]);
999 }, "No files matching 'fixtures/files/*' were found (glob was disabled).");
1002 it("should report on all files passed explicitly, even if ignored by default", () => {
1004 engine
= new CLIEngine({
1005 cwd
: getFixturePath("cli-engine")
1008 const report
= engine
.executeOnFiles(["node_modules/foo.js"]);
1009 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
1011 assert
.strictEqual(report
.results
.length
, 1);
1012 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1013 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1014 assert
.strictEqual(report
.results
[0].fatalErrorCount
, 0);
1015 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1016 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1017 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1018 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1021 it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", () => {
1023 engine
= new CLIEngine({
1024 cwd
: getFixturePath("cli-engine"),
1026 quotes
: [2, "single"]
1030 const report
= engine
.executeOnFiles(["hidden/.hiddenfolder/*.js"]);
1032 assert
.strictEqual(report
.results
.length
, 1);
1033 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1034 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1035 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1036 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1037 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1040 it("should not check default ignored files without --no-ignore flag", () => {
1042 engine
= new CLIEngine({
1043 cwd
: getFixturePath("cli-engine")
1046 assert
.throws(() => {
1047 engine
.executeOnFiles(["node_modules"]);
1048 }, "All files matched by 'node_modules' are ignored.");
1051 // https://github.com/eslint/eslint/issues/5547
1052 it("should not check node_modules files even with --no-ignore flag", () => {
1054 engine
= new CLIEngine({
1055 cwd
: getFixturePath("cli-engine"),
1059 assert
.throws(() => {
1060 engine
.executeOnFiles(["node_modules"]);
1061 }, "All files matched by 'node_modules' are ignored.");
1064 it("should not check .hidden files if they are passed explicitly without --no-ignore flag", () => {
1066 engine
= new CLIEngine({
1067 cwd
: getFixturePath(".."),
1070 quotes
: [2, "single"]
1074 const report
= engine
.executeOnFiles(["fixtures/files/.bar.js"]);
1075 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1077 assert
.strictEqual(report
.results
.length
, 1);
1078 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1079 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1080 assert
.strictEqual(report
.results
[0].fatalErrorCount
, 0);
1081 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1082 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1083 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1084 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1087 // https://github.com/eslint/eslint/issues/12873
1088 it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", () => {
1089 engine
= new CLIEngine({
1090 cwd
: getFixturePath("cli-engine"),
1093 quotes
: [2, "single"]
1097 const report
= engine
.executeOnFiles(["hidden/.hiddenfolder/double-quotes.js"]);
1098 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1100 assert
.strictEqual(report
.results
.length
, 1);
1101 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1102 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1103 assert
.strictEqual(report
.results
[0].fatalErrorCount
, 0);
1104 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1105 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1106 assert
.strictEqual(report
.results
[0].messages
[0].message
, expectedMsg
);
1107 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1110 it("should check .hidden files if they are passed explicitly with --no-ignore flag", () => {
1112 engine
= new CLIEngine({
1113 cwd
: getFixturePath(".."),
1117 quotes
: [2, "single"]
1121 const report
= engine
.executeOnFiles(["fixtures/files/.bar.js"]);
1123 assert
.strictEqual(report
.results
.length
, 1);
1124 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1125 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1126 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1127 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1128 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1129 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1132 it("should check .hidden files if they are unignored with an --ignore-pattern", () => {
1134 engine
= new CLIEngine({
1135 cwd
: getFixturePath("cli-engine"),
1138 ignorePattern
: "!.hidden*",
1140 quotes
: [2, "single"]
1144 const report
= engine
.executeOnFiles(["hidden/"]);
1146 assert
.strictEqual(report
.results
.length
, 1);
1147 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1148 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1149 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1150 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1151 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1152 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1155 it("should report zero messages when given a pattern with a .js and a .js2 file", () => {
1157 engine
= new CLIEngine({
1158 extensions
: [".js", ".js2"],
1160 cwd
: path
.join(fixtureDir
, "..")
1163 const report
= engine
.executeOnFiles(["fixtures/files/*.?s*"]);
1165 assert
.strictEqual(report
.results
.length
, 2);
1166 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1167 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1168 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
1169 assert
.strictEqual(report
.results
[1].suppressedMessages
.length
, 0);
1172 it("should return one error message when given a config with rules with options and severity level set to error", () => {
1174 engine
= new CLIEngine({
1175 cwd
: getFixturePath("configurations"),
1176 configFile
: getFixturePath("configurations", "quotes-error.json")
1178 const report
= engine
.executeOnFiles([getFixturePath("single-quoted.js")]);
1180 assert
.strictEqual(report
.results
.length
, 1);
1181 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1182 assert
.strictEqual(report
.errorCount
, 1);
1183 assert
.strictEqual(report
.warningCount
, 0);
1184 assert
.strictEqual(report
.fixableErrorCount
, 1);
1185 assert
.strictEqual(report
.fixableWarningCount
, 0);
1186 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1187 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1188 assert
.strictEqual(report
.results
[0].errorCount
, 1);
1189 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1190 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 1);
1191 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1192 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1195 it("should return 3 messages when given a config file and a directory of 3 valid files", () => {
1197 engine
= new CLIEngine({
1198 cwd
: path
.join(fixtureDir
, ".."),
1199 configFile
: getFixturePath("configurations", "semi-error.json")
1202 const fixturePath
= getFixturePath("formatters");
1203 const report
= engine
.executeOnFiles([fixturePath
]);
1205 assert
.strictEqual(report
.errorCount
, 0);
1206 assert
.strictEqual(report
.warningCount
, 0);
1207 assert
.strictEqual(report
.fixableErrorCount
, 0);
1208 assert
.strictEqual(report
.fixableWarningCount
, 0);
1209 assert
.strictEqual(report
.results
.length
, 5);
1210 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[0].filePath
), "async.js");
1211 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1212 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1213 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1214 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1215 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1216 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1217 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[1].filePath
), "broken.js");
1218 assert
.strictEqual(report
.results
[1].errorCount
, 0);
1219 assert
.strictEqual(report
.results
[1].warningCount
, 0);
1220 assert
.strictEqual(report
.results
[1].fixableErrorCount
, 0);
1221 assert
.strictEqual(report
.results
[1].fixableWarningCount
, 0);
1222 assert
.strictEqual(report
.results
[1].messages
.length
, 0);
1223 assert
.strictEqual(report
.results
[1].suppressedMessages
.length
, 0);
1224 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[2].filePath
), "cwd.js");
1225 assert
.strictEqual(report
.results
[2].errorCount
, 0);
1226 assert
.strictEqual(report
.results
[2].warningCount
, 0);
1227 assert
.strictEqual(report
.results
[2].fixableErrorCount
, 0);
1228 assert
.strictEqual(report
.results
[2].fixableWarningCount
, 0);
1229 assert
.strictEqual(report
.results
[2].messages
.length
, 0);
1230 assert
.strictEqual(report
.results
[2].suppressedMessages
.length
, 0);
1231 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[3].filePath
), "simple.js");
1232 assert
.strictEqual(report
.results
[3].errorCount
, 0);
1233 assert
.strictEqual(report
.results
[3].warningCount
, 0);
1234 assert
.strictEqual(report
.results
[3].fixableErrorCount
, 0);
1235 assert
.strictEqual(report
.results
[3].fixableWarningCount
, 0);
1236 assert
.strictEqual(report
.results
[3].messages
.length
, 0);
1237 assert
.strictEqual(report
.results
[3].suppressedMessages
.length
, 0);
1238 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[4].filePath
), path
.join("test", "simple.js"));
1239 assert
.strictEqual(report
.results
[4].errorCount
, 0);
1240 assert
.strictEqual(report
.results
[4].warningCount
, 0);
1241 assert
.strictEqual(report
.results
[4].fixableErrorCount
, 0);
1242 assert
.strictEqual(report
.results
[4].fixableWarningCount
, 0);
1243 assert
.strictEqual(report
.results
[4].messages
.length
, 0);
1244 assert
.strictEqual(report
.results
[4].suppressedMessages
.length
, 0);
1248 it("should return the total number of errors when given multiple files", () => {
1250 engine
= new CLIEngine({
1251 cwd
: path
.join(fixtureDir
, ".."),
1252 configFile
: getFixturePath("configurations", "single-quotes-error.json")
1255 const fixturePath
= getFixturePath("formatters");
1256 const report
= engine
.executeOnFiles([fixturePath
]);
1258 assert
.strictEqual(report
.errorCount
, 6);
1259 assert
.strictEqual(report
.warningCount
, 0);
1260 assert
.strictEqual(report
.fixableErrorCount
, 6);
1261 assert
.strictEqual(report
.fixableWarningCount
, 0);
1262 assert
.strictEqual(report
.results
.length
, 5);
1263 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[0].filePath
), "async.js");
1264 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1265 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1266 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1267 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1268 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[1].filePath
), "broken.js");
1269 assert
.strictEqual(report
.results
[1].errorCount
, 0);
1270 assert
.strictEqual(report
.results
[1].warningCount
, 0);
1271 assert
.strictEqual(report
.results
[1].fixableErrorCount
, 0);
1272 assert
.strictEqual(report
.results
[1].fixableWarningCount
, 0);
1273 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[2].filePath
), "cwd.js");
1274 assert
.strictEqual(report
.results
[2].errorCount
, 0);
1275 assert
.strictEqual(report
.results
[2].warningCount
, 0);
1276 assert
.strictEqual(report
.results
[2].fixableErrorCount
, 0);
1277 assert
.strictEqual(report
.results
[2].fixableWarningCount
, 0);
1278 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[3].filePath
), "simple.js");
1279 assert
.strictEqual(report
.results
[3].errorCount
, 3);
1280 assert
.strictEqual(report
.results
[3].warningCount
, 0);
1281 assert
.strictEqual(report
.results
[3].fixableErrorCount
, 3);
1282 assert
.strictEqual(report
.results
[3].fixableWarningCount
, 0);
1283 assert
.strictEqual(path
.relative(fixturePath
, report
.results
[4].filePath
), path
.join("test", "simple.js"));
1284 assert
.strictEqual(report
.results
[4].errorCount
, 3);
1285 assert
.strictEqual(report
.results
[4].warningCount
, 0);
1286 assert
.strictEqual(report
.results
[4].fixableErrorCount
, 3);
1287 assert
.strictEqual(report
.results
[4].fixableWarningCount
, 0);
1290 it("should process when file is given by not specifying extensions", () => {
1292 engine
= new CLIEngine({
1294 cwd
: path
.join(fixtureDir
, "..")
1297 const report
= engine
.executeOnFiles(["fixtures/files/foo.js2"]);
1299 assert
.strictEqual(report
.results
.length
, 1);
1300 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1301 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1304 it("should return zero messages when given a config with environment set to browser", () => {
1306 engine
= new CLIEngine({
1307 cwd
: path
.join(fixtureDir
, ".."),
1308 configFile
: getFixturePath("configurations", "env-browser.json")
1311 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1313 assert
.strictEqual(report
.results
.length
, 1);
1314 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1315 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1318 it("should return zero messages when given an option to set environment to browser", () => {
1320 engine
= new CLIEngine({
1321 cwd
: path
.join(fixtureDir
, ".."),
1329 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1331 assert
.strictEqual(report
.results
.length
, 1);
1332 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1333 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1336 it("should return zero messages when given a config with environment set to Node.js", () => {
1338 engine
= new CLIEngine({
1339 cwd
: path
.join(fixtureDir
, ".."),
1340 configFile
: getFixturePath("configurations", "env-node.json")
1343 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("globals-node.js"))]);
1345 assert
.strictEqual(report
.results
.length
, 1);
1346 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1347 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1350 it("should not return results from previous call when calling more than once", () => {
1352 engine
= new CLIEngine({
1353 cwd
: path
.join(fixtureDir
, ".."),
1360 const failFilePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1361 const passFilePath
= fs
.realpathSync(getFixturePath("passing.js"));
1363 let report
= engine
.executeOnFiles([failFilePath
]);
1365 assert
.strictEqual(report
.results
.length
, 1);
1366 assert
.strictEqual(report
.results
[0].filePath
, failFilePath
);
1367 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1368 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "semi");
1369 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1370 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1372 report
= engine
.executeOnFiles([passFilePath
]);
1373 assert
.strictEqual(report
.results
.length
, 1);
1374 assert
.strictEqual(report
.results
[0].filePath
, passFilePath
);
1375 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1376 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1380 it("should throw an error when given a directory with all eslint excluded files in the directory", () => {
1382 engine
= new CLIEngine({
1383 ignorePath
: getFixturePath(".eslintignore")
1386 assert
.throws(() => {
1387 engine
.executeOnFiles([getFixturePath("./cli-engine/")]);
1388 }, `All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`);
1391 it("should throw an error when all given files are ignored", () => {
1393 engine
= new CLIEngine({
1394 ignorePath
: getFixturePath(".eslintignore")
1397 assert
.throws(() => {
1398 engine
.executeOnFiles(["tests/fixtures/cli-engine/"]);
1399 }, "All files matched by 'tests/fixtures/cli-engine/' are ignored.");
1402 it("should throw an error when all given files are ignored even with a `./` prefix", () => {
1403 engine
= new CLIEngine({
1404 ignorePath
: getFixturePath(".eslintignore")
1407 assert
.throws(() => {
1408 engine
.executeOnFiles(["./tests/fixtures/cli-engine/"]);
1409 }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
1412 // https://github.com/eslint/eslint/issues/3788
1413 it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", () => {
1414 engine
= new CLIEngine({
1415 ignorePath
: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
1418 quotes
: [2, "double"]
1420 cwd
: getFixturePath("cli-engine", "nested_node_modules")
1423 const report
= engine
.executeOnFiles(["."]);
1425 assert
.strictEqual(report
.results
.length
, 1);
1426 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1427 assert
.strictEqual(report
.results
[0].warningCount
, 0);
1428 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1429 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1430 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1433 // https://github.com/eslint/eslint/issues/3812
1434 it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", () => {
1435 engine
= new CLIEngine({
1436 ignorePath
: getFixturePath("cli-engine/.eslintignore2"),
1439 quotes
: [2, "double"]
1443 assert
.throws(() => {
1444 engine
.executeOnFiles(["./tests/fixtures/cli-engine/"]);
1445 }, "All files matched by './tests/fixtures/cli-engine/' are ignored.");
1448 it("should throw an error when all given files are ignored via ignore-pattern", () => {
1449 engine
= new CLIEngine({
1450 ignorePattern
: "tests/fixtures/single-quoted.js"
1453 assert
.throws(() => {
1454 engine
.executeOnFiles(["tests/fixtures/*-quoted.js"]);
1455 }, "All files matched by 'tests/fixtures/*-quoted.js' are ignored.");
1458 it("should return a warning when an explicitly given file is ignored", () => {
1459 engine
= new CLIEngine({
1460 ignorePath
: getFixturePath(".eslintignore"),
1461 cwd
: getFixturePath()
1464 const filePath
= getFixturePath("passing.js");
1466 const report
= engine
.executeOnFiles([filePath
]);
1468 assert
.strictEqual(report
.results
.length
, 1);
1469 assert
.strictEqual(report
.errorCount
, 0);
1470 assert
.strictEqual(report
.warningCount
, 1);
1471 assert
.strictEqual(report
.fatalErrorCount
, 0);
1472 assert
.strictEqual(report
.fixableErrorCount
, 0);
1473 assert
.strictEqual(report
.fixableWarningCount
, 0);
1474 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1475 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1476 assert
.strictEqual(report
.results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
1477 assert
.strictEqual(report
.results
[0].errorCount
, 0);
1478 assert
.strictEqual(report
.results
[0].warningCount
, 1);
1479 assert
.strictEqual(report
.results
[0].fatalErrorCount
, 0);
1480 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
1481 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
1482 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1485 it("should return two messages when given a file in excluded files list while ignore is off", () => {
1487 engine
= new CLIEngine({
1488 ignorePath
: getFixturePath(".eslintignore"),
1495 const filePath
= fs
.realpathSync(getFixturePath("undef.js"));
1497 const report
= engine
.executeOnFiles([filePath
]);
1499 assert
.strictEqual(report
.results
.length
, 1);
1500 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1501 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-undef");
1502 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1503 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-undef");
1504 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 2);
1505 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1508 it("should return zero messages when executing a file with a shebang", () => {
1510 engine
= new CLIEngine({
1514 const report
= engine
.executeOnFiles([getFixturePath("shebang.js")]);
1516 assert
.strictEqual(report
.results
.length
, 1);
1517 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1518 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1521 it("should give a warning when loading a custom rule that doesn't exist", () => {
1523 engine
= new CLIEngine({
1525 rulesPaths
: [getFixturePath("rules", "dir1")],
1526 configFile
: getFixturePath("rules", "missing-rule.json")
1528 const report
= engine
.executeOnFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1530 assert
.strictEqual(report
.results
.length
, 1);
1531 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1532 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "missing-rule");
1533 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1534 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Definition for rule 'missing-rule' was not found.");
1535 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1538 it("should throw an error when loading a bad custom rule", () => {
1540 engine
= new CLIEngine({
1542 rulePaths
: [getFixturePath("rules", "wrong")],
1543 configFile
: getFixturePath("rules", "eslint.json")
1547 assert
.throws(() => {
1548 engine
.executeOnFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1549 }, /Error while loading rule 'custom-rule'/u);
1552 it("should return one message when a custom rule matches a file", () => {
1554 engine
= new CLIEngine({
1557 rulePaths
: [getFixturePath("rules/")],
1558 configFile
: getFixturePath("rules", "eslint.json")
1561 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1563 const report
= engine
.executeOnFiles([filePath
]);
1565 assert
.strictEqual(report
.results
.length
, 1);
1566 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1567 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1568 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "custom-rule");
1569 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1570 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1573 it("should load custom rule from the provided cwd", () => {
1574 const cwd
= path
.resolve(getFixturePath("rules"));
1576 engine
= new CLIEngine({
1580 configFile
: "eslint.json"
1583 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1585 const report
= engine
.executeOnFiles([filePath
]);
1587 assert
.strictEqual(report
.results
.length
, 1);
1588 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1589 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1590 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "custom-rule");
1591 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1592 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1595 it("should return messages when multiple custom rules match a file", () => {
1597 engine
= new CLIEngine({
1600 getFixturePath("rules", "dir1"),
1601 getFixturePath("rules", "dir2")
1603 configFile
: getFixturePath("rules", "multi-rulesdirs.json")
1606 const filePath
= fs
.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.js"));
1608 const report
= engine
.executeOnFiles([filePath
]);
1610 assert
.strictEqual(report
.results
.length
, 1);
1611 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1612 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
1613 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-literals");
1614 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1615 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "no-strings");
1616 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 2);
1617 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1620 it("should return zero messages when executing without useEslintrc flag", () => {
1622 engine
= new CLIEngine({
1627 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1629 const report
= engine
.executeOnFiles([filePath
]);
1631 assert
.strictEqual(report
.results
.length
, 1);
1632 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1633 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1634 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1637 it("should return zero messages when executing without useEslintrc flag in Node.js environment", () => {
1639 engine
= new CLIEngine({
1645 const filePath
= fs
.realpathSync(getFixturePath("process-exit.js"));
1647 const report
= engine
.executeOnFiles([filePath
]);
1649 assert
.strictEqual(report
.results
.length
, 1);
1650 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1651 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1652 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1655 it("should return zero messages when executing with base-config flag set to false", () => {
1657 engine
= new CLIEngine({
1663 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1665 const report
= engine
.executeOnFiles([filePath
]);
1667 assert
.strictEqual(report
.results
.length
, 1);
1668 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1669 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1670 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1673 it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", () => {
1675 engine
= new CLIEngine({
1681 const filePath
= fs
.realpathSync(getFixturePath("eslintrc", "quotes.js"));
1683 const report
= engine
.executeOnFiles([filePath
]);
1685 assert
.strictEqual(report
.results
.length
, 1);
1686 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1687 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1688 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1691 it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", () => {
1693 engine
= new CLIEngine({
1699 const filePath
= fs
.realpathSync(getFixturePath("packagejson", "quotes.js"));
1701 const report
= engine
.executeOnFiles([filePath
]);
1703 assert
.strictEqual(report
.results
.length
, 1);
1704 assert
.strictEqual(report
.results
[0].filePath
, filePath
);
1705 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1706 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1709 it("should warn when deprecated rules are configured", () => {
1710 engine
= new CLIEngine({
1712 configFile
: ".eslintrc.js",
1720 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1722 assert
.sameDeepMembers(
1723 report
.usedDeprecatedRules
,
1725 { ruleId
: "indent-legacy", replacedBy
: ["indent"] },
1726 { ruleId
: "require-jsdoc", replacedBy
: [] },
1727 { ruleId
: "valid-jsdoc", replacedBy
: [] }
1730 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1733 it("should not warn when deprecated rules are not configured", () => {
1734 engine
= new CLIEngine({
1736 configFile
: ".eslintrc.js",
1737 rules
: { indent
: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
1740 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1742 assert
.deepStrictEqual(report
.usedDeprecatedRules
, []);
1743 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1746 it("should warn when deprecated rules are found in a config", () => {
1747 engine
= new CLIEngine({
1749 configFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
1753 const report
= engine
.executeOnFiles(["lib/cli*.js"]);
1755 assert
.deepStrictEqual(
1756 report
.usedDeprecatedRules
,
1757 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
1759 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1762 describe("Fix Mode", () => {
1764 it("should return fixed text on multiple files when in fix mode", () => {
1767 * Converts CRLF to LF in output.
1768 * This is a workaround for git's autocrlf option on Windows.
1769 * @param {Object} result A result object to convert.
1772 function convertCRLF(result
) {
1773 if (result
&& result
.output
) {
1774 result
.output
= result
.output
.replace(/\r\n/gu, "\n");
1778 engine
= new CLIEngine({
1779 cwd
: path
.join(fixtureDir
, ".."),
1784 quotes
: [2, "double"],
1787 "space-infix-ops": 2
1791 const report
= engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1793 report
.results
.forEach(convertCRLF
);
1794 assert
.deepStrictEqual(report
.results
, [
1796 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/multipass.js")),
1798 suppressedMessages
: [],
1802 fixableErrorCount
: 0,
1803 fixableWarningCount
: 0,
1804 output
: "true ? \"yes\" : \"no\";\n"
1807 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/ok.js")),
1809 suppressedMessages
: [],
1813 fixableErrorCount
: 0,
1814 fixableWarningCount
: 0
1817 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes-semi-eqeqeq.js")),
1824 message
: "Expected '===' and instead saw '=='.",
1825 messageId
: "unexpected",
1826 nodeType
: "BinaryExpression",
1831 suppressedMessages
: [],
1835 fixableErrorCount
: 0,
1836 fixableWarningCount
: 0,
1837 output
: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n"
1840 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes.js")),
1848 message
: "'foo' is not defined.",
1849 nodeType
: "Identifier",
1854 suppressedMessages
: [],
1858 fixableErrorCount
: 0,
1859 fixableWarningCount
: 0,
1860 output
: "var msg = \"hi\" + foo;\n"
1863 assert
.strictEqual(report
.errorCount
, 2);
1864 assert
.strictEqual(report
.warningCount
, 0);
1865 assert
.strictEqual(report
.fixableErrorCount
, 0);
1866 assert
.strictEqual(report
.fixableWarningCount
, 0);
1869 it("should run autofix even if files are cached without autofix results", () => {
1870 const baseOptions
= {
1871 cwd
: path
.join(fixtureDir
, ".."),
1875 quotes
: [2, "double"],
1878 "space-infix-ops": 2
1882 engine
= new CLIEngine(Object
.assign({}, baseOptions
, { cache
: true, fix
: false }));
1884 // Do initial lint run and populate the cache file
1885 engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1887 engine
= new CLIEngine(Object
.assign({}, baseOptions
, { cache
: true, fix
: true }));
1889 const report
= engine
.executeOnFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1891 assert
.ok(report
.results
.some(result
=> result
.output
));
1896 // These tests have to do with https://github.com/eslint/eslint/issues/963
1898 describe("configuration hierarchy", () => {
1900 // Default configuration - blank
1901 it("should return zero messages when executing with no .eslintrc", () => {
1903 engine
= new CLIEngine({
1904 cwd
: path
.join(fixtureDir
, ".."),
1908 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1910 assert
.strictEqual(report
.results
.length
, 1);
1911 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1912 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1915 // No default configuration rules - conf/environments.js (/*eslint-env node*/)
1916 it("should return zero messages when executing with no .eslintrc in the Node.js environment", () => {
1918 engine
= new CLIEngine({
1919 cwd
: path
.join(fixtureDir
, ".."),
1924 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
1926 assert
.strictEqual(report
.results
.length
, 1);
1927 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1928 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1931 // Project configuration - first level .eslintrc
1932 it("should return zero messages when executing with .eslintrc in the Node.js environment", () => {
1934 engine
= new CLIEngine({
1935 cwd
: path
.join(fixtureDir
, "..")
1938 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1940 assert
.strictEqual(report
.results
.length
, 1);
1941 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1942 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1945 // Project configuration - first level .eslintrc
1946 it("should return zero messages when executing with .eslintrc in the Node.js environment", () => {
1948 engine
= new CLIEngine({
1949 cwd
: path
.join(fixtureDir
, "..")
1952 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1954 assert
.strictEqual(report
.results
.length
, 1);
1955 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
1958 // Project configuration - first level .eslintrc
1959 it("should return one message when executing with .eslintrc", () => {
1961 engine
= new CLIEngine({
1962 cwd
: path
.join(fixtureDir
, "..")
1965 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1967 assert
.strictEqual(report
.results
.length
, 1);
1968 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1969 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
1970 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
1971 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1974 // Project configuration - second level .eslintrc
1975 it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", () => {
1977 engine
= new CLIEngine({
1978 cwd
: path
.join(fixtureDir
, "..")
1981 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1983 assert
.strictEqual(report
.results
.length
, 1);
1984 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
1985 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
1986 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
1987 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
1990 // Project configuration - third level .eslintrc
1991 it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", () => {
1993 engine
= new CLIEngine({
1994 cwd
: path
.join(fixtureDir
, "..")
1997 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
1999 assert
.strictEqual(report
.results
.length
, 1);
2000 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2001 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2002 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2003 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2006 // Project configuration - first level package.json
2007 it("should return one message when executing with package.json", () => {
2009 engine
= new CLIEngine({
2010 cwd
: path
.join(fixtureDir
, "..")
2013 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
2015 assert
.strictEqual(report
.results
.length
, 1);
2016 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2017 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2018 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2019 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2022 // Project configuration - second level package.json
2023 it("should return zero messages when executing with local package.json that overrides parent package.json", () => {
2025 engine
= new CLIEngine({
2026 cwd
: path
.join(fixtureDir
, "..")
2029 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
2031 assert
.strictEqual(report
.results
.length
, 1);
2032 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
2033 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2036 // Project configuration - third level package.json
2037 it("should return one message when executing with local package.json that overrides parent and grandparent package.json", () => {
2039 engine
= new CLIEngine({
2040 cwd
: path
.join(fixtureDir
, "..")
2043 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
2045 assert
.strictEqual(report
.results
.length
, 1);
2046 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2047 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2048 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
2049 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2052 // Project configuration - .eslintrc overrides package.json in same directory
2053 it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", () => {
2055 engine
= new CLIEngine({
2056 cwd
: path
.join(fixtureDir
, "..")
2059 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
2061 assert
.strictEqual(report
.results
.length
, 1);
2062 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2063 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2064 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
2065 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2068 // Command line configuration - --config with first level .eslintrc
2069 it("should return two messages when executing with config file that adds to local .eslintrc", () => {
2071 engine
= new CLIEngine({
2072 cwd
: path
.join(fixtureDir
, ".."),
2073 configFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
2076 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2078 assert
.strictEqual(report
.results
.length
, 1);
2079 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2080 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2081 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 2);
2082 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "semi");
2083 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 1);
2084 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2087 // Command line configuration - --config with first level .eslintrc
2088 it("should return no messages when executing with config file that overrides local .eslintrc", () => {
2090 engine
= new CLIEngine({
2091 cwd
: path
.join(fixtureDir
, ".."),
2092 configFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
2095 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2097 assert
.strictEqual(report
.results
.length
, 1);
2098 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
2099 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2102 // Command line configuration - --config with second level .eslintrc
2103 it("should return two messages when executing with config file that adds to local and parent .eslintrc", () => {
2105 engine
= new CLIEngine({
2106 cwd
: path
.join(fixtureDir
, ".."),
2107 configFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
2110 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
2112 assert
.strictEqual(report
.results
.length
, 1);
2113 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2114 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
2115 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2116 assert
.strictEqual(report
.results
[0].messages
[1].ruleId
, "semi");
2117 assert
.strictEqual(report
.results
[0].messages
[1].severity
, 1);
2118 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2121 // Command line configuration - --config with second level .eslintrc
2122 it("should return one message when executing with config file that overrides local and parent .eslintrc", () => {
2124 engine
= new CLIEngine({
2125 cwd
: path
.join(fixtureDir
, ".."),
2126 configFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml")
2129 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
2131 assert
.strictEqual(report
.results
.length
, 1);
2132 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2133 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "no-console");
2134 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2135 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2138 // Command line configuration - --config with first level .eslintrc
2139 it("should return no messages when executing with config file that overrides local .eslintrc", () => {
2141 engine
= new CLIEngine({
2142 cwd
: path
.join(fixtureDir
, ".."),
2143 configFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
2146 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2148 assert
.strictEqual(report
.results
.length
, 1);
2149 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
2150 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2153 // Command line configuration - --rule with --config and first level .eslintrc
2154 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", () => {
2156 engine
= new CLIEngine({
2157 cwd
: path
.join(fixtureDir
, ".."),
2158 configFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
2160 quotes
: [1, "double"]
2164 const report
= engine
.executeOnFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2166 assert
.strictEqual(report
.results
.length
, 1);
2167 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2168 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2169 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2170 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2173 // Command line configuration - --rule with --config and first level .eslintrc
2174 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", () => {
2176 engine
= new CLIEngine({
2177 cwd
: path
.join(fixtureDir
, ".."),
2178 configFile
: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
2180 quotes
: [1, "double"]
2184 const report
= engine
.executeOnFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
2186 assert
.strictEqual(report
.results
.length
, 1);
2187 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2188 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "quotes");
2189 assert
.strictEqual(report
.results
[0].messages
[0].severity
, 1);
2190 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2195 describe("plugins", () => {
2196 it("should return two messages when executing with config file that specifies a plugin", () => {
2197 engine
= cliEngineWithPlugins({
2198 cwd
: path
.join(fixtureDir
, ".."),
2199 configFile
: getFixturePath("configurations", "plugins-with-prefix.json"),
2203 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
2205 assert
.strictEqual(report
.results
.length
, 1);
2206 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2207 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2208 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2211 it("should return two messages when executing with config file that specifies a plugin with namespace", () => {
2212 engine
= cliEngineWithPlugins({
2213 cwd
: path
.join(fixtureDir
, ".."),
2214 configFile
: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
2218 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2220 assert
.strictEqual(report
.results
.length
, 1);
2221 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2222 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2223 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2226 it("should return two messages when executing with config file that specifies a plugin without prefix", () => {
2227 engine
= cliEngineWithPlugins({
2228 cwd
: path
.join(fixtureDir
, ".."),
2229 configFile
: getFixturePath("configurations", "plugins-without-prefix.json"),
2233 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2235 assert
.strictEqual(report
.results
.length
, 1);
2236 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2237 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2238 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2241 it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", () => {
2242 engine
= cliEngineWithPlugins({
2243 cwd
: path
.join(fixtureDir
, ".."),
2244 configFile
: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
2248 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2250 assert
.strictEqual(report
.results
.length
, 1);
2251 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2252 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2253 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2256 it("should return two messages when executing with cli option that specifies a plugin", () => {
2257 engine
= cliEngineWithPlugins({
2258 cwd
: path
.join(fixtureDir
, ".."),
2260 plugins
: ["example"],
2261 rules
: { "example/example-rule": 1 }
2264 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2266 assert
.strictEqual(report
.results
.length
, 1);
2267 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2268 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "example/example-rule");
2269 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2272 it("should return two messages when executing with cli option that specifies preloaded plugin", () => {
2273 engine
= new CLIEngine({
2274 cwd
: path
.join(fixtureDir
, ".."),
2277 rules
: { "test/example-rule": 1 }
2280 "eslint-plugin-test": {
2282 "example-rule": require("../../fixtures/rules/custom-rule")
2288 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2290 assert
.strictEqual(report
.results
.length
, 1);
2291 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2292 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "test/example-rule");
2293 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2296 it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", () => {
2297 engine
= new CLIEngine({
2298 resolvePluginsRelativeTo
: getFixturePath("plugins"),
2300 plugins
: ["with-rules"],
2301 rules
: { "with-rules/rule1": "error" }
2306 const report
= engine
.executeOnText("foo");
2308 assert
.strictEqual(report
.results
.length
, 1);
2309 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
2310 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "with-rules/rule1");
2311 assert
.strictEqual(report
.results
[0].messages
[0].message
, "Rule report from plugin");
2312 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
2316 describe("cache", () => {
2319 * helper method to delete a file without caring about exceptions
2320 * @param {string} filePath The file path
2323 function doDelete(filePath
) {
2325 fs
.unlinkSync(filePath
);
2329 * we don't care if the file didn't exist, since our
2330 * intention was to remove the file
2336 * helper method to delete the cache files created during testing
2339 function deleteCache() {
2340 doDelete(path
.resolve(".eslintcache"));
2341 doDelete(path
.resolve(".cache/custom-cache"));
2353 describe("when the cacheFile is a directory or looks like a directory", () => {
2356 * helper method to delete the cache files created during testing
2359 function deleteCacheDir() {
2361 fs
.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
2365 * we don't care if the file didn't exist, since our
2366 * intention was to remove the file
2378 it("should create the cache file inside the provided directory", () => {
2379 assert
.isFalse(shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2381 engine
= new CLIEngine({
2384 // specifying cache true the cache will be created
2386 cacheFile
: "./tmp/.cacheFileDir/",
2395 const file
= getFixturePath("cache/src", "test-file.js");
2397 engine
.executeOnFiles([file
]);
2399 assert
.isTrue(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2405 it("should create the cache file inside the provided directory using the cacheLocation option", () => {
2406 assert
.isFalse(shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2408 engine
= new CLIEngine({
2411 // specifying cache true the cache will be created
2413 cacheLocation
: "./tmp/.cacheFileDir/",
2422 const file
= getFixturePath("cache/src", "test-file.js");
2424 engine
.executeOnFiles([file
]);
2426 assert
.isTrue(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2431 it("should create the cache file inside cwd when no cacheLocation provided", () => {
2432 const cwd
= path
.resolve(getFixturePath("cli-engine"));
2434 engine
= new CLIEngine({
2445 const file
= getFixturePath("cli-engine", "console.js");
2447 engine
.executeOnFiles([file
]);
2449 assert
.isTrue(shell
.test("-f", path
.resolve(cwd
, ".eslintcache")), "the cache for eslint was created at provided cwd");
2452 it("should invalidate the cache if the configuration changed between executions", () => {
2453 assert
.isFalse(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2455 engine
= new CLIEngine({
2458 // specifying cache true the cache will be created
2468 let spy
= sinon
.spy(fs
, "readFileSync");
2470 let file
= getFixturePath("cache/src", "test-file.js");
2472 file
= fs
.realpathSync(file
);
2474 const result
= engine
.executeOnFiles([file
]);
2476 assert
.strictEqual(result
.errorCount
+ result
.warningCount
, 0, "the file passed without errors or warnings");
2477 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2478 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2483 engine
= new CLIEngine({
2486 // specifying cache true the cache will be created
2497 spy
= sinon
.spy(fs
, "readFileSync");
2499 const cachedResult
= engine
.executeOnFiles([file
]);
2501 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed because the config changed");
2502 assert
.strictEqual(cachedResult
.errorCount
, 1, "since configuration changed the cache was not used an one error was reported");
2503 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2506 it("should remember the files from a previous run and do not operate on them if not changed", () => {
2508 assert
.isFalse(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2510 engine
= new CLIEngine({
2513 // specifying cache true the cache will be created
2523 let spy
= sinon
.spy(fs
, "readFileSync");
2525 let file
= getFixturePath("cache/src", "test-file.js");
2527 file
= fs
.realpathSync(file
);
2529 const result
= engine
.executeOnFiles([file
]);
2531 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2532 assert
.isTrue(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2537 engine
= new CLIEngine({
2540 // specifying cache true the cache will be created
2551 spy
= sinon
.spy(fs
, "readFileSync");
2553 const cachedResult
= engine
.executeOnFiles([file
]);
2555 assert
.deepStrictEqual(result
, cachedResult
, "the result is the same regardless of using cache or not");
2557 // assert the file was not processed because the cache was used
2558 assert
.isFalse(spy
.calledWith(file
), "the file was not loaded because it used the cache");
2561 it("should remember the files from a previous run and do not operate on then if not changed", () => {
2563 const cacheFile
= getFixturePath(".eslintcache");
2564 const cliEngineOptions
= {
2567 // specifying cache true the cache will be created
2575 cwd
: path
.join(fixtureDir
, "..")
2578 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint does not exist");
2580 engine
= new CLIEngine(cliEngineOptions
);
2582 let file
= getFixturePath("cache/src", "test-file.js");
2584 file
= fs
.realpathSync(file
);
2586 engine
.executeOnFiles([file
]);
2588 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint was created");
2590 cliEngineOptions
.cache
= false;
2591 engine
= new CLIEngine(cliEngineOptions
);
2593 engine
.executeOnFiles([file
]);
2595 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint was deleted since last run did not used the cache");
2598 it("should store in the cache a file that failed the test", () => {
2600 const cacheFile
= getFixturePath(".eslintcache");
2602 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint does not exist");
2604 engine
= new CLIEngine({
2605 cwd
: path
.join(fixtureDir
, ".."),
2608 // specifying cache true the cache will be created
2618 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2619 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2621 const result
= engine
.executeOnFiles([badFile
, goodFile
]);
2623 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint was created");
2625 const fileCache
= fCache
.createFromFile(cacheFile
);
2626 const { cache
} = fileCache
;
2628 assert
.isTrue(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2630 assert
.isTrue(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2632 const cachedResult
= engine
.executeOnFiles([badFile
, goodFile
]);
2634 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2637 it("should not contain in the cache a file that was deleted", () => {
2639 const cacheFile
= getFixturePath(".eslintcache");
2641 doDelete(cacheFile
);
2643 engine
= new CLIEngine({
2644 cwd
: path
.join(fixtureDir
, ".."),
2647 // specifying cache true the cache will be created
2657 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2658 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2659 const toBeDeletedFile
= fs
.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
2661 engine
.executeOnFiles([badFile
, goodFile
, toBeDeletedFile
]);
2663 const fileCache
= fCache
.createFromFile(cacheFile
);
2664 let { cache
} = fileCache
;
2666 assert
.isTrue(typeof cache
.getKey(toBeDeletedFile
) === "object", "the entry for the file to be deleted is in the cache");
2668 // delete the file from the file system
2669 fs
.unlinkSync(toBeDeletedFile
);
2672 * file-entry-cache@2.0.0 will remove from the cache deleted files
2673 * even when they were not part of the array of files to be analyzed
2675 engine
.executeOnFiles([badFile
, goodFile
]);
2677 cache
= JSON
.parse(fs
.readFileSync(cacheFile
));
2679 assert
.isTrue(typeof cache
[toBeDeletedFile
] === "undefined", "the entry for the file to be deleted is not in the cache");
2682 it("should contain files that were not visited in the cache provided they still exist", () => {
2684 const cacheFile
= getFixturePath(".eslintcache");
2686 doDelete(cacheFile
);
2688 engine
= new CLIEngine({
2689 cwd
: path
.join(fixtureDir
, ".."),
2692 // specifying cache true the cache will be created
2702 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2703 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2704 const testFile2
= fs
.realpathSync(getFixturePath("cache/src", "test-file2.js"));
2706 engine
.executeOnFiles([badFile
, goodFile
, testFile2
]);
2708 let fileCache
= fCache
.createFromFile(cacheFile
);
2709 let { cache
} = fileCache
;
2711 assert
.isTrue(typeof cache
.getKey(testFile2
) === "object", "the entry for the test-file2 is in the cache");
2714 * we pass a different set of files minus test-file2
2715 * previous version of file-entry-cache would remove the non visited
2716 * entries. 2.0.0 version will keep them unless they don't exist
2718 engine
.executeOnFiles([badFile
, goodFile
]);
2720 fileCache
= fCache
.createFromFile(cacheFile
);
2721 cache
= fileCache
.cache
;
2723 assert
.isTrue(typeof cache
.getKey(testFile2
) === "object", "the entry for the test-file2 is in the cache");
2726 it("should not delete cache when executing on text", () => {
2727 const cacheFile
= getFixturePath(".eslintcache");
2729 engine
= new CLIEngine({
2730 cwd
: path
.join(fixtureDir
, ".."),
2740 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2742 engine
.executeOnText("var foo = 'bar';");
2744 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2747 it("should not delete cache when executing on text with a provided filename", () => {
2748 const cacheFile
= getFixturePath(".eslintcache");
2750 engine
= new CLIEngine({
2751 cwd
: path
.join(fixtureDir
, ".."),
2761 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2763 engine
.executeOnText("var bar = foo;", "fixtures/passing.js");
2765 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2768 it("should not delete cache when executing on files with --cache flag", () => {
2769 const cacheFile
= getFixturePath(".eslintcache");
2771 engine
= new CLIEngine({
2772 cwd
: path
.join(fixtureDir
, ".."),
2783 const file
= getFixturePath("cli-engine", "console.js");
2785 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2787 engine
.executeOnFiles([file
]);
2789 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint still exists");
2792 it("should delete cache when executing on files without --cache flag", () => {
2793 const cacheFile
= getFixturePath(".eslintcache");
2795 engine
= new CLIEngine({
2796 cwd
: path
.join(fixtureDir
, ".."),
2806 const file
= getFixturePath("cli-engine", "console.js");
2808 assert
.isTrue(shell
.test("-f", cacheFile
), "the cache for eslint exists");
2810 engine
.executeOnFiles([file
]);
2812 assert
.isFalse(shell
.test("-f", cacheFile
), "the cache for eslint has been deleted");
2815 describe("cacheFile", () => {
2816 it("should use the specified cache file", () => {
2817 const customCacheFile
= path
.resolve(".cache/custom-cache");
2819 assert
.isFalse(shell
.test("-f", customCacheFile
), "the cache for eslint does not exist");
2821 engine
= new CLIEngine({
2824 // specify a custom cache file
2825 cacheFile
: customCacheFile
,
2827 // specifying cache true the cache will be created
2834 cwd
: path
.join(fixtureDir
, "..")
2837 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2838 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2840 const result
= engine
.executeOnFiles([badFile
, goodFile
]);
2842 assert
.isTrue(shell
.test("-f", customCacheFile
), "the cache for eslint was created");
2844 const fileCache
= fCache
.createFromFile(customCacheFile
);
2845 const { cache
} = fileCache
;
2847 assert
.isTrue(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2849 assert
.isTrue(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2851 const cachedResult
= engine
.executeOnFiles([badFile
, goodFile
]);
2853 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2857 describe("cacheStrategy", () => {
2858 it("should detect changes using a file's modification time when set to 'metadata'", () => {
2859 const cacheFile
= getFixturePath(".eslintcache");
2860 const badFile
= getFixturePath("cache/src", "fail-file.js");
2861 const goodFile
= getFixturePath("cache/src", "test-file.js");
2863 doDelete(cacheFile
);
2865 engine
= new CLIEngine({
2866 cwd
: path
.join(fixtureDir
, ".."),
2869 // specifying cache true the cache will be created
2872 cacheStrategy
: "metadata",
2880 engine
.executeOnFiles([badFile
, goodFile
]);
2882 let fileCache
= fCache
.createFromFile(cacheFile
, false);
2883 const entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2885 entries
.forEach(entry
=> {
2886 assert
.isFalse(entry
.changed
, `the entry for ${entry.key} is initially unchanged`);
2889 // this should result in a changed entry
2890 shell
.touch(goodFile
);
2891 fileCache
= fCache
.createFromFile(cacheFile
, false);
2892 assert
.isFalse(fileCache
.getFileDescriptor(badFile
).changed
, `the entry for ${badFile} is unchanged`);
2893 assert
.isTrue(fileCache
.getFileDescriptor(goodFile
).changed
, `the entry for ${goodFile} is changed`);
2896 it("should not detect changes using a file's modification time when set to 'content'", () => {
2897 const cacheFile
= getFixturePath(".eslintcache");
2898 const badFile
= getFixturePath("cache/src", "fail-file.js");
2899 const goodFile
= getFixturePath("cache/src", "test-file.js");
2901 doDelete(cacheFile
);
2903 engine
= new CLIEngine({
2904 cwd
: path
.join(fixtureDir
, ".."),
2907 // specifying cache true the cache will be created
2910 cacheStrategy
: "content",
2918 engine
.executeOnFiles([badFile
, goodFile
]);
2920 let fileCache
= fCache
.createFromFile(cacheFile
, true);
2921 let entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2923 entries
.forEach(entry
=> {
2924 assert
.isFalse(entry
.changed
, `the entry for ${entry.key} is initially unchanged`);
2927 // this should NOT result in a changed entry
2928 shell
.touch(goodFile
);
2929 fileCache
= fCache
.createFromFile(cacheFile
, true);
2930 entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2931 entries
.forEach(entry
=> {
2932 assert
.isFalse(entry
.changed
, `the entry for ${entry.key} remains unchanged`);
2936 it("should detect changes using a file's contents when set to 'content'", () => {
2937 const cacheFile
= getFixturePath(".eslintcache");
2938 const badFile
= getFixturePath("cache/src", "fail-file.js");
2939 const goodFile
= getFixturePath("cache/src", "test-file.js");
2940 const goodFileCopy
= path
.resolve(`${path.dirname(goodFile)}`, "test-file-copy.js");
2942 shell
.cp(goodFile
, goodFileCopy
);
2944 doDelete(cacheFile
);
2946 engine
= new CLIEngine({
2947 cwd
: path
.join(fixtureDir
, ".."),
2950 // specifying cache true the cache will be created
2953 cacheStrategy
: "content",
2961 engine
.executeOnFiles([badFile
, goodFileCopy
]);
2963 let fileCache
= fCache
.createFromFile(cacheFile
, true);
2964 const entries
= fileCache
.normalizeEntries([badFile
, goodFileCopy
]);
2966 entries
.forEach(entry
=> {
2967 assert
.isFalse(entry
.changed
, `the entry for ${entry.key} is initially unchanged`);
2970 // this should result in a changed entry
2971 shell
.sed("-i", "abc", "xzy", goodFileCopy
);
2972 fileCache
= fCache
.createFromFile(cacheFile
, true);
2973 assert
.isFalse(fileCache
.getFileDescriptor(badFile
).changed
, `the entry for ${badFile} is unchanged`);
2974 assert
.isTrue(fileCache
.getFileDescriptor(goodFileCopy
).changed
, `the entry for ${goodFileCopy} is changed`);
2979 describe("processors", () => {
2980 it("should return two messages when executing with config file that specifies a processor", () => {
2981 engine
= cliEngineWithPlugins({
2982 configFile
: getFixturePath("configurations", "processors.json"),
2984 extensions
: ["js", "txt"],
2985 cwd
: path
.join(fixtureDir
, "..")
2988 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2990 assert
.strictEqual(report
.results
.length
, 1);
2991 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
2993 it("should return two messages when executing with config file that specifies preloaded processor", () => {
2994 engine
= new CLIEngine({
2996 plugins
: ["test-processor"],
3001 extensions
: ["js", "txt"],
3002 cwd
: path
.join(fixtureDir
, "..")
3011 postprocess(messages
) {
3020 const report
= engine
.executeOnFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
3022 assert
.strictEqual(report
.results
.length
, 1);
3023 assert
.strictEqual(report
.results
[0].messages
.length
, 2);
3025 it("should run processors when calling executeOnFiles with config file that specifies a processor", () => {
3026 engine
= cliEngineWithPlugins({
3027 configFile
: getFixturePath("configurations", "processors.json"),
3029 extensions
: ["js", "txt"],
3030 cwd
: path
.join(fixtureDir
, "..")
3033 const report
= engine
.executeOnFiles([getFixturePath("processors", "test", "test-processor.txt")]);
3035 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
3036 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
3038 it("should run processors when calling executeOnFiles with config file that specifies preloaded processor", () => {
3039 engine
= new CLIEngine({
3041 plugins
: ["test-processor"],
3046 extensions
: ["js", "txt"],
3047 cwd
: path
.join(fixtureDir
, "..")
3054 return [text
.replace("a()", "b()")];
3056 postprocess(messages
) {
3057 messages
[0][0].ruleId
= "post-processed";
3066 const report
= engine
.executeOnFiles([getFixturePath("processors", "test", "test-processor.txt")]);
3068 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
3069 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
3071 it("should run processors when calling executeOnText with config file that specifies a processor", () => {
3072 engine
= cliEngineWithPlugins({
3073 configFile
: getFixturePath("configurations", "processors.json"),
3075 extensions
: ["js", "txt"],
3079 const report
= engine
.executeOnText("function a() {console.log(\"Test\");}", "tests/fixtures/processors/test/test-processor.txt");
3081 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
3082 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
3084 it("should run processors when calling executeOnText with config file that specifies preloaded processor", () => {
3085 engine
= new CLIEngine({
3087 plugins
: ["test-processor"],
3092 extensions
: ["js", "txt"],
3100 return [text
.replace("a()", "b()")];
3102 postprocess(messages
) {
3103 messages
[0][0].ruleId
= "post-processed";
3112 const report
= engine
.executeOnText("function a() {console.log(\"Test\");}", "tests/fixtures/processors/test/test-processor.txt");
3114 assert
.strictEqual(report
.results
[0].messages
[0].message
, "'b' is defined but never used.");
3115 assert
.strictEqual(report
.results
[0].messages
[0].ruleId
, "post-processed");
3118 describe("autofixing with processors", () => {
3119 const HTML_PROCESSOR
= Object
.freeze({
3121 return [text
.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
3123 postprocess(problemLists
) {
3124 return problemLists
[0].map(problem
=> {
3126 const updatedFix
= Object
.assign({}, problem
.fix
, {
3127 range
: problem
.fix
.range
.map(index
=> index
+ "<script>".length
)
3130 return Object
.assign({}, problem
, { fix
: updatedFix
});
3138 it("should run in autofix mode when using a processor that supports autofixing", () => {
3139 engine
= new CLIEngine({
3141 plugins
: ["test-processor"],
3145 extensions
: ["js", "txt"],
3152 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
3158 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
3160 assert
.strictEqual(report
.results
[0].messages
.length
, 0);
3161 assert
.strictEqual(report
.results
[0].output
, "<script>foo;</script>");
3164 it("should not run in autofix mode when using a processor that does not support autofixing", () => {
3165 engine
= new CLIEngine({
3167 plugins
: ["test-processor"],
3171 extensions
: ["js", "txt"],
3178 ".html": HTML_PROCESSOR
3184 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
3186 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
3187 assert
.isFalse(Object
.prototype.hasOwnProperty
.call(report
.results
[0], "output"));
3190 it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", () => {
3191 engine
= new CLIEngine({
3193 plugins
: ["test-processor"],
3197 extensions
: ["js", "txt"],
3203 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
3209 const report
= engine
.executeOnText("<script>foo</script>", "foo.html");
3211 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
3212 assert
.isFalse(Object
.prototype.hasOwnProperty
.call(report
.results
[0], "output"));
3217 describe("Patterns which match no file should throw errors.", () => {
3219 engine
= new CLIEngine({
3220 cwd
: getFixturePath("cli-engine"),
3225 it("one file", () => {
3226 assert
.throws(() => {
3227 engine
.executeOnFiles(["non-exist.js"]);
3228 }, "No files matching 'non-exist.js' were found.");
3231 it("should throw if the directory exists and is empty", () => {
3232 assert
.throws(() => {
3233 engine
.executeOnFiles(["empty"]);
3234 }, "No files matching 'empty' were found.");
3237 it("one glob pattern", () => {
3238 assert
.throws(() => {
3239 engine
.executeOnFiles(["non-exist/**/*.js"]);
3240 }, "No files matching 'non-exist/**/*.js' were found.");
3243 it("two files", () => {
3244 assert
.throws(() => {
3245 engine
.executeOnFiles(["aaa.js", "bbb.js"]);
3246 }, "No files matching 'aaa.js' were found.");
3249 it("a mix of an existing file and a non-existing file", () => {
3250 assert
.throws(() => {
3251 engine
.executeOnFiles(["console.js", "non-exist.js"]);
3252 }, "No files matching 'non-exist.js' were found.");
3256 describe("overrides", () => {
3258 engine
= new CLIEngine({
3259 cwd
: getFixturePath("cli-engine/overrides-with-dot"),
3264 it("should recognize dotfiles", () => {
3265 const ret
= engine
.executeOnFiles([".test-target.js"]);
3267 assert
.strictEqual(ret
.results
.length
, 1);
3268 assert
.strictEqual(ret
.results
[0].messages
.length
, 1);
3269 assert
.strictEqual(ret
.results
[0].messages
[0].ruleId
, "no-unused-vars");
3270 assert
.strictEqual(ret
.results
[0].suppressedMessages
.length
, 0);
3274 describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
3276 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3277 cwd
: path
.join(os
.tmpdir(), "cli-engine/11510"),
3279 "no-console-error-in-overrides.json": {
3282 rules
: { "no-console": "error" }
3286 extends: "./no-console-error-in-overrides.json",
3287 rules
: { "no-console": "off" }
3289 "a.js": "console.log();"
3294 engine
= new CLIEngine({
3303 it("should not report 'no-console' error.", () => {
3304 const { results
} = engine
.executeOnFiles("a.js");
3306 assert
.strictEqual(results
.length
, 1);
3307 assert
.deepStrictEqual(results
[0].messages
, []);
3308 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3312 describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
3313 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3314 cwd
: path
.join(os
.tmpdir(), "cli-engine/11559"),
3316 "node_modules/eslint-plugin-test/index.js": `
3318 recommended: { plugins: ["test"] }
3322 meta: { schema: [{ type: "number" }] },
3323 create() { return {}; }
3329 // Import via the recommended config.
3330 extends: "plugin:test/recommended",
3332 // Has invalid option.
3333 rules
: { "test/foo": ["error", "invalid-option"] }
3335 "a.js": "console.log();"
3340 engine
= new CLIEngine({
3349 it("should throw fatal error.", () => {
3350 assert
.throws(() => {
3351 engine
.executeOnFiles("a.js");
3352 }, /invalid-option/u);
3356 describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
3358 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3359 cwd
: path
.join(os
.tmpdir(), "cli-engine/11586"),
3361 "node_modules/eslint-plugin-test/index.js": `
3364 meta: { type: "problem", fixable: "code" },
3368 if (node.name === "example") {
3372 fix: fixer => fixer.replaceText(node, "fixed")
3383 rules
: { "test/no-example": "error" }
3390 engine
= new CLIEngine({
3393 fixTypes
: ["problem"]
3402 it("should not crash.", () => {
3403 const { results
} = engine
.executeOnFiles("a.js");
3405 assert
.strictEqual(results
.length
, 1);
3406 assert
.deepStrictEqual(results
[0].messages
, []);
3407 assert
.deepStrictEqual(results
[0].output
, "fixed;");
3408 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3412 describe("multiple processors", () => {
3413 const root
= path
.join(os
.tmpdir(), "eslint/cli-engine/multiple-processors");
3414 const commonFiles
= {
3415 "node_modules/pattern-processor/index.js": fs
.readFileSync(
3416 require
.resolve("../../fixtures/processors/pattern-processor"),
3419 "node_modules/eslint-plugin-markdown/index.js": `
3420 const { defineProcessor } = require("pattern-processor");
3421 const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
3422 exports.processors = {
3423 ".md": { ...processor, supportsAutofix: true },
3424 "non-fixable": processor
3427 "node_modules/eslint-plugin-html/index.js": `
3428 const { defineProcessor } = require("pattern-processor");
3429 const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
3430 const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
3431 exports.processors = {
3432 ".html": { ...processor, supportsAutofix: true },
3433 "non-fixable": processor,
3434 "legacy": legacyProcessor
3437 "test.md": unIndent
`
3439 console
.log("hello")
3444 console
.log("hello")
3447 console
.log("hello")
3459 afterEach(() => cleanup());
3461 it("should lint only JavaScript blocks if '--ext' was not given.", async () => {
3462 const teardown
= createCustomTeardown({
3467 plugins
: ["markdown", "html"],
3468 rules
: { semi
: "error" }
3473 cleanup
= teardown
.cleanup
;
3474 await teardown
.prepare();
3475 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3477 const { results
} = engine
.executeOnFiles(["test.md"]);
3479 assert
.strictEqual(results
.length
, 1);
3480 assert
.strictEqual(results
[0].messages
.length
, 1);
3481 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3482 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3483 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3486 it("should fix only JavaScript blocks if '--ext' was not given.", async () => {
3488 const teardown
= createCustomTeardown({
3493 plugins
: ["markdown", "html"],
3494 rules
: { semi
: "error" }
3499 await teardown
.prepare();
3500 cleanup
= teardown
.cleanup
;
3501 engine
= new CLIEngine({
3502 cwd
: teardown
.getPath(),
3506 const { results
} = engine
.executeOnFiles(["test.md"]);
3508 assert
.strictEqual(results
.length
, 1);
3509 assert
.strictEqual(results
[0].messages
.length
, 0);
3510 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3511 assert
.strictEqual(results
[0].output
, unIndent
`
3513 console
.log("hello");${/* ← fixed */""}
3518 console
.log("hello")${/* ← ignored */""}
3521 console
.log("hello")${/* ← ignored */""}
3527 it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3528 const teardown
= createCustomTeardown({
3533 plugins
: ["markdown", "html"],
3534 rules
: { semi
: "error" }
3539 await teardown
.prepare();
3540 cleanup
= teardown
.cleanup
;
3541 engine
= new CLIEngine({
3542 cwd
: teardown
.getPath(),
3543 extensions
: ["js", "html"]
3546 const { results
} = engine
.executeOnFiles(["test.md"]);
3548 assert
.strictEqual(results
.length
, 1);
3549 assert
.strictEqual(results
[0].messages
.length
, 2);
3550 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3551 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3552 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3553 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3554 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3557 it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3558 const teardown
= createCustomTeardown({
3563 plugins
: ["markdown", "html"],
3564 rules
: { semi
: "error" }
3569 await teardown
.prepare();
3570 cleanup
= teardown
.cleanup
;
3571 engine
= new CLIEngine({
3572 cwd
: teardown
.getPath(),
3573 extensions
: ["js", "html"],
3577 const { results
} = engine
.executeOnFiles(["test.md"]);
3579 assert
.strictEqual(results
.length
, 1);
3580 assert
.strictEqual(results
[0].messages
.length
, 0);
3581 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3582 assert
.strictEqual(results
[0].output
, unIndent
`
3584 console
.log("hello");${/* ← fixed */""}
3589 console
.log("hello");${/* ← fixed */""}
3592 console
.log("hello")${/* ← ignored */""}
3598 it("should use overridden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", async () => {
3600 const teardown
= createCustomTeardown({
3605 plugins
: ["markdown", "html"],
3606 rules
: { semi
: "error" },
3610 processor
: "html/non-fixable" // supportsAutofix: false
3617 await teardown
.prepare();
3618 cleanup
= teardown
.cleanup
;
3619 engine
= new CLIEngine({
3620 cwd
: teardown
.getPath(),
3621 extensions
: ["js", "html"],
3625 const { results
} = engine
.executeOnFiles(["test.md"]);
3627 assert
.strictEqual(results
.length
, 1);
3628 assert
.strictEqual(results
[0].messages
.length
, 1);
3629 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS Block in HTML Block
3630 assert
.strictEqual(results
[0].messages
[0].line
, 7);
3631 assert
.strictEqual(results
[0].messages
[0].fix
, void 0);
3632 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3633 assert
.strictEqual(results
[0].output
, unIndent
`
3635 console
.log("hello");${/* ← fixed */""}
3640 console
.log("hello")${/* ← reported but not fixed */""}
3643 console
.log("hello")
3649 it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", async () => {
3651 const teardown
= createCustomTeardown({
3656 plugins
: ["markdown", "html"],
3657 rules
: { semi
: "error" },
3662 // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
3669 files
: "**/*.html/*.js",
3672 "no-console": "error"
3680 await teardown
.prepare();
3681 cleanup
= teardown
.cleanup
;
3682 engine
= new CLIEngine({
3683 cwd
: teardown
.getPath(),
3684 extensions
: ["js", "html"]
3687 const { results
} = engine
.executeOnFiles(["test.md"]);
3689 assert
.strictEqual(results
.length
, 1);
3690 assert
.strictEqual(results
[0].messages
.length
, 2);
3691 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3692 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3693 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3694 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3695 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3698 it("should use the same config as one which has 'processor' property in order to lint blocks in HTML if the processor was legacy style.", async () => {
3700 const teardown
= createCustomTeardown({
3705 plugins
: ["markdown", "html"],
3706 rules
: { semi
: "error" },
3710 processor
: "html/legacy", // this processor returns strings rather than `{text, filename}`
3713 "no-console": "error"
3717 files
: "**/*.html/*.js",
3728 await teardown
.prepare();
3729 cleanup
= teardown
.cleanup
;
3730 engine
= new CLIEngine({
3731 cwd
: teardown
.getPath(),
3732 extensions
: ["js", "html"]
3735 const { results
} = engine
.executeOnFiles(["test.md"]);
3737 assert
.strictEqual(results
.length
, 1);
3738 assert
.strictEqual(results
[0].messages
.length
, 3);
3739 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3740 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3741 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3742 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3743 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-console");
3744 assert
.strictEqual(results
[0].messages
[2].line
, 10);
3745 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3748 it("should throw an error if invalid processor was specified.", async () => {
3750 const teardown
= createCustomTeardown({
3755 plugins
: ["markdown", "html"],
3756 processor
: "markdown/unknown"
3761 await teardown
.prepare();
3762 cleanup
= teardown
.cleanup
;
3763 engine
= new CLIEngine({
3764 cwd
: teardown
.getPath()
3767 assert
.throws(() => {
3768 engine
.executeOnFiles(["test.md"]);
3769 }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
3772 it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", async () => {
3774 const teardown
= createCustomTeardown({
3779 plugins
: ["markdown", "html"],
3780 rules
: { semi
: "error" },
3784 processor
: "html/.html"
3788 processor
: "markdown/.md"
3795 await teardown
.prepare();
3796 cleanup
= teardown
.cleanup
;
3797 engine
= new CLIEngine({
3798 cwd
: teardown
.getPath()
3801 const { results
} = engine
.executeOnFiles(["test.md"]);
3803 assert
.strictEqual(results
.length
, 1);
3804 assert
.strictEqual(results
[0].messages
.length
, 2);
3805 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3806 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3807 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3808 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3809 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
3813 describe("MODULE_NOT_FOUND error handling", () => {
3814 const cwd
= getFixturePath("module-not-found");
3817 engine
= new CLIEngine({ cwd
});
3820 it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", () => {
3822 engine
.executeOnText("test", "extends-js/test.js");
3824 assert
.strictEqual(err
.messageTemplate
, "extend-config-missing");
3825 assert
.deepStrictEqual(err
.messageData
, {
3826 configName
: "nonexistent-config",
3827 importerName
: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
3831 assert
.fail("Expected to throw an error");
3834 it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", () => {
3836 engine
.executeOnText("test", "extends-plugin/test.js");
3838 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3839 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3840 assert
.deepStrictEqual(err
.messageData
, {
3841 importerName
: `extends-plugin${path.sep}.eslintrc.yml`,
3842 pluginName
: "eslint-plugin-nonexistent-plugin",
3843 resolvePluginsRelativeTo
: path
.join(cwd
, "extends-plugin") // the directory of the config file.
3847 assert
.fail("Expected to throw an error");
3850 it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", () => {
3852 engine
.executeOnText("test", "plugins/test.js");
3854 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3855 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3856 assert
.deepStrictEqual(err
.messageData
, {
3857 importerName
: `plugins${path.sep}.eslintrc.yml`,
3858 pluginName
: "eslint-plugin-nonexistent-plugin",
3859 resolvePluginsRelativeTo
: path
.join(cwd
, "plugins") // the directory of the config file.
3863 assert
.fail("Expected to throw an error");
3866 it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", () => {
3868 engine
.executeOnText("test", "throw-in-config-itself/test.js");
3870 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3871 assert
.strictEqual(err
.messageTemplate
, void 0);
3874 assert
.fail("Expected to throw an error");
3877 it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", () => {
3879 engine
.executeOnText("test", "throw-in-extends-js/test.js");
3881 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3882 assert
.strictEqual(err
.messageTemplate
, void 0);
3885 assert
.fail("Expected to throw an error");
3888 it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", () => {
3890 engine
.executeOnText("test", "throw-in-extends-plugin/test.js");
3892 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3893 assert
.strictEqual(err
.messageTemplate
, void 0);
3896 assert
.fail("Expected to throw an error");
3899 it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", () => {
3901 engine
.executeOnText("test", "throw-in-plugins/test.js");
3903 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3904 assert
.strictEqual(err
.messageTemplate
, void 0);
3907 assert
.fail("Expected to throw an error");
3911 describe("with '--rulesdir' option", () => {
3913 const rootPath
= getFixturePath("cli-engine/with-rulesdir");
3915 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3918 "internal-rules/test.js": `
3919 module.exports = context => ({
3920 ExpressionStatement(node) {
3921 context.report({ node, message: "ok" })
3927 rules
: { test
: "error" }
3929 "test.js": "console.log('hello')"
3933 beforeEach(prepare
);
3937 it("should use the configured rules which are defined by '--rulesdir' option.", () => {
3939 engine
= new CLIEngine({
3941 rulePaths
: ["internal-rules"]
3943 const report
= engine
.executeOnFiles(["test.js"]);
3945 assert
.strictEqual(report
.results
.length
, 1);
3946 assert
.strictEqual(report
.results
[0].messages
.length
, 1);
3947 assert
.strictEqual(report
.results
[0].messages
[0].message
, "ok");
3948 assert
.strictEqual(report
.results
[0].suppressedMessages
.length
, 0);
3952 describe("glob pattern '[ab].js'", () => {
3953 const root
= getFixturePath("cli-engine/unmatched-glob");
3958 cleanup
= () => { };
3961 afterEach(() => cleanup());
3963 it("should match '[ab].js' if existed.", async () => {
3965 const teardown
= createCustomTeardown({
3972 ".eslintrc.yml": "root: true"
3976 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
3978 await teardown
.prepare();
3979 cleanup
= teardown
.cleanup
;
3981 const { results
} = engine
.executeOnFiles(["[ab].js"]);
3982 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3984 assert
.deepStrictEqual(filenames
, ["[ab].js"]);
3987 it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", async () => {
3989 const teardown
= createCustomTeardown({
3995 ".eslintrc.yml": "root: true"
3999 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
4001 await teardown
.prepare();
4002 cleanup
= teardown
.cleanup
;
4004 const { results
} = engine
.executeOnFiles(["[ab].js"]);
4005 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
4007 assert
.deepStrictEqual(filenames
, ["a.js", "b.js"]);
4011 describe("with 'noInlineConfig' setting", () => {
4012 const root
= getFixturePath("cli-engine/noInlineConfig");
4017 cleanup
= () => { };
4020 afterEach(() => cleanup());
4022 it("should warn directive comments if 'noInlineConfig' was given.", async () => {
4024 const teardown
= createCustomTeardown({
4027 "test.js": "/* globals foo */",
4028 ".eslintrc.yml": "noInlineConfig: true"
4032 await teardown
.prepare();
4033 cleanup
= teardown
.cleanup
;
4034 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
4036 const { results
} = engine
.executeOnFiles(["test.js"]);
4037 const messages
= results
[0].messages
;
4039 assert
.strictEqual(messages
.length
, 1);
4040 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
4041 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
4044 it("should show the config file what the 'noInlineConfig' came from.", async () => {
4046 const teardown
= createCustomTeardown({
4049 "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
4050 "test.js": "/* globals foo */",
4051 ".eslintrc.yml": "extends: foo"
4055 await teardown
.prepare();
4056 cleanup
= teardown
.cleanup
;
4057 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
4059 const { results
} = engine
.executeOnFiles(["test.js"]);
4060 const messages
= results
[0].messages
;
4062 assert
.strictEqual(messages
.length
, 1);
4063 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
4064 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
4068 describe("with 'reportUnusedDisableDirectives' setting", () => {
4069 const root
= getFixturePath("cli-engine/reportUnusedDisableDirectives");
4074 cleanup
= () => { };
4077 afterEach(() => cleanup());
4079 it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", async () => {
4080 const teardown
= createCustomTeardown({
4083 "test.js": "/* eslint-disable eqeqeq */",
4084 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
4088 await teardown
.prepare();
4089 cleanup
= teardown
.cleanup
;
4090 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
4092 const { results
} = engine
.executeOnFiles(["test.js"]);
4093 const messages
= results
[0].messages
;
4095 assert
.strictEqual(messages
.length
, 1);
4096 assert
.strictEqual(messages
[0].severity
, 1);
4097 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
4098 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
4101 describe("the runtime option overrides config files.", () => {
4102 it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", async () => {
4103 const teardown
= createCustomTeardown({
4106 "test.js": "/* eslint-disable eqeqeq */",
4107 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
4111 await teardown
.prepare();
4112 cleanup
= teardown
.cleanup
;
4114 engine
= new CLIEngine({
4115 cwd
: teardown
.getPath(),
4116 reportUnusedDisableDirectives
: "off"
4119 const { results
} = engine
.executeOnFiles(["test.js"]);
4120 const messages
= results
[0].messages
;
4122 assert
.strictEqual(messages
.length
, 0);
4123 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
4126 it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", async () => {
4127 const teardown
= createCustomTeardown({
4130 "test.js": "/* eslint-disable eqeqeq */",
4131 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
4135 await teardown
.prepare();
4136 cleanup
= teardown
.cleanup
;
4138 engine
= new CLIEngine({
4139 cwd
: teardown
.getPath(),
4140 reportUnusedDisableDirectives
: "error"
4143 const { results
} = engine
.executeOnFiles(["test.js"]);
4144 const messages
= results
[0].messages
;
4146 assert
.strictEqual(messages
.length
, 1);
4147 assert
.strictEqual(messages
[0].severity
, 2);
4148 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
4149 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
4154 describe("with 'overrides[*].extends' setting on deep locations", () => {
4155 const root
= getFixturePath("cli-engine/deeply-overrides-i-extends");
4157 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
4160 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
4161 overrides: [{ files: ["*test*"], extends: "two" }]
4163 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
4164 overrides: [{ files: ["*.js"], extends: "three" }]
4166 "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
4167 rules: { "no-console": "error" }
4169 "test.js": "console.log('hello')",
4170 ".eslintrc.yml": "extends: one"
4174 beforeEach(prepare
);
4177 it("should not throw.", () => {
4178 engine
= new CLIEngine({ cwd
: getPath() });
4180 const { results
} = engine
.executeOnFiles(["test.js"]);
4181 const messages
= results
[0].messages
;
4183 assert
.strictEqual(messages
.length
, 1);
4184 assert
.strictEqual(messages
[0].ruleId
, "no-console");
4185 assert
.strictEqual(results
[0].suppressedMessages
.length
, 0);
4189 describe("don't ignore the entry directory.", () => {
4190 const root
= getFixturePath("cli-engine/dont-ignore-entry-dir");
4198 afterEach(async () => {
4201 const configFilePath
= path
.resolve(root
, "../.eslintrc.json");
4203 if (shell
.test("-e", configFilePath
)) {
4204 shell
.rm(configFilePath
);
4208 it("'executeOnFiles(\".\")' should not load config files from outside of \".\".", async () => {
4209 const teardown
= createCustomTeardown({
4212 "../.eslintrc.json": "BROKEN FILE",
4213 ".eslintrc.json": JSON
.stringify({ root
: true }),
4214 "index.js": "console.log(\"hello\")"
4218 await teardown
.prepare();
4219 cleanup
= teardown
.cleanup
;
4220 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
4222 // Don't throw "failed to load config file" error.
4223 engine
.executeOnFiles(".");
4226 it("'executeOnFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", async () => {
4227 const teardown
= createCustomTeardown({
4230 "../.eslintrc.json": { ignorePatterns
: ["/dont-ignore-entry-dir"] },
4231 ".eslintrc.json": { root
: true },
4232 "index.js": "console.log(\"hello\")"
4236 await teardown
.prepare();
4237 cleanup
= teardown
.cleanup
;
4238 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
4241 // Don't throw "file not found" error.
4242 engine
.executeOnFiles(".");
4245 it("'executeOnFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", async () => {
4246 const teardown
= createCustomTeardown({
4249 ".eslintrc.json": { ignorePatterns
: ["/subdir"] },
4250 "subdir/.eslintrc.json": { root
: true },
4251 "subdir/index.js": "console.log(\"hello\")"
4255 await teardown
.prepare();
4256 cleanup
= teardown
.cleanup
;
4257 engine
= new CLIEngine({ cwd
: teardown
.getPath() });
4259 // Don't throw "file not found" error.
4260 engine
.executeOnFiles("subdir");
4265 describe("getConfigForFile", () => {
4267 it("should return the info from Config#getConfig when called", () => {
4269 configFile
: getFixturePath("configurations", "quotes-error.json")
4271 const engine
= new CLIEngine(options
);
4272 const filePath
= getFixturePath("single-quoted.js");
4274 const actualConfig
= engine
.getConfigForFile(filePath
);
4275 const expectedConfig
= new CascadingConfigArrayFactory({ specificConfigPath
: options
.configFile
})
4276 .getConfigArrayForFile(filePath
)
4277 .extractConfig(filePath
)
4278 .toCompatibleObjectAsConfigFileContent();
4280 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4284 it("should return the config when run from within a subdir", () => {
4286 cwd
: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
4288 const engine
= new CLIEngine(options
);
4289 const filePath
= getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
4291 const actualConfig
= engine
.getConfigForFile("./.eslintrc");
4292 const expectedConfig
= new CascadingConfigArrayFactory(options
)
4293 .getConfigArrayForFile(filePath
)
4294 .extractConfig(filePath
)
4295 .toCompatibleObjectAsConfigFileContent();
4297 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4300 it("should throw an error if a directory path was given.", () => {
4301 const engine
= new CLIEngine();
4304 engine
.getConfigForFile(".");
4306 assert
.strictEqual(error
.messageTemplate
, "print-config-with-directory-path");
4309 assert
.fail("should throw an error");
4313 describe("isPathIgnored", () => {
4314 it("should check if the given path is ignored", () => {
4315 const engine
= new CLIEngine({
4316 ignorePath
: getFixturePath(".eslintignore2"),
4317 cwd
: getFixturePath()
4320 assert
.isTrue(engine
.isPathIgnored("undef.js"));
4321 assert
.isFalse(engine
.isPathIgnored("passing.js"));
4324 it("should return false if ignoring is disabled", () => {
4325 const engine
= new CLIEngine({
4327 ignorePath
: getFixturePath(".eslintignore2"),
4328 cwd
: getFixturePath()
4331 assert
.isFalse(engine
.isPathIgnored("undef.js"));
4334 // https://github.com/eslint/eslint/issues/5547
4335 it("should return true for default ignores even if ignoring is disabled", () => {
4336 const engine
= new CLIEngine({
4338 cwd
: getFixturePath("cli-engine")
4341 assert
.isTrue(engine
.isPathIgnored("node_modules/foo.js"));
4344 describe("about the default ignore patterns", () => {
4345 it("should always apply defaultPatterns if ignore option is true", () => {
4346 const cwd
= getFixturePath("ignored-paths");
4347 const engine
= new CLIEngine({ cwd
});
4349 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
4350 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
4353 it("should still apply defaultPatterns if ignore option is is false", () => {
4354 const cwd
= getFixturePath("ignored-paths");
4355 const engine
= new CLIEngine({ ignore
: false, cwd
});
4357 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
4358 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
4361 it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", () => {
4362 const cwd
= getFixturePath("ignored-paths");
4363 const engine
= new CLIEngine({ cwd
, ignorePattern
: "!/node_modules/package" });
4365 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4368 it("should allow subfolders of defaultPatterns to be unignored by ignorePath", () => {
4369 const cwd
= getFixturePath("ignored-paths");
4370 const engine
= new CLIEngine({ cwd
, ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
4372 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4375 it("should ignore dotfiles", () => {
4376 const cwd
= getFixturePath("ignored-paths");
4377 const engine
= new CLIEngine({ cwd
});
4379 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4380 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4383 it("should ignore directories beginning with a dot", () => {
4384 const cwd
= getFixturePath("ignored-paths");
4385 const engine
= new CLIEngine({ cwd
});
4387 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4388 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4391 it("should still ignore dotfiles when ignore option disabled", () => {
4392 const cwd
= getFixturePath("ignored-paths");
4393 const engine
= new CLIEngine({ ignore
: false, cwd
});
4395 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4396 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4399 it("should still ignore directories beginning with a dot when ignore option disabled", () => {
4400 const cwd
= getFixturePath("ignored-paths");
4401 const engine
= new CLIEngine({ ignore
: false, cwd
});
4403 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4404 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4407 it("should not ignore absolute paths containing '..'", () => {
4408 const cwd
= getFixturePath("ignored-paths");
4409 const engine
= new CLIEngine({ cwd
});
4411 assert(!engine
.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
4414 it("should ignore /node_modules/ relative to .eslintignore when loaded", () => {
4415 const cwd
= getFixturePath("ignored-paths");
4416 const engine
= new CLIEngine({ ignorePath
: getFixturePath("ignored-paths", ".eslintignore"), cwd
});
4418 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
4419 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
4422 it("should ignore /node_modules/ relative to cwd without an .eslintignore", () => {
4423 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4424 const engine
= new CLIEngine({ cwd
});
4426 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
4427 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
4431 describe("with no .eslintignore file", () => {
4432 it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", () => {
4433 const cwd
= getFixturePath("ignored-paths", "configurations");
4434 const engine
= new CLIEngine({ cwd
});
4436 // a .eslintignore in parent directories includes `*.js`, but don't load it.
4437 assert(!engine
.isPathIgnored("foo.js"));
4438 assert(engine
.isPathIgnored("node_modules/foo.js"));
4441 it("should return false for files outside of the cwd (with no ignore file provided)", () => {
4443 // Default ignore patterns should not inadvertently ignore files in parent directories
4444 const engine
= new CLIEngine({ cwd
: getFixturePath("ignored-paths", "no-ignore-file") });
4446 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4450 describe("with .eslintignore file or package.json file", () => {
4451 it("should load .eslintignore from cwd when explicitly passed", () => {
4452 const cwd
= getFixturePath("ignored-paths");
4453 const engine
= new CLIEngine({ cwd
});
4455 // `${cwd}/.eslintignore` includes `sampleignorepattern`.
4456 assert(engine
.isPathIgnored("sampleignorepattern"));
4459 it("should use package.json's eslintIgnore files if no specified .eslintignore file", () => {
4460 const cwd
= getFixturePath("ignored-paths", "package-json-ignore");
4461 const engine
= new CLIEngine({ cwd
});
4463 assert(engine
.isPathIgnored("hello.js"));
4464 assert(engine
.isPathIgnored("world.js"));
4467 it("should use correct message template if failed to parse package.json", () => {
4468 const cwd
= getFixturePath("ignored-paths", "broken-package-json");
4470 assert
.throw(() => {
4472 // eslint-disable-next-line no-new -- Check for throwing
4473 new CLIEngine({ cwd
});
4475 assert
.strictEqual(error
.messageTemplate
, "failed-to-read-json");
4481 it("should not use package.json's eslintIgnore files if specified .eslintignore file", () => {
4482 const cwd
= getFixturePath("ignored-paths");
4483 const engine
= new CLIEngine({ cwd
});
4486 * package.json includes `hello.js` and `world.js`.
4487 * .eslintignore includes `sampleignorepattern`.
4489 assert(!engine
.isPathIgnored("hello.js"));
4490 assert(!engine
.isPathIgnored("world.js"));
4491 assert(engine
.isPathIgnored("sampleignorepattern"));
4494 it("should error if package.json's eslintIgnore is not an array of file paths", () => {
4495 const cwd
= getFixturePath("ignored-paths", "bad-package-json-ignore");
4497 assert
.throws(() => {
4498 // eslint-disable-next-line no-new -- Check for throwing
4499 new CLIEngine({ cwd
});
4500 }, "Package.json eslintIgnore property requires an array of paths");
4504 describe("with --ignore-pattern option", () => {
4505 it("should accept a string for options.ignorePattern", () => {
4506 const cwd
= getFixturePath("ignored-paths", "ignore-pattern");
4507 const engine
= new CLIEngine({
4508 ignorePattern
: "ignore-me.txt",
4512 assert(engine
.isPathIgnored("ignore-me.txt"));
4515 it("should accept an array for options.ignorePattern", () => {
4516 const engine
= new CLIEngine({
4517 ignorePattern
: ["a", "b"],
4521 assert(engine
.isPathIgnored("a"));
4522 assert(engine
.isPathIgnored("b"));
4523 assert(!engine
.isPathIgnored("c"));
4526 it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", () => {
4527 const cwd
= getFixturePath("ignored-paths");
4528 const engine
= new CLIEngine({
4529 ignorePattern
: "not-a-file",
4533 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
4536 it("should return true for file matching an ignore pattern exactly", () => {
4537 const cwd
= getFixturePath("ignored-paths");
4538 const engine
= new CLIEngine({ ignorePattern
: "undef.js", cwd
});
4540 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4543 it("should return false for file matching an invalid ignore pattern with leading './'", () => {
4544 const cwd
= getFixturePath("ignored-paths");
4545 const engine
= new CLIEngine({ ignorePattern
: "./undef.js", cwd
});
4547 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4550 it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", () => {
4551 const cwd
= getFixturePath("ignored-paths");
4552 const engine
= new CLIEngine({ ignorePattern
: "/undef.js", cwd
});
4554 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
4557 it("should return true for file matching a child of an ignore pattern", () => {
4558 const cwd
= getFixturePath("ignored-paths");
4559 const engine
= new CLIEngine({ ignorePattern
: "ignore-pattern", cwd
});
4561 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
4564 it("should return true for file matching a grandchild of an ignore pattern", () => {
4565 const cwd
= getFixturePath("ignored-paths");
4566 const engine
= new CLIEngine({ ignorePattern
: "ignore-pattern", cwd
});
4568 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
4571 it("should return false for file not matching any ignore pattern", () => {
4572 const cwd
= getFixturePath("ignored-paths");
4573 const engine
= new CLIEngine({ ignorePattern
: "failing.js", cwd
});
4575 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
4578 it("two globstar '**' ignore pattern should ignore files in nested directories", () => {
4579 const cwd
= getFixturePath("ignored-paths");
4580 const engine
= new CLIEngine({ ignorePattern
: "**/*.js", cwd
});
4582 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4583 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
4584 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
4585 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
4586 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
4587 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
4591 describe("with --ignore-path option", () => {
4592 it("should load empty array with ignorePath set to false", () => {
4593 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4594 const engine
= new CLIEngine({ ignorePath
: false, cwd
});
4596 // a .eslintignore in parent directories includes `*.js`, but don't load it.
4597 assert(!engine
.isPathIgnored("foo.js"));
4598 assert(engine
.isPathIgnored("node_modules/foo.js"));
4601 it("initialization with ignorePath should work when cwd is a parent directory", () => {
4602 const cwd
= getFixturePath("ignored-paths");
4603 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4604 const engine
= new CLIEngine({ ignorePath
, cwd
});
4606 assert(engine
.isPathIgnored("custom-name/foo.js"));
4609 it("initialization with ignorePath should work when the file is in the cwd", () => {
4610 const cwd
= getFixturePath("ignored-paths", "custom-name");
4611 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4612 const engine
= new CLIEngine({ ignorePath
, cwd
});
4614 assert(engine
.isPathIgnored("foo.js"));
4617 it("initialization with ignorePath should work when cwd is a subdirectory", () => {
4618 const cwd
= getFixturePath("ignored-paths", "custom-name", "subdirectory");
4619 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4620 const engine
= new CLIEngine({ ignorePath
, cwd
});
4622 assert(engine
.isPathIgnored("../custom-name/foo.js"));
4625 it("initialization with invalid file should throw error", () => {
4626 const cwd
= getFixturePath("ignored-paths");
4627 const ignorePath
= getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
4629 assert
.throws(() => {
4630 // eslint-disable-next-line no-new -- Check for throwing
4631 new CLIEngine({ ignorePath
, cwd
});
4632 }, "Cannot read .eslintignore file");
4635 it("should return false for files outside of ignorePath's directory", () => {
4636 const cwd
= getFixturePath("ignored-paths");
4637 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4638 const engine
= new CLIEngine({ ignorePath
, cwd
});
4640 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4643 it("should resolve relative paths from CWD", () => {
4644 const cwd
= getFixturePath("ignored-paths", "subdir");
4645 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4646 const engine
= new CLIEngine({ ignorePath
, cwd
});
4648 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4649 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4652 it("should resolve relative paths from CWD when it's in a child directory", () => {
4653 const cwd
= getFixturePath("ignored-paths");
4654 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4655 const engine
= new CLIEngine({ ignorePath
, cwd
});
4657 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4658 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4659 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4660 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
4662 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
4665 it("should resolve relative paths from CWD when it contains negated globs", () => {
4666 const cwd
= getFixturePath("ignored-paths");
4667 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4668 const engine
= new CLIEngine({ ignorePath
, cwd
});
4670 assert(engine
.isPathIgnored("subdir/blah.txt"));
4671 assert(engine
.isPathIgnored("blah.txt"));
4672 assert(engine
.isPathIgnored("subdir/bar.txt"));
4673 assert(!engine
.isPathIgnored("bar.txt"));
4674 assert(!engine
.isPathIgnored("subdir/baz.txt"));
4675 assert(!engine
.isPathIgnored("baz.txt"));
4678 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", () => {
4679 const cwd
= getFixturePath("ignored-paths");
4680 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4681 const engine
= new CLIEngine({ ignorePath
, cwd
});
4683 assert(engine
.isPathIgnored("node_modules/blah.js"));
4686 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", () => {
4687 const cwd
= getFixturePath("ignored-paths", "subdir");
4688 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4689 const engine
= new CLIEngine({ ignorePath
, cwd
});
4691 assert(engine
.isPathIgnored("node_modules/blah.js"));
4694 it("should handle .eslintignore which contains CRLF correctly.", () => {
4695 const ignoreFileContent
= fs
.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
4697 assert(ignoreFileContent
.includes("\r"), "crlf/.eslintignore should contains CR.");
4699 const cwd
= getFixturePath("ignored-paths");
4700 const ignorePath
= getFixturePath("ignored-paths", "crlf/.eslintignore");
4701 const engine
= new CLIEngine({ ignorePath
, cwd
});
4703 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
4704 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
4705 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
4708 it("should not include comments in ignore rules", () => {
4709 const cwd
= getFixturePath("ignored-paths");
4710 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithComments");
4711 const engine
= new CLIEngine({ ignorePath
, cwd
});
4713 assert(!engine
.isPathIgnored("# should be ignored"));
4714 assert(engine
.isPathIgnored("this_one_not"));
4717 it("should ignore a non-negated pattern", () => {
4718 const cwd
= getFixturePath("ignored-paths");
4719 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4720 const engine
= new CLIEngine({ ignorePath
, cwd
});
4722 assert(engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
4725 it("should not ignore a negated pattern", () => {
4726 const cwd
= getFixturePath("ignored-paths");
4727 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4728 const engine
= new CLIEngine({ ignorePath
, cwd
});
4730 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
4734 describe("with --ignore-path option and --ignore-pattern option", () => {
4735 it("should return false for ignored file when unignored with ignore pattern", () => {
4736 const cwd
= getFixturePath("ignored-paths");
4737 const engine
= new CLIEngine({
4738 ignorePath
: getFixturePath("ignored-paths", ".eslintignore"),
4739 ignorePattern
: "!sampleignorepattern",
4743 assert(!engine
.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
4748 describe("getFormatter()", () => {
4750 it("should return a function when a bundled formatter is requested", () => {
4751 const engine
= new CLIEngine(),
4752 formatter
= engine
.getFormatter("compact");
4754 assert
.isFunction(formatter
);
4757 it("should return a function when no argument is passed", () => {
4758 const engine
= new CLIEngine(),
4759 formatter
= engine
.getFormatter();
4761 assert
.isFunction(formatter
);
4764 it("should return a function when a custom formatter is requested", () => {
4765 const engine
= new CLIEngine(),
4766 formatter
= engine
.getFormatter(getFixturePath("formatters", "simple.js"));
4768 assert
.isFunction(formatter
);
4771 it("should return a function when a custom formatter is requested, also if the path has backslashes", () => {
4772 const engine
= new CLIEngine({
4773 cwd
: path
.join(fixtureDir
, "..")
4775 formatter
= engine
.getFormatter(".\\fixtures\\formatters\\simple.js");
4777 assert
.isFunction(formatter
);
4780 it("should return a function when a formatter prefixed with eslint-formatter is requested", () => {
4781 const engine
= new CLIEngine({
4782 cwd
: getFixturePath("cli-engine")
4784 formatter
= engine
.getFormatter("bar");
4786 assert
.isFunction(formatter
);
4789 it("should return a function when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", () => {
4790 const engine
= new CLIEngine({
4791 cwd
: getFixturePath("cli-engine")
4793 formatter
= engine
.getFormatter("eslint-formatter-bar");
4795 assert
.isFunction(formatter
);
4798 it("should return a function when a formatter is requested within a scoped npm package", () => {
4799 const engine
= new CLIEngine({
4800 cwd
: getFixturePath("cli-engine")
4802 formatter
= engine
.getFormatter("@somenamespace/foo");
4804 assert
.isFunction(formatter
);
4807 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", () => {
4808 const engine
= new CLIEngine({
4809 cwd
: getFixturePath("cli-engine")
4811 formatter
= engine
.getFormatter("@somenamespace/eslint-formatter-foo");
4813 assert
.isFunction(formatter
);
4816 it("should return null when a custom formatter doesn't exist", () => {
4817 const engine
= new CLIEngine(),
4818 formatterPath
= getFixturePath("formatters", "doesntexist.js"),
4819 fullFormatterPath
= path
.resolve(formatterPath
);
4821 assert
.throws(() => {
4822 engine
.getFormatter(formatterPath
);
4823 }, `There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`);
4826 it("should return null when a built-in formatter doesn't exist", () => {
4827 const engine
= new CLIEngine();
4828 const fullFormatterPath
= path
.resolve(__dirname
, "../../../lib/cli-engine/formatters/special");
4830 assert
.throws(() => {
4831 engine
.getFormatter("special");
4832 }, `There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`);
4835 it("should throw when a built-in formatter no longer exists", () => {
4836 const engine
= new CLIEngine();
4838 assert
.throws(() => {
4839 engine
.getFormatter("table");
4840 }, "The table formatter is no longer part of core ESLint. Install it manually with `npm install -D eslint-formatter-table`");
4842 assert
.throws(() => {
4843 engine
.getFormatter("codeframe");
4844 }, "The codeframe formatter is no longer part of core ESLint. Install it manually with `npm install -D eslint-formatter-codeframe`");
4847 it("should throw if the required formatter exists but has an error", () => {
4848 const engine
= new CLIEngine(),
4849 formatterPath
= getFixturePath("formatters", "broken.js");
4851 assert
.throws(() => {
4852 engine
.getFormatter(formatterPath
);
4853 }, `There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`);
4856 it("should return null when a non-string formatter name is passed", () => {
4857 const engine
= new CLIEngine(),
4858 formatter
= engine
.getFormatter(5);
4860 assert
.isNull(formatter
);
4863 it("should return a function when called as a static function on CLIEngine", () => {
4864 const formatter
= CLIEngine
.getFormatter();
4866 assert
.isFunction(formatter
);
4869 it("should return a function when called as a static function on CLIEngine and a custom formatter is requested", () => {
4870 const formatter
= CLIEngine
.getFormatter(getFixturePath("formatters", "simple.js"));
4872 assert
.isFunction(formatter
);
4877 describe("getErrorResults()", () => {
4878 it("should report 5 error messages when looking for errors only", () => {
4880 process
.chdir(originalDir
);
4881 const engine
= new CLIEngine();
4883 const report
= engine
.executeOnText("var foo = 'bar';");
4884 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4886 assert
.lengthOf(errorResults
[0].messages
, 5);
4887 assert
.strictEqual(errorResults
[0].errorCount
, 5);
4888 assert
.strictEqual(errorResults
[0].fixableErrorCount
, 3);
4889 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4890 assert
.strictEqual(errorResults
[0].messages
[0].ruleId
, "strict");
4891 assert
.strictEqual(errorResults
[0].messages
[0].severity
, 2);
4892 assert
.strictEqual(errorResults
[0].messages
[1].ruleId
, "no-var");
4893 assert
.strictEqual(errorResults
[0].messages
[1].severity
, 2);
4894 assert
.strictEqual(errorResults
[0].messages
[2].ruleId
, "no-unused-vars");
4895 assert
.strictEqual(errorResults
[0].messages
[2].severity
, 2);
4896 assert
.strictEqual(errorResults
[0].messages
[3].ruleId
, "quotes");
4897 assert
.strictEqual(errorResults
[0].messages
[3].severity
, 2);
4898 assert
.strictEqual(errorResults
[0].messages
[4].ruleId
, "eol-last");
4899 assert
.strictEqual(errorResults
[0].messages
[4].severity
, 2);
4900 assert
.lengthOf(errorResults
[0].suppressedMessages
, 0);
4903 it("should report no error messages when looking for errors only", () => {
4904 process
.chdir(originalDir
);
4905 const engine
= new CLIEngine();
4907 const report
= engine
.executeOnText("var foo = 'bar'; // eslint-disable-line strict, no-var, no-unused-vars, quotes, eol-last -- justification");
4908 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4910 assert
.lengthOf(errorResults
, 0);
4913 it("should not mutate passed report.results parameter", () => {
4914 process
.chdir(originalDir
);
4915 const engine
= new CLIEngine({
4916 rules
: { quotes
: [1, "double"] }
4919 const report
= engine
.executeOnText("var foo = 'bar';");
4920 const reportResultsLength
= report
.results
[0].messages
.length
;
4922 CLIEngine
.getErrorResults(report
.results
);
4924 assert
.lengthOf(report
.results
[0].messages
, reportResultsLength
);
4927 it("should report no suppressed error messages when looking for errors only", () => {
4928 process
.chdir(originalDir
);
4929 const engine
= new CLIEngine({
4931 quotes
: [1, "double"],
4936 const report
= engine
.executeOnText("var foo = 'bar'; // eslint-disable-line quotes -- justification\n");
4937 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4939 assert
.lengthOf(report
.results
[0].messages
, 3);
4940 assert
.lengthOf(report
.results
[0].suppressedMessages
, 1);
4941 assert
.lengthOf(errorResults
[0].messages
, 3);
4942 assert
.lengthOf(errorResults
[0].suppressedMessages
, 0);
4945 it("should report a warningCount of 0 when looking for errors only", () => {
4947 process
.chdir(originalDir
);
4948 const engine
= new CLIEngine();
4950 const report
= engine
.executeOnText("var foo = 'bar';");
4951 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4953 assert
.strictEqual(errorResults
[0].warningCount
, 0);
4954 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4957 it("should return 0 error or warning messages even when the file has warnings", () => {
4958 const engine
= new CLIEngine({
4959 ignorePath
: path
.join(fixtureDir
, ".eslintignore"),
4960 cwd
: path
.join(fixtureDir
, "..")
4963 const report
= engine
.executeOnText("var bar = foo;", "fixtures/passing.js", true);
4964 const errorReport
= CLIEngine
.getErrorResults(report
.results
);
4966 assert
.lengthOf(errorReport
, 0);
4967 assert
.lengthOf(report
.results
, 1);
4968 assert
.strictEqual(report
.errorCount
, 0);
4969 assert
.strictEqual(report
.warningCount
, 1);
4970 assert
.strictEqual(report
.fatalErrorCount
, 0);
4971 assert
.strictEqual(report
.fixableErrorCount
, 0);
4972 assert
.strictEqual(report
.fixableWarningCount
, 0);
4973 assert
.strictEqual(report
.results
[0].errorCount
, 0);
4974 assert
.strictEqual(report
.results
[0].warningCount
, 1);
4975 assert
.strictEqual(report
.results
[0].fatalErrorCount
, 0);
4976 assert
.strictEqual(report
.results
[0].fixableErrorCount
, 0);
4977 assert
.strictEqual(report
.results
[0].fixableWarningCount
, 0);
4980 it("should return source code of file in the `source` property", () => {
4981 process
.chdir(originalDir
);
4982 const engine
= new CLIEngine({
4984 rules
: { quotes
: [2, "double"] }
4988 const report
= engine
.executeOnText("var foo = 'bar';");
4989 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
4991 assert
.lengthOf(errorResults
[0].messages
, 1);
4992 assert
.strictEqual(errorResults
[0].source
, "var foo = 'bar';");
4995 it("should contain `output` property after fixes", () => {
4996 process
.chdir(originalDir
);
4997 const engine
= new CLIEngine({
5006 const report
= engine
.executeOnText("console.log('foo')");
5007 const errorResults
= CLIEngine
.getErrorResults(report
.results
);
5009 assert
.lengthOf(errorResults
[0].messages
, 1);
5010 assert
.strictEqual(errorResults
[0].output
, "console.log('foo');");
5014 describe("outputFixes()", () => {
5016 sinon
.verifyAndRestore();
5019 it("should call fs.writeFileSync() for each result with output", () => {
5021 writeFileSync
: () => {}
5023 localCLIEngine
= proxyquire("../../../lib/cli-engine/cli-engine", {
5039 const spy
= sinon
.spy(fakeFS
, "writeFileSync");
5041 localCLIEngine
.outputFixes(report
);
5043 assert
.strictEqual(spy
.callCount
, 2);
5044 assert
.isTrue(spy
.firstCall
.calledWithExactly("foo.js", "bar"), "First call was incorrect.");
5045 assert
.isTrue(spy
.secondCall
.calledWithExactly("bar.js", "baz"), "Second call was incorrect.");
5049 it("should call fs.writeFileSync() for each result with output and not at all for a result without output", () => {
5051 writeFileSync
: () => {}
5053 localCLIEngine
= proxyquire("../../../lib/cli-engine/cli-engine", {
5072 const spy
= sinon
.spy(fakeFS
, "writeFileSync");
5074 localCLIEngine
.outputFixes(report
);
5076 assert
.strictEqual(spy
.callCount
, 2);
5077 assert
.isTrue(spy
.firstCall
.calledWithExactly("foo.js", "bar"), "First call was incorrect.");
5078 assert
.isTrue(spy
.secondCall
.calledWithExactly("bar.js", "baz"), "Second call was incorrect.");
5084 describe("getRules()", () => {
5085 it("should expose the list of rules", () => {
5086 const engine
= new CLIEngine();
5088 assert(engine
.getRules().has("no-eval"), "no-eval is present");
5091 it("should expose the list of plugin rules", () => {
5092 const engine
= new CLIEngine({ plugins
: ["n"] });
5094 assert(engine
.getRules().has("n/no-deprecated-api"), "n/no-deprecated-api is present");
5097 it("should expose the list of rules from a preloaded plugin", () => {
5098 const engine
= new CLIEngine({
5102 foo
: require("eslint-plugin-n")
5106 assert(engine
.getRules().has("foo/no-deprecated-api"), "foo/no-deprecated-api is present");
5110 describe("resolveFileGlobPatterns", () => {
5113 [".", ["**/*.{js}"]],
5114 ["./", ["**/*.{js}"]],
5115 ["../", ["../**/*.{js}"]],
5117 ].forEach(([input
, expected
]) => {
5119 it(`should correctly resolve ${input} to ${expected}`, () => {
5120 const engine
= new CLIEngine();
5122 const result
= engine
.resolveFileGlobPatterns([input
]);
5124 assert
.deepStrictEqual(result
, expected
);
5129 it("should convert a directory name with no provided extensions into a glob pattern", () => {
5130 const patterns
= ["one-js-file"];
5132 cwd
: getFixturePath("glob-util")
5134 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5136 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
5139 it("should not convert path with globInputPaths option false", () => {
5140 const patterns
= ["one-js-file"];
5142 cwd
: getFixturePath("glob-util"),
5143 globInputPaths
: false
5145 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5147 assert
.deepStrictEqual(result
, ["one-js-file"]);
5150 it("should convert an absolute directory name with no provided extensions into a posix glob pattern", () => {
5151 const patterns
= [getFixturePath("glob-util", "one-js-file")];
5153 cwd
: getFixturePath("glob-util")
5155 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5156 const expected
= [`${getFixturePath("glob-util", "one-js-file").replace(/\\/gu, "/")}/**/*.{js}`];
5158 assert
.deepStrictEqual(result
, expected
);
5161 it("should convert a directory name with a single provided extension into a glob pattern", () => {
5162 const patterns
= ["one-js-file"];
5164 cwd
: getFixturePath("glob-util"),
5165 extensions
: [".jsx"]
5167 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5169 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{jsx}"]);
5172 it("should convert a directory name with multiple provided extensions into a glob pattern", () => {
5173 const patterns
= ["one-js-file"];
5175 cwd
: getFixturePath("glob-util"),
5176 extensions
: [".jsx", ".js"]
5178 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5180 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{jsx,js}"]);
5183 it("should convert multiple directory names into glob patterns", () => {
5184 const patterns
= ["one-js-file", "two-js-files"];
5186 cwd
: getFixturePath("glob-util")
5188 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5190 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}", "two-js-files/**/*.{js}"]);
5193 it("should remove leading './' from glob patterns", () => {
5194 const patterns
= ["./one-js-file"];
5196 cwd
: getFixturePath("glob-util")
5198 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5200 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
5203 it("should convert a directory name with a trailing '/' into a glob pattern", () => {
5204 const patterns
= ["one-js-file/"];
5206 cwd
: getFixturePath("glob-util")
5208 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5210 assert
.deepStrictEqual(result
, ["one-js-file/**/*.{js}"]);
5213 it("should return filenames as they are", () => {
5214 const patterns
= ["some-file.js"];
5216 cwd
: getFixturePath("glob-util")
5218 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5220 assert
.deepStrictEqual(result
, ["some-file.js"]);
5223 it("should convert backslashes into forward slashes", () => {
5224 const patterns
= ["one-js-file\\example.js"];
5226 cwd
: getFixturePath()
5228 const result
= new CLIEngine(opts
).resolveFileGlobPatterns(patterns
);
5230 assert
.deepStrictEqual(result
, ["one-js-file/example.js"]);
5234 describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
5236 it("should report a violation for disabling rules", () => {
5238 "alert('test'); // eslint-disable-line no-alert"
5244 allowInlineConfig
: false,
5248 "no-trailing-spaces": 0,
5254 const eslintCLI
= new CLIEngine(config
);
5256 const report
= eslintCLI
.executeOnText(code
);
5257 const { messages
, suppressedMessages
} = report
.results
[0];
5259 assert
.strictEqual(messages
.length
, 1);
5260 assert
.strictEqual(messages
[0].ruleId
, "no-alert");
5261 assert
.strictEqual(suppressedMessages
.length
, 0);
5264 it("should not report a violation by default", () => {
5266 "alert('test'); // eslint-disable-line no-alert"
5273 // allowInlineConfig: true is the default
5277 "no-trailing-spaces": 0,
5283 const eslintCLI
= new CLIEngine(config
);
5285 const report
= eslintCLI
.executeOnText(code
);
5286 const { messages
, suppressedMessages
} = report
.results
[0];
5288 assert
.strictEqual(messages
.length
, 0);
5289 assert
.strictEqual(suppressedMessages
.length
, 1);
5290 assert
.strictEqual(suppressedMessages
[0].ruleId
, "no-alert");
5295 describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
5296 it("should report problems for unused eslint-disable directives", () => {
5297 const cliEngine
= new CLIEngine({ useEslintrc
: false, reportUnusedDisableDirectives
: true });
5299 assert
.deepStrictEqual(
5300 cliEngine
.executeOnText("/* eslint-disable */"),
5308 message
: "Unused eslint-disable directive (no problems were reported).",
5319 suppressedMessages
: [],
5323 fixableErrorCount
: 1,
5324 fixableWarningCount
: 0,
5325 source
: "/* eslint-disable */"
5331 fixableErrorCount
: 1,
5332 fixableWarningCount
: 0,
5333 usedDeprecatedRules
: []
5339 describe("when retrieving version number", () => {
5340 it("should return current version number", () => {
5341 const eslintCLI
= require("../../../lib/cli-engine").CLIEngine
;
5342 const version
= eslintCLI
.version
;
5344 assert
.isString(version
);
5345 assert
.isTrue(parseInt(version
[0], 10) >= 3);
5349 describe("mutability", () => {
5350 describe("plugins", () => {
5351 it("Loading plugin in one instance doesn't mutate to another instance", () => {
5352 const filePath
= getFixturePath("single-quoted.js");
5353 const engine1
= cliEngineWithPlugins({
5354 cwd
: path
.join(fixtureDir
, ".."),
5356 plugins
: ["example"],
5357 rules
: { "example/example-rule": 1 }
5359 const engine2
= new CLIEngine({
5360 cwd
: path
.join(fixtureDir
, ".."),
5363 const fileConfig1
= engine1
.getConfigForFile(filePath
);
5364 const fileConfig2
= engine2
.getConfigForFile(filePath
);
5367 assert
.deepStrictEqual(fileConfig1
.plugins
, ["example"], "Plugin is present for engine 1");
5368 assert
.deepStrictEqual(fileConfig2
.plugins
, [], "Plugin is not present for engine 2");
5372 describe("rules", () => {
5373 it("Loading rules in one instance doesn't mutate to another instance", () => {
5374 const filePath
= getFixturePath("single-quoted.js");
5375 const engine1
= new CLIEngine({
5376 cwd
: path
.join(fixtureDir
, ".."),
5378 rules
: { "example/example-rule": 1 }
5380 const engine2
= new CLIEngine({
5381 cwd
: path
.join(fixtureDir
, ".."),
5384 const fileConfig1
= engine1
.getConfigForFile(filePath
);
5385 const fileConfig2
= engine2
.getConfigForFile(filePath
);
5388 assert
.deepStrictEqual(fileConfig1
.rules
["example/example-rule"], [1], "example is present for engine 1");
5389 assert
.isUndefined(fileConfig2
.rules
["example/example-rule"], "example is not present for engine 2");
5394 describe("with ignorePatterns config", () => {
5395 const root
= getFixturePath("cli-engine/ignore-patterns");
5397 describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
5399 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5403 ignorePatterns
: "foo.js"
5407 "subdir/foo.js": "",
5412 beforeEach(prepare
);
5415 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5416 const engine
= new CLIEngine({ cwd
: getPath() });
5418 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5419 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5422 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5423 const engine
= new CLIEngine({ cwd
: getPath() });
5425 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5426 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), false);
5429 it("'executeOnFiles()' should not verify 'foo.js'.", () => {
5430 const engine
= new CLIEngine({ cwd
: getPath() });
5431 const filePaths
= engine
.executeOnFiles("**/*.js")
5433 .map(r
=> r
.filePath
)
5436 assert
.deepStrictEqual(filePaths
, [
5437 path
.join(root
, "bar.js"),
5438 path
.join(root
, "subdir/bar.js")
5443 describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
5444 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5448 ignorePatterns
: ["foo.js", "/bar.js"]
5453 "subdir/foo.js": "",
5454 "subdir/bar.js": "",
5459 beforeEach(prepare
);
5462 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5463 const engine
= new CLIEngine({ cwd
: getPath() });
5465 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5466 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5469 it("'isPathIgnored()' should return 'true' for '/bar.js'.", () => {
5470 const engine
= new CLIEngine({ cwd
: getPath() });
5472 assert
.strictEqual(engine
.isPathIgnored("bar.js"), true);
5473 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), false);
5476 it("'executeOnFiles()' should not verify 'foo.js' and '/bar.js'.", () => {
5477 const engine
= new CLIEngine({ cwd
: getPath() });
5478 const filePaths
= engine
.executeOnFiles("**/*.js")
5480 .map(r
=> r
.filePath
)
5483 assert
.deepStrictEqual(filePaths
, [
5484 path
.join(root
, "baz.js"),
5485 path
.join(root
, "subdir/bar.js"),
5486 path
.join(root
, "subdir/baz.js")
5491 describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
5493 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5497 ignorePatterns
: "!/node_modules/foo"
5499 "node_modules/foo/index.js": "",
5500 "node_modules/foo/.dot.js": "",
5501 "node_modules/bar/index.js": "",
5506 beforeEach(prepare
);
5509 it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", () => {
5510 const engine
= new CLIEngine({ cwd
: getPath() });
5512 assert
.strictEqual(engine
.isPathIgnored("node_modules/foo/index.js"), false);
5515 it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", () => {
5516 const engine
= new CLIEngine({ cwd
: getPath() });
5518 assert
.strictEqual(engine
.isPathIgnored("node_modules/foo/.dot.js"), true);
5521 it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", () => {
5522 const engine
= new CLIEngine({ cwd
: getPath() });
5524 assert
.strictEqual(engine
.isPathIgnored("node_modules/bar/index.js"), true);
5527 it("'executeOnFiles()' should verify 'node_modules/foo/index.js'.", () => {
5528 const engine
= new CLIEngine({ cwd
: getPath() });
5529 const filePaths
= engine
.executeOnFiles("**/*.js")
5531 .map(r
=> r
.filePath
)
5534 assert
.deepStrictEqual(filePaths
, [
5535 path
.join(root
, "foo.js"),
5536 path
.join(root
, "node_modules/foo/index.js")
5541 describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
5543 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5546 ".eslintrc.js": `module.exports = ${JSON.stringify({
5547 ignorePatterns: "!.eslintrc.js"
5553 beforeEach(prepare
);
5556 it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", () => {
5557 const engine
= new CLIEngine({ cwd
: getPath() });
5559 assert
.strictEqual(engine
.isPathIgnored(".eslintrc.js"), false);
5562 it("'executeOnFiles()' should verify '.eslintrc.js'.", () => {
5563 const engine
= new CLIEngine({ cwd
: getPath() });
5564 const filePaths
= engine
.executeOnFiles("**/*.js")
5566 .map(r
=> r
.filePath
)
5569 assert
.deepStrictEqual(filePaths
, [
5570 path
.join(root
, ".eslintrc.js"),
5571 path
.join(root
, "foo.js")
5576 describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
5577 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5580 ".eslintrc.js": `module.exports = ${JSON.stringify({
5581 ignorePatterns: "!.*"
5583 ".eslintignore": ".foo*",
5589 beforeEach(prepare
);
5592 it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", () => {
5593 const engine
= new CLIEngine({ cwd
: getPath() });
5595 assert
.strictEqual(engine
.isPathIgnored(".foo.js"), true);
5598 it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", () => {
5599 const engine
= new CLIEngine({ cwd
: getPath() });
5601 assert
.strictEqual(engine
.isPathIgnored(".bar.js"), false);
5604 it("'executeOnFiles()' should not verify re-ignored '.foo.js'.", () => {
5605 const engine
= new CLIEngine({ cwd
: getPath() });
5606 const filePaths
= engine
.executeOnFiles("**/*.js")
5608 .map(r
=> r
.filePath
)
5611 assert
.deepStrictEqual(filePaths
, [
5612 path
.join(root
, ".bar.js"),
5613 path
.join(root
, ".eslintrc.js")
5618 describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
5620 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5623 ".eslintrc.js": `module.exports = ${JSON.stringify({
5624 ignorePatterns: "*.js"
5626 ".eslintignore": "!foo.js",
5632 beforeEach(prepare
);
5635 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", () => {
5636 const engine
= new CLIEngine({ cwd
: getPath() });
5638 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5641 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", () => {
5642 const engine
= new CLIEngine({ cwd
: getPath() });
5644 assert
.strictEqual(engine
.isPathIgnored("bar.js"), true);
5647 it("'executeOnFiles()' should verify unignored 'foo.js'.", () => {
5648 const engine
= new CLIEngine({ cwd
: getPath() });
5649 const filePaths
= engine
.executeOnFiles("**/*.js")
5651 .map(r
=> r
.filePath
)
5654 assert
.deepStrictEqual(filePaths
, [
5655 path
.join(root
, "foo.js")
5660 describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
5661 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5664 ".eslintrc.json": JSON
.stringify({
5665 ignorePatterns
: "foo.js"
5667 "subdir/.eslintrc.json": JSON
.stringify({
5668 ignorePatterns
: "bar.js"
5672 "subdir/foo.js": "",
5673 "subdir/bar.js": "",
5674 "subdir/subsubdir/foo.js": "",
5675 "subdir/subsubdir/bar.js": ""
5679 beforeEach(prepare
);
5682 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5683 const engine
= new CLIEngine({ cwd
: getPath() });
5685 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5686 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5687 assert
.strictEqual(engine
.isPathIgnored("subdir/subsubdir/foo.js"), true);
5690 it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", () => {
5691 const engine
= new CLIEngine({ cwd
: getPath() });
5693 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5694 assert
.strictEqual(engine
.isPathIgnored("subdir/subsubdir/bar.js"), true);
5697 it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", () => {
5698 const engine
= new CLIEngine({ cwd
: getPath() });
5700 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5703 it("'executeOnFiles()' should verify 'bar.js' in the outside of 'subdir'.", () => {
5704 const engine
= new CLIEngine({ cwd
: getPath() });
5705 const filePaths
= engine
.executeOnFiles("**/*.js")
5707 .map(r
=> r
.filePath
)
5710 assert
.deepStrictEqual(filePaths
, [
5711 path
.join(root
, "bar.js")
5716 describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
5717 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5720 ".eslintrc.json": JSON
.stringify({
5721 ignorePatterns
: "foo.js"
5723 "subdir/.eslintrc.json": JSON
.stringify({
5724 ignorePatterns
: "!foo.js"
5731 beforeEach(prepare
);
5734 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", () => {
5735 const engine
= new CLIEngine({ cwd
: getPath() });
5737 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5740 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", () => {
5741 const engine
= new CLIEngine({ cwd
: getPath() });
5743 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5746 it("'executeOnFiles()' should verify 'foo.js' in the child directory.", () => {
5747 const engine
= new CLIEngine({ cwd
: getPath() });
5748 const filePaths
= engine
.executeOnFiles("**/*.js")
5750 .map(r
=> r
.filePath
)
5753 assert
.deepStrictEqual(filePaths
, [
5754 path
.join(root
, "subdir/foo.js")
5759 describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
5760 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5763 ".eslintrc.json": {},
5764 "subdir/.eslintrc.json": {
5765 ignorePatterns
: "*.js"
5767 ".eslintignore": "!foo.js",
5769 "subdir/foo.js": "",
5774 beforeEach(prepare
);
5777 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", () => {
5778 const engine
= new CLIEngine({ cwd
: getPath() });
5780 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
5781 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5784 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", () => {
5785 const engine
= new CLIEngine({ cwd
: getPath() });
5787 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5790 it("'executeOnFiles()' should verify unignored 'foo.js'.", () => {
5791 const engine
= new CLIEngine({ cwd
: getPath() });
5792 const filePaths
= engine
.executeOnFiles("**/*.js")
5794 .map(r
=> r
.filePath
)
5797 assert
.deepStrictEqual(filePaths
, [
5798 path
.join(root
, "foo.js"),
5799 path
.join(root
, "subdir/foo.js")
5804 describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
5805 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5809 ignorePatterns
: "foo.js"
5811 "subdir/.eslintrc.json": {
5813 ignorePatterns
: "bar.js"
5817 "subdir/foo.js": "",
5822 beforeEach(prepare
);
5825 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", () => {
5826 const engine
= new CLIEngine({ cwd
: getPath() });
5828 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5831 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", () => {
5832 const engine
= new CLIEngine({ cwd
: getPath() });
5834 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5837 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", () => {
5838 const engine
= new CLIEngine({ cwd
: getPath() });
5840 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5843 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", () => {
5844 const engine
= new CLIEngine({ cwd
: getPath() });
5846 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5849 it("'executeOnFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", () => {
5850 const engine
= new CLIEngine({ cwd
: getPath() });
5851 const filePaths
= engine
.executeOnFiles("**/*.js")
5853 .map(r
=> r
.filePath
)
5856 assert
.deepStrictEqual(filePaths
, [
5857 path
.join(root
, "bar.js"),
5858 path
.join(root
, "subdir/foo.js")
5863 describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
5865 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5868 ".eslintrc.json": JSON
.stringify({}),
5869 "subdir/.eslintrc.json": JSON
.stringify({
5871 ignorePatterns
: "bar.js"
5873 ".eslintignore": "foo.js",
5876 "subdir/foo.js": "",
5881 beforeEach(prepare
);
5884 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5885 const engine
= new CLIEngine({ cwd
: getPath() });
5887 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5888 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), true);
5891 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", () => {
5892 const engine
= new CLIEngine({ cwd
: getPath() });
5894 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5897 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", () => {
5898 const engine
= new CLIEngine({ cwd
: getPath() });
5900 assert
.strictEqual(engine
.isPathIgnored("subdir/bar.js"), true);
5903 it("'executeOnFiles()' should verify 'bar.js' in the root directory.", () => {
5904 const engine
= new CLIEngine({ cwd
: getPath() });
5905 const filePaths
= engine
.executeOnFiles("**/*.js")
5907 .map(r
=> r
.filePath
)
5910 assert
.deepStrictEqual(filePaths
, [
5911 path
.join(root
, "bar.js")
5916 describe("ignorePatterns in the shareable config should be used.", () => {
5917 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5920 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5921 ignorePatterns: "foo.js"
5923 ".eslintrc.json": JSON
.stringify({
5931 beforeEach(prepare
);
5934 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5935 const engine
= new CLIEngine({ cwd
: getPath() });
5937 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5940 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
5941 const engine
= new CLIEngine({ cwd
: getPath() });
5943 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
5946 it("'executeOnFiles()' should verify 'bar.js'.", () => {
5947 const engine
= new CLIEngine({ cwd
: getPath() });
5948 const filePaths
= engine
.executeOnFiles("**/*.js")
5950 .map(r
=> r
.filePath
)
5953 assert
.deepStrictEqual(filePaths
, [
5954 path
.join(root
, "bar.js")
5959 describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
5961 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5964 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5965 ignorePatterns: "/foo.js"
5967 ".eslintrc.json": JSON
.stringify({
5975 beforeEach(prepare
);
5979 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
5980 const engine
= new CLIEngine({ cwd
: getPath() });
5982 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
5985 it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", () => {
5986 const engine
= new CLIEngine({ cwd
: getPath() });
5988 assert
.strictEqual(engine
.isPathIgnored("subdir/foo.js"), false);
5991 it("'executeOnFiles()' should verify 'subdir/foo.js'.", () => {
5992 const engine
= new CLIEngine({ cwd
: getPath() });
5993 const filePaths
= engine
.executeOnFiles("**/*.js")
5995 .map(r
=> r
.filePath
)
5998 assert
.deepStrictEqual(filePaths
, [
5999 path
.join(root
, "subdir/foo.js")
6004 describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
6006 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6009 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6010 ignorePatterns: "*.js"
6012 ".eslintrc.json": JSON
.stringify({
6014 ignorePatterns
: "!bar.js"
6021 beforeEach(prepare
);
6024 it("'isPathIgnored()' should return 'true' for 'foo.js'.", () => {
6025 const engine
= new CLIEngine({ cwd
: getPath() });
6027 assert
.strictEqual(engine
.isPathIgnored("foo.js"), true);
6030 it("'isPathIgnored()' should return 'false' for 'bar.js'.", () => {
6031 const engine
= new CLIEngine({ cwd
: getPath() });
6033 assert
.strictEqual(engine
.isPathIgnored("bar.js"), false);
6036 it("'executeOnFiles()' should verify 'bar.js'.", () => {
6037 const engine
= new CLIEngine({ cwd
: getPath() });
6038 const filePaths
= engine
.executeOnFiles("**/*.js")
6040 .map(r
=> r
.filePath
)
6043 assert
.deepStrictEqual(filePaths
, [
6044 path
.join(root
, "bar.js")
6049 describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
6050 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6053 ".eslintrc.json": JSON
.stringify({
6054 ignorePatterns
: "*.js"
6060 beforeEach(prepare
);
6063 it("'isPathIgnored()' should return 'false' for 'foo.js'.", () => {
6064 const engine
= new CLIEngine({ cwd
: getPath(), ignore
: false });
6066 assert
.strictEqual(engine
.isPathIgnored("foo.js"), false);
6069 it("'executeOnFiles()' should verify 'foo.js'.", () => {
6070 const engine
= new CLIEngine({ cwd
: getPath(), ignore
: false });
6071 const filePaths
= engine
.executeOnFiles("**/*.js")
6073 .map(r
=> r
.filePath
)
6076 assert
.deepStrictEqual(filePaths
, [
6077 path
.join(root
, "foo.js")
6082 describe("ignorePatterns in overrides section is not allowed.", () => {
6084 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6087 ".eslintrc.js": `module.exports = ${JSON.stringify({
6091 ignorePatterns: "foo.js"
6099 beforeEach(prepare
);
6102 it("should throw a configuration error.", () => {
6103 assert
.throws(() => {
6104 const engine
= new CLIEngine({ cwd
: getPath() });
6106 engine
.executeOnFiles("*.js");
6107 }, "Unexpected top-level property \"overrides[0].ignorePatterns\"");
6113 describe("'overrides[].files' adds lint targets", () => {
6114 const root
= getFixturePath("cli-engine/additional-lint-targets");
6116 describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
6118 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6121 ".eslintrc.json": JSON
.stringify({
6125 excludedFiles
: "**/ignore.txt"
6129 "foo/nested/test.txt": "",
6132 "foo/ignore.txt": "",
6135 "bar/ignore.txt": "",
6142 beforeEach(prepare
);
6145 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt'.", () => {
6146 const engine
= new CLIEngine({ cwd
: getPath() });
6147 const filePaths
= engine
.executeOnFiles(".")
6149 .map(r
=> r
.filePath
)
6152 assert
.deepStrictEqual(filePaths
, [
6153 path
.join(root
, "bar/test.js"),
6154 path
.join(root
, "foo/test.js"),
6155 path
.join(root
, "foo/test.txt"),
6156 path
.join(root
, "test.js")
6160 it("'executeOnFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", () => {
6161 const engine
= new CLIEngine({ cwd
: getPath() });
6162 const filePaths
= engine
.executeOnFiles("**/*.js")
6164 .map(r
=> r
.filePath
)
6167 assert
.deepStrictEqual(filePaths
, [
6168 path
.join(root
, "bar/test.js"),
6169 path
.join(root
, "foo/test.js"),
6170 path
.join(root
, "test.js")
6175 describe("if { files: 'foo/**/*.txt' } is present,", () => {
6177 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6180 ".eslintrc.json": JSON
.stringify({
6183 files
: "foo/**/*.txt"
6187 "foo/nested/test.txt": "",
6197 beforeEach(prepare
);
6200 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
6201 const engine
= new CLIEngine({ cwd
: getPath() });
6202 const filePaths
= engine
.executeOnFiles(".")
6204 .map(r
=> r
.filePath
)
6207 assert
.deepStrictEqual(filePaths
, [
6208 path
.join(root
, "bar/test.js"),
6209 path
.join(root
, "foo/nested/test.txt"),
6210 path
.join(root
, "foo/test.js"),
6211 path
.join(root
, "foo/test.txt"),
6212 path
.join(root
, "test.js")
6217 describe("if { files: 'foo/**/*' } is present,", () => {
6218 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6221 ".eslintrc.json": JSON
.stringify({
6228 "foo/nested/test.txt": "",
6238 beforeEach(prepare
);
6241 it("'executeOnFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
6242 const engine
= new CLIEngine({ cwd
: getPath() });
6243 const filePaths
= engine
.executeOnFiles(".")
6245 .map(r
=> r
.filePath
)
6248 assert
.deepStrictEqual(filePaths
, [
6249 path
.join(root
, "bar/test.js"),
6250 path
.join(root
, "foo/test.js"),
6251 path
.join(root
, "test.js")
6256 describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
6257 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6260 "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
6263 files: "foo/**/*.txt"
6267 ".eslintrc.json": JSON
.stringify({
6270 "foo/nested/test.txt": "",
6280 beforeEach(prepare
);
6283 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
6284 const engine
= new CLIEngine({ cwd
: getPath() });
6285 const filePaths
= engine
.executeOnFiles(".")
6287 .map(r
=> r
.filePath
)
6290 assert
.deepStrictEqual(filePaths
, [
6291 path
.join(root
, "bar/test.js"),
6292 path
.join(root
, "foo/nested/test.txt"),
6293 path
.join(root
, "foo/test.js"),
6294 path
.join(root
, "foo/test.txt"),
6295 path
.join(root
, "test.js")
6300 describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
6301 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6304 "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
6308 files: "foo/**/*.txt"
6313 ".eslintrc.json": JSON
.stringify({
6314 extends: "plugin:foo/bar"
6316 "foo/nested/test.txt": "",
6326 beforeEach(prepare
);
6329 it("'executeOnFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", () => {
6330 const engine
= new CLIEngine({ cwd
: getPath() });
6331 const filePaths
= engine
.executeOnFiles(".")
6333 .map(r
=> r
.filePath
)
6336 assert
.deepStrictEqual(filePaths
, [
6337 path
.join(root
, "bar/test.js"),
6338 path
.join(root
, "foo/nested/test.txt"),
6339 path
.join(root
, "foo/test.js"),
6340 path
.join(root
, "foo/test.txt"),
6341 path
.join(root
, "test.js")
6347 describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
6348 const root
= getFixturePath("cli-engine/config-and-overrides-files");
6350 describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6351 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6354 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6364 "node_modules/myconf/foo/test.js": "a == b",
6365 "foo/test.js": "a == b"
6369 beforeEach(prepare
);
6372 it("'executeOnFiles()' with 'foo/test.js' should use the override entry.", () => {
6373 const engine
= new CLIEngine({
6374 configFile
: "node_modules/myconf/.eslintrc.json",
6379 const { results
} = engine
.executeOnFiles("foo/test.js");
6381 // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
6382 assert
.deepStrictEqual(results
, [
6385 filePath
: path
.join(root
, "foo/test.js"),
6386 fixableErrorCount
: 0,
6387 fixableWarningCount
: 0,
6394 message
: "Expected '===' and instead saw '=='.",
6395 messageId
: "unexpected",
6396 nodeType
: "BinaryExpression",
6401 suppressedMessages
: [],
6409 it("'executeOnFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", () => {
6410 const engine
= new CLIEngine({
6411 configFile
: "node_modules/myconf/.eslintrc.json",
6416 const { results
} = engine
.executeOnFiles("node_modules/myconf/foo/test.js");
6418 // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
6419 assert
.deepStrictEqual(results
, [
6422 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
6423 fixableErrorCount
: 0,
6424 fixableWarningCount
: 0,
6426 suppressedMessages
: [],
6434 describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6435 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6438 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6442 excludedFiles
: "foo/*.js",
6449 "node_modules/myconf/foo/test.js": "a == b",
6450 "foo/test.js": "a == b"
6454 beforeEach(prepare
);
6457 it("'executeOnFiles()' with 'foo/test.js' should NOT use the override entry.", () => {
6458 const engine
= new CLIEngine({
6459 configFile
: "node_modules/myconf/.eslintrc.json",
6464 const { results
} = engine
.executeOnFiles("foo/test.js");
6466 // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
6467 assert
.deepStrictEqual(results
, [
6470 filePath
: path
.join(root
, "foo/test.js"),
6471 fixableErrorCount
: 0,
6472 fixableWarningCount
: 0,
6474 suppressedMessages
: [],
6481 it("'executeOnFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", () => {
6482 const engine
= new CLIEngine({
6483 configFile
: "node_modules/myconf/.eslintrc.json",
6488 const { results
} = engine
.executeOnFiles("node_modules/myconf/foo/test.js");
6490 // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
6491 assert
.deepStrictEqual(results
, [
6494 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
6495 fixableErrorCount
: 0,
6496 fixableWarningCount
: 0,
6503 message
: "Expected '===' and instead saw '=='.",
6504 messageId
: "unexpected",
6505 nodeType
: "BinaryExpression",
6510 suppressedMessages
: [],
6519 describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6520 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6523 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6524 ignorePatterns
: ["!/node_modules/myconf", "foo/*.js"],
6529 "node_modules/myconf/foo/test.js": "a == b",
6530 "foo/test.js": "a == b"
6534 beforeEach(prepare
);
6537 it("'executeOnFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", () => {
6538 const engine
= new CLIEngine({
6539 configFile
: "node_modules/myconf/.eslintrc.json",
6543 const files
= engine
.executeOnFiles("**/*.js")
6545 .map(r
=> r
.filePath
)
6548 assert
.deepStrictEqual(files
, [
6549 path
.join(root
, "node_modules/myconf/foo/test.js")
6555 describe("plugin conflicts", () => {
6557 const root
= getFixturePath("cli-engine/plugin-conflicts-");
6560 * Verify thrown errors.
6561 * @param {() => void} f The function to run and throw.
6562 * @param {Record<string, any>} props The properties to verify.
6565 function assertThrows(f
, props
) {
6569 for (const [key
, value
] of Object
.entries(props
)) {
6570 assert
.deepStrictEqual(error
[key
], value
, key
);
6575 assert
.fail("Function should throw an error, but not.");
6578 describe("between a config file and linear extendees.", () => {
6580 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6581 cwd
: `${root}${++uid}`,
6583 "node_modules/eslint-plugin-foo/index.js": "",
6584 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6585 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6589 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6590 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6593 ".eslintrc.json": JSON
.stringify({
6601 beforeEach(prepare
);
6604 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", () => {
6605 const engine
= new CLIEngine({ cwd
: getPath() });
6607 engine
.executeOnFiles("test.js");
6611 describe("between a config file and same-depth extendees.", () => {
6612 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6613 cwd
: `${root}${++uid}`,
6615 "node_modules/eslint-plugin-foo/index.js": "",
6616 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6617 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6620 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6621 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6624 ".eslintrc.json": JSON
.stringify({
6625 extends: ["one", "two"],
6632 beforeEach(prepare
);
6635 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", () => {
6636 const engine
= new CLIEngine({ cwd
: getPath() });
6638 engine
.executeOnFiles("test.js");
6642 describe("between two config files in different directories, with single node_modules.", () => {
6643 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6644 cwd
: `${root}${++uid}`,
6646 "node_modules/eslint-plugin-foo/index.js": "",
6647 ".eslintrc.json": JSON
.stringify({
6650 "subdir/.eslintrc.json": JSON
.stringify({
6653 "subdir/test.js": ""
6657 beforeEach(prepare
);
6660 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.)", () => {
6661 const engine
= new CLIEngine({ cwd
: getPath() });
6663 engine
.executeOnFiles("subdir/test.js");
6667 describe("between two config files in different directories, with multiple node_modules.", () => {
6668 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6669 cwd
: `${root}${++uid}`,
6671 "node_modules/eslint-plugin-foo/index.js": "",
6672 ".eslintrc.json": JSON
.stringify({
6675 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6676 "subdir/.eslintrc.json": JSON
.stringify({
6679 "subdir/test.js": ""
6683 beforeEach(prepare
);
6686 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.)", () => {
6687 const engine
= new CLIEngine({ cwd
: getPath() });
6690 () => engine
.executeOnFiles("subdir/test.js"),
6692 message
: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
6693 messageTemplate
: "plugin-conflict",
6698 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6699 importerName
: `subdir${path.sep}.eslintrc.json`
6702 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6703 importerName
: ".eslintrc.json"
6712 describe("between '--config' option and a regular config file, with single node_modules.", () => {
6713 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6714 cwd
: `${root}${++uid}`,
6716 "node_modules/eslint-plugin-foo/index.js": "",
6717 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6720 ".eslintrc.json": JSON
.stringify({
6727 beforeEach(prepare
);
6730 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.)", () => {
6731 const engine
= new CLIEngine({
6733 configFile
: "node_modules/mine/.eslintrc.json"
6736 engine
.executeOnFiles("test.js");
6740 describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
6741 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6742 cwd
: `${root}${++uid}`,
6744 "node_modules/eslint-plugin-foo/index.js": "",
6745 "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
6746 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6749 ".eslintrc.json": JSON
.stringify({
6756 beforeEach(prepare
);
6759 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.)", () => {
6760 const engine
= new CLIEngine({
6762 configFile
: "node_modules/mine/.eslintrc.json"
6766 () => engine
.executeOnFiles("test.js"),
6768 message
: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
6769 messageTemplate
: "plugin-conflict",
6774 filePath
: path
.join(getPath(), "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
6775 importerName
: "--config"
6778 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6779 importerName
: ".eslintrc.json"
6788 describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
6789 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6790 cwd
: `${root}${++uid}`,
6792 "node_modules/eslint-plugin-foo/index.js": "",
6793 "subdir/.eslintrc.json": JSON
.stringify({
6796 "subdir/test.js": ""
6800 beforeEach(prepare
);
6803 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.)", () => {
6804 const engine
= new CLIEngine({
6809 engine
.executeOnFiles("subdir/test.js");
6813 describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
6814 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6815 cwd
: `${root}${++uid}`,
6817 "node_modules/eslint-plugin-foo/index.js": "",
6818 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6819 "subdir/.eslintrc.json": JSON
.stringify({
6822 "subdir/test.js": ""
6826 beforeEach(prepare
);
6829 it("'executeOnFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", () => {
6830 const engine
= new CLIEngine({
6836 () => engine
.executeOnFiles("subdir/test.js"),
6838 message
: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
6839 messageTemplate
: "plugin-conflict",
6844 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6845 importerName
: "CLIOptions"
6848 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6849 importerName
: `subdir${path.sep}.eslintrc.json`
6858 describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
6859 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6860 cwd
: `${root}${++uid}`,
6862 "node_modules/eslint-plugin-foo/index.js": "",
6863 ".eslintrc.json": JSON
.stringify({
6866 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6867 "subdir/.eslintrc.json": JSON
.stringify({
6870 "subdir/test.js": ""
6874 beforeEach(prepare
);
6877 it("'executeOnFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", () => {
6878 const engine
= new CLIEngine({
6880 resolvePluginsRelativeTo
: getPath()
6883 engine
.executeOnFiles("subdir/test.js");
6887 describe("between two config files with different target files.", () => {
6888 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6889 cwd
: `${root}${++uid}`,
6891 "one/node_modules/eslint-plugin-foo/index.js": "",
6892 "one/.eslintrc.json": JSON
.stringify({
6896 "two/node_modules/eslint-plugin-foo/index.js": "",
6897 "two/.eslintrc.json": JSON
.stringify({
6904 beforeEach(prepare
);
6907 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.)", () => {
6908 const engine
= new CLIEngine({ cwd
: getPath() });
6909 const { results
} = engine
.executeOnFiles("*/test.js");
6911 assert
.strictEqual(results
.length
, 2);