2 * @fileoverview Tests for the ESLint class.
4 * @author Toru Nagashima
9 //------------------------------------------------------------------------------
11 //------------------------------------------------------------------------------
13 const assert
= require("assert");
14 const fs
= require("fs");
15 const os
= require("os");
16 const path
= require("path");
17 const escapeStringRegExp
= require("escape-string-regexp");
18 const fCache
= require("file-entry-cache");
19 const sinon
= require("sinon");
20 const proxyquire
= require("proxyquire").noCallThru().noPreserveCache();
21 const shell
= require("shelljs");
24 CascadingConfigArrayFactory
26 } = require("@eslint/eslintrc");
27 const hash
= require("../../../lib/cli-engine/hash");
28 const { unIndent
, createCustomTeardown
} = require("../../_utils");
29 const coreRules
= require("../../../lib/rules");
30 const childProcess
= require("child_process");
32 //------------------------------------------------------------------------------
34 //------------------------------------------------------------------------------
36 describe("ESLint", () => {
37 const examplePluginName
= "eslint-plugin-example";
38 const examplePluginNameWithNamespace
= "@eslint/eslint-plugin-example";
39 const examplePlugin
= {
41 "example-rule": require("../../fixtures/rules/custom-rule"),
42 "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
45 const examplePreprocessorName
= "eslint-plugin-processor";
46 const originalDir
= process
.cwd();
47 const fixtureDir
= path
.resolve(fs
.realpathSync(os
.tmpdir()), "eslint/fixtures");
49 /** @type {import("../../../lib/eslint").ESLint} */
53 * Returns the path inside of the fixture directory.
54 * @param {...string} args file path segments.
55 * @returns {string} The path inside the fixture directory.
58 function getFixturePath(...args
) {
59 const filepath
= path
.join(fixtureDir
, ...args
);
62 return fs
.realpathSync(filepath
);
69 * Create the ESLint object by mocking some of the plugins
70 * @param {Object} options options for ESLint
71 * @returns {ESLint} engine object
74 function eslintWithPlugins(options
) {
78 [examplePluginName
]: examplePlugin
,
79 [examplePluginNameWithNamespace
]: examplePlugin
,
80 [examplePreprocessorName
]: require("../../fixtures/processors/custom-processor")
86 * Call the last argument.
87 * @param {any[]} args Arguments
90 function callLastArgument(...args
) {
91 process
.nextTick(args
[args
.length
- 1], null);
94 // copy into clean area so as not to get "infected" by this project's .eslintrc files
98 * GitHub Actions Windows and macOS runners occasionally exhibit
99 * extremely slow filesystem operations, during which copying fixtures
100 * exceeds the default test timeout, so raise it just for this hook.
101 * Mocha uses `this` to set timeouts on an individual hook level.
103 this.timeout(60 * 1000); // eslint-disable-line no-invalid-this -- Mocha API
104 shell
.mkdir("-p", fixtureDir
);
105 shell
.cp("-r", "./tests/fixtures/.", fixtureDir
);
109 ({ ESLint
} = require("../../../lib/eslint/eslint"));
113 shell
.rm("-r", fixtureDir
);
116 describe("ESLint constructor function", () => {
117 it("the default value of 'options.cwd' should be the current working directory.", async () => {
118 process
.chdir(__dirname
);
120 const engine
= new ESLint();
121 const results
= await engine
.lintFiles("eslint.js");
123 assert
.strictEqual(path
.dirname(results
[0].filePath
), __dirname
);
125 process
.chdir(originalDir
);
129 it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
130 assert
.throws(() => {
131 // eslint-disable-next-line no-new -- Check for throwing
132 new ESLint({ ignorePath
: fixtureDir
});
133 }, new RegExp(escapeStringRegExp(`Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`), "u"));
136 // https://github.com/eslint/eslint/issues/2380
137 it("should not modify baseConfig when format is specified", () => {
138 const customBaseConfig
= { root
: true };
140 new ESLint({ baseConfig
: customBaseConfig
}); // eslint-disable-line no-new -- Check for argument side effects
142 assert
.deepStrictEqual(customBaseConfig
, { root
: true });
145 it("should throw readable messages if removed options are present", () => {
158 new RegExp(escapeStringRegExp([
160 "- Unknown options: cacheFile, configFile, envs, globals, ignorePattern, parser, parserOptions, rules",
161 "- 'cacheFile' has been removed. Please use the 'cacheLocation' option instead.",
162 "- 'configFile' has been removed. Please use the 'overrideConfigFile' option instead.",
163 "- 'envs' has been removed. Please use the 'overrideConfig.env' option instead.",
164 "- 'globals' has been removed. Please use the 'overrideConfig.globals' option instead.",
165 "- 'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.",
166 "- 'parser' has been removed. Please use the 'overrideConfig.parser' option instead.",
167 "- 'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead.",
168 "- 'rules' has been removed. Please use the 'overrideConfig.rules' option instead.",
169 "- 'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead."
174 it("should throw readable messages if wrong type values are given to options", () => {
177 allowInlineConfig
: "",
182 errorOnUnmatchedPattern
: "",
190 overrideConfigFile
: "",
192 reportUnusedDisableDirectives
: "",
193 resolvePluginsRelativeTo
: "",
197 new RegExp(escapeStringRegExp([
199 "- 'allowInlineConfig' must be a boolean.",
200 "- 'baseConfig' must be an object or null.",
201 "- 'cache' must be a boolean.",
202 "- 'cacheLocation' must be a non-empty string.",
203 "- 'cwd' must be an absolute path.",
204 "- 'errorOnUnmatchedPattern' must be a boolean.",
205 "- 'extensions' must be an array of non-empty strings or null.",
206 "- 'fix' must be a boolean or a function.",
207 "- 'fixTypes' must be an array of any of \"directive\", \"problem\", \"suggestion\", and \"layout\".",
208 "- 'globInputPaths' must be a boolean.",
209 "- 'ignore' must be a boolean.",
210 "- 'ignorePath' must be a non-empty string or null.",
211 "- 'overrideConfig' must be an object or null.",
212 "- 'overrideConfigFile' must be a non-empty string or null.",
213 "- 'plugins' must be an object or null.",
214 "- 'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.",
215 "- 'resolvePluginsRelativeTo' must be a non-empty string or null.",
216 "- 'rulePaths' must be an array of non-empty strings.",
217 "- 'useEslintrc' must be a boolean."
222 it("should throw readable messages if 'plugins' option contains empty key", () => {
226 "eslint-plugin-foo": {},
227 "eslint-plugin-bar": {},
231 new RegExp(escapeStringRegExp([
233 "- 'plugins' must not include an empty string."
239 describe("lintText()", () => {
242 it("should report the total and per file errors when using local cwd .eslintrc", async () => {
243 eslint
= new ESLint();
244 const results
= await eslint
.lintText("var foo = 'bar';");
246 assert
.strictEqual(results
.length
, 1);
247 assert
.strictEqual(results
[0].messages
.length
, 5);
248 assert
.strictEqual(results
[0].messages
[0].ruleId
, "strict");
249 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-var");
250 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-unused-vars");
251 assert
.strictEqual(results
[0].messages
[3].ruleId
, "quotes");
252 assert
.strictEqual(results
[0].messages
[4].ruleId
, "eol-last");
253 assert
.strictEqual(results
[0].fixableErrorCount
, 3);
254 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
255 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
258 it("should report the total and per file warnings when using local cwd .eslintrc", async () => {
259 eslint
= new ESLint({
270 const results
= await eslint
.lintText("var foo = 'bar';");
272 assert
.strictEqual(results
.length
, 1);
273 assert
.strictEqual(results
[0].messages
.length
, 5);
274 assert
.strictEqual(results
[0].messages
[0].ruleId
, "strict");
275 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-var");
276 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-unused-vars");
277 assert
.strictEqual(results
[0].messages
[3].ruleId
, "quotes");
278 assert
.strictEqual(results
[0].messages
[4].ruleId
, "eol-last");
279 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
280 assert
.strictEqual(results
[0].fixableWarningCount
, 3);
281 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
284 it("should report one message when using specific config file", async () => {
285 eslint
= new ESLint({
286 overrideConfigFile
: "fixtures/configurations/quotes-error.json",
288 cwd
: getFixturePath("..")
290 const results
= await eslint
.lintText("var foo = 'bar';");
292 assert
.strictEqual(results
.length
, 1);
293 assert
.strictEqual(results
[0].messages
.length
, 1);
294 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
295 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
296 assert
.strictEqual(results
[0].errorCount
, 1);
297 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
298 assert
.strictEqual(results
[0].warningCount
, 0);
299 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
302 it("should report the filename when passed in", async () => {
303 eslint
= new ESLint({
305 cwd
: getFixturePath()
307 const options
= { filePath
: "test.js" };
308 const results
= await eslint
.lintText("var foo = 'bar';", options
);
310 assert
.strictEqual(results
[0].filePath
, getFixturePath("test.js"));
313 it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", async () => {
314 eslint
= new ESLint({
315 ignorePath
: getFixturePath(".eslintignore"),
316 cwd
: getFixturePath("..")
318 const options
= { filePath
: "fixtures/passing.js", warnIgnored
: true };
319 const results
= await eslint
.lintText("var bar = foo;", options
);
321 assert
.strictEqual(results
.length
, 1);
322 assert
.strictEqual(results
[0].filePath
, getFixturePath("passing.js"));
323 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
324 assert
.strictEqual(results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
325 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
326 assert
.strictEqual(results
[0].errorCount
, 0);
327 assert
.strictEqual(results
[0].warningCount
, 1);
328 assert
.strictEqual(results
[0].fatalErrorCount
, 0);
329 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
330 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
331 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
334 it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", async () => {
335 eslint
= new ESLint({
336 ignorePath
: getFixturePath(".eslintignore"),
337 cwd
: getFixturePath("..")
340 filePath
: "fixtures/passing.js",
344 // intentional parsing error
345 const results
= await eslint
.lintText("va r bar = foo;", options
);
347 // should not report anything because the file is ignored
348 assert
.strictEqual(results
.length
, 0);
351 it("should suppress excluded file warnings by default", async () => {
352 eslint
= new ESLint({
353 ignorePath
: getFixturePath(".eslintignore"),
354 cwd
: getFixturePath("..")
356 const options
= { filePath
: "fixtures/passing.js" };
357 const results
= await eslint
.lintText("var bar = foo;", options
);
359 // should not report anything because there are no errors
360 assert
.strictEqual(results
.length
, 0);
363 it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", async () => {
364 eslint
= new ESLint({
365 ignorePath
: "fixtures/.eslintignore",
366 cwd
: getFixturePath(".."),
375 const options
= { filePath
: "fixtures/passing.js" };
376 const results
= await eslint
.lintText("var bar = foo;", options
);
378 assert
.strictEqual(results
.length
, 1);
379 assert
.strictEqual(results
[0].filePath
, getFixturePath("passing.js"));
380 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
381 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
382 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
385 it("should return a message and fixed text when in fix mode", async () => {
386 eslint
= new ESLint({
395 cwd
: getFixturePath()
397 const options
= { filePath
: "passing.js" };
398 const results
= await eslint
.lintText("var bar = foo", options
);
400 assert
.deepStrictEqual(results
, [
402 filePath
: getFixturePath("passing.js"),
404 suppressedMessages
: [],
408 fixableErrorCount
: 0,
409 fixableWarningCount
: 0,
410 output
: "var bar = foo;",
411 usedDeprecatedRules
: []
416 it("should use eslint:recommended rules when eslint:recommended configuration is specified", async () => {
417 eslint
= new ESLint({
420 extends: ["eslint:recommended"]
423 cwd
: getFixturePath()
425 const options
= { filePath
: "file.js" };
426 const results
= await eslint
.lintText("foo ()", options
);
428 assert
.strictEqual(results
.length
, 1);
429 assert
.strictEqual(results
[0].messages
.length
, 1);
430 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
431 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
434 it("should use eslint:all rules when eslint:all configuration is specified", async () => {
435 eslint
= new ESLint({
438 extends: ["eslint:all"]
441 cwd
: getFixturePath()
443 const options
= { filePath
: "file.js" };
444 const results
= await eslint
.lintText("foo ()", options
);
446 assert
.strictEqual(results
.length
, 1);
448 const { messages
} = results
[0];
450 // Some rules that should report errors in the given code. Not all, as we don't want to update this test when we add new rules.
451 const expectedRules
= ["no-undef", "semi", "func-call-spacing"];
453 expectedRules
.forEach(ruleId
=> {
454 const messageFromRule
= messages
.find(message
=> message
.ruleId
=== ruleId
);
457 typeof messageFromRule
=== "object" && messageFromRule
!== null, // LintMessage object
458 `Expected a message from rule '${ruleId}'`
460 assert
.strictEqual(messageFromRule
.severity
, 2);
465 it("correctly autofixes semicolon-conflicting-fixes", async () => {
466 eslint
= new ESLint({
467 cwd
: path
.join(fixtureDir
, ".."),
471 const inputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.js");
472 const outputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
473 const results
= await eslint
.lintFiles([inputPath
]);
474 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
476 assert
.strictEqual(results
[0].output
, expectedOutput
);
479 it("correctly autofixes return-conflicting-fixes", async () => {
480 eslint
= new ESLint({
481 cwd
: path
.join(fixtureDir
, ".."),
485 const inputPath
= getFixturePath("autofix/return-conflicting-fixes.js");
486 const outputPath
= getFixturePath("autofix/return-conflicting-fixes.expected.js");
487 const results
= await eslint
.lintFiles([inputPath
]);
488 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
490 assert
.strictEqual(results
[0].output
, expectedOutput
);
493 describe("Fix Types", () => {
494 it("should throw an error when an invalid fix type is specified", () => {
495 assert
.throws(() => {
496 eslint
= new ESLint({
497 cwd
: path
.join(fixtureDir
, ".."),
502 }, /'fixTypes' must be an array of any of "directive", "problem", "suggestion", and "layout"\./iu);
505 it("should not fix any rules when fixTypes is used without fix", async () => {
506 eslint
= new ESLint({
507 cwd
: path
.join(fixtureDir
, ".."),
512 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
513 const results
= await eslint
.lintFiles([inputPath
]);
515 assert
.strictEqual(results
[0].output
, void 0);
518 it("should not fix non-style rules when fixTypes has only 'layout'", async () => {
519 eslint
= new ESLint({
520 cwd
: path
.join(fixtureDir
, ".."),
525 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
526 const outputPath
= getFixturePath("fix-types/fix-only-semi.expected.js");
527 const results
= await eslint
.lintFiles([inputPath
]);
528 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
530 assert
.strictEqual(results
[0].output
, expectedOutput
);
533 it("should not fix style or problem rules when fixTypes has only 'suggestion'", async () => {
534 eslint
= new ESLint({
535 cwd
: path
.join(fixtureDir
, ".."),
538 fixTypes
: ["suggestion"]
540 const inputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
541 const outputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
542 const results
= await eslint
.lintFiles([inputPath
]);
543 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
545 assert
.strictEqual(results
[0].output
, expectedOutput
);
548 it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", async () => {
549 eslint
= new ESLint({
550 cwd
: path
.join(fixtureDir
, ".."),
553 fixTypes
: ["suggestion", "layout"]
555 const inputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
556 const outputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
557 const results
= await eslint
.lintFiles([inputPath
]);
558 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
560 assert
.strictEqual(results
[0].output
, expectedOutput
);
563 it("should not throw an error when a rule doesn't have a 'meta' property", async () => {
564 eslint
= new ESLint({
565 cwd
: path
.join(fixtureDir
, ".."),
568 fixTypes
: ["layout"],
569 rulePaths
: [getFixturePath("rules", "fix-types-test")]
571 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
572 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
573 const results
= await eslint
.lintFiles([inputPath
]);
574 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
576 assert
.strictEqual(results
[0].output
, expectedOutput
);
579 it("should not throw an error when a rule is loaded after initialization with lintFiles()", async () => {
580 eslint
= new ESLint({
581 cwd
: path
.join(fixtureDir
, ".."),
584 fixTypes
: ["layout"],
588 "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
593 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
594 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
595 const results
= await eslint
.lintFiles([inputPath
]);
596 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
598 assert
.strictEqual(results
[0].output
, expectedOutput
);
601 it("should not throw an error when a rule is loaded after initialization with lintText()", async () => {
602 eslint
= new ESLint({
603 cwd
: path
.join(fixtureDir
, ".."),
606 fixTypes
: ["layout"],
610 "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
615 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
616 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
617 const results
= await eslint
.lintText(fs
.readFileSync(inputPath
, { encoding
: "utf8" }), { filePath
: inputPath
});
618 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
620 assert
.strictEqual(results
[0].output
, expectedOutput
);
624 it("should return a message and omit fixed text when in fix mode and fixes aren't done", async () => {
625 eslint
= new ESLint({
634 cwd
: getFixturePath()
636 const options
= { filePath
: "passing.js" };
637 const results
= await eslint
.lintText("var bar = foo", options
);
639 assert
.deepStrictEqual(results
, [
641 filePath
: getFixturePath("passing.js"),
647 message
: "'foo' is not defined.",
652 nodeType
: "Identifier"
655 suppressedMessages
: [],
659 fixableErrorCount
: 0,
660 fixableWarningCount
: 0,
661 source
: "var bar = foo",
662 usedDeprecatedRules
: []
667 it("should not delete code if there is a syntax error after trying to autofix.", async () => {
668 eslint
= eslintWithPlugins({
672 plugins
: ["example"],
674 "example/make-syntax-error": "error"
678 cwd
: getFixturePath()
680 const options
= { filePath
: "test.js" };
681 const results
= await eslint
.lintText("var bar = foo", options
);
683 assert
.deepStrictEqual(results
, [
685 filePath
: getFixturePath("test.js"),
691 message
: "Parsing error: Unexpected token is",
697 suppressedMessages
: [],
701 fixableErrorCount
: 0,
702 fixableWarningCount
: 0,
703 output
: "var bar = foothis is a syntax error.",
704 usedDeprecatedRules
: []
709 it("should not crash even if there are any syntax error since the first time.", async () => {
710 eslint
= new ESLint({
715 "example/make-syntax-error": "error"
719 cwd
: getFixturePath()
721 const options
= { filePath
: "test.js" };
722 const results
= await eslint
.lintText("var bar =", options
);
724 assert
.deepStrictEqual(results
, [
726 filePath
: getFixturePath("test.js"),
732 message
: "Parsing error: Unexpected token",
738 suppressedMessages
: [],
742 fixableErrorCount
: 0,
743 fixableWarningCount
: 0,
745 usedDeprecatedRules
: []
750 it("should return source code of file in `source` property when errors are present", async () => {
751 eslint
= new ESLint({
757 const results
= await eslint
.lintText("var foo = 'bar'");
759 assert
.strictEqual(results
[0].source
, "var foo = 'bar'");
762 it("should return source code of file in `source` property when warnings are present", async () => {
763 eslint
= new ESLint({
769 const results
= await eslint
.lintText("var foo = 'bar'");
771 assert
.strictEqual(results
[0].source
, "var foo = 'bar'");
775 it("should not return a `source` property when no errors or warnings are present", async () => {
776 eslint
= new ESLint({
782 const results
= await eslint
.lintText("var foo = 'bar';");
784 assert
.strictEqual(results
[0].messages
.length
, 0);
785 assert
.strictEqual(results
[0].source
, void 0);
788 it("should not return a `source` property when fixes are applied", async () => {
789 eslint
= new ESLint({
799 const results
= await eslint
.lintText("var msg = 'hi' + foo\n");
801 assert
.strictEqual(results
[0].source
, void 0);
802 assert
.strictEqual(results
[0].output
, "var msg = 'hi' + foo;\n");
805 it("should return a `source` property when a parsing error has occurred", async () => {
806 eslint
= new ESLint({
812 const results
= await eslint
.lintText("var bar = foothis is a syntax error.\n return bar;");
814 assert
.deepStrictEqual(results
, [
822 message
: "Parsing error: Unexpected token is",
828 suppressedMessages
: [],
832 fixableErrorCount
: 0,
833 fixableWarningCount
: 0,
834 source
: "var bar = foothis is a syntax error.\n return bar;",
835 usedDeprecatedRules
: []
840 // https://github.com/eslint/eslint/issues/5547
841 it("should respect default ignore rules, even with --no-ignore", async () => {
842 eslint
= new ESLint({
843 cwd
: getFixturePath(),
846 const results
= await eslint
.lintText("var bar = foo;", { filePath
: "node_modules/passing.js", warnIgnored
: true });
847 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
849 assert
.strictEqual(results
.length
, 1);
850 assert
.strictEqual(results
[0].filePath
, getFixturePath("node_modules/passing.js"));
851 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
854 describe('plugin shorthand notation ("@scope" for "@scope/eslint-plugin")', () => {
855 const Module
= require("module");
856 let originalFindPath
= null;
858 /* eslint-disable no-underscore-dangle -- Override Node API */
860 originalFindPath
= Module
._findPath
;
861 Module
._findPath = function(id
, ...otherArgs
) {
862 if (id
=== "@scope/eslint-plugin") {
863 return path
.resolve(__dirname
, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
865 return originalFindPath
.call(this, id
, ...otherArgs
);
869 Module
._findPath
= originalFindPath
;
871 /* eslint-enable no-underscore-dangle -- Override Node API */
873 it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
874 eslint
= new ESLint({ cwd
: getFixturePath("plugin-shorthand/basic") });
875 const [result
] = await eslint
.lintText("var x = 0", { filePath
: "index.js" });
877 assert
.strictEqual(result
.filePath
, getFixturePath("plugin-shorthand/basic/index.js"));
878 assert
.strictEqual(result
.messages
[0].ruleId
, "@scope/rule");
879 assert
.strictEqual(result
.messages
[0].message
, "OK");
882 it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
883 eslint
= new ESLint({ cwd
: getFixturePath("plugin-shorthand/extends") });
884 const [result
] = await eslint
.lintText("var x = 0", { filePath
: "index.js" });
886 assert
.strictEqual(result
.filePath
, getFixturePath("plugin-shorthand/extends/index.js"));
887 assert
.strictEqual(result
.messages
[0].ruleId
, "@scope/rule");
888 assert
.strictEqual(result
.messages
[0].message
, "OK");
892 it("should warn when deprecated rules are found in a config", async () => {
893 eslint
= new ESLint({
896 overrideConfigFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
898 const [result
] = await eslint
.lintText("foo");
900 assert
.deepStrictEqual(
901 result
.usedDeprecatedRules
,
902 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
906 it("should throw if non-string value is given to 'code' parameter", async () => {
907 eslint
= new ESLint();
908 await assert
.rejects(() => eslint
.lintText(100), /'code' must be a string/u);
911 it("should throw if non-object value is given to 'options' parameter", async () => {
912 eslint
= new ESLint();
913 await assert
.rejects(() => eslint
.lintText("var a = 0", "foo.js"), /'options' must be an object, null, or undefined/u);
916 it("should throw if 'options' argument contains unknown key", async () => {
917 eslint
= new ESLint();
918 await assert
.rejects(() => eslint
.lintText("var a = 0", { filename
: "foo.js" }), /'options' must not include the unknown option\(s\): filename/u);
921 it("should throw if non-string value is given to 'options.filePath' option", async () => {
922 eslint
= new ESLint();
923 await assert
.rejects(() => eslint
.lintText("var a = 0", { filePath
: "" }), /'options.filePath' must be a non-empty string or undefined/u);
926 it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
927 eslint
= new ESLint();
928 await assert
.rejects(() => eslint
.lintText("var a = 0", { warnIgnored
: "" }), /'options.warnIgnored' must be a boolean or undefined/u);
932 describe("lintFiles()", () => {
934 /** @type {InstanceType<import("../../../lib/eslint").ESLint>} */
937 it("should use correct parser when custom parser is specified", async () => {
938 eslint
= new ESLint({
942 const filePath
= path
.resolve(__dirname
, "../../fixtures/configurations/parser/custom.js");
943 const results
= await eslint
.lintFiles([filePath
]);
945 assert
.strictEqual(results
.length
, 1);
946 assert
.strictEqual(results
[0].messages
.length
, 1);
947 assert
.strictEqual(results
[0].messages
[0].message
, "Parsing error: Boom!");
950 it("should report zero messages when given a config file and a valid file", async () => {
951 eslint
= new ESLint({
953 overrideConfigFile
: ".eslintrc.js"
955 const results
= await eslint
.lintFiles(["lib/**/cli*.js"]);
957 assert
.strictEqual(results
.length
, 2);
958 assert
.strictEqual(results
[0].messages
.length
, 0);
959 assert
.strictEqual(results
[1].messages
.length
, 0);
962 it("should handle multiple patterns with overlapping files", async () => {
963 eslint
= new ESLint({
965 overrideConfigFile
: ".eslintrc.js"
967 const results
= await eslint
.lintFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
969 assert
.strictEqual(results
.length
, 2);
970 assert
.strictEqual(results
[0].messages
.length
, 0);
971 assert
.strictEqual(results
[1].messages
.length
, 0);
974 it("should report zero messages when given a config file and a valid file and espree as parser", async () => {
975 eslint
= new ESLint({
984 const results
= await eslint
.lintFiles(["lib/cli.js"]);
986 assert
.strictEqual(results
.length
, 1);
987 assert
.strictEqual(results
[0].messages
.length
, 0);
990 it("should report zero messages when given a config file and a valid file and esprima as parser", async () => {
991 eslint
= new ESLint({
998 const results
= await eslint
.lintFiles(["tests/fixtures/passing.js"]);
1000 assert
.strictEqual(results
.length
, 1);
1001 assert
.strictEqual(results
[0].messages
.length
, 0);
1004 it("should throw an error when given a config file and a valid file and invalid parser", async () => {
1005 eslint
= new ESLint({
1012 await assert
.rejects(async () => await eslint
.lintFiles(["lib/cli.js"]), /Cannot find module
'test11'/u
);
1015 it("should report zero messages when given a directory with a .js2 file", async () => {
1016 eslint
= new ESLint({
1017 cwd
: path
.join(fixtureDir
, ".."),
1018 extensions
: [".js2"]
1020 const results
= await eslint
.lintFiles([getFixturePath("files/foo.js2")]);
1022 assert
.strictEqual(results
.length
, 1);
1023 assert
.strictEqual(results
[0].messages
.length
, 0);
1026 it("should fall back to defaults when extensions is set to an empty array", async () => {
1027 eslint
= new ESLint({
1028 cwd
: getFixturePath("configurations"),
1029 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json"),
1032 const results
= await eslint
.lintFiles([getFixturePath("single-quoted.js")]);
1034 assert
.strictEqual(results
.length
, 1);
1035 assert
.strictEqual(results
[0].messages
.length
, 1);
1036 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1037 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1038 assert
.strictEqual(results
[0].errorCount
, 1);
1039 assert
.strictEqual(results
[0].warningCount
, 0);
1040 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1041 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1044 it("should report zero messages when given a directory with a .js and a .js2 file", async () => {
1045 eslint
= new ESLint({
1046 extensions
: [".js", ".js2"],
1048 cwd
: getFixturePath("..")
1050 const results
= await eslint
.lintFiles(["fixtures/files/"]);
1052 assert
.strictEqual(results
.length
, 2);
1053 assert
.strictEqual(results
[0].messages
.length
, 0);
1054 assert
.strictEqual(results
[1].messages
.length
, 0);
1057 it("should report zero messages when given a '**' pattern with a .js and a .js2 file", async () => {
1058 eslint
= new ESLint({
1059 extensions
: [".js", ".js2"],
1061 cwd
: path
.join(fixtureDir
, "..")
1063 const results
= await eslint
.lintFiles(["fixtures/files/*"]);
1065 assert
.strictEqual(results
.length
, 2);
1066 assert
.strictEqual(results
[0].messages
.length
, 0);
1067 assert
.strictEqual(results
[1].messages
.length
, 0);
1070 it("should resolve globs when 'globInputPaths' option is true", async () => {
1071 eslint
= new ESLint({
1072 extensions
: [".js", ".js2"],
1074 cwd
: getFixturePath("..")
1076 const results
= await eslint
.lintFiles(["fixtures/files/*"]);
1078 assert
.strictEqual(results
.length
, 2);
1079 assert
.strictEqual(results
[0].messages
.length
, 0);
1080 assert
.strictEqual(results
[1].messages
.length
, 0);
1083 it("should not resolve globs when 'globInputPaths' option is false", async () => {
1084 eslint
= new ESLint({
1085 extensions
: [".js", ".js2"],
1087 cwd
: getFixturePath(".."),
1088 globInputPaths
: false
1091 await assert
.rejects(async () => {
1092 await eslint
.lintFiles(["fixtures/files/*"]);
1093 }, /No files matching 'fixtures\/files\/\*' were found \(glob was disabled\)\./u);
1096 it("should report on all files passed explicitly, even if ignored by default", async () => {
1097 eslint
= new ESLint({
1098 cwd
: getFixturePath("cli-engine")
1100 const results
= await eslint
.lintFiles(["node_modules/foo.js"]);
1101 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
1103 assert
.strictEqual(results
.length
, 1);
1104 assert
.strictEqual(results
[0].errorCount
, 0);
1105 assert
.strictEqual(results
[0].warningCount
, 1);
1106 assert
.strictEqual(results
[0].fatalErrorCount
, 0);
1107 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1108 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1109 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1112 it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", async () => {
1113 eslint
= new ESLint({
1114 cwd
: getFixturePath("cli-engine"),
1117 quotes
: [2, "single"]
1121 const results
= await eslint
.lintFiles(["hidden/.hiddenfolder/*.js"]);
1123 assert
.strictEqual(results
.length
, 1);
1124 assert
.strictEqual(results
[0].errorCount
, 1);
1125 assert
.strictEqual(results
[0].warningCount
, 0);
1126 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1127 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1130 it("should not check default ignored files without --no-ignore flag", async () => {
1131 eslint
= new ESLint({
1132 cwd
: getFixturePath("cli-engine")
1135 await assert
.rejects(async () => {
1136 await eslint
.lintFiles(["node_modules"]);
1137 }, /All files matched by 'node_modules' are ignored\./u);
1140 // https://github.com/eslint/eslint/issues/5547
1141 it("should not check node_modules files even with --no-ignore flag", async () => {
1142 eslint
= new ESLint({
1143 cwd
: getFixturePath("cli-engine"),
1147 await assert
.rejects(async () => {
1148 await eslint
.lintFiles(["node_modules"]);
1149 }, /All files matched by 'node_modules' are ignored\./u);
1152 it("should not check .hidden files if they are passed explicitly without --no-ignore flag", async () => {
1153 eslint
= new ESLint({
1154 cwd
: getFixturePath(".."),
1158 quotes
: [2, "single"]
1162 const results
= await eslint
.lintFiles(["fixtures/files/.bar.js"]);
1163 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1165 assert
.strictEqual(results
.length
, 1);
1166 assert
.strictEqual(results
[0].errorCount
, 0);
1167 assert
.strictEqual(results
[0].warningCount
, 1);
1168 assert
.strictEqual(results
[0].fatalErrorCount
, 0);
1169 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1170 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1171 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1174 // https://github.com/eslint/eslint/issues/12873
1175 it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", async () => {
1176 eslint
= new ESLint({
1177 cwd
: getFixturePath("cli-engine"),
1181 quotes
: [2, "single"]
1185 const results
= await eslint
.lintFiles(["hidden/.hiddenfolder/double-quotes.js"]);
1186 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1188 assert
.strictEqual(results
.length
, 1);
1189 assert
.strictEqual(results
[0].errorCount
, 0);
1190 assert
.strictEqual(results
[0].warningCount
, 1);
1191 assert
.strictEqual(results
[0].fatalErrorCount
, 0);
1192 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1193 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1194 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1197 it("should check .hidden files if they are passed explicitly with --no-ignore flag", async () => {
1198 eslint
= new ESLint({
1199 cwd
: getFixturePath(".."),
1204 quotes
: [2, "single"]
1208 const results
= await eslint
.lintFiles(["fixtures/files/.bar.js"]);
1210 assert
.strictEqual(results
.length
, 1);
1211 assert
.strictEqual(results
[0].warningCount
, 0);
1212 assert
.strictEqual(results
[0].errorCount
, 1);
1213 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1214 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1215 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1218 it("should check .hidden files if they are unignored with an --ignore-pattern", async () => {
1219 eslint
= new ESLint({
1220 cwd
: getFixturePath("cli-engine"),
1224 ignorePatterns
: "!.hidden*",
1226 quotes
: [2, "single"]
1230 const results
= await eslint
.lintFiles(["hidden/"]);
1232 assert
.strictEqual(results
.length
, 1);
1233 assert
.strictEqual(results
[0].warningCount
, 0);
1234 assert
.strictEqual(results
[0].errorCount
, 1);
1235 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1236 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1237 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1240 it("should report zero messages when given a pattern with a .js and a .js2 file", async () => {
1241 eslint
= new ESLint({
1242 extensions
: [".js", ".js2"],
1244 cwd
: path
.join(fixtureDir
, "..")
1246 const results
= await eslint
.lintFiles(["fixtures/files/*.?s*"]);
1248 assert
.strictEqual(results
.length
, 2);
1249 assert
.strictEqual(results
[0].messages
.length
, 0);
1250 assert
.strictEqual(results
[1].messages
.length
, 0);
1253 it("should return one error message when given a config with rules with options and severity level set to error", async () => {
1254 eslint
= new ESLint({
1255 cwd
: getFixturePath("configurations"),
1256 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json")
1258 const results
= await eslint
.lintFiles([getFixturePath("single-quoted.js")]);
1260 assert
.strictEqual(results
.length
, 1);
1261 assert
.strictEqual(results
[0].messages
.length
, 1);
1262 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1263 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1264 assert
.strictEqual(results
[0].errorCount
, 1);
1265 assert
.strictEqual(results
[0].warningCount
, 0);
1266 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1267 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1270 it("should return 3 messages when given a config file and a directory of 3 valid files", async () => {
1271 eslint
= new ESLint({
1272 cwd
: path
.join(fixtureDir
, ".."),
1273 overrideConfigFile
: getFixturePath("configurations", "semi-error.json")
1275 const fixturePath
= getFixturePath("formatters");
1276 const results
= await eslint
.lintFiles([fixturePath
]);
1278 assert
.strictEqual(results
.length
, 5);
1279 assert
.strictEqual(path
.relative(fixturePath
, results
[0].filePath
), "async.js");
1280 assert
.strictEqual(results
[0].errorCount
, 0);
1281 assert
.strictEqual(results
[0].warningCount
, 0);
1282 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1283 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1284 assert
.strictEqual(results
[0].messages
.length
, 0);
1285 assert
.strictEqual(path
.relative(fixturePath
, results
[1].filePath
), "broken.js");
1286 assert
.strictEqual(results
[1].errorCount
, 0);
1287 assert
.strictEqual(results
[1].warningCount
, 0);
1288 assert
.strictEqual(results
[1].fixableErrorCount
, 0);
1289 assert
.strictEqual(results
[1].fixableWarningCount
, 0);
1290 assert
.strictEqual(results
[1].messages
.length
, 0);
1291 assert
.strictEqual(path
.relative(fixturePath
, results
[2].filePath
), "cwd.js");
1292 assert
.strictEqual(results
[2].errorCount
, 0);
1293 assert
.strictEqual(results
[2].warningCount
, 0);
1294 assert
.strictEqual(results
[2].fixableErrorCount
, 0);
1295 assert
.strictEqual(results
[2].fixableWarningCount
, 0);
1296 assert
.strictEqual(results
[2].messages
.length
, 0);
1297 assert
.strictEqual(path
.relative(fixturePath
, results
[3].filePath
), "simple.js");
1298 assert
.strictEqual(results
[3].errorCount
, 0);
1299 assert
.strictEqual(results
[3].warningCount
, 0);
1300 assert
.strictEqual(results
[3].fixableErrorCount
, 0);
1301 assert
.strictEqual(results
[3].fixableWarningCount
, 0);
1302 assert
.strictEqual(results
[3].messages
.length
, 0);
1303 assert
.strictEqual(path
.relative(fixturePath
, results
[4].filePath
), path
.join("test", "simple.js"));
1304 assert
.strictEqual(results
[4].errorCount
, 0);
1305 assert
.strictEqual(results
[4].warningCount
, 0);
1306 assert
.strictEqual(results
[4].fixableErrorCount
, 0);
1307 assert
.strictEqual(results
[4].fixableWarningCount
, 0);
1308 assert
.strictEqual(results
[4].messages
.length
, 0);
1311 it("should process when file is given by not specifying extensions", async () => {
1312 eslint
= new ESLint({
1314 cwd
: path
.join(fixtureDir
, "..")
1316 const results
= await eslint
.lintFiles(["fixtures/files/foo.js2"]);
1318 assert
.strictEqual(results
.length
, 1);
1319 assert
.strictEqual(results
[0].messages
.length
, 0);
1322 it("should return zero messages when given a config with environment set to browser", async () => {
1323 eslint
= new ESLint({
1324 cwd
: path
.join(fixtureDir
, ".."),
1325 overrideConfigFile
: getFixturePath("configurations", "env-browser.json")
1327 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1329 assert
.strictEqual(results
.length
, 1);
1330 assert
.strictEqual(results
[0].messages
.length
, 0);
1333 it("should return zero messages when given an option to set environment to browser", async () => {
1334 eslint
= new ESLint({
1335 cwd
: path
.join(fixtureDir
, ".."),
1337 env
: { browser
: true },
1344 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1346 assert
.strictEqual(results
.length
, 1);
1347 assert
.strictEqual(results
[0].messages
.length
, 0);
1350 it("should return zero messages when given a config with environment set to Node.js", async () => {
1351 eslint
= new ESLint({
1352 cwd
: path
.join(fixtureDir
, ".."),
1353 overrideConfigFile
: getFixturePath("configurations", "env-node.json")
1355 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-node.js"))]);
1357 assert
.strictEqual(results
.length
, 1);
1358 assert
.strictEqual(results
[0].messages
.length
, 0);
1361 it("should not return results from previous call when calling more than once", async () => {
1362 eslint
= new ESLint({
1363 cwd
: path
.join(fixtureDir
, ".."),
1371 const failFilePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1372 const passFilePath
= fs
.realpathSync(getFixturePath("passing.js"));
1374 let results
= await eslint
.lintFiles([failFilePath
]);
1376 assert
.strictEqual(results
.length
, 1);
1377 assert
.strictEqual(results
[0].filePath
, failFilePath
);
1378 assert
.strictEqual(results
[0].messages
.length
, 1);
1379 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
1380 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1382 results
= await eslint
.lintFiles([passFilePath
]);
1383 assert
.strictEqual(results
.length
, 1);
1384 assert
.strictEqual(results
[0].filePath
, passFilePath
);
1385 assert
.strictEqual(results
[0].messages
.length
, 0);
1388 it("should throw an error when given a directory with all eslint excluded files in the directory", async () => {
1389 eslint
= new ESLint({
1390 ignorePath
: getFixturePath(".eslintignore")
1393 await assert
.rejects(async () => {
1394 await eslint
.lintFiles([getFixturePath("./cli-engine/")]);
1395 }, new RegExp(escapeStringRegExp(`All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`), "u"));
1398 it("should throw an error when all given files are ignored", async () => {
1399 await assert
.rejects(async () => {
1400 await eslint
.lintFiles(["tests/fixtures/cli-engine/"]);
1401 }, /All files matched by 'tests\/fixtures\/cli-engine\/' are ignored\./u);
1404 it("should throw an error when all given files are ignored even with a `./` prefix", async () => {
1405 eslint
= new ESLint({
1406 ignorePath
: getFixturePath(".eslintignore")
1409 await assert
.rejects(async () => {
1410 await eslint
.lintFiles(["./tests/fixtures/cli-engine/"]);
1411 }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
1414 // https://github.com/eslint/eslint/issues/3788
1415 it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", async () => {
1416 eslint
= new ESLint({
1417 ignorePath
: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
1421 quotes
: [2, "double"]
1424 cwd
: getFixturePath("cli-engine", "nested_node_modules")
1426 const results
= await eslint
.lintFiles(["."]);
1428 assert
.strictEqual(results
.length
, 1);
1429 assert
.strictEqual(results
[0].errorCount
, 0);
1430 assert
.strictEqual(results
[0].warningCount
, 0);
1431 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1432 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1435 // https://github.com/eslint/eslint/issues/3812
1436 it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", async () => {
1437 eslint
= new ESLint({
1438 ignorePath
: getFixturePath("cli-engine/.eslintignore2"),
1442 quotes
: [2, "double"]
1447 await assert
.rejects(async () => {
1448 await eslint
.lintFiles(["./tests/fixtures/cli-engine/"]);
1449 }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
1452 // https://github.com/eslint/eslint/issues/15642
1453 it("should ignore files that are ignored by patterns with escaped brackets", async () => {
1454 eslint
= new ESLint({
1455 ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithEscapedBrackets"),
1457 cwd
: getFixturePath("ignored-paths")
1460 // Only `brackets/index.js` should be linted. Other files in `brackets/` should be ignored.
1461 const results
= await eslint
.lintFiles(["brackets/*.js"]);
1463 assert
.strictEqual(results
.length
, 1);
1464 assert
.strictEqual(results
[0].filePath
, getFixturePath("ignored-paths", "brackets", "index.js"));
1467 it("should throw an error when all given files are ignored via ignore-pattern", async () => {
1468 eslint
= new ESLint({
1470 ignorePatterns
: "tests/fixtures/single-quoted.js"
1474 await assert
.rejects(async () => {
1475 await eslint
.lintFiles(["tests/fixtures/*-quoted.js"]);
1476 }, /All files matched by 'tests\/fixtures\/\*-quoted\.js' are ignored\./u);
1479 it("should return a warning when an explicitly given file is ignored", async () => {
1480 eslint
= new ESLint({
1481 ignorePath
: getFixturePath(".eslintignore"),
1482 cwd
: getFixturePath()
1484 const filePath
= getFixturePath("passing.js");
1485 const results
= await eslint
.lintFiles([filePath
]);
1487 assert
.strictEqual(results
.length
, 1);
1488 assert
.strictEqual(results
[0].filePath
, filePath
);
1489 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1490 assert
.strictEqual(results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
1491 assert
.strictEqual(results
[0].errorCount
, 0);
1492 assert
.strictEqual(results
[0].warningCount
, 1);
1493 assert
.strictEqual(results
[0].fatalErrorCount
, 0);
1494 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1495 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1498 it("should return two messages when given a file in excluded files list while ignore is off", async () => {
1499 eslint
= new ESLint({
1500 ignorePath
: getFixturePath(".eslintignore"),
1508 const filePath
= fs
.realpathSync(getFixturePath("undef.js"));
1509 const results
= await eslint
.lintFiles([filePath
]);
1511 assert
.strictEqual(results
.length
, 1);
1512 assert
.strictEqual(results
[0].filePath
, filePath
);
1513 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
1514 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1515 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-undef");
1516 assert
.strictEqual(results
[0].messages
[1].severity
, 2);
1519 it("should return zero messages when executing a file with a shebang", async () => {
1520 eslint
= new ESLint({
1523 const results
= await eslint
.lintFiles([getFixturePath("shebang.js")]);
1525 assert
.strictEqual(results
.length
, 1);
1526 assert
.strictEqual(results
[0].messages
.length
, 0);
1529 it("should give a warning when loading a custom rule that doesn't exist", async () => {
1530 eslint
= new ESLint({
1532 rulePaths
: [getFixturePath("rules", "dir1")],
1533 overrideConfigFile
: getFixturePath("rules", "missing-rule.json")
1535 const results
= await eslint
.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1537 assert
.strictEqual(results
.length
, 1);
1538 assert
.strictEqual(results
[0].messages
.length
, 1);
1539 assert
.strictEqual(results
[0].messages
[0].ruleId
, "missing-rule");
1540 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1541 assert
.strictEqual(results
[0].messages
[0].message
, "Definition for rule 'missing-rule' was not found.");
1544 it("should throw an error when loading a bad custom rule", async () => {
1545 eslint
= new ESLint({
1547 rulePaths
: [getFixturePath("rules", "wrong")],
1548 overrideConfigFile
: getFixturePath("rules", "eslint.json")
1552 await assert
.rejects(async () => {
1553 await eslint
.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1554 }, /Error while loading rule 'custom-rule'/u);
1557 it("should return one message when a custom rule matches a file", async () => {
1558 eslint
= new ESLint({
1561 rulePaths
: [getFixturePath("rules/")],
1562 overrideConfigFile
: getFixturePath("rules", "eslint.json")
1564 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1565 const results
= await eslint
.lintFiles([filePath
]);
1567 assert
.strictEqual(results
.length
, 1);
1568 assert
.strictEqual(results
[0].filePath
, filePath
);
1569 assert
.strictEqual(results
[0].messages
.length
, 2);
1570 assert
.strictEqual(results
[0].messages
[0].ruleId
, "custom-rule");
1571 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1574 it("should load custom rule from the provided cwd", async () => {
1575 const cwd
= path
.resolve(getFixturePath("rules"));
1577 eslint
= new ESLint({
1581 overrideConfigFile
: "eslint.json"
1583 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1584 const results
= await eslint
.lintFiles([filePath
]);
1586 assert
.strictEqual(results
.length
, 1);
1587 assert
.strictEqual(results
[0].filePath
, filePath
);
1588 assert
.strictEqual(results
[0].messages
.length
, 2);
1589 assert
.strictEqual(results
[0].messages
[0].ruleId
, "custom-rule");
1590 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1593 it("should return messages when multiple custom rules match a file", async () => {
1594 eslint
= new ESLint({
1597 getFixturePath("rules", "dir1"),
1598 getFixturePath("rules", "dir2")
1600 overrideConfigFile
: getFixturePath("rules", "multi-rulesdirs.json")
1602 const filePath
= fs
.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.js"));
1603 const results
= await eslint
.lintFiles([filePath
]);
1605 assert
.strictEqual(results
.length
, 1);
1606 assert
.strictEqual(results
[0].filePath
, filePath
);
1607 assert
.strictEqual(results
[0].messages
.length
, 2);
1608 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-literals");
1609 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1610 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-strings");
1611 assert
.strictEqual(results
[0].messages
[1].severity
, 2);
1614 it("should return zero messages when executing without useEslintrc flag", async () => {
1615 eslint
= new ESLint({
1619 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1620 const results
= await eslint
.lintFiles([filePath
]);
1622 assert
.strictEqual(results
.length
, 1);
1623 assert
.strictEqual(results
[0].filePath
, filePath
);
1624 assert
.strictEqual(results
[0].messages
.length
, 0);
1627 it("should return zero messages when executing without useEslintrc flag in Node.js environment", async () => {
1628 eslint
= new ESLint({
1635 const filePath
= fs
.realpathSync(getFixturePath("process-exit.js"));
1636 const results
= await eslint
.lintFiles([filePath
]);
1638 assert
.strictEqual(results
.length
, 1);
1639 assert
.strictEqual(results
[0].filePath
, filePath
);
1640 assert
.strictEqual(results
[0].messages
.length
, 0);
1643 it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", async () => {
1644 eslint
= new ESLint({
1651 const filePath
= fs
.realpathSync(getFixturePath("eslintrc", "quotes.js"));
1652 const results
= await eslint
.lintFiles([filePath
]);
1654 assert
.strictEqual(results
.length
, 1);
1655 assert
.strictEqual(results
[0].filePath
, filePath
);
1656 assert
.strictEqual(results
[0].messages
.length
, 0);
1659 it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", async () => {
1660 eslint
= new ESLint({
1667 const filePath
= fs
.realpathSync(getFixturePath("packagejson", "quotes.js"));
1668 const results
= await eslint
.lintFiles([filePath
]);
1670 assert
.strictEqual(results
.length
, 1);
1671 assert
.strictEqual(results
[0].filePath
, filePath
);
1672 assert
.strictEqual(results
[0].messages
.length
, 0);
1675 it("should warn when deprecated rules are configured", async () => {
1676 eslint
= new ESLint({
1678 overrideConfigFile
: ".eslintrc.js",
1687 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1689 assert
.deepStrictEqual(
1690 results
[0].usedDeprecatedRules
,
1692 { ruleId
: "indent-legacy", replacedBy
: ["indent"] },
1693 { ruleId
: "require-jsdoc", replacedBy
: [] },
1694 { ruleId
: "valid-jsdoc", replacedBy
: [] }
1699 it("should not warn when deprecated rules are not configured", async () => {
1700 eslint
= new ESLint({
1702 overrideConfigFile
: ".eslintrc.js",
1704 rules
: { indent
: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
1707 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1709 assert
.deepStrictEqual(results
[0].usedDeprecatedRules
, []);
1712 it("should warn when deprecated rules are found in a config", async () => {
1713 eslint
= new ESLint({
1715 overrideConfigFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
1718 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1720 assert
.deepStrictEqual(
1721 results
[0].usedDeprecatedRules
,
1722 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
1726 describe("Fix Mode", () => {
1727 it("should return fixed text on multiple files when in fix mode", async () => {
1730 * Converts CRLF to LF in output.
1731 * This is a workaround for git's autocrlf option on Windows.
1732 * @param {Object} result A result object to convert.
1735 function convertCRLF(result
) {
1736 if (result
&& result
.output
) {
1737 result
.output
= result
.output
.replace(/\r\n/gu, "\n");
1741 eslint
= new ESLint({
1742 cwd
: path
.join(fixtureDir
, ".."),
1748 quotes
: [2, "double"],
1751 "space-infix-ops": 2
1755 const results
= await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1757 results
.forEach(convertCRLF
);
1758 assert
.deepStrictEqual(results
, [
1760 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/multipass.js")),
1762 suppressedMessages
: [],
1766 fixableErrorCount
: 0,
1767 fixableWarningCount
: 0,
1768 output
: "true ? \"yes\" : \"no\";\n",
1769 usedDeprecatedRules
: []
1772 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/ok.js")),
1774 suppressedMessages
: [],
1778 fixableErrorCount
: 0,
1779 fixableWarningCount
: 0,
1780 usedDeprecatedRules
: []
1783 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes-semi-eqeqeq.js")),
1790 message
: "Expected '===' and instead saw '=='.",
1791 messageId
: "unexpected",
1792 nodeType
: "BinaryExpression",
1797 suppressedMessages
: [],
1801 fixableErrorCount
: 0,
1802 fixableWarningCount
: 0,
1803 output
: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n",
1804 usedDeprecatedRules
: []
1807 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes.js")),
1815 message
: "'foo' is not defined.",
1816 nodeType
: "Identifier",
1821 suppressedMessages
: [],
1825 fixableErrorCount
: 0,
1826 fixableWarningCount
: 0,
1827 output
: "var msg = \"hi\" + foo;\n",
1828 usedDeprecatedRules
: []
1833 it("should run autofix even if files are cached without autofix results", async () => {
1834 const baseOptions
= {
1835 cwd
: path
.join(fixtureDir
, ".."),
1840 quotes
: [2, "double"],
1843 "space-infix-ops": 2
1848 eslint
= new ESLint(Object
.assign({}, baseOptions
, { cache
: true, fix
: false }));
1850 // Do initial lint run and populate the cache file
1851 await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1853 eslint
= new ESLint(Object
.assign({}, baseOptions
, { cache
: true, fix
: true }));
1854 const results
= await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1856 assert(results
.some(result
=> result
.output
));
1860 // These tests have to do with https://github.com/eslint/eslint/issues/963
1862 describe("configuration hierarchy", () => {
1864 // Default configuration - blank
1865 it("should return zero messages when executing with no .eslintrc", async () => {
1866 eslint
= new ESLint({
1867 cwd
: path
.join(fixtureDir
, ".."),
1870 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1872 assert
.strictEqual(results
.length
, 1);
1873 assert
.strictEqual(results
[0].messages
.length
, 0);
1876 // No default configuration rules - conf/environments.js (/*eslint-env node*/)
1877 it("should return zero messages when executing with no .eslintrc in the Node.js environment", async () => {
1878 eslint
= new ESLint({
1879 cwd
: path
.join(fixtureDir
, ".."),
1882 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
1884 assert
.strictEqual(results
.length
, 1);
1885 assert
.strictEqual(results
[0].messages
.length
, 0);
1888 // Project configuration - first level .eslintrc
1889 it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
1890 eslint
= new ESLint({
1891 cwd
: path
.join(fixtureDir
, "..")
1893 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1895 assert
.strictEqual(results
.length
, 1);
1896 assert
.strictEqual(results
[0].messages
.length
, 0);
1899 // Project configuration - first level .eslintrc
1900 it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
1901 eslint
= new ESLint({
1902 cwd
: path
.join(fixtureDir
, "..")
1904 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1906 assert
.strictEqual(results
.length
, 1);
1907 assert
.strictEqual(results
[0].messages
.length
, 0);
1910 // Project configuration - first level .eslintrc
1911 it("should return one message when executing with .eslintrc", async () => {
1912 eslint
= new ESLint({
1913 cwd
: path
.join(fixtureDir
, "..")
1915 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1917 assert
.strictEqual(results
.length
, 1);
1918 assert
.strictEqual(results
[0].messages
.length
, 1);
1919 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1920 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1923 // Project configuration - second level .eslintrc
1924 it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", async () => {
1925 eslint
= new ESLint({
1926 cwd
: path
.join(fixtureDir
, "..")
1928 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1930 assert
.strictEqual(results
.length
, 1);
1931 assert
.strictEqual(results
[0].messages
.length
, 1);
1932 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1933 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1936 // Project configuration - third level .eslintrc
1937 it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", async () => {
1938 eslint
= new ESLint({
1939 cwd
: path
.join(fixtureDir
, "..")
1941 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
1943 assert
.strictEqual(results
.length
, 1);
1944 assert
.strictEqual(results
[0].messages
.length
, 1);
1945 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1946 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1949 // Project configuration - first level package.json
1950 it("should return one message when executing with package.json", async () => {
1951 eslint
= new ESLint({
1952 cwd
: path
.join(fixtureDir
, "..")
1954 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
1956 assert
.strictEqual(results
.length
, 1);
1957 assert
.strictEqual(results
[0].messages
.length
, 1);
1958 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1959 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1962 // Project configuration - second level package.json
1963 it("should return zero messages when executing with local package.json that overrides parent package.json", async () => {
1964 eslint
= new ESLint({
1965 cwd
: path
.join(fixtureDir
, "..")
1967 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
1969 assert
.strictEqual(results
.length
, 1);
1970 assert
.strictEqual(results
[0].messages
.length
, 0);
1973 // Project configuration - third level package.json
1974 it("should return one message when executing with local package.json that overrides parent and grandparent package.json", async () => {
1975 eslint
= new ESLint({
1976 cwd
: path
.join(fixtureDir
, "..")
1978 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
1980 assert
.strictEqual(results
.length
, 1);
1981 assert
.strictEqual(results
[0].messages
.length
, 1);
1982 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1983 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1986 // Project configuration - .eslintrc overrides package.json in same directory
1987 it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", async () => {
1988 eslint
= new ESLint({
1989 cwd
: path
.join(fixtureDir
, "..")
1991 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
1993 assert
.strictEqual(results
.length
, 1);
1994 assert
.strictEqual(results
[0].messages
.length
, 1);
1995 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1996 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1999 // Command line configuration - --config with first level .eslintrc
2000 it("should return two messages when executing with config file that adds to local .eslintrc", async () => {
2001 eslint
= new ESLint({
2002 cwd
: path
.join(fixtureDir
, ".."),
2003 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
2005 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2007 assert
.strictEqual(results
.length
, 1);
2008 assert
.strictEqual(results
[0].messages
.length
, 2);
2009 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
2010 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
2011 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi");
2012 assert
.strictEqual(results
[0].messages
[1].severity
, 1);
2015 // Command line configuration - --config with first level .eslintrc
2016 it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
2017 eslint
= new ESLint({
2018 cwd
: path
.join(fixtureDir
, ".."),
2019 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
2021 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2023 assert
.strictEqual(results
.length
, 1);
2024 assert
.strictEqual(results
[0].messages
.length
, 0);
2027 // Command line configuration - --config with second level .eslintrc
2028 it("should return two messages when executing with config file that adds to local and parent .eslintrc", async () => {
2029 eslint
= new ESLint({
2030 cwd
: path
.join(fixtureDir
, ".."),
2031 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
2033 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
2035 assert
.strictEqual(results
.length
, 1);
2036 assert
.strictEqual(results
[0].messages
.length
, 2);
2037 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
2038 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
2039 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi");
2040 assert
.strictEqual(results
[0].messages
[1].severity
, 1);
2043 // Command line configuration - --config with second level .eslintrc
2044 it("should return one message when executing with config file that overrides local and parent .eslintrc", async () => {
2045 eslint
= new ESLint({
2046 cwd
: path
.join(fixtureDir
, ".."),
2047 overrideConfigFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml")
2049 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
2051 assert
.strictEqual(results
.length
, 1);
2052 assert
.strictEqual(results
[0].messages
.length
, 1);
2053 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
2054 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
2057 // Command line configuration - --config with first level .eslintrc
2058 it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
2059 eslint
= new ESLint({
2060 cwd
: path
.join(fixtureDir
, ".."),
2061 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
2063 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2065 assert
.strictEqual(results
.length
, 1);
2066 assert
.strictEqual(results
[0].messages
.length
, 0);
2069 // Command line configuration - --rule with --config and first level .eslintrc
2070 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
2071 eslint
= new ESLint({
2072 cwd
: path
.join(fixtureDir
, ".."),
2073 overrideConfigFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
2076 quotes
: [1, "double"]
2080 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
2082 assert
.strictEqual(results
.length
, 1);
2083 assert
.strictEqual(results
[0].messages
.length
, 1);
2084 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
2085 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
2088 // Command line configuration - --rule with --config and first level .eslintrc
2089 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
2090 eslint
= new ESLint({
2091 cwd
: path
.join(fixtureDir
, ".."),
2092 overrideConfigFile
: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
2095 quotes
: [1, "double"]
2099 const results
= await eslint
.lintFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
2101 assert
.strictEqual(results
.length
, 1);
2102 assert
.strictEqual(results
[0].messages
.length
, 1);
2103 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
2104 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
2108 describe("plugins", () => {
2109 it("should return two messages when executing with config file that specifies a plugin", async () => {
2110 eslint
= eslintWithPlugins({
2111 cwd
: path
.join(fixtureDir
, ".."),
2112 overrideConfigFile
: getFixturePath("configurations", "plugins-with-prefix.json"),
2115 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
2117 assert
.strictEqual(results
.length
, 1);
2118 assert
.strictEqual(results
[0].messages
.length
, 2);
2119 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2122 it("should return two messages when executing with config file that specifies a plugin with namespace", async () => {
2123 eslint
= eslintWithPlugins({
2124 cwd
: path
.join(fixtureDir
, ".."),
2125 overrideConfigFile
: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
2128 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2130 assert
.strictEqual(results
.length
, 1);
2131 assert
.strictEqual(results
[0].messages
.length
, 2);
2132 assert
.strictEqual(results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2135 it("should return two messages when executing with config file that specifies a plugin without prefix", async () => {
2136 eslint
= eslintWithPlugins({
2137 cwd
: path
.join(fixtureDir
, ".."),
2138 overrideConfigFile
: getFixturePath("configurations", "plugins-without-prefix.json"),
2141 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2143 assert
.strictEqual(results
.length
, 1);
2144 assert
.strictEqual(results
[0].messages
.length
, 2);
2145 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2148 it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", async () => {
2149 eslint
= eslintWithPlugins({
2150 cwd
: path
.join(fixtureDir
, ".."),
2151 overrideConfigFile
: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
2154 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2156 assert
.strictEqual(results
.length
, 1);
2157 assert
.strictEqual(results
[0].messages
.length
, 2);
2158 assert
.strictEqual(results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2161 it("should return two messages when executing with cli option that specifies a plugin", async () => {
2162 eslint
= eslintWithPlugins({
2163 cwd
: path
.join(fixtureDir
, ".."),
2166 plugins
: ["example"],
2167 rules
: { "example/example-rule": 1 }
2170 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2172 assert
.strictEqual(results
.length
, 1);
2173 assert
.strictEqual(results
[0].messages
.length
, 2);
2174 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2177 it("should return two messages when executing with cli option that specifies preloaded plugin", async () => {
2178 eslint
= new ESLint({
2179 cwd
: path
.join(fixtureDir
, ".."),
2183 rules
: { "test/example-rule": 1 }
2186 "eslint-plugin-test": { rules
: { "example-rule": require("../../fixtures/rules/custom-rule") } }
2189 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2191 assert
.strictEqual(results
.length
, 1);
2192 assert
.strictEqual(results
[0].messages
.length
, 2);
2193 assert
.strictEqual(results
[0].messages
[0].ruleId
, "test/example-rule");
2196 it("should return two messages when executing with `baseConfig` that extends preloaded plugin config", async () => {
2197 eslint
= new ESLint({
2198 cwd
: path
.join(fixtureDir
, ".."),
2201 extends: ["plugin:test/preset"]
2206 "example-rule": require("../../fixtures/rules/custom-rule")
2211 "test/example-rule": 1
2219 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2221 assert
.strictEqual(results
.length
, 1);
2222 assert
.strictEqual(results
[0].messages
.length
, 2);
2223 assert
.strictEqual(results
[0].messages
[0].ruleId
, "test/example-rule");
2226 it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", async () => {
2227 eslint
= new ESLint({
2228 resolvePluginsRelativeTo
: getFixturePath("plugins"),
2230 plugins
: ["with-rules"],
2231 rules
: { "with-rules/rule1": "error" }
2235 const results
= await eslint
.lintText("foo");
2237 assert
.strictEqual(results
.length
, 1);
2238 assert
.strictEqual(results
[0].messages
.length
, 1);
2239 assert
.strictEqual(results
[0].messages
[0].ruleId
, "with-rules/rule1");
2240 assert
.strictEqual(results
[0].messages
[0].message
, "Rule report from plugin");
2244 describe("cache", () => {
2247 * helper method to delete a file without caring about exceptions
2248 * @param {string} filePath The file path
2251 function doDelete(filePath
) {
2253 fs
.unlinkSync(filePath
);
2257 * we don't care if the file didn't exist, since our
2258 * intention was to remove the file
2264 * helper method to delete the cache files created during testing
2267 function deleteCache() {
2268 doDelete(path
.resolve(".eslintcache"));
2269 doDelete(path
.resolve(".cache/custom-cache"));
2281 describe("when the cacheFile is a directory or looks like a directory", () => {
2284 * helper method to delete the cache files created during testing
2287 function deleteCacheDir() {
2289 fs
.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
2293 * we don't care if the file didn't exist, since our
2294 * intention was to remove the file
2306 it("should create the cache file inside the provided directory", async () => {
2307 assert(!shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2309 eslint
= new ESLint({
2312 // specifying cache true the cache will be created
2314 cacheLocation
: "./tmp/.cacheFileDir/",
2324 const file
= getFixturePath("cache/src", "test-file.js");
2326 await eslint
.lintFiles([file
]);
2328 assert(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2334 it("should create the cache file inside the provided directory using the cacheLocation option", async () => {
2335 assert(!shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2337 eslint
= new ESLint({
2340 // specifying cache true the cache will be created
2342 cacheLocation
: "./tmp/.cacheFileDir/",
2352 const file
= getFixturePath("cache/src", "test-file.js");
2354 await eslint
.lintFiles([file
]);
2356 assert(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2361 it("should create the cache file inside cwd when no cacheLocation provided", async () => {
2362 const cwd
= path
.resolve(getFixturePath("cli-engine"));
2364 eslint
= new ESLint({
2376 const file
= getFixturePath("cli-engine", "console.js");
2378 await eslint
.lintFiles([file
]);
2380 assert(shell
.test("-f", path
.resolve(cwd
, ".eslintcache")), "the cache for eslint was created at provided cwd");
2383 it("should invalidate the cache if the configuration changed between executions", async () => {
2384 assert(!shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2386 eslint
= new ESLint({
2389 // specifying cache true the cache will be created
2401 let spy
= sinon
.spy(fs
, "readFileSync");
2403 let file
= getFixturePath("cache/src", "test-file.js");
2405 file
= fs
.realpathSync(file
);
2406 const results
= await eslint
.lintFiles([file
]);
2408 for (const { errorCount
, warningCount
} of results
) {
2409 assert
.strictEqual(errorCount
+ warningCount
, 0, "the file passed without errors or warnings");
2411 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2412 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2417 eslint
= new ESLint({
2420 // specifying cache true the cache will be created
2433 spy
= sinon
.spy(fs
, "readFileSync");
2435 const [cachedResult
] = await eslint
.lintFiles([file
]);
2437 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed because the config changed");
2438 assert
.strictEqual(cachedResult
.errorCount
, 1, "since configuration changed the cache was not used an one error was reported");
2439 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2442 it("should remember the files from a previous run and do not operate on them if not changed", async () => {
2443 assert(!shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2445 eslint
= new ESLint({
2448 // specifying cache true the cache will be created
2460 let spy
= sinon
.spy(fs
, "readFileSync");
2462 let file
= getFixturePath("cache/src", "test-file.js");
2464 file
= fs
.realpathSync(file
);
2466 const result
= await eslint
.lintFiles([file
]);
2468 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2469 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2474 eslint
= new ESLint({
2477 // specifying cache true the cache will be created
2490 spy
= sinon
.spy(fs
, "readFileSync");
2492 const cachedResult
= await eslint
.lintFiles([file
]);
2494 assert
.deepStrictEqual(result
, cachedResult
, "the result is the same regardless of using cache or not");
2496 // assert the file was not processed because the cache was used
2497 assert(!spy
.calledWith(file
), "the file was not loaded because it used the cache");
2500 it("should remember the files from a previous run and do not operate on then if not changed", async () => {
2501 const cacheLocation
= getFixturePath(".eslintcache");
2502 const eslintOptions
= {
2505 // specifying cache true the cache will be created
2515 cwd
: path
.join(fixtureDir
, "..")
2518 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint does not exist");
2520 eslint
= new ESLint(eslintOptions
);
2522 let file
= getFixturePath("cache/src", "test-file.js");
2524 file
= fs
.realpathSync(file
);
2526 await eslint
.lintFiles([file
]);
2528 assert(shell
.test("-f", cacheLocation
), "the cache for eslint was created");
2530 eslintOptions
.cache
= false;
2531 eslint
= new ESLint(eslintOptions
);
2533 await eslint
.lintFiles([file
]);
2535 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint was deleted since last run did not used the cache");
2538 it("should store in the cache a file that failed the test", async () => {
2539 const cacheLocation
= getFixturePath(".eslintcache");
2541 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint does not exist");
2543 eslint
= new ESLint({
2544 cwd
: path
.join(fixtureDir
, ".."),
2547 // specifying cache true the cache will be created
2558 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2559 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2560 const result
= await eslint
.lintFiles([badFile
, goodFile
]);
2562 assert(shell
.test("-f", cacheLocation
), "the cache for eslint was created");
2563 const fileCache
= fCache
.createFromFile(cacheLocation
);
2564 const { cache
} = fileCache
;
2566 assert
.strictEqual(typeof cache
.getKey(goodFile
), "object", "the entry for the good file is in the cache");
2567 assert
.strictEqual(typeof cache
.getKey(badFile
), "object", "the entry for the bad file is in the cache");
2568 const cachedResult
= await eslint
.lintFiles([badFile
, goodFile
]);
2570 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2573 it("should not contain in the cache a file that was deleted", async () => {
2574 const cacheLocation
= getFixturePath(".eslintcache");
2576 doDelete(cacheLocation
);
2578 eslint
= new ESLint({
2579 cwd
: path
.join(fixtureDir
, ".."),
2582 // specifying cache true the cache will be created
2593 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2594 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2595 const toBeDeletedFile
= fs
.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
2597 await eslint
.lintFiles([badFile
, goodFile
, toBeDeletedFile
]);
2598 const fileCache
= fCache
.createFromFile(cacheLocation
);
2599 let { cache
} = fileCache
;
2601 assert
.strictEqual(typeof cache
.getKey(toBeDeletedFile
), "object", "the entry for the file to be deleted is in the cache");
2603 // delete the file from the file system
2604 fs
.unlinkSync(toBeDeletedFile
);
2607 * file-entry-cache@2.0.0 will remove from the cache deleted files
2608 * even when they were not part of the array of files to be analyzed
2610 await eslint
.lintFiles([badFile
, goodFile
]);
2612 cache
= JSON
.parse(fs
.readFileSync(cacheLocation
));
2614 assert
.strictEqual(typeof cache
[toBeDeletedFile
], "undefined", "the entry for the file to be deleted is not in the cache");
2617 it("should contain files that were not visited in the cache provided they still exist", async () => {
2618 const cacheLocation
= getFixturePath(".eslintcache");
2620 doDelete(cacheLocation
);
2622 eslint
= new ESLint({
2623 cwd
: path
.join(fixtureDir
, ".."),
2626 // specifying cache true the cache will be created
2637 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2638 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2639 const testFile2
= fs
.realpathSync(getFixturePath("cache/src", "test-file2.js"));
2641 await eslint
.lintFiles([badFile
, goodFile
, testFile2
]);
2643 let fileCache
= fCache
.createFromFile(cacheLocation
);
2644 let { cache
} = fileCache
;
2646 assert
.strictEqual(typeof cache
.getKey(testFile2
), "object", "the entry for the test-file2 is in the cache");
2649 * we pass a different set of files minus test-file2
2650 * previous version of file-entry-cache would remove the non visited
2651 * entries. 2.0.0 version will keep them unless they don't exist
2653 await eslint
.lintFiles([badFile
, goodFile
]);
2655 fileCache
= fCache
.createFromFile(cacheLocation
);
2656 cache
= fileCache
.cache
;
2658 assert
.strictEqual(typeof cache
.getKey(testFile2
), "object", "the entry for the test-file2 is in the cache");
2661 it("should not delete cache when executing on text", async () => {
2662 const cacheLocation
= getFixturePath(".eslintcache");
2664 eslint
= new ESLint({
2665 cwd
: path
.join(fixtureDir
, ".."),
2677 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2679 await eslint
.lintText("var foo = 'bar';");
2681 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2684 it("should not delete cache when executing on text with a provided filename", async () => {
2685 const cacheLocation
= getFixturePath(".eslintcache");
2687 eslint
= new ESLint({
2688 cwd
: path
.join(fixtureDir
, ".."),
2700 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2702 await eslint
.lintText("var bar = foo;", { filePath
: "fixtures/passing.js" });
2704 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2707 it("should not delete cache when executing on files with --cache flag", async () => {
2708 const cacheLocation
= getFixturePath(".eslintcache");
2710 eslint
= new ESLint({
2711 cwd
: path
.join(fixtureDir
, ".."),
2723 const file
= getFixturePath("cli-engine", "console.js");
2725 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2727 await eslint
.lintFiles([file
]);
2729 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2732 it("should delete cache when executing on files without --cache flag", async () => {
2733 const cacheLocation
= getFixturePath(".eslintcache");
2735 eslint
= new ESLint({
2736 cwd
: path
.join(fixtureDir
, ".."),
2747 const file
= getFixturePath("cli-engine", "console.js");
2749 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2751 await eslint
.lintFiles([file
]);
2753 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint has been deleted");
2756 describe("cacheFile", () => {
2757 it("should use the specified cache file", async () => {
2758 const customCacheFile
= path
.resolve(".cache/custom-cache");
2760 assert(!shell
.test("-f", customCacheFile
), "the cache for eslint does not exist");
2762 eslint
= new ESLint({
2765 // specify a custom cache file
2766 cacheLocation
: customCacheFile
,
2768 // specifying cache true the cache will be created
2777 cwd
: path
.join(fixtureDir
, "..")
2779 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2780 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2781 const result
= await eslint
.lintFiles([badFile
, goodFile
]);
2783 assert(shell
.test("-f", customCacheFile
), "the cache for eslint was created");
2784 const fileCache
= fCache
.createFromFile(customCacheFile
);
2785 const { cache
} = fileCache
;
2787 assert(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2789 assert(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2790 const cachedResult
= await eslint
.lintFiles([badFile
, goodFile
]);
2792 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2796 describe("cacheStrategy", () => {
2797 it("should detect changes using a file's modification time when set to 'metadata'", async () => {
2798 const cacheLocation
= getFixturePath(".eslintcache");
2800 doDelete(cacheLocation
);
2802 eslint
= new ESLint({
2803 cwd
: path
.join(fixtureDir
, ".."),
2806 // specifying cache true the cache will be created
2809 cacheStrategy
: "metadata",
2818 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2819 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2821 await eslint
.lintFiles([badFile
, goodFile
]);
2822 let fileCache
= fCache
.createFromFile(cacheLocation
);
2823 const entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2825 entries
.forEach(entry
=> {
2826 assert(entry
.changed
=== false, `the entry for ${entry.key} is initially unchanged`);
2829 // this should result in a changed entry
2830 shell
.touch(goodFile
);
2831 fileCache
= fCache
.createFromFile(cacheLocation
);
2832 assert(fileCache
.getFileDescriptor(badFile
).changed
=== false, `the entry for ${badFile} is unchanged`);
2833 assert(fileCache
.getFileDescriptor(goodFile
).changed
=== true, `the entry for ${goodFile} is changed`);
2836 it("should not detect changes using a file's modification time when set to 'content'", async () => {
2837 const cacheLocation
= getFixturePath(".eslintcache");
2839 doDelete(cacheLocation
);
2841 eslint
= new ESLint({
2842 cwd
: path
.join(fixtureDir
, ".."),
2845 // specifying cache true the cache will be created
2848 cacheStrategy
: "content",
2857 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2858 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2860 await eslint
.lintFiles([badFile
, goodFile
]);
2861 let fileCache
= fCache
.createFromFile(cacheLocation
, true);
2862 let entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2864 entries
.forEach(entry
=> {
2865 assert(entry
.changed
=== false, `the entry for ${entry.key} is initially unchanged`);
2868 // this should NOT result in a changed entry
2869 shell
.touch(goodFile
);
2870 fileCache
= fCache
.createFromFile(cacheLocation
, true);
2871 entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2872 entries
.forEach(entry
=> {
2873 assert(entry
.changed
=== false, `the entry for ${entry.key} remains unchanged`);
2877 it("should detect changes using a file's contents when set to 'content'", async () => {
2878 const cacheLocation
= getFixturePath(".eslintcache");
2880 doDelete(cacheLocation
);
2882 eslint
= new ESLint({
2883 cwd
: path
.join(fixtureDir
, ".."),
2886 // specifying cache true the cache will be created
2889 cacheStrategy
: "content",
2898 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2899 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2900 const goodFileCopy
= path
.resolve(`${path.dirname(goodFile)}`, "test-file-copy.js");
2902 shell
.cp(goodFile
, goodFileCopy
);
2904 await eslint
.lintFiles([badFile
, goodFileCopy
]);
2905 let fileCache
= fCache
.createFromFile(cacheLocation
, true);
2906 const entries
= fileCache
.normalizeEntries([badFile
, goodFileCopy
]);
2908 entries
.forEach(entry
=> {
2909 assert(entry
.changed
=== false, `the entry for ${entry.key} is initially unchanged`);
2912 // this should result in a changed entry
2913 shell
.sed("-i", "abc", "xzy", goodFileCopy
);
2914 fileCache
= fCache
.createFromFile(cacheLocation
, true);
2915 assert(fileCache
.getFileDescriptor(badFile
).changed
=== false, `the entry for ${badFile} is unchanged`);
2916 assert(fileCache
.getFileDescriptor(goodFileCopy
).changed
=== true, `the entry for ${goodFileCopy} is changed`);
2921 describe("processors", () => {
2922 it("should return two messages when executing with config file that specifies a processor", async () => {
2923 eslint
= eslintWithPlugins({
2924 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2926 extensions
: ["js", "txt"],
2927 cwd
: path
.join(fixtureDir
, "..")
2929 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2931 assert
.strictEqual(results
.length
, 1);
2932 assert
.strictEqual(results
[0].messages
.length
, 2);
2935 it("should return two messages when executing with config file that specifies preloaded processor", async () => {
2936 eslint
= new ESLint({
2939 plugins
: ["test-processor"],
2945 extensions
: ["js", "txt"],
2946 cwd
: path
.join(fixtureDir
, ".."),
2954 postprocess(messages
) {
2962 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2964 assert
.strictEqual(results
.length
, 1);
2965 assert
.strictEqual(results
[0].messages
.length
, 2);
2968 it("should run processors when calling lintFiles with config file that specifies a processor", async () => {
2969 eslint
= eslintWithPlugins({
2970 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2972 extensions
: ["js", "txt"],
2973 cwd
: path
.join(fixtureDir
, "..")
2975 const results
= await eslint
.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2977 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2978 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2981 it("should run processors when calling lintFiles with config file that specifies preloaded processor", async () => {
2982 eslint
= new ESLint({
2985 plugins
: ["test-processor"],
2991 extensions
: ["js", "txt"],
2992 cwd
: path
.join(fixtureDir
, ".."),
2998 return [text
.replace("a()", "b()")];
3000 postprocess(messages
) {
3001 messages
[0][0].ruleId
= "post-processed";
3009 const results
= await eslint
.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
3011 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
3012 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
3015 it("should run processors when calling lintText with config file that specifies a processor", async () => {
3016 eslint
= eslintWithPlugins({
3017 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
3019 extensions
: ["js", "txt"],
3022 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
3024 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
3025 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
3028 it("should run processors when calling lintText with config file that specifies preloaded processor", async () => {
3029 eslint
= new ESLint({
3032 plugins
: ["test-processor"],
3038 extensions
: ["js", "txt"],
3045 return [text
.replace("a()", "b()")];
3047 postprocess(messages
) {
3048 messages
[0][0].ruleId
= "post-processed";
3056 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
3058 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
3059 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
3062 it("should run processors when calling lintText with processor resolves same extension but different content correctly", async () => {
3065 eslint
= new ESLint({
3068 plugins
: ["test-processor"],
3070 files
: ["**/*.txt/*.txt"],
3077 extensions
: ["txt"],
3088 // it will be run twice, and text will be as-is at the second time, then it will not run third time
3089 text
: text
.replace("a()", "b()"),
3094 postprocess(messages
) {
3095 messages
[0][0].ruleId
= "post-processed";
3103 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
3105 assert
.strictEqual(count
, 2);
3106 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
3107 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
3110 describe("autofixing with processors", () => {
3111 const HTML_PROCESSOR
= Object
.freeze({
3113 return [text
.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
3115 postprocess(problemLists
) {
3116 return problemLists
[0].map(problem
=> {
3118 const updatedFix
= Object
.assign({}, problem
.fix
, {
3119 range
: problem
.fix
.range
.map(index
=> index
+ "<script>".length
)
3122 return Object
.assign({}, problem
, { fix
: updatedFix
});
3130 it("should run in autofix mode when using a processor that supports autofixing", async () => {
3131 eslint
= new ESLint({
3134 plugins
: ["test-processor"],
3139 extensions
: ["js", "txt"],
3145 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
3150 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
3152 assert
.strictEqual(results
[0].messages
.length
, 0);
3153 assert
.strictEqual(results
[0].output
, "<script>foo;</script>");
3156 it("should not run in autofix mode when using a processor that does not support autofixing", async () => {
3157 eslint
= new ESLint({
3160 plugins
: ["test-processor"],
3165 extensions
: ["js", "txt"],
3169 "test-processor": { processors
: { ".html": HTML_PROCESSOR
} }
3172 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
3174 assert
.strictEqual(results
[0].messages
.length
, 1);
3175 assert(!Object
.prototype.hasOwnProperty
.call(results
[0], "output"));
3178 it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", async () => {
3179 eslint
= new ESLint({
3182 plugins
: ["test-processor"],
3187 extensions
: ["js", "txt"],
3192 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
3197 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
3199 assert
.strictEqual(results
[0].messages
.length
, 1);
3200 assert(!Object
.prototype.hasOwnProperty
.call(results
[0], "output"));
3205 describe("Patterns which match no file should throw errors.", () => {
3207 eslint
= new ESLint({
3208 cwd
: getFixturePath("cli-engine"),
3213 it("one file", async () => {
3214 await assert
.rejects(async () => {
3215 await eslint
.lintFiles(["non-exist.js"]);
3216 }, /No files matching 'non-exist\.js' were found\./u);
3219 it("should throw if the directory exists and is empty", async () => {
3220 await assert
.rejects(async () => {
3221 await eslint
.lintFiles(["empty"]);
3222 }, /No files matching 'empty' were found\./u);
3225 it("one glob pattern", async () => {
3226 await assert
.rejects(async () => {
3227 await eslint
.lintFiles(["non-exist/**/*.js"]);
3228 }, /No files matching 'non-exist\/\*\*\/\*\.js' were found\./u);
3231 it("two files", async () => {
3232 await assert
.rejects(async () => {
3233 await eslint
.lintFiles(["aaa.js", "bbb.js"]);
3234 }, /No files matching 'aaa\.js' were found\./u);
3237 it("a mix of an existing file and a non-existing file", async () => {
3238 await assert
.rejects(async () => {
3239 await eslint
.lintFiles(["console.js", "non-exist.js"]);
3240 }, /No files matching 'non-exist\.js' were found\./u);
3244 describe("overrides", () => {
3246 eslint
= new ESLint({
3247 cwd
: getFixturePath("cli-engine/overrides-with-dot"),
3252 it("should recognize dotfiles", async () => {
3253 const ret
= await eslint
.lintFiles([".test-target.js"]);
3255 assert
.strictEqual(ret
.length
, 1);
3256 assert
.strictEqual(ret
[0].messages
.length
, 1);
3257 assert
.strictEqual(ret
[0].messages
[0].ruleId
, "no-unused-vars");
3261 describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
3263 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3264 cwd
: path
.join(os
.tmpdir(), "eslint/11510"),
3266 "no-console-error-in-overrides.json": JSON
.stringify({
3269 rules
: { "no-console": "error" }
3272 ".eslintrc.json": JSON
.stringify({
3273 extends: "./no-console-error-in-overrides.json",
3274 rules
: { "no-console": "off" }
3276 "a.js": "console.log();"
3281 eslint
= new ESLint({ cwd
: getPath() });
3287 it("should not report 'no-console' error.", async () => {
3288 const results
= await eslint
.lintFiles("a.js");
3290 assert
.strictEqual(results
.length
, 1);
3291 assert
.deepStrictEqual(results
[0].messages
, []);
3295 describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
3297 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3298 cwd
: path
.join(os
.tmpdir(), "eslint/11559"),
3300 "node_modules/eslint-plugin-test/index.js": `
3302 recommended: { plugins: ["test"] }
3306 meta: { schema: [{ type: "number" }] },
3307 create() { return {}; }
3311 ".eslintrc.json": JSON
.stringify({
3313 // Import via the recommended config.
3314 extends: "plugin:test/recommended",
3316 // Has invalid option.
3317 rules
: { "test/foo": ["error", "invalid-option"] }
3319 "a.js": "console.log();"
3324 eslint
= new ESLint({ cwd
: getPath() });
3331 it("should throw fatal error.", async () => {
3332 await assert
.rejects(async () => {
3333 await eslint
.lintFiles("a.js");
3334 }, /invalid-option/u);
3338 describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
3339 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3340 cwd
: path
.join(os
.tmpdir(), "cli-engine/11586"),
3342 "node_modules/eslint-plugin-test/index.js": `
3345 meta: { type: "problem", fixable: "code" },
3349 if (node.name === "example") {
3353 fix: fixer => fixer.replaceText(node, "fixed")
3364 rules
: { "test/no-example": "error" }
3371 eslint
= new ESLint({
3374 fixTypes
: ["problem"]
3382 it("should not crash.", async () => {
3383 const results
= await eslint
.lintFiles("a.js");
3385 assert
.strictEqual(results
.length
, 1);
3386 assert
.deepStrictEqual(results
[0].messages
, []);
3387 assert
.deepStrictEqual(results
[0].output
, "fixed;");
3391 describe("multiple processors", () => {
3392 const root
= path
.join(os
.tmpdir(), "eslint/eslint/multiple-processors");
3393 const commonFiles
= {
3394 "node_modules/pattern-processor/index.js": fs
.readFileSync(
3395 require
.resolve("../../fixtures/processors/pattern-processor"),
3398 "node_modules/eslint-plugin-markdown/index.js": `
3399 const { defineProcessor } = require("pattern-processor");
3400 const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
3401 exports.processors = {
3402 ".md": { ...processor, supportsAutofix: true },
3403 "non-fixable": processor
3406 "node_modules/eslint-plugin-html/index.js": `
3407 const { defineProcessor } = require("pattern-processor");
3408 const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
3409 const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
3410 exports.processors = {
3411 ".html": { ...processor, supportsAutofix: true },
3412 "non-fixable": processor,
3413 "legacy": legacyProcessor
3416 "test.md": unIndent
`
3418 console
.log("hello")
3423 console
.log("hello")
3426 console
.log("hello")
3435 cleanup
= () => { };
3438 afterEach(() => cleanup());
3440 it("should lint only JavaScript blocks if '--ext' was not given.", async () => {
3441 const teardown
= createCustomTeardown({
3446 plugins
: ["markdown", "html"],
3447 rules
: { semi
: "error" }
3452 cleanup
= teardown
.cleanup
;
3453 await teardown
.prepare();
3454 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3455 const results
= await eslint
.lintFiles(["test.md"]);
3457 assert
.strictEqual(results
.length
, 1);
3458 assert
.strictEqual(results
[0].messages
.length
, 1);
3459 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3460 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3463 it("should fix only JavaScript blocks if '--ext' was not given.", async () => {
3464 const teardown
= createCustomTeardown({
3469 plugins
: ["markdown", "html"],
3470 rules
: { semi
: "error" }
3475 await teardown
.prepare();
3476 cleanup
= teardown
.cleanup
;
3477 eslint
= new ESLint({ cwd
: teardown
.getPath(), fix
: true });
3478 const results
= await eslint
.lintFiles(["test.md"]);
3480 assert
.strictEqual(results
.length
, 1);
3481 assert
.strictEqual(results
[0].messages
.length
, 0);
3482 assert
.strictEqual(results
[0].output
, unIndent
`
3484 console
.log("hello");${/* ← fixed */""}
3489 console
.log("hello")${/* ← ignored */""}
3492 console
.log("hello")${/* ← ignored */""}
3498 it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3499 const teardown
= createCustomTeardown({
3504 plugins
: ["markdown", "html"],
3505 rules
: { semi
: "error" }
3510 await teardown
.prepare();
3511 cleanup
= teardown
.cleanup
;
3512 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3513 const results
= await eslint
.lintFiles(["test.md"]);
3515 assert
.strictEqual(results
.length
, 1);
3516 assert
.strictEqual(results
[0].messages
.length
, 2);
3517 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3518 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3519 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3520 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3523 it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3524 const teardown
= createCustomTeardown({
3529 plugins
: ["markdown", "html"],
3530 rules
: { semi
: "error" }
3535 await teardown
.prepare();
3536 cleanup
= teardown
.cleanup
;
3537 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"], fix
: true });
3538 const results
= await eslint
.lintFiles(["test.md"]);
3540 assert
.strictEqual(results
.length
, 1);
3541 assert
.strictEqual(results
[0].messages
.length
, 0);
3542 assert
.strictEqual(results
[0].output
, unIndent
`
3544 console
.log("hello");${/* ← fixed */""}
3549 console
.log("hello");${/* ← fixed */""}
3552 console
.log("hello")${/* ← ignored */""}
3558 it("should use overridden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", async () => {
3559 const teardown
= createCustomTeardown({
3564 plugins
: ["markdown", "html"],
3565 rules
: { semi
: "error" },
3569 processor
: "html/non-fixable" // supportsAutofix: false
3576 await teardown
.prepare();
3577 cleanup
= teardown
.cleanup
;
3578 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"], fix
: true });
3579 const results
= await eslint
.lintFiles(["test.md"]);
3581 assert
.strictEqual(results
.length
, 1);
3582 assert
.strictEqual(results
[0].messages
.length
, 1);
3583 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS Block in HTML Block
3584 assert
.strictEqual(results
[0].messages
[0].line
, 7);
3585 assert
.strictEqual(results
[0].messages
[0].fix
, void 0);
3586 assert
.strictEqual(results
[0].output
, unIndent
`
3588 console
.log("hello");${/* ← fixed */""}
3593 console
.log("hello")${/* ← reported but not fixed */""}
3596 console
.log("hello")
3602 it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", async () => {
3603 const teardown
= createCustomTeardown({
3608 plugins
: ["markdown", "html"],
3609 rules
: { semi
: "error" },
3614 // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
3621 files
: "**/*.html/*.js",
3624 "no-console": "error"
3632 await teardown
.prepare();
3633 cleanup
= teardown
.cleanup
;
3634 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3635 const results
= await eslint
.lintFiles(["test.md"]);
3637 assert
.strictEqual(results
.length
, 1);
3638 assert
.strictEqual(results
[0].messages
.length
, 2);
3639 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3640 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3641 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3642 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3645 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 () => {
3646 const teardown
= createCustomTeardown({
3651 plugins
: ["markdown", "html"],
3652 rules
: { semi
: "error" },
3656 processor
: "html/legacy", // this processor returns strings rather than `{text, filename}`
3659 "no-console": "error"
3663 files
: "**/*.html/*.js",
3674 await teardown
.prepare();
3675 cleanup
= teardown
.cleanup
;
3676 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3677 const results
= await eslint
.lintFiles(["test.md"]);
3679 assert
.strictEqual(results
.length
, 1);
3680 assert
.strictEqual(results
[0].messages
.length
, 3);
3681 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3682 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3683 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3684 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3685 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-console");
3686 assert
.strictEqual(results
[0].messages
[2].line
, 10);
3689 it("should throw an error if invalid processor was specified.", async () => {
3690 const teardown
= createCustomTeardown({
3695 plugins
: ["markdown", "html"],
3696 processor
: "markdown/unknown"
3701 await teardown
.prepare();
3702 cleanup
= teardown
.cleanup
;
3703 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3705 await assert
.rejects(async () => {
3706 await eslint
.lintFiles(["test.md"]);
3707 }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
3710 it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", async () => {
3711 const teardown
= createCustomTeardown({
3716 plugins
: ["markdown", "html"],
3717 rules
: { semi
: "error" },
3721 processor
: "html/.html"
3725 processor
: "markdown/.md"
3732 await teardown
.prepare();
3733 cleanup
= teardown
.cleanup
;
3734 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3735 const results
= await eslint
.lintFiles(["test.md"]);
3737 assert
.strictEqual(results
.length
, 1);
3738 assert
.strictEqual(results
[0].messages
.length
, 2);
3739 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3740 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3741 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3742 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3746 describe("MODULE_NOT_FOUND error handling", () => {
3747 const cwd
= getFixturePath("module-not-found");
3750 eslint
= new ESLint({ cwd
});
3753 it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", async () => {
3755 await eslint
.lintText("test", { filePath
: "extends-js/test.js" });
3757 assert
.strictEqual(err
.messageTemplate
, "extend-config-missing");
3758 assert
.deepStrictEqual(err
.messageData
, {
3759 configName
: "nonexistent-config",
3760 importerName
: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
3764 assert
.fail("Expected to throw an error");
3767 it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", async () => {
3769 await eslint
.lintText("test", { filePath
: "extends-plugin/test.js" });
3771 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3772 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3773 assert
.deepStrictEqual(err
.messageData
, {
3774 importerName
: `extends-plugin${path.sep}.eslintrc.yml`,
3775 pluginName
: "eslint-plugin-nonexistent-plugin",
3776 resolvePluginsRelativeTo
: path
.join(cwd
, "extends-plugin") // the directory of the config file.
3780 assert
.fail("Expected to throw an error");
3783 it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", async () => {
3785 await eslint
.lintText("test", { filePath
: "plugins/test.js" });
3787 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3788 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3789 assert
.deepStrictEqual(err
.messageData
, {
3790 importerName
: `plugins${path.sep}.eslintrc.yml`,
3791 pluginName
: "eslint-plugin-nonexistent-plugin",
3792 resolvePluginsRelativeTo
: path
.join(cwd
, "plugins") // the directory of the config file.
3796 assert
.fail("Expected to throw an error");
3799 it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", async () => {
3801 await eslint
.lintText("test", { filePath
: "throw-in-config-itself/test.js" });
3803 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3804 assert
.strictEqual(err
.messageTemplate
, void 0);
3807 assert
.fail("Expected to throw an error");
3810 it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3812 await eslint
.lintText("test", { filePath
: "throw-in-extends-js/test.js" });
3814 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3815 assert
.strictEqual(err
.messageTemplate
, void 0);
3818 assert
.fail("Expected to throw an error");
3821 it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3823 await eslint
.lintText("test", { filePath
: "throw-in-extends-plugin/test.js" });
3825 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3826 assert
.strictEqual(err
.messageTemplate
, void 0);
3829 assert
.fail("Expected to throw an error");
3832 it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3834 await eslint
.lintText("test", { filePath
: "throw-in-plugins/test.js" });
3836 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3837 assert
.strictEqual(err
.messageTemplate
, void 0);
3840 assert
.fail("Expected to throw an error");
3844 describe("with '--rulesdir' option", () => {
3846 const rootPath
= getFixturePath("cli-engine/with-rulesdir");
3847 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3850 "internal-rules/test.js": `
3851 module.exports = context => ({
3852 ExpressionStatement(node) {
3853 context.report({ node, message: "ok" })
3859 rules
: { test
: "error" }
3861 "test.js": "console.log('hello')"
3865 beforeEach(prepare
);
3869 it("should use the configured rules which are defined by '--rulesdir' option.", async () => {
3870 eslint
= new ESLint({
3872 rulePaths
: ["internal-rules"]
3874 const results
= await eslint
.lintFiles(["test.js"]);
3876 assert
.strictEqual(results
.length
, 1);
3877 assert
.strictEqual(results
[0].messages
.length
, 1);
3878 assert
.strictEqual(results
[0].messages
[0].message
, "ok");
3882 describe("glob pattern '[ab].js'", () => {
3883 const root
= getFixturePath("cli-engine/unmatched-glob");
3888 cleanup
= () => { };
3891 afterEach(() => cleanup());
3893 it("should match '[ab].js' if existed.", async () => {
3895 const teardown
= createCustomTeardown({
3902 ".eslintrc.yml": "root: true"
3906 await teardown
.prepare();
3907 cleanup
= teardown
.cleanup
;
3909 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3910 const results
= await eslint
.lintFiles(["[ab].js"]);
3911 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3913 assert
.deepStrictEqual(filenames
, ["[ab].js"]);
3916 it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", async () => {
3917 const teardown
= createCustomTeardown({
3923 ".eslintrc.yml": "root: true"
3927 await teardown
.prepare();
3928 cleanup
= teardown
.cleanup
;
3929 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3930 const results
= await eslint
.lintFiles(["[ab].js"]);
3931 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3933 assert
.deepStrictEqual(filenames
, ["a.js", "b.js"]);
3937 describe("with 'noInlineConfig' setting", () => {
3938 const root
= getFixturePath("cli-engine/noInlineConfig");
3943 cleanup
= () => { };
3946 afterEach(() => cleanup());
3948 it("should warn directive comments if 'noInlineConfig' was given.", async () => {
3949 const teardown
= createCustomTeardown({
3952 "test.js": "/* globals foo */",
3953 ".eslintrc.yml": "noInlineConfig: true"
3957 await teardown
.prepare();
3958 cleanup
= teardown
.cleanup
;
3959 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3961 const results
= await eslint
.lintFiles(["test.js"]);
3962 const messages
= results
[0].messages
;
3964 assert
.strictEqual(messages
.length
, 1);
3965 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
3968 it("should show the config file what the 'noInlineConfig' came from.", async () => {
3969 const teardown
= createCustomTeardown({
3972 "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
3973 "test.js": "/* globals foo */",
3974 ".eslintrc.yml": "extends: foo"
3978 await teardown
.prepare();
3979 cleanup
= teardown
.cleanup
;
3980 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3982 const results
= await eslint
.lintFiles(["test.js"]);
3983 const messages
= results
[0].messages
;
3985 assert
.strictEqual(messages
.length
, 1);
3986 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
3990 describe("with 'reportUnusedDisableDirectives' setting", () => {
3991 const root
= getFixturePath("cli-engine/reportUnusedDisableDirectives");
3996 cleanup
= () => { };
3999 afterEach(() => cleanup());
4001 it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", async () => {
4002 const teardown
= createCustomTeardown({
4005 "test.js": "/* eslint-disable eqeqeq */",
4006 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
4011 await teardown
.prepare();
4012 cleanup
= teardown
.cleanup
;
4013 eslint
= new ESLint({ cwd
: teardown
.getPath() });
4015 const results
= await eslint
.lintFiles(["test.js"]);
4016 const messages
= results
[0].messages
;
4018 assert
.strictEqual(messages
.length
, 1);
4019 assert
.strictEqual(messages
[0].severity
, 1);
4020 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
4023 describe("the runtime option overrides config files.", () => {
4024 it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", async () => {
4025 const teardown
= createCustomTeardown({
4028 "test.js": "/* eslint-disable eqeqeq */",
4029 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
4033 await teardown
.prepare();
4034 cleanup
= teardown
.cleanup
;
4036 eslint
= new ESLint({
4037 cwd
: teardown
.getPath(),
4038 reportUnusedDisableDirectives
: "off"
4041 const results
= await eslint
.lintFiles(["test.js"]);
4042 const messages
= results
[0].messages
;
4044 assert
.strictEqual(messages
.length
, 0);
4047 it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", async () => {
4048 const teardown
= createCustomTeardown({
4051 "test.js": "/* eslint-disable eqeqeq */",
4052 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
4056 await teardown
.prepare();
4057 cleanup
= teardown
.cleanup
;
4059 eslint
= new ESLint({
4060 cwd
: teardown
.getPath(),
4061 reportUnusedDisableDirectives
: "error"
4064 const results
= await eslint
.lintFiles(["test.js"]);
4065 const messages
= results
[0].messages
;
4067 assert
.strictEqual(messages
.length
, 1);
4068 assert
.strictEqual(messages
[0].severity
, 2);
4069 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
4074 describe("with 'overrides[*].extends' setting on deep locations", () => {
4075 const root
= getFixturePath("cli-engine/deeply-overrides-i-extends");
4076 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
4079 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
4080 overrides: [{ files: ["*test*"], extends: "two" }]
4082 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
4083 overrides: [{ files: ["*.js"], extends: "three" }]
4085 "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
4086 rules: { "no-console": "error" }
4088 "test.js": "console.log('hello')",
4089 ".eslintrc.yml": "extends: one"
4093 beforeEach(prepare
);
4096 it("should not throw.", async () => {
4097 eslint
= new ESLint({ cwd
: getPath() });
4098 const results
= await eslint
.lintFiles(["test.js"]);
4099 const messages
= results
[0].messages
;
4101 assert
.strictEqual(messages
.length
, 1);
4102 assert
.strictEqual(messages
[0].ruleId
, "no-console");
4106 describe("don't ignore the entry directory.", () => {
4107 const root
= getFixturePath("cli-engine/dont-ignore-entry-dir");
4112 cleanup
= () => { };
4115 afterEach(async () => {
4118 const configFilePath
= path
.resolve(root
, "../.eslintrc.json");
4120 if (shell
.test("-e", configFilePath
)) {
4121 shell
.rm(configFilePath
);
4125 it("'lintFiles(\".\")' should not load config files from outside of \".\".", async () => {
4126 const teardown
= createCustomTeardown({
4129 "../.eslintrc.json": "BROKEN FILE",
4130 ".eslintrc.json": JSON
.stringify({ root
: true }),
4131 "index.js": "console.log(\"hello\")"
4135 await teardown
.prepare();
4136 cleanup
= teardown
.cleanup
;
4137 eslint
= new ESLint({ cwd
: teardown
.getPath() });
4139 // Don't throw "failed to load config file" error.
4140 await eslint
.lintFiles(".");
4143 it("'lintFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", async () => {
4144 const teardown
= createCustomTeardown({
4147 "../.eslintrc.json": { ignorePatterns
: ["/dont-ignore-entry-dir"] },
4148 ".eslintrc.json": { root
: true },
4149 "index.js": "console.log(\"hello\")"
4153 await teardown
.prepare();
4154 cleanup
= teardown
.cleanup
;
4155 eslint
= new ESLint({ cwd
: teardown
.getPath() });
4157 // Don't throw "file not found" error.
4158 await eslint
.lintFiles(".");
4161 it("'lintFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", async () => {
4162 const teardown
= createCustomTeardown({
4165 ".eslintrc.json": { ignorePatterns
: ["/subdir"] },
4166 "subdir/.eslintrc.json": { root
: true },
4167 "subdir/index.js": "console.log(\"hello\")"
4171 await teardown
.prepare();
4172 cleanup
= teardown
.cleanup
;
4173 eslint
= new ESLint({ cwd
: teardown
.getPath() });
4175 // Don't throw "file not found" error.
4176 await eslint
.lintFiles("subdir");
4180 it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
4181 eslint
= new ESLint();
4182 await assert
.rejects(() => eslint
.lintFiles(777), /'patterns' must be a non-empty string or an array of non-empty strings/u);
4183 await assert
.rejects(() => eslint
.lintFiles([null]), /'patterns' must be a non-empty string or an array of non-empty strings/u);
4187 describe("calculateConfigForFile", () => {
4188 it("should return the info from Config#getConfig when called", async () => {
4190 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json")
4192 const engine
= new ESLint(options
);
4193 const filePath
= getFixturePath("single-quoted.js");
4194 const actualConfig
= await engine
.calculateConfigForFile(filePath
);
4195 const expectedConfig
= new CascadingConfigArrayFactory({ specificConfigPath
: options
.overrideConfigFile
})
4196 .getConfigArrayForFile(filePath
)
4197 .extractConfig(filePath
)
4198 .toCompatibleObjectAsConfigFileContent();
4200 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4203 it("should return the config for a file that doesn't exist", async () => {
4204 const engine
= new ESLint();
4205 const filePath
= getFixturePath("does_not_exist.js");
4206 const existingSiblingFilePath
= getFixturePath("single-quoted.js");
4207 const actualConfig
= await engine
.calculateConfigForFile(filePath
);
4208 const expectedConfig
= await engine
.calculateConfigForFile(existingSiblingFilePath
);
4210 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4213 it("should return the config for a virtual file that is a child of an existing file", async () => {
4214 const engine
= new ESLint();
4215 const parentFileName
= "single-quoted.js";
4216 const filePath
= getFixturePath(parentFileName
, "virtual.js"); // single-quoted.js/virtual.js
4217 const parentFilePath
= getFixturePath(parentFileName
);
4218 const actualConfig
= await engine
.calculateConfigForFile(filePath
);
4219 const expectedConfig
= await engine
.calculateConfigForFile(parentFilePath
);
4221 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4224 it("should return the config when run from within a subdir", async () => {
4226 cwd
: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
4228 const engine
= new ESLint(options
);
4229 const filePath
= getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
4230 const actualConfig
= await engine
.calculateConfigForFile("./.eslintrc");
4231 const expectedConfig
= new CascadingConfigArrayFactory(options
)
4232 .getConfigArrayForFile(filePath
)
4233 .extractConfig(filePath
)
4234 .toCompatibleObjectAsConfigFileContent();
4236 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4239 it("should throw an error if a directory path was given.", async () => {
4240 const engine
= new ESLint();
4243 await engine
.calculateConfigForFile(".");
4245 assert
.strictEqual(error
.messageTemplate
, "print-config-with-directory-path");
4248 assert
.fail("should throw an error");
4251 it("should throw if non-string value is given to 'filePath' parameter", async () => {
4252 const eslint
= new ESLint();
4254 await assert
.rejects(() => eslint
.calculateConfigForFile(null), /'filePath' must be a non-empty string/u);
4257 // https://github.com/eslint/eslint/issues/13793
4258 it("should throw with an invalid built-in rule config", async () => {
4262 "no-alert": ["error", {
4263 thisDoesNotExist
: true
4268 const engine
= new ESLint(options
);
4269 const filePath
= getFixturePath("single-quoted.js");
4271 await assert
.rejects(
4272 () => engine
.calculateConfigForFile(filePath
),
4273 /Configuration for rule "no-alert" is invalid:/u
4278 describe("isPathIgnored", () => {
4279 it("should check if the given path is ignored", async () => {
4280 const engine
= new ESLint({
4281 ignorePath
: getFixturePath(".eslintignore2"),
4282 cwd
: getFixturePath()
4285 assert(await engine
.isPathIgnored("undef.js"));
4286 assert(!await engine
.isPathIgnored("passing.js"));
4289 it("should return false if ignoring is disabled", async () => {
4290 const engine
= new ESLint({
4292 ignorePath
: getFixturePath(".eslintignore2"),
4293 cwd
: getFixturePath()
4296 assert(!await engine
.isPathIgnored("undef.js"));
4299 // https://github.com/eslint/eslint/issues/5547
4300 it("should return true for default ignores even if ignoring is disabled", async () => {
4301 const engine
= new ESLint({
4303 cwd
: getFixturePath("cli-engine")
4306 assert(await engine
.isPathIgnored("node_modules/foo.js"));
4309 describe("about the default ignore patterns", () => {
4310 it("should always apply defaultPatterns if ignore option is true", async () => {
4311 const cwd
= getFixturePath("ignored-paths");
4312 const engine
= new ESLint({ cwd
});
4314 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
4315 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
4318 it("should still apply defaultPatterns if ignore option is is false", async () => {
4319 const cwd
= getFixturePath("ignored-paths");
4320 const engine
= new ESLint({ ignore
: false, cwd
});
4322 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
4323 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
4326 it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", async () => {
4327 const cwd
= getFixturePath("ignored-paths");
4328 const engine
= new ESLint({
4331 ignorePatterns
: "!/node_modules/package"
4335 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4338 it("should allow subfolders of defaultPatterns to be unignored by ignorePath", async () => {
4339 const cwd
= getFixturePath("ignored-paths");
4340 const engine
= new ESLint({ cwd
, ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
4342 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4345 it("should ignore dotfiles", async () => {
4346 const cwd
= getFixturePath("ignored-paths");
4347 const engine
= new ESLint({ cwd
});
4349 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4350 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4353 it("should ignore directories beginning with a dot", async () => {
4354 const cwd
= getFixturePath("ignored-paths");
4355 const engine
= new ESLint({ cwd
});
4357 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4358 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4361 it("should still ignore dotfiles when ignore option disabled", async () => {
4362 const cwd
= getFixturePath("ignored-paths");
4363 const engine
= new ESLint({ ignore
: false, cwd
});
4365 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4366 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4369 it("should still ignore directories beginning with a dot when ignore option disabled", async () => {
4370 const cwd
= getFixturePath("ignored-paths");
4371 const engine
= new ESLint({ ignore
: false, cwd
});
4373 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4374 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4377 it("should not ignore absolute paths containing '..'", async () => {
4378 const cwd
= getFixturePath("ignored-paths");
4379 const engine
= new ESLint({ cwd
});
4381 assert(!await engine
.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
4384 it("should ignore /node_modules/ relative to .eslintignore when loaded", async () => {
4385 const cwd
= getFixturePath("ignored-paths");
4386 const engine
= new ESLint({ ignorePath
: getFixturePath("ignored-paths", ".eslintignore"), cwd
});
4388 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
4389 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
4392 it("should ignore /node_modules/ relative to cwd without an .eslintignore", async () => {
4393 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4394 const engine
= new ESLint({ cwd
});
4396 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
4397 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
4401 describe("with no .eslintignore file", () => {
4402 it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", async () => {
4403 const cwd
= getFixturePath("ignored-paths", "configurations");
4404 const engine
= new ESLint({ cwd
});
4406 // an .eslintignore in parent directories includes `*.js`, but don't load it.
4407 assert(!await engine
.isPathIgnored("foo.js"));
4408 assert(await engine
.isPathIgnored("node_modules/foo.js"));
4411 it("should return false for files outside of the cwd (with no ignore file provided)", async () => {
4413 // Default ignore patterns should not inadvertently ignore files in parent directories
4414 const engine
= new ESLint({ cwd
: getFixturePath("ignored-paths", "no-ignore-file") });
4416 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4420 describe("with .eslintignore file or package.json file", () => {
4421 it("should load .eslintignore from cwd when explicitly passed", async () => {
4422 const cwd
= getFixturePath("ignored-paths");
4423 const engine
= new ESLint({ cwd
});
4425 // `${cwd}/.eslintignore` includes `sampleignorepattern`.
4426 assert(await engine
.isPathIgnored("sampleignorepattern"));
4429 it("should use package.json's eslintIgnore files if no specified .eslintignore file", async () => {
4430 const cwd
= getFixturePath("ignored-paths", "package-json-ignore");
4431 const engine
= new ESLint({ cwd
});
4433 assert(await engine
.isPathIgnored("hello.js"));
4434 assert(await engine
.isPathIgnored("world.js"));
4437 it("should use correct message template if failed to parse package.json", () => {
4438 const cwd
= getFixturePath("ignored-paths", "broken-package-json");
4440 assert
.throws(() => {
4442 // eslint-disable-next-line no-new -- Check for error
4443 new ESLint({ cwd
});
4445 assert
.strictEqual(error
.messageTemplate
, "failed-to-read-json");
4451 it("should not use package.json's eslintIgnore files if specified .eslintignore file", async () => {
4452 const cwd
= getFixturePath("ignored-paths");
4453 const engine
= new ESLint({ cwd
});
4456 * package.json includes `hello.js` and `world.js`.
4457 * .eslintignore includes `sampleignorepattern`.
4459 assert(!await engine
.isPathIgnored("hello.js"));
4460 assert(!await engine
.isPathIgnored("world.js"));
4461 assert(await engine
.isPathIgnored("sampleignorepattern"));
4464 it("should error if package.json's eslintIgnore is not an array of file paths", () => {
4465 const cwd
= getFixturePath("ignored-paths", "bad-package-json-ignore");
4467 assert
.throws(() => {
4468 // eslint-disable-next-line no-new -- Check for throwing
4469 new ESLint({ cwd
});
4470 }, /Package\.json eslintIgnore property requires an array of paths/u);
4474 describe("with --ignore-pattern option", () => {
4475 it("should accept a string for options.ignorePattern", async () => {
4476 const cwd
= getFixturePath("ignored-paths", "ignore-pattern");
4477 const engine
= new ESLint({
4479 ignorePatterns
: "ignore-me.txt"
4484 assert(await engine
.isPathIgnored("ignore-me.txt"));
4487 it("should accept an array for options.ignorePattern", async () => {
4488 const engine
= new ESLint({
4490 ignorePatterns
: ["a", "b"]
4495 assert(await engine
.isPathIgnored("a"));
4496 assert(await engine
.isPathIgnored("b"));
4497 assert(!await engine
.isPathIgnored("c"));
4500 it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", async () => {
4501 const cwd
= getFixturePath("ignored-paths");
4502 const engine
= new ESLint({
4504 ignorePatterns
: "not-a-file"
4509 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
4512 it("should return true for file matching an ignore pattern exactly", async () => {
4513 const cwd
= getFixturePath("ignored-paths");
4514 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "undef.js" }, cwd
});
4516 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4519 it("should return false for file matching an invalid ignore pattern with leading './'", async () => {
4520 const cwd
= getFixturePath("ignored-paths");
4521 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "./undef.js" }, cwd
});
4523 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4526 it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", async () => {
4527 const cwd
= getFixturePath("ignored-paths");
4528 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "/undef.js" }, cwd
});
4530 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
4533 it("should return true for file matching a child of an ignore pattern", async () => {
4534 const cwd
= getFixturePath("ignored-paths");
4535 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "ignore-pattern" }, cwd
});
4537 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
4540 it("should return true for file matching a grandchild of an ignore pattern", async () => {
4541 const cwd
= getFixturePath("ignored-paths");
4542 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "ignore-pattern" }, cwd
});
4544 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
4547 it("should return false for file not matching any ignore pattern", async () => {
4548 const cwd
= getFixturePath("ignored-paths");
4549 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "failing.js" }, cwd
});
4551 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
4554 it("two globstar '**' ignore pattern should ignore files in nested directories", async () => {
4555 const cwd
= getFixturePath("ignored-paths");
4556 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "**/*.js" }, cwd
});
4558 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4559 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
4560 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
4561 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
4562 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
4563 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
4567 describe("with --ignore-path option", () => {
4568 it("initialization with ignorePath should work when cwd is a parent directory", async () => {
4569 const cwd
= getFixturePath("ignored-paths");
4570 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4571 const engine
= new ESLint({ ignorePath
, cwd
});
4573 assert(await engine
.isPathIgnored("custom-name/foo.js"));
4576 it("initialization with ignorePath should work when the file is in the cwd", async () => {
4577 const cwd
= getFixturePath("ignored-paths", "custom-name");
4578 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4579 const engine
= new ESLint({ ignorePath
, cwd
});
4581 assert(await engine
.isPathIgnored("foo.js"));
4584 it("initialization with ignorePath should work when cwd is a subdirectory", async () => {
4585 const cwd
= getFixturePath("ignored-paths", "custom-name", "subdirectory");
4586 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4587 const engine
= new ESLint({ ignorePath
, cwd
});
4589 assert(await engine
.isPathIgnored("../custom-name/foo.js"));
4592 it("initialization with invalid file should throw error", () => {
4593 const cwd
= getFixturePath("ignored-paths");
4594 const ignorePath
= getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
4596 assert
.throws(() => {
4597 // eslint-disable-next-line no-new -- Check for throwing
4598 new ESLint({ ignorePath
, cwd
});
4599 }, /Cannot read \.eslintignore file/u);
4602 it("should return false for files outside of ignorePath's directory", async () => {
4603 const cwd
= getFixturePath("ignored-paths");
4604 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4605 const engine
= new ESLint({ ignorePath
, cwd
});
4607 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4610 it("should resolve relative paths from CWD", async () => {
4611 const cwd
= getFixturePath("ignored-paths", "subdir");
4612 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4613 const engine
= new ESLint({ ignorePath
, cwd
});
4615 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4616 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4619 it("should resolve relative paths from CWD when it's in a child directory", async () => {
4620 const cwd
= getFixturePath("ignored-paths");
4621 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4622 const engine
= new ESLint({ ignorePath
, cwd
});
4624 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4625 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4626 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4627 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
4629 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
4632 it("should resolve relative paths from CWD when it contains negated globs", async () => {
4633 const cwd
= getFixturePath("ignored-paths");
4634 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4635 const engine
= new ESLint({ ignorePath
, cwd
});
4637 assert(await engine
.isPathIgnored("subdir/blah.txt"));
4638 assert(await engine
.isPathIgnored("blah.txt"));
4639 assert(await engine
.isPathIgnored("subdir/bar.txt"));
4640 assert(!await engine
.isPathIgnored("bar.txt"));
4641 assert(!await engine
.isPathIgnored("subdir/baz.txt"));
4642 assert(!await engine
.isPathIgnored("baz.txt"));
4645 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", async () => {
4646 const cwd
= getFixturePath("ignored-paths");
4647 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4648 const engine
= new ESLint({ ignorePath
, cwd
});
4650 assert(await engine
.isPathIgnored("node_modules/blah.js"));
4653 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", async () => {
4654 const cwd
= getFixturePath("ignored-paths", "subdir");
4655 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4656 const engine
= new ESLint({ ignorePath
, cwd
});
4658 assert(await engine
.isPathIgnored("node_modules/blah.js"));
4661 it("should handle .eslintignore which contains CRLF correctly.", async () => {
4662 const ignoreFileContent
= fs
.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
4664 assert(ignoreFileContent
.includes("\r"), "crlf/.eslintignore should contains CR.");
4665 const cwd
= getFixturePath("ignored-paths");
4666 const ignorePath
= getFixturePath("ignored-paths", "crlf/.eslintignore");
4667 const engine
= new ESLint({ ignorePath
, cwd
});
4669 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
4670 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
4671 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
4674 it("should not include comments in ignore rules", async () => {
4675 const cwd
= getFixturePath("ignored-paths");
4676 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithComments");
4677 const engine
= new ESLint({ ignorePath
, cwd
});
4679 assert(!await engine
.isPathIgnored("# should be ignored"));
4680 assert(await engine
.isPathIgnored("this_one_not"));
4683 it("should ignore a non-negated pattern", async () => {
4684 const cwd
= getFixturePath("ignored-paths");
4685 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4686 const engine
= new ESLint({ ignorePath
, cwd
});
4688 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
4691 it("should not ignore a negated pattern", async () => {
4692 const cwd
= getFixturePath("ignored-paths");
4693 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4694 const engine
= new ESLint({ ignorePath
, cwd
});
4696 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
4699 // https://github.com/eslint/eslint/issues/15642
4700 it("should correctly handle patterns with escaped brackets", async () => {
4701 const cwd
= getFixturePath("ignored-paths");
4702 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithEscapedBrackets");
4703 const engine
= new ESLint({ ignorePath
, cwd
});
4705 const subdir
= "brackets";
4708 !await engine
.isPathIgnored(getFixturePath("ignored-paths", subdir
, "index.js")),
4709 `'${subdir}/index.js' should not be ignored`
4712 for (const filename
of ["[index.js", "index].js", "[index].js"]) {
4714 await engine
.isPathIgnored(getFixturePath("ignored-paths", subdir
, filename
)),
4715 `'${subdir}/${filename}' should be ignored`
4722 describe("with --ignore-path option and --ignore-pattern option", () => {
4723 it("should return false for ignored file when unignored with ignore pattern", async () => {
4724 const cwd
= getFixturePath("ignored-paths");
4725 const engine
= new ESLint({
4726 ignorePath
: getFixturePath("ignored-paths", ".eslintignore"),
4728 ignorePatterns
: "!sampleignorepattern"
4733 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
4737 it("should throw if non-string value is given to 'filePath' parameter", async () => {
4738 const eslint
= new ESLint();
4740 await assert
.rejects(() => eslint
.isPathIgnored(null), /'filePath' must be a non-empty string/u);
4744 describe("loadFormatter()", () => {
4745 it("should return a formatter object when a bundled formatter is requested", async () => {
4746 const engine
= new ESLint();
4747 const formatter
= await engine
.loadFormatter("compact");
4749 assert
.strictEqual(typeof formatter
, "object");
4750 assert
.strictEqual(typeof formatter
.format
, "function");
4753 it("should return a formatter object when no argument is passed", async () => {
4754 const engine
= new ESLint();
4755 const formatter
= await engine
.loadFormatter();
4757 assert
.strictEqual(typeof formatter
, "object");
4758 assert
.strictEqual(typeof formatter
.format
, "function");
4761 it("should return a formatter object when a custom formatter is requested", async () => {
4762 const engine
= new ESLint();
4763 const formatter
= await engine
.loadFormatter(getFixturePath("formatters", "simple.js"));
4765 assert
.strictEqual(typeof formatter
, "object");
4766 assert
.strictEqual(typeof formatter
.format
, "function");
4769 it("should return a formatter object when a custom formatter is requested, also if the path has backslashes", async () => {
4770 const engine
= new ESLint({
4771 cwd
: path
.join(fixtureDir
, "..")
4773 const formatter
= await engine
.loadFormatter(".\\fixtures\\formatters\\simple.js");
4775 assert
.strictEqual(typeof formatter
, "object");
4776 assert
.strictEqual(typeof formatter
.format
, "function");
4779 it("should return a formatter object when a formatter prefixed with eslint-formatter is requested", async () => {
4780 const engine
= new ESLint({
4781 cwd
: getFixturePath("cli-engine")
4783 const formatter
= await engine
.loadFormatter("bar");
4785 assert
.strictEqual(typeof formatter
, "object");
4786 assert
.strictEqual(typeof formatter
.format
, "function");
4789 it("should return a formatter object when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", async () => {
4790 const engine
= new ESLint({
4791 cwd
: getFixturePath("cli-engine")
4793 const formatter
= await engine
.loadFormatter("eslint-formatter-bar");
4795 assert
.strictEqual(typeof formatter
, "object");
4796 assert
.strictEqual(typeof formatter
.format
, "function");
4799 it("should return a formatter object when a formatter is requested within a scoped npm package", async () => {
4800 const engine
= new ESLint({
4801 cwd
: getFixturePath("cli-engine")
4803 const formatter
= await engine
.loadFormatter("@somenamespace/foo");
4805 assert
.strictEqual(typeof formatter
, "object");
4806 assert
.strictEqual(typeof formatter
.format
, "function");
4809 it("should return a formatter object when a formatter is requested within a scoped npm package, also when the eslint-formatter prefix is included in the format argument", async () => {
4810 const engine
= new ESLint({
4811 cwd
: getFixturePath("cli-engine")
4813 const formatter
= await engine
.loadFormatter("@somenamespace/eslint-formatter-foo");
4815 assert
.strictEqual(typeof formatter
, "object");
4816 assert
.strictEqual(typeof formatter
.format
, "function");
4819 it("should throw if a custom formatter doesn't exist", async () => {
4820 const engine
= new ESLint();
4821 const formatterPath
= getFixturePath("formatters", "doesntexist.js");
4822 const fullFormatterPath
= path
.resolve(formatterPath
);
4824 await assert
.rejects(async () => {
4825 await engine
.loadFormatter(formatterPath
);
4826 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
4829 it("should throw if a built-in formatter doesn't exist", async () => {
4830 const engine
= new ESLint();
4831 const fullFormatterPath
= path
.resolve(__dirname
, "../../../lib/cli-engine/formatters/special");
4833 await assert
.rejects(async () => {
4834 await engine
.loadFormatter("special");
4835 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
4838 it("should throw if the required formatter exists but has an error", async () => {
4839 const engine
= new ESLint();
4840 const formatterPath
= getFixturePath("formatters", "broken.js");
4842 await assert
.rejects(async () => {
4843 await engine
.loadFormatter(formatterPath
);
4844 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`), "u"));
4847 it("should throw if a non-string formatter name is passed", async () => {
4848 const engine
= new ESLint();
4850 await assert
.rejects(async () => {
4851 await engine
.loadFormatter(5);
4852 }, /'name' must be a string/u);
4855 it("should pass cwd to the `cwd` property of the second argument.", async () => {
4856 const cwd
= getFixturePath();
4857 const engine
= new ESLint({ cwd
});
4858 const formatterPath
= getFixturePath("formatters", "cwd.js");
4859 const formatter
= await engine
.loadFormatter(formatterPath
);
4861 assert
.strictEqual(formatter
.format([]), cwd
);
4865 describe("getErrorResults()", () => {
4866 it("should report 5 error messages when looking for errors only", async () => {
4867 process
.chdir(originalDir
);
4868 const engine
= new ESLint();
4869 const results
= await engine
.lintText("var foo = 'bar';");
4870 const errorResults
= ESLint
.getErrorResults(results
);
4872 assert
.strictEqual(errorResults
[0].messages
.length
, 5);
4873 assert
.strictEqual(errorResults
[0].errorCount
, 5);
4874 assert
.strictEqual(errorResults
[0].fixableErrorCount
, 3);
4875 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4876 assert
.strictEqual(errorResults
[0].messages
[0].ruleId
, "strict");
4877 assert
.strictEqual(errorResults
[0].messages
[0].severity
, 2);
4878 assert
.strictEqual(errorResults
[0].messages
[1].ruleId
, "no-var");
4879 assert
.strictEqual(errorResults
[0].messages
[1].severity
, 2);
4880 assert
.strictEqual(errorResults
[0].messages
[2].ruleId
, "no-unused-vars");
4881 assert
.strictEqual(errorResults
[0].messages
[2].severity
, 2);
4882 assert
.strictEqual(errorResults
[0].messages
[3].ruleId
, "quotes");
4883 assert
.strictEqual(errorResults
[0].messages
[3].severity
, 2);
4884 assert
.strictEqual(errorResults
[0].messages
[4].ruleId
, "eol-last");
4885 assert
.strictEqual(errorResults
[0].messages
[4].severity
, 2);
4888 it("should not mutate passed report parameter", async () => {
4889 process
.chdir(originalDir
);
4890 const engine
= new ESLint({
4892 rules
: { quotes
: [1, "double"] }
4895 const results
= await engine
.lintText("var foo = 'bar';");
4896 const reportResultsLength
= results
[0].messages
.length
;
4898 ESLint
.getErrorResults(results
);
4900 assert
.strictEqual(results
[0].messages
.length
, reportResultsLength
);
4903 it("should report a warningCount of 0 when looking for errors only", async () => {
4904 process
.chdir(originalDir
);
4905 const engine
= new ESLint();
4906 const results
= await engine
.lintText("var foo = 'bar';");
4907 const errorResults
= ESLint
.getErrorResults(results
);
4909 assert
.strictEqual(errorResults
[0].warningCount
, 0);
4910 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4913 it("should return 0 error or warning messages even when the file has warnings", async () => {
4914 const engine
= new ESLint({
4915 ignorePath
: path
.join(fixtureDir
, ".eslintignore"),
4916 cwd
: path
.join(fixtureDir
, "..")
4919 filePath
: "fixtures/passing.js",
4922 const results
= await engine
.lintText("var bar = foo;", options
);
4923 const errorReport
= ESLint
.getErrorResults(results
);
4925 assert
.strictEqual(errorReport
.length
, 0);
4926 assert
.strictEqual(results
.length
, 1);
4927 assert
.strictEqual(results
[0].errorCount
, 0);
4928 assert
.strictEqual(results
[0].warningCount
, 1);
4929 assert
.strictEqual(results
[0].fatalErrorCount
, 0);
4930 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
4931 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
4934 it("should return source code of file in the `source` property", async () => {
4935 process
.chdir(originalDir
);
4936 const engine
= new ESLint({
4939 rules
: { quotes
: [2, "double"] }
4942 const results
= await engine
.lintText("var foo = 'bar';");
4943 const errorResults
= ESLint
.getErrorResults(results
);
4945 assert
.strictEqual(errorResults
[0].messages
.length
, 1);
4946 assert
.strictEqual(errorResults
[0].source
, "var foo = 'bar';");
4949 it("should contain `output` property after fixes", async () => {
4950 process
.chdir(originalDir
);
4951 const engine
= new ESLint({
4961 const results
= await engine
.lintText("console.log('foo')");
4962 const errorResults
= ESLint
.getErrorResults(results
);
4964 assert
.strictEqual(errorResults
[0].messages
.length
, 1);
4965 assert
.strictEqual(errorResults
[0].output
, "console.log('foo');");
4969 describe("getRulesMetaForResults()", () => {
4970 it("should return empty object when there are no linting errors", async () => {
4971 const engine
= new ESLint({
4975 const rulesMeta
= engine
.getRulesMetaForResults([]);
4977 assert
.deepStrictEqual(rulesMeta
, {});
4980 it("should return one rule meta when there is a linting error", async () => {
4981 const engine
= new ESLint({
4990 const results
= await engine
.lintText("a");
4991 const rulesMeta
= engine
.getRulesMetaForResults(results
);
4993 assert
.strictEqual(Object
.keys(rulesMeta
).length
, 1);
4994 assert
.strictEqual(rulesMeta
.semi
, coreRules
.get("semi").meta
);
4997 it("should return one rule meta when there is a suppressed linting error", async () => {
4998 const engine
= new ESLint({
5007 const results
= await engine
.lintText("a // eslint-disable-line semi");
5008 const rulesMeta
= engine
.getRulesMetaForResults(results
);
5010 assert
.strictEqual(Object
.keys(rulesMeta
).length
, 1);
5011 assert
.strictEqual(rulesMeta
.semi
, coreRules
.get("semi").meta
);
5014 it("should return multiple rule meta when there are multiple linting errors", async () => {
5015 const engine
= new ESLint({
5020 quotes
: [2, "double"]
5025 const results
= await engine
.lintText("'a'");
5026 const rulesMeta
= engine
.getRulesMetaForResults(results
);
5028 assert
.strictEqual(rulesMeta
.semi
, coreRules
.get("semi").meta
);
5029 assert
.strictEqual(rulesMeta
.quotes
, coreRules
.get("quotes").meta
);
5032 it("should return multiple rule meta when there are multiple linting errors from a plugin", async () => {
5033 const nodePlugin
= require("eslint-plugin-n");
5034 const engine
= new ESLint({
5042 "n/no-new-require": 2,
5044 quotes
: [2, "double"]
5049 const results
= await engine
.lintText("new require('hi')");
5050 const rulesMeta
= engine
.getRulesMetaForResults(results
);
5052 assert
.strictEqual(rulesMeta
.semi
, coreRules
.get("semi").meta
);
5053 assert
.strictEqual(rulesMeta
.quotes
, coreRules
.get("quotes").meta
);
5055 rulesMeta
["n/no-new-require"],
5056 nodePlugin
.rules
["no-new-require"].meta
5060 it("should ignore messages not related to a rule", async () => {
5061 const engine
= new ESLint({
5064 ignorePatterns
: "ignored.js",
5069 reportUnusedDisableDirectives
: "warn"
5073 const results
= await engine
.lintText("syntax error");
5074 const rulesMeta
= engine
.getRulesMetaForResults(results
);
5076 assert
.deepStrictEqual(rulesMeta
, {});
5079 const results
= await engine
.lintText("// eslint-disable-line no-var");
5080 const rulesMeta
= engine
.getRulesMetaForResults(results
);
5082 assert
.deepStrictEqual(rulesMeta
, {});
5085 const results
= await engine
.lintText("", { filePath
: "ignored.js", warnIgnored
: true });
5086 const rulesMeta
= engine
.getRulesMetaForResults(results
);
5088 assert
.deepStrictEqual(rulesMeta
, {});
5092 it("should return a non-empty value if some of the messages are related to a rule", async () => {
5093 const engine
= new ESLint({
5095 overrideConfig
: { rules
: { "no-var": "warn" } },
5096 reportUnusedDisableDirectives
: "warn"
5099 const results
= await engine
.lintText("// eslint-disable-line no-var\nvar foo;");
5100 const rulesMeta
= engine
.getRulesMetaForResults(results
);
5102 assert
.deepStrictEqual(rulesMeta
, { "no-var": coreRules
.get("no-var").meta
});
5106 describe("outputFixes()", () => {
5108 sinon
.verifyAndRestore();
5111 it("should call fs.writeFile() for each result with output", async () => {
5113 writeFile
: sinon
.spy(callLastArgument
)
5115 const spy
= fakeFS
.writeFile
;
5116 const { ESLint
: localESLint
} = proxyquire("../../../lib/eslint/eslint", {
5122 filePath
: path
.resolve("foo.js"),
5126 filePath
: path
.resolve("bar.js"),
5131 await localESLint
.outputFixes(results
);
5133 assert
.strictEqual(spy
.callCount
, 2);
5134 assert(spy
.firstCall
.calledWithExactly(path
.resolve("foo.js"), "bar", sinon
.match
.func
), "First call was incorrect.");
5135 assert(spy
.secondCall
.calledWithExactly(path
.resolve("bar.js"), "baz", sinon
.match
.func
), "Second call was incorrect.");
5138 it("should call fs.writeFile() for each result with output and not at all for a result without output", async () => {
5140 writeFile
: sinon
.spy(callLastArgument
)
5142 const spy
= fakeFS
.writeFile
;
5143 const { ESLint
: localESLint
} = proxyquire("../../../lib/eslint/eslint", {
5148 filePath
: path
.resolve("foo.js"),
5152 filePath
: path
.resolve("abc.js")
5155 filePath
: path
.resolve("bar.js"),
5160 await localESLint
.outputFixes(results
);
5162 assert
.strictEqual(spy
.callCount
, 2);
5163 assert(spy
.firstCall
.calledWithExactly(path
.resolve("foo.js"), "bar", sinon
.match
.func
), "First call was incorrect.");
5164 assert(spy
.secondCall
.calledWithExactly(path
.resolve("bar.js"), "baz", sinon
.match
.func
), "Second call was incorrect.");
5167 it("should throw if non object array is given to 'results' parameter", async () => {
5168 await assert
.rejects(() => ESLint
.outputFixes(null), /'results' must be an array/u);
5169 await assert
.rejects(() => ESLint
.outputFixes([null]), /'results' must include only objects/u);
5173 describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
5174 it("should report a violation for disabling rules", async () => {
5176 "alert('test'); // eslint-disable-line no-alert"
5181 allowInlineConfig
: false,
5183 env
: { browser
: true },
5187 "no-trailing-spaces": 0,
5193 const eslintCLI
= new ESLint(config
);
5194 const results
= await eslintCLI
.lintText(code
);
5195 const messages
= results
[0].messages
;
5197 assert
.strictEqual(messages
.length
, 1);
5198 assert
.strictEqual(messages
[0].ruleId
, "no-alert");
5201 it("should not report a violation by default", async () => {
5203 "alert('test'); // eslint-disable-line no-alert"
5208 allowInlineConfig
: true,
5210 env
: { browser
: true },
5214 "no-trailing-spaces": 0,
5220 const eslintCLI
= new ESLint(config
);
5221 const results
= await eslintCLI
.lintText(code
);
5222 const messages
= results
[0].messages
;
5224 assert
.strictEqual(messages
.length
, 0);
5228 describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
5229 it("should report problems for unused eslint-disable directives", async () => {
5230 const eslint
= new ESLint({ useEslintrc
: false, reportUnusedDisableDirectives
: "error" });
5232 assert
.deepStrictEqual(
5233 await eslint
.lintText("/* eslint-disable */"),
5240 message
: "Unused eslint-disable directive (no problems were reported).",
5251 suppressedMessages
: [],
5255 fixableErrorCount
: 1,
5256 fixableWarningCount
: 0,
5257 source
: "/* eslint-disable */",
5258 usedDeprecatedRules
: []
5265 describe("when retrieving version number", () => {
5266 it("should return current version number", () => {
5267 const eslintCLI
= require("../../../lib/eslint").ESLint
;
5268 const version
= eslintCLI
.version
;
5270 assert
.strictEqual(typeof version
, "string");
5271 assert(parseInt(version
[0], 10) >= 3);
5275 describe("mutability", () => {
5276 describe("plugins", () => {
5277 it("Loading plugin in one instance doesn't mutate to another instance", async () => {
5278 const filePath
= getFixturePath("single-quoted.js");
5279 const engine1
= eslintWithPlugins({
5280 cwd
: path
.join(fixtureDir
, ".."),
5283 plugins
: ["example"],
5284 rules
: { "example/example-rule": 1 }
5287 const engine2
= new ESLint({
5288 cwd
: path
.join(fixtureDir
, ".."),
5291 const fileConfig1
= await engine1
.calculateConfigForFile(filePath
);
5292 const fileConfig2
= await engine2
.calculateConfigForFile(filePath
);
5295 assert
.deepStrictEqual(fileConfig1
.plugins
, ["example"], "Plugin is present for engine 1");
5296 assert
.deepStrictEqual(fileConfig2
.plugins
, [], "Plugin is not present for engine 2");
5300 describe("rules", () => {
5301 it("Loading rules in one instance doesn't mutate to another instance", async () => {
5302 const filePath
= getFixturePath("single-quoted.js");
5303 const engine1
= new ESLint({
5304 cwd
: path
.join(fixtureDir
, ".."),
5306 overrideConfig
: { rules
: { "example/example-rule": 1 } }
5308 const engine2
= new ESLint({
5309 cwd
: path
.join(fixtureDir
, ".."),
5312 const fileConfig1
= await engine1
.calculateConfigForFile(filePath
);
5313 const fileConfig2
= await engine2
.calculateConfigForFile(filePath
);
5316 assert
.deepStrictEqual(fileConfig1
.rules
["example/example-rule"], [1], "example is present for engine 1");
5317 assert
.strictEqual(fileConfig2
.rules
["example/example-rule"], void 0, "example is not present for engine 2");
5322 describe("with ignorePatterns config", () => {
5323 const root
= getFixturePath("cli-engine/ignore-patterns");
5325 describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
5326 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5330 ignorePatterns
: "foo.js"
5334 "subdir/foo.js": "",
5339 beforeEach(prepare
);
5342 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5343 const engine
= new ESLint({ cwd
: getPath() });
5345 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5346 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5349 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5350 const engine
= new ESLint({ cwd
: getPath() });
5352 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5353 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), false);
5356 it("'lintFiles()' should not verify 'foo.js'.", async () => {
5357 const engine
= new ESLint({ cwd
: getPath() });
5358 const filePaths
= (await engine
.lintFiles("**/*.js"))
5359 .map(r
=> r
.filePath
)
5362 assert
.deepStrictEqual(filePaths
, [
5363 path
.join(root
, "bar.js"),
5364 path
.join(root
, "subdir/bar.js")
5369 describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
5370 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5374 ignorePatterns
: ["foo.js", "/bar.js"]
5379 "subdir/foo.js": "",
5380 "subdir/bar.js": "",
5385 beforeEach(prepare
);
5388 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5389 const engine
= new ESLint({ cwd
: getPath() });
5391 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5392 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5395 it("'isPathIgnored()' should return 'true' for '/bar.js'.", async () => {
5396 const engine
= new ESLint({ cwd
: getPath() });
5398 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), true);
5399 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), false);
5402 it("'lintFiles()' should not verify 'foo.js' and '/bar.js'.", async () => {
5403 const engine
= new ESLint({ cwd
: getPath() });
5404 const filePaths
= (await engine
.lintFiles("**/*.js"))
5405 .map(r
=> r
.filePath
)
5408 assert
.deepStrictEqual(filePaths
, [
5409 path
.join(root
, "baz.js"),
5410 path
.join(root
, "subdir/bar.js"),
5411 path
.join(root
, "subdir/baz.js")
5416 describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
5418 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5422 ignorePatterns
: "!/node_modules/foo"
5424 "node_modules/foo/index.js": "",
5425 "node_modules/foo/.dot.js": "",
5426 "node_modules/bar/index.js": "",
5431 beforeEach(prepare
);
5434 it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", async () => {
5435 const engine
= new ESLint({ cwd
: getPath() });
5437 assert
.strictEqual(await engine
.isPathIgnored("node_modules/foo/index.js"), false);
5440 it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", async () => {
5441 const engine
= new ESLint({ cwd
: getPath() });
5443 assert
.strictEqual(await engine
.isPathIgnored("node_modules/foo/.dot.js"), true);
5446 it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", async () => {
5447 const engine
= new ESLint({ cwd
: getPath() });
5449 assert
.strictEqual(await engine
.isPathIgnored("node_modules/bar/index.js"), true);
5452 it("'lintFiles()' should verify 'node_modules/foo/index.js'.", async () => {
5453 const engine
= new ESLint({ cwd
: getPath() });
5454 const filePaths
= (await engine
.lintFiles("**/*.js"))
5455 .map(r
=> r
.filePath
)
5458 assert
.deepStrictEqual(filePaths
, [
5459 path
.join(root
, "foo.js"),
5460 path
.join(root
, "node_modules/foo/index.js")
5465 describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
5467 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5470 ".eslintrc.js": `module.exports = ${JSON.stringify({
5471 ignorePatterns: "!.eslintrc.js"
5477 beforeEach(prepare
);
5480 it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", async () => {
5481 const engine
= new ESLint({ cwd
: getPath() });
5483 assert
.strictEqual(await engine
.isPathIgnored(".eslintrc.js"), false);
5486 it("'lintFiles()' should verify '.eslintrc.js'.", async () => {
5487 const engine
= new ESLint({ cwd
: getPath() });
5488 const filePaths
= (await engine
.lintFiles("**/*.js"))
5489 .map(r
=> r
.filePath
)
5492 assert
.deepStrictEqual(filePaths
, [
5493 path
.join(root
, ".eslintrc.js"),
5494 path
.join(root
, "foo.js")
5499 describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
5500 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5503 ".eslintrc.js": `module.exports = ${JSON.stringify({
5504 ignorePatterns: "!.*"
5506 ".eslintignore": ".foo*",
5512 beforeEach(prepare
);
5515 it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", async () => {
5516 const engine
= new ESLint({ cwd
: getPath() });
5518 assert
.strictEqual(await engine
.isPathIgnored(".foo.js"), true);
5521 it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", async () => {
5522 const engine
= new ESLint({ cwd
: getPath() });
5524 assert
.strictEqual(await engine
.isPathIgnored(".bar.js"), false);
5527 it("'lintFiles()' should not verify re-ignored '.foo.js'.", async () => {
5528 const engine
= new ESLint({ cwd
: getPath() });
5529 const filePaths
= (await engine
.lintFiles("**/*.js"))
5530 .map(r
=> r
.filePath
)
5533 assert
.deepStrictEqual(filePaths
, [
5534 path
.join(root
, ".bar.js"),
5535 path
.join(root
, ".eslintrc.js")
5540 describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
5541 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5544 ".eslintrc.js": `module.exports = ${JSON.stringify({
5545 ignorePatterns: "*.js"
5547 ".eslintignore": "!foo.js",
5553 beforeEach(prepare
);
5556 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
5557 const engine
= new ESLint({ cwd
: getPath() });
5559 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5562 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
5563 const engine
= new ESLint({ cwd
: getPath() });
5565 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), true);
5568 it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
5569 const engine
= new ESLint({ cwd
: getPath() });
5570 const filePaths
= (await engine
.lintFiles("**/*.js"))
5571 .map(r
=> r
.filePath
)
5574 assert
.deepStrictEqual(filePaths
, [
5575 path
.join(root
, "foo.js")
5580 describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
5581 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5584 ".eslintrc.json": JSON
.stringify({
5585 ignorePatterns
: "foo.js"
5587 "subdir/.eslintrc.json": JSON
.stringify({
5588 ignorePatterns
: "bar.js"
5592 "subdir/foo.js": "",
5593 "subdir/bar.js": "",
5594 "subdir/subsubdir/foo.js": "",
5595 "subdir/subsubdir/bar.js": ""
5600 beforeEach(prepare
);
5603 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5604 const engine
= new ESLint({ cwd
: getPath() });
5606 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5607 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5608 assert
.strictEqual(await engine
.isPathIgnored("subdir/subsubdir/foo.js"), true);
5611 it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", async () => {
5612 const engine
= new ESLint({ cwd
: getPath() });
5614 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5615 assert
.strictEqual(await engine
.isPathIgnored("subdir/subsubdir/bar.js"), true);
5618 it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", async () => {
5619 const engine
= new ESLint({ cwd
: getPath() });
5621 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5624 it("'lintFiles()' should verify 'bar.js' in the outside of 'subdir'.", async () => {
5625 const engine
= new ESLint({ cwd
: getPath() });
5626 const filePaths
= (await engine
.lintFiles("**/*.js"))
5627 .map(r
=> r
.filePath
)
5630 assert
.deepStrictEqual(filePaths
, [
5631 path
.join(root
, "bar.js")
5636 describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
5637 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5640 ".eslintrc.json": JSON
.stringify({
5641 ignorePatterns
: "foo.js"
5643 "subdir/.eslintrc.json": JSON
.stringify({
5644 ignorePatterns
: "!foo.js"
5651 beforeEach(prepare
);
5654 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
5655 const engine
= new ESLint({ cwd
: getPath() });
5657 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5660 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
5661 const engine
= new ESLint({ cwd
: getPath() });
5663 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5666 it("'lintFiles()' should verify 'foo.js' in the child directory.", async () => {
5667 const engine
= new ESLint({ cwd
: getPath() });
5668 const filePaths
= (await engine
.lintFiles("**/*.js"))
5669 .map(r
=> r
.filePath
)
5672 assert
.deepStrictEqual(filePaths
, [
5673 path
.join(root
, "subdir/foo.js")
5678 describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
5679 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5682 ".eslintrc.json": JSON
.stringify({}),
5683 "subdir/.eslintrc.json": JSON
.stringify({
5684 ignorePatterns
: "*.js"
5686 ".eslintignore": "!foo.js",
5688 "subdir/foo.js": "",
5693 beforeEach(prepare
);
5696 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
5697 const engine
= new ESLint({ cwd
: getPath() });
5699 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5700 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5703 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
5704 const engine
= new ESLint({ cwd
: getPath() });
5706 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5709 it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
5710 const engine
= new ESLint({ cwd
: getPath() });
5711 const filePaths
= (await engine
.lintFiles("**/*.js"))
5712 .map(r
=> r
.filePath
)
5715 assert
.deepStrictEqual(filePaths
, [
5716 path
.join(root
, "foo.js"),
5717 path
.join(root
, "subdir/foo.js")
5722 describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
5723 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5726 ".eslintrc.json": JSON
.stringify({
5727 ignorePatterns
: "foo.js"
5729 "subdir/.eslintrc.json": JSON
.stringify({
5731 ignorePatterns
: "bar.js"
5735 "subdir/foo.js": "",
5740 beforeEach(prepare
);
5743 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
5744 const engine
= new ESLint({ cwd
: getPath() });
5746 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5749 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
5750 const engine
= new ESLint({ cwd
: getPath() });
5752 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5755 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
5756 const engine
= new ESLint({ cwd
: getPath() });
5758 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5761 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
5762 const engine
= new ESLint({ cwd
: getPath() });
5764 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5767 it("'lintFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", async () => {
5768 const engine
= new ESLint({ cwd
: getPath() });
5769 const filePaths
= (await engine
.lintFiles("**/*.js"))
5770 .map(r
=> r
.filePath
)
5773 assert
.deepStrictEqual(filePaths
, [
5774 path
.join(root
, "bar.js"),
5775 path
.join(root
, "subdir/foo.js")
5780 describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
5781 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5784 ".eslintrc.json": JSON
.stringify({}),
5785 "subdir/.eslintrc.json": JSON
.stringify({
5787 ignorePatterns
: "bar.js"
5789 ".eslintignore": "foo.js",
5792 "subdir/foo.js": "",
5797 beforeEach(prepare
);
5800 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5801 const engine
= new ESLint({ cwd
: getPath() });
5803 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5804 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5807 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
5808 const engine
= new ESLint({ cwd
: getPath() });
5810 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5813 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
5814 const engine
= new ESLint({ cwd
: getPath() });
5816 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5819 it("'lintFiles()' should verify 'bar.js' in the root directory.", async () => {
5820 const engine
= new ESLint({ cwd
: getPath() });
5821 const filePaths
= (await engine
.lintFiles("**/*.js"))
5822 .map(r
=> r
.filePath
)
5825 assert
.deepStrictEqual(filePaths
, [
5826 path
.join(root
, "bar.js")
5831 describe("ignorePatterns in the shareable config should be used.", () => {
5832 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5835 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5836 ignorePatterns: "foo.js"
5838 ".eslintrc.json": JSON
.stringify({
5846 beforeEach(prepare
);
5849 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5850 const engine
= new ESLint({ cwd
: getPath() });
5852 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5855 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5856 const engine
= new ESLint({ cwd
: getPath() });
5858 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5861 it("'lintFiles()' should verify 'bar.js'.", async () => {
5862 const engine
= new ESLint({ cwd
: getPath() });
5863 const filePaths
= (await engine
.lintFiles("**/*.js"))
5864 .map(r
=> r
.filePath
)
5867 assert
.deepStrictEqual(filePaths
, [
5868 path
.join(root
, "bar.js")
5873 describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
5875 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5878 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5879 ignorePatterns: "/foo.js"
5881 ".eslintrc.json": JSON
.stringify({
5889 beforeEach(prepare
);
5892 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5893 const engine
= new ESLint({ cwd
: getPath() });
5895 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5898 it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", async () => {
5899 const engine
= new ESLint({ cwd
: getPath() });
5901 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5904 it("'lintFiles()' should verify 'subdir/foo.js'.", async () => {
5905 const engine
= new ESLint({ cwd
: getPath() });
5906 const filePaths
= (await engine
.lintFiles("**/*.js"))
5907 .map(r
=> r
.filePath
)
5910 assert
.deepStrictEqual(filePaths
, [
5911 path
.join(root
, "subdir/foo.js")
5916 describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
5917 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5920 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5921 ignorePatterns: "*.js"
5923 ".eslintrc.json": JSON
.stringify({
5925 ignorePatterns
: "!bar.js"
5932 beforeEach(prepare
);
5935 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5936 const engine
= new ESLint({ cwd
: getPath() });
5938 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5941 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5942 const engine
= new ESLint({ cwd
: getPath() });
5944 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5947 it("'lintFiles()' should verify 'bar.js'.", async () => {
5948 const engine
= new ESLint({ cwd
: getPath() });
5949 const filePaths
= (await engine
.lintFiles("**/*.js"))
5950 .map(r
=> r
.filePath
)
5953 assert
.deepStrictEqual(filePaths
, [
5954 path
.join(root
, "bar.js")
5959 describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
5961 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5964 ".eslintrc.json": JSON
.stringify({
5965 ignorePatterns
: "*.js"
5971 beforeEach(prepare
);
5974 it("'isPathIgnored()' should return 'false' for 'foo.js'.", async () => {
5975 const engine
= new ESLint({ cwd
: getPath(), ignore
: false });
5977 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5980 it("'lintFiles()' should verify 'foo.js'.", async () => {
5981 const engine
= new ESLint({ cwd
: getPath(), ignore
: false });
5982 const filePaths
= (await engine
.lintFiles("**/*.js"))
5983 .map(r
=> r
.filePath
)
5986 assert
.deepStrictEqual(filePaths
, [
5987 path
.join(root
, "foo.js")
5992 describe("ignorePatterns in overrides section is not allowed.", () => {
5994 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5997 ".eslintrc.js": `module.exports = ${JSON.stringify({
6001 ignorePatterns: "foo.js"
6009 beforeEach(prepare
);
6012 it("should throw a configuration error.", async () => {
6013 await assert
.rejects(async () => {
6014 const engine
= new ESLint({ cwd
: getPath() });
6016 await engine
.lintFiles("*.js");
6017 }, /Unexpected top-level property "overrides\[0\]\.ignorePatterns"/u);
6022 describe("'overrides[].files' adds lint targets", () => {
6023 const root
= getFixturePath("cli-engine/additional-lint-targets");
6026 describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
6027 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6030 ".eslintrc.json": JSON
.stringify({
6034 excludedFiles
: "**/ignore.txt"
6038 "foo/nested/test.txt": "",
6041 "foo/ignore.txt": "",
6044 "bar/ignore.txt": "",
6051 beforeEach(prepare
);
6054 it("'lintFiles()' with a directory path should contain 'foo/test.txt'.", async () => {
6055 const engine
= new ESLint({ cwd
: getPath() });
6056 const filePaths
= (await engine
.lintFiles("."))
6057 .map(r
=> r
.filePath
)
6060 assert
.deepStrictEqual(filePaths
, [
6061 path
.join(root
, "bar/test.js"),
6062 path
.join(root
, "foo/test.js"),
6063 path
.join(root
, "foo/test.txt"),
6064 path
.join(root
, "test.js")
6068 it("'lintFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", async () => {
6069 const engine
= new ESLint({ cwd
: getPath() });
6070 const filePaths
= (await engine
.lintFiles("**/*.js"))
6071 .map(r
=> r
.filePath
)
6074 assert
.deepStrictEqual(filePaths
, [
6075 path
.join(root
, "bar/test.js"),
6076 path
.join(root
, "foo/test.js"),
6077 path
.join(root
, "test.js")
6082 describe("if { files: 'foo/**/*.txt' } is present,", () => {
6084 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6087 ".eslintrc.json": JSON
.stringify({
6090 files
: "foo/**/*.txt"
6094 "foo/nested/test.txt": "",
6104 beforeEach(prepare
);
6107 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
6108 const engine
= new ESLint({ cwd
: getPath() });
6109 const filePaths
= (await engine
.lintFiles("."))
6110 .map(r
=> r
.filePath
)
6113 assert
.deepStrictEqual(filePaths
, [
6114 path
.join(root
, "bar/test.js"),
6115 path
.join(root
, "foo/nested/test.txt"),
6116 path
.join(root
, "foo/test.js"),
6117 path
.join(root
, "foo/test.txt"),
6118 path
.join(root
, "test.js")
6123 describe("if { files: 'foo/**/*' } is present,", () => {
6125 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6128 ".eslintrc.json": JSON
.stringify({
6135 "foo/nested/test.txt": "",
6145 beforeEach(prepare
);
6148 it("'lintFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
6149 const engine
= new ESLint({ cwd
: getPath() });
6150 const filePaths
= (await engine
.lintFiles("."))
6151 .map(r
=> r
.filePath
)
6154 assert
.deepStrictEqual(filePaths
, [
6155 path
.join(root
, "bar/test.js"),
6156 path
.join(root
, "foo/test.js"),
6157 path
.join(root
, "test.js")
6162 describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
6164 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6167 "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
6170 files: "foo/**/*.txt"
6174 ".eslintrc.json": JSON
.stringify({
6177 "foo/nested/test.txt": "",
6187 beforeEach(prepare
);
6190 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
6191 const engine
= new ESLint({ cwd
: getPath() });
6192 const filePaths
= (await engine
.lintFiles("."))
6193 .map(r
=> r
.filePath
)
6196 assert
.deepStrictEqual(filePaths
, [
6197 path
.join(root
, "bar/test.js"),
6198 path
.join(root
, "foo/nested/test.txt"),
6199 path
.join(root
, "foo/test.js"),
6200 path
.join(root
, "foo/test.txt"),
6201 path
.join(root
, "test.js")
6206 describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
6208 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6211 "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
6215 files: "foo/**/*.txt"
6220 ".eslintrc.json": JSON
.stringify({
6221 extends: "plugin:foo/bar"
6223 "foo/nested/test.txt": "",
6233 beforeEach(prepare
);
6236 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
6237 const engine
= new ESLint({ cwd
: getPath() });
6238 const filePaths
= (await engine
.lintFiles("."))
6239 .map(r
=> r
.filePath
)
6242 assert
.deepStrictEqual(filePaths
, [
6243 path
.join(root
, "bar/test.js"),
6244 path
.join(root
, "foo/nested/test.txt"),
6245 path
.join(root
, "foo/test.js"),
6246 path
.join(root
, "foo/test.txt"),
6247 path
.join(root
, "test.js")
6253 describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
6254 const root
= getFixturePath("cli-engine/config-and-overrides-files");
6256 describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6257 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6260 "node_modules/myconf/.eslintrc.json": {
6270 "node_modules/myconf/foo/test.js": "a == b",
6271 "foo/test.js": "a == b"
6275 beforeEach(prepare
);
6278 it("'lintFiles()' with 'foo/test.js' should use the override entry.", async () => {
6279 const engine
= new ESLint({
6280 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6285 const results
= await engine
.lintFiles("foo/test.js");
6287 // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
6288 assert
.deepStrictEqual(results
, [
6291 filePath
: path
.join(getPath(), "foo/test.js"),
6292 fixableErrorCount
: 0,
6293 fixableWarningCount
: 0,
6300 message
: "Expected '===' and instead saw '=='.",
6301 messageId
: "unexpected",
6302 nodeType
: "BinaryExpression",
6307 suppressedMessages
: [],
6309 usedDeprecatedRules
: [],
6316 it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", async () => {
6317 const engine
= new ESLint({
6318 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6323 const results
= await engine
.lintFiles("node_modules/myconf/foo/test.js");
6325 // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
6326 assert
.deepStrictEqual(results
, [
6329 filePath
: path
.join(getPath(), "node_modules/myconf/foo/test.js"),
6330 fixableErrorCount
: 0,
6331 fixableWarningCount
: 0,
6333 suppressedMessages
: [],
6334 usedDeprecatedRules
: [],
6342 describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6343 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6346 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6350 excludedFiles
: "foo/*.js",
6357 "node_modules/myconf/foo/test.js": "a == b",
6358 "foo/test.js": "a == b"
6362 beforeEach(prepare
);
6365 it("'lintFiles()' with 'foo/test.js' should NOT use the override entry.", async () => {
6366 const engine
= new ESLint({
6367 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6372 const results
= await engine
.lintFiles("foo/test.js");
6374 // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
6375 assert
.deepStrictEqual(results
, [
6378 filePath
: path
.join(getPath(), "foo/test.js"),
6379 fixableErrorCount
: 0,
6380 fixableWarningCount
: 0,
6382 suppressedMessages
: [],
6383 usedDeprecatedRules
: [],
6390 it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", async () => {
6391 const engine
= new ESLint({
6392 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6397 const results
= await engine
.lintFiles("node_modules/myconf/foo/test.js");
6399 // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
6400 assert
.deepStrictEqual(results
, [
6403 filePath
: path
.join(getPath(), "node_modules/myconf/foo/test.js"),
6404 fixableErrorCount
: 0,
6405 fixableWarningCount
: 0,
6412 message
: "Expected '===' and instead saw '=='.",
6413 messageId
: "unexpected",
6414 nodeType
: "BinaryExpression",
6419 suppressedMessages
: [],
6421 usedDeprecatedRules
: [],
6429 describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6430 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6433 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6434 ignorePatterns
: ["!/node_modules/myconf", "foo/*.js"],
6439 "node_modules/myconf/foo/test.js": "a == b",
6440 "foo/test.js": "a == b"
6444 beforeEach(prepare
);
6447 it("'lintFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", async () => {
6448 const engine
= new ESLint({
6449 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6453 const files
= (await engine
.lintFiles("**/*.js"))
6454 .map(r
=> r
.filePath
)
6457 assert
.deepStrictEqual(files
, [
6458 path
.join(root
, "node_modules/myconf/foo/test.js")
6464 describe("plugin conflicts", () => {
6466 const root
= getFixturePath("cli-engine/plugin-conflicts-");
6469 * Verify thrown errors.
6470 * @param {() => Promise<any>} f The function to run and throw.
6471 * @param {Record<string, any>} props The properties to verify.
6472 * @returns {Promise<void>} void
6474 async
function assertThrows(f
, props
) {
6478 for (const [key
, value
] of Object
.entries(props
)) {
6479 assert
.deepStrictEqual(error
[key
], value
, key
);
6484 assert
.fail("Function should throw an error, but not.");
6487 describe("between a config file and linear extendees.", () => {
6489 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6490 cwd
: `${root}${++uid}`,
6492 "node_modules/eslint-plugin-foo/index.js": "",
6493 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6494 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6498 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6499 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6502 ".eslintrc.json": JSON
.stringify({
6510 beforeEach(prepare
);
6513 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
6514 const engine
= new ESLint({ cwd
: getPath() });
6516 await engine
.lintFiles("test.js");
6520 describe("between a config file and same-depth extendees.", () => {
6522 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6523 cwd
: `${root}${++uid}`,
6525 "node_modules/eslint-plugin-foo/index.js": "",
6526 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6527 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6530 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6531 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6534 ".eslintrc.json": JSON
.stringify({
6535 extends: ["one", "two"],
6542 beforeEach(prepare
);
6545 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
6546 const engine
= new ESLint({ cwd
: getPath() });
6548 await engine
.lintFiles("test.js");
6552 describe("between two config files in different directories, with single node_modules.", () => {
6554 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6555 cwd
: `${root}${++uid}`,
6557 "node_modules/eslint-plugin-foo/index.js": "",
6558 ".eslintrc.json": JSON
.stringify({
6561 "subdir/.eslintrc.json": JSON
.stringify({
6564 "subdir/test.js": ""
6568 beforeEach(prepare
);
6571 it("'lintFiles()' 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.)", async () => {
6572 const engine
= new ESLint({ cwd
: getPath() });
6574 await engine
.lintFiles("subdir/test.js");
6578 describe("between two config files in different directories, with multiple node_modules.", () => {
6580 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6581 cwd
: `${root}${++uid}`,
6583 "node_modules/eslint-plugin-foo/index.js": "",
6584 ".eslintrc.json": JSON
.stringify({
6587 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6588 "subdir/.eslintrc.json": JSON
.stringify({
6591 "subdir/test.js": ""
6595 beforeEach(prepare
);
6598 it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files.)", async () => {
6599 const engine
= new ESLint({ cwd
: getPath() });
6602 () => engine
.lintFiles("subdir/test.js"),
6604 message
: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
6605 messageTemplate
: "plugin-conflict",
6610 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6611 importerName
: `subdir${path.sep}.eslintrc.json`
6614 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6615 importerName
: ".eslintrc.json"
6624 describe("between '--config' option and a regular config file, with single node_modules.", () => {
6626 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6627 cwd
: `${root}${++uid}`,
6629 "node_modules/eslint-plugin-foo/index.js": "",
6630 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6633 ".eslintrc.json": JSON
.stringify({
6640 beforeEach(prepare
);
6643 it("'lintFiles()' 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.)", async () => {
6644 const engine
= new ESLint({
6646 overrideConfigFile
: "node_modules/mine/.eslintrc.json"
6649 await engine
.lintFiles("test.js");
6653 describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
6655 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6656 cwd
: `${root}${++uid}`,
6658 "node_modules/eslint-plugin-foo/index.js": "",
6659 "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
6660 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6663 ".eslintrc.json": JSON
.stringify({
6670 beforeEach(prepare
);
6673 it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files.)", async () => {
6674 const engine
= new ESLint({
6676 overrideConfigFile
: "node_modules/mine/.eslintrc.json"
6680 () => engine
.lintFiles("test.js"),
6682 message
: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
6683 messageTemplate
: "plugin-conflict",
6688 filePath
: path
.join(getPath(), "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
6689 importerName
: "--config"
6692 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6693 importerName
: ".eslintrc.json"
6702 describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
6704 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6705 cwd
: `${root}${++uid}`,
6707 "node_modules/eslint-plugin-foo/index.js": "",
6708 "subdir/.eslintrc.json": JSON
.stringify({
6711 "subdir/test.js": ""
6716 beforeEach(prepare
);
6719 it("'lintFiles()' 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.)", async () => {
6720 const engine
= new ESLint({
6722 overrideConfig
: { plugins
: ["foo"] }
6725 await engine
.lintFiles("subdir/test.js");
6729 describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
6731 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6732 cwd
: `${root}${++uid}`,
6734 "node_modules/eslint-plugin-foo/index.js": "",
6735 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6736 "subdir/.eslintrc.json": JSON
.stringify({
6739 "subdir/test.js": ""
6743 beforeEach(prepare
);
6746 it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", async () => {
6747 const engine
= new ESLint({
6749 overrideConfig
: { plugins
: ["foo"] }
6753 () => engine
.lintFiles("subdir/test.js"),
6755 message
: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
6756 messageTemplate
: "plugin-conflict",
6761 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6762 importerName
: "CLIOptions"
6765 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6766 importerName
: `subdir${path.sep}.eslintrc.json`
6775 describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
6777 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6778 cwd
: `${root}${++uid}`,
6780 "node_modules/eslint-plugin-foo/index.js": "",
6781 ".eslintrc.json": JSON
.stringify({
6784 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6785 "subdir/.eslintrc.json": JSON
.stringify({
6788 "subdir/test.js": ""
6792 beforeEach(prepare
);
6795 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", async () => {
6796 const engine
= new ESLint({
6798 resolvePluginsRelativeTo
: getPath()
6801 await engine
.lintFiles("subdir/test.js");
6805 describe("between two config files with different target files.", () => {
6807 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6808 cwd
: `${root}${++uid}`,
6810 "one/node_modules/eslint-plugin-foo/index.js": "",
6811 "one/.eslintrc.json": JSON
.stringify({
6815 "two/node_modules/eslint-plugin-foo/index.js": "",
6816 "two/.eslintrc.json": JSON
.stringify({
6823 beforeEach(prepare
);
6826 it("'lintFiles()' 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.)", async () => {
6827 const engine
= new ESLint({ cwd
: getPath() });
6828 const results
= await engine
.lintFiles("*/test.js");
6830 assert
.strictEqual(results
.length
, 2);
6835 describe("loading rules", () => {
6836 it("should not load unused core rules", done
=> {
6837 let calledDone
= false;
6839 const cwd
= getFixturePath("lazy-loading-rules");
6840 const pattern
= "foo.js";
6841 const usedRules
= ["semi"];
6843 const forkedProcess
= childProcess
.fork(
6844 path
.join(__dirname
, "../../_utils/test-lazy-loading-rules.js"),
6845 [cwd
, pattern
, String(usedRules
)]
6848 // this is an error message
6849 forkedProcess
.on("message", ({ message
, stack
}) => {
6855 const error
= new Error(message
);
6857 error
.stack
= stack
;
6861 forkedProcess
.on("exit", exitCode
=> {
6867 if (exitCode
=== 0) {
6870 done(new Error("Forked process exited with a non-zero exit code"));