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");
31 //------------------------------------------------------------------------------
33 //------------------------------------------------------------------------------
35 describe("ESLint", () => {
36 const examplePluginName
= "eslint-plugin-example";
37 const examplePluginNameWithNamespace
= "@eslint/eslint-plugin-example";
38 const examplePlugin
= {
40 "example-rule": require("../../fixtures/rules/custom-rule"),
41 "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
44 const examplePreprocessorName
= "eslint-plugin-processor";
45 const originalDir
= process
.cwd();
46 const fixtureDir
= path
.resolve(fs
.realpathSync(os
.tmpdir()), "eslint/fixtures");
48 /** @type {import("../../../lib/eslint").ESLint} */
52 * Returns the path inside of the fixture directory.
53 * @param {...string} args file path segments.
54 * @returns {string} The path inside the fixture directory.
57 function getFixturePath(...args
) {
58 const filepath
= path
.join(fixtureDir
, ...args
);
61 return fs
.realpathSync(filepath
);
68 * Create the ESLint object by mocking some of the plugins
69 * @param {Object} options options for ESLint
70 * @returns {ESLint} engine object
73 function eslintWithPlugins(options
) {
77 [examplePluginName
]: examplePlugin
,
78 [examplePluginNameWithNamespace
]: examplePlugin
,
79 [examplePreprocessorName
]: require("../../fixtures/processors/custom-processor")
85 * Call the last argument.
86 * @param {any[]} args Arguments
89 function callLastArgument(...args
) {
90 process
.nextTick(args
[args
.length
- 1], null);
93 // copy into clean area so as not to get "infected" by this project's .eslintrc files
97 * GitHub Actions Windows and macOS runners occasionally exhibit
98 * extremely slow filesystem operations, during which copying fixtures
99 * exceeds the default test timeout, so raise it just for this hook.
100 * Mocha uses `this` to set timeouts on an individual hook level.
102 this.timeout(60 * 1000); // eslint-disable-line no-invalid-this -- Mocha API
103 shell
.mkdir("-p", fixtureDir
);
104 shell
.cp("-r", "./tests/fixtures/.", fixtureDir
);
108 ({ ESLint
} = require("../../../lib/eslint/eslint"));
112 shell
.rm("-r", fixtureDir
);
115 describe("ESLint constructor function", () => {
116 it("the default value of 'options.cwd' should be the current working directory.", async () => {
117 process
.chdir(__dirname
);
119 const engine
= new ESLint();
120 const results
= await engine
.lintFiles("eslint.js");
122 assert
.strictEqual(path
.dirname(results
[0].filePath
), __dirname
);
124 process
.chdir(originalDir
);
128 it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
129 assert
.throws(() => {
130 // eslint-disable-next-line no-new -- Check for throwing
131 new ESLint({ ignorePath
: fixtureDir
});
132 }, new RegExp(escapeStringRegExp(`Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`), "u"));
135 // https://github.com/eslint/eslint/issues/2380
136 it("should not modify baseConfig when format is specified", () => {
137 const customBaseConfig
= { root
: true };
139 new ESLint({ baseConfig
: customBaseConfig
}); // eslint-disable-line no-new -- Check for argument side effects
141 assert
.deepStrictEqual(customBaseConfig
, { root
: true });
144 it("should throw readable messages if removed options are present", () => {
157 new RegExp(escapeStringRegExp([
159 "- Unknown options: cacheFile, configFile, envs, globals, ignorePattern, parser, parserOptions, rules",
160 "- 'cacheFile' has been removed. Please use the 'cacheLocation' option instead.",
161 "- 'configFile' has been removed. Please use the 'overrideConfigFile' option instead.",
162 "- 'envs' has been removed. Please use the 'overrideConfig.env' option instead.",
163 "- 'globals' has been removed. Please use the 'overrideConfig.globals' option instead.",
164 "- 'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.",
165 "- 'parser' has been removed. Please use the 'overrideConfig.parser' option instead.",
166 "- 'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead.",
167 "- 'rules' has been removed. Please use the 'overrideConfig.rules' option instead.",
168 "- 'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead."
173 it("should throw readable messages if wrong type values are given to options", () => {
176 allowInlineConfig
: "",
181 errorOnUnmatchedPattern
: "",
189 overrideConfigFile
: "",
191 reportUnusedDisableDirectives
: "",
192 resolvePluginsRelativeTo
: "",
196 new RegExp(escapeStringRegExp([
198 "- 'allowInlineConfig' must be a boolean.",
199 "- 'baseConfig' must be an object or null.",
200 "- 'cache' must be a boolean.",
201 "- 'cacheLocation' must be a non-empty string.",
202 "- 'cwd' must be an absolute path.",
203 "- 'errorOnUnmatchedPattern' must be a boolean.",
204 "- 'extensions' must be an array of non-empty strings or null.",
205 "- 'fix' must be a boolean or a function.",
206 "- 'fixTypes' must be an array of any of \"directive\", \"problem\", \"suggestion\", and \"layout\".",
207 "- 'globInputPaths' must be a boolean.",
208 "- 'ignore' must be a boolean.",
209 "- 'ignorePath' must be a non-empty string or null.",
210 "- 'overrideConfig' must be an object or null.",
211 "- 'overrideConfigFile' must be a non-empty string or null.",
212 "- 'plugins' must be an object or null.",
213 "- 'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.",
214 "- 'resolvePluginsRelativeTo' must be a non-empty string or null.",
215 "- 'rulePaths' must be an array of non-empty strings.",
216 "- 'useEslintrc' must be a boolean."
221 it("should throw readable messages if 'plugins' option contains empty key", () => {
225 "eslint-plugin-foo": {},
226 "eslint-plugin-bar": {},
230 new RegExp(escapeStringRegExp([
232 "- 'plugins' must not include an empty string."
238 describe("lintText()", () => {
241 it("should report the total and per file errors when using local cwd .eslintrc", async () => {
242 eslint
= new ESLint();
243 const results
= await eslint
.lintText("var foo = 'bar';");
245 assert
.strictEqual(results
.length
, 1);
246 assert
.strictEqual(results
[0].messages
.length
, 5);
247 assert
.strictEqual(results
[0].messages
[0].ruleId
, "strict");
248 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-var");
249 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-unused-vars");
250 assert
.strictEqual(results
[0].messages
[3].ruleId
, "quotes");
251 assert
.strictEqual(results
[0].messages
[4].ruleId
, "eol-last");
252 assert
.strictEqual(results
[0].fixableErrorCount
, 3);
253 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
254 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
257 it("should report the total and per file warnings when using local cwd .eslintrc", async () => {
258 eslint
= new ESLint({
269 const results
= await eslint
.lintText("var foo = 'bar';");
271 assert
.strictEqual(results
.length
, 1);
272 assert
.strictEqual(results
[0].messages
.length
, 5);
273 assert
.strictEqual(results
[0].messages
[0].ruleId
, "strict");
274 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-var");
275 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-unused-vars");
276 assert
.strictEqual(results
[0].messages
[3].ruleId
, "quotes");
277 assert
.strictEqual(results
[0].messages
[4].ruleId
, "eol-last");
278 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
279 assert
.strictEqual(results
[0].fixableWarningCount
, 3);
280 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
283 it("should report one message when using specific config file", async () => {
284 eslint
= new ESLint({
285 overrideConfigFile
: "fixtures/configurations/quotes-error.json",
287 cwd
: getFixturePath("..")
289 const results
= await eslint
.lintText("var foo = 'bar';");
291 assert
.strictEqual(results
.length
, 1);
292 assert
.strictEqual(results
[0].messages
.length
, 1);
293 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
294 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
295 assert
.strictEqual(results
[0].errorCount
, 1);
296 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
297 assert
.strictEqual(results
[0].warningCount
, 0);
298 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
301 it("should report the filename when passed in", async () => {
302 eslint
= new ESLint({
304 cwd
: getFixturePath()
306 const options
= { filePath
: "test.js" };
307 const results
= await eslint
.lintText("var foo = 'bar';", options
);
309 assert
.strictEqual(results
[0].filePath
, getFixturePath("test.js"));
312 it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", async () => {
313 eslint
= new ESLint({
314 ignorePath
: getFixturePath(".eslintignore"),
315 cwd
: getFixturePath("..")
317 const options
= { filePath
: "fixtures/passing.js", warnIgnored
: true };
318 const results
= await eslint
.lintText("var bar = foo;", options
);
320 assert
.strictEqual(results
.length
, 1);
321 assert
.strictEqual(results
[0].filePath
, getFixturePath("passing.js"));
322 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
323 assert
.strictEqual(results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
324 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
325 assert
.strictEqual(results
[0].errorCount
, 0);
326 assert
.strictEqual(results
[0].warningCount
, 1);
327 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
328 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
329 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
332 it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", async () => {
333 eslint
= new ESLint({
334 ignorePath
: getFixturePath(".eslintignore"),
335 cwd
: getFixturePath("..")
338 filePath
: "fixtures/passing.js",
342 // intentional parsing error
343 const results
= await eslint
.lintText("va r bar = foo;", options
);
345 // should not report anything because the file is ignored
346 assert
.strictEqual(results
.length
, 0);
349 it("should suppress excluded file warnings by default", async () => {
350 eslint
= new ESLint({
351 ignorePath
: getFixturePath(".eslintignore"),
352 cwd
: getFixturePath("..")
354 const options
= { filePath
: "fixtures/passing.js" };
355 const results
= await eslint
.lintText("var bar = foo;", options
);
357 // should not report anything because there are no errors
358 assert
.strictEqual(results
.length
, 0);
361 it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", async () => {
362 eslint
= new ESLint({
363 ignorePath
: "fixtures/.eslintignore",
364 cwd
: getFixturePath(".."),
373 const options
= { filePath
: "fixtures/passing.js" };
374 const results
= await eslint
.lintText("var bar = foo;", options
);
376 assert
.strictEqual(results
.length
, 1);
377 assert
.strictEqual(results
[0].filePath
, getFixturePath("passing.js"));
378 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
379 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
380 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
383 it("should return a message and fixed text when in fix mode", async () => {
384 eslint
= new ESLint({
393 cwd
: getFixturePath()
395 const options
= { filePath
: "passing.js" };
396 const results
= await eslint
.lintText("var bar = foo", options
);
398 assert
.deepStrictEqual(results
, [
400 filePath
: getFixturePath("passing.js"),
405 fixableErrorCount
: 0,
406 fixableWarningCount
: 0,
407 output
: "var bar = foo;",
408 usedDeprecatedRules
: []
413 it("correctly autofixes semicolon-conflicting-fixes", async () => {
414 eslint
= new ESLint({
415 cwd
: path
.join(fixtureDir
, ".."),
419 const inputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.js");
420 const outputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
421 const results
= await eslint
.lintFiles([inputPath
]);
422 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
424 assert
.strictEqual(results
[0].output
, expectedOutput
);
427 it("correctly autofixes return-conflicting-fixes", async () => {
428 eslint
= new ESLint({
429 cwd
: path
.join(fixtureDir
, ".."),
433 const inputPath
= getFixturePath("autofix/return-conflicting-fixes.js");
434 const outputPath
= getFixturePath("autofix/return-conflicting-fixes.expected.js");
435 const results
= await eslint
.lintFiles([inputPath
]);
436 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
438 assert
.strictEqual(results
[0].output
, expectedOutput
);
441 describe("Fix Types", () => {
442 it("should throw an error when an invalid fix type is specified", () => {
443 assert
.throws(() => {
444 eslint
= new ESLint({
445 cwd
: path
.join(fixtureDir
, ".."),
450 }, /'fixTypes' must be an array of any of "directive", "problem", "suggestion", and "layout"\./iu);
453 it("should not fix any rules when fixTypes is used without fix", async () => {
454 eslint
= new ESLint({
455 cwd
: path
.join(fixtureDir
, ".."),
460 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
461 const results
= await eslint
.lintFiles([inputPath
]);
463 assert
.strictEqual(results
[0].output
, void 0);
466 it("should not fix non-style rules when fixTypes has only 'layout'", async () => {
467 eslint
= new ESLint({
468 cwd
: path
.join(fixtureDir
, ".."),
473 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
474 const outputPath
= getFixturePath("fix-types/fix-only-semi.expected.js");
475 const results
= await eslint
.lintFiles([inputPath
]);
476 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
478 assert
.strictEqual(results
[0].output
, expectedOutput
);
481 it("should not fix style or problem rules when fixTypes has only 'suggestion'", async () => {
482 eslint
= new ESLint({
483 cwd
: path
.join(fixtureDir
, ".."),
486 fixTypes
: ["suggestion"]
488 const inputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
489 const outputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
490 const results
= await eslint
.lintFiles([inputPath
]);
491 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
493 assert
.strictEqual(results
[0].output
, expectedOutput
);
496 it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", async () => {
497 eslint
= new ESLint({
498 cwd
: path
.join(fixtureDir
, ".."),
501 fixTypes
: ["suggestion", "layout"]
503 const inputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
504 const outputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
505 const results
= await eslint
.lintFiles([inputPath
]);
506 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
508 assert
.strictEqual(results
[0].output
, expectedOutput
);
511 it("should not throw an error when a rule doesn't have a 'meta' property", async () => {
512 eslint
= new ESLint({
513 cwd
: path
.join(fixtureDir
, ".."),
516 fixTypes
: ["layout"],
517 rulePaths
: [getFixturePath("rules", "fix-types-test")]
519 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
520 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
521 const results
= await eslint
.lintFiles([inputPath
]);
522 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
524 assert
.strictEqual(results
[0].output
, expectedOutput
);
527 it("should not throw an error when a rule is loaded after initialization with lintFiles()", async () => {
528 eslint
= new ESLint({
529 cwd
: path
.join(fixtureDir
, ".."),
532 fixTypes
: ["layout"],
536 "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
541 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
542 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
543 const results
= await eslint
.lintFiles([inputPath
]);
544 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
546 assert
.strictEqual(results
[0].output
, expectedOutput
);
549 it("should not throw an error when a rule is loaded after initialization with lintText()", async () => {
550 eslint
= new ESLint({
551 cwd
: path
.join(fixtureDir
, ".."),
554 fixTypes
: ["layout"],
558 "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
563 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
564 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
565 const results
= await eslint
.lintText(fs
.readFileSync(inputPath
, { encoding
: "utf8" }), { filePath
: inputPath
});
566 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
568 assert
.strictEqual(results
[0].output
, expectedOutput
);
572 it("should return a message and omit fixed text when in fix mode and fixes aren't done", async () => {
573 eslint
= new ESLint({
582 cwd
: getFixturePath()
584 const options
= { filePath
: "passing.js" };
585 const results
= await eslint
.lintText("var bar = foo", options
);
587 assert
.deepStrictEqual(results
, [
589 filePath
: getFixturePath("passing.js"),
595 message
: "'foo' is not defined.",
600 nodeType
: "Identifier"
606 fixableErrorCount
: 0,
607 fixableWarningCount
: 0,
608 source
: "var bar = foo",
609 usedDeprecatedRules
: []
614 it("should not delete code if there is a syntax error after trying to autofix.", async () => {
615 eslint
= eslintWithPlugins({
619 plugins
: ["example"],
621 "example/make-syntax-error": "error"
625 cwd
: getFixturePath()
627 const options
= { filePath
: "test.js" };
628 const results
= await eslint
.lintText("var bar = foo", options
);
630 assert
.deepStrictEqual(results
, [
632 filePath
: getFixturePath("test.js"),
638 message
: "Parsing error: Unexpected token is",
646 fixableErrorCount
: 0,
647 fixableWarningCount
: 0,
648 output
: "var bar = foothis is a syntax error.",
649 usedDeprecatedRules
: []
654 it("should not crash even if there are any syntax error since the first time.", async () => {
655 eslint
= new ESLint({
660 "example/make-syntax-error": "error"
664 cwd
: getFixturePath()
666 const options
= { filePath
: "test.js" };
667 const results
= await eslint
.lintText("var bar =", options
);
669 assert
.deepStrictEqual(results
, [
671 filePath
: getFixturePath("test.js"),
677 message
: "Parsing error: Unexpected token",
685 fixableErrorCount
: 0,
686 fixableWarningCount
: 0,
688 usedDeprecatedRules
: []
693 it("should return source code of file in `source` property when errors are present", async () => {
694 eslint
= new ESLint({
700 const results
= await eslint
.lintText("var foo = 'bar'");
702 assert
.strictEqual(results
[0].source
, "var foo = 'bar'");
705 it("should return source code of file in `source` property when warnings are present", async () => {
706 eslint
= new ESLint({
712 const results
= await eslint
.lintText("var foo = 'bar'");
714 assert
.strictEqual(results
[0].source
, "var foo = 'bar'");
718 it("should not return a `source` property when no errors or warnings are present", async () => {
719 eslint
= new ESLint({
725 const results
= await eslint
.lintText("var foo = 'bar';");
727 assert
.strictEqual(results
[0].messages
.length
, 0);
728 assert
.strictEqual(results
[0].source
, void 0);
731 it("should not return a `source` property when fixes are applied", async () => {
732 eslint
= new ESLint({
742 const results
= await eslint
.lintText("var msg = 'hi' + foo\n");
744 assert
.strictEqual(results
[0].source
, void 0);
745 assert
.strictEqual(results
[0].output
, "var msg = 'hi' + foo;\n");
748 it("should return a `source` property when a parsing error has occurred", async () => {
749 eslint
= new ESLint({
755 const results
= await eslint
.lintText("var bar = foothis is a syntax error.\n return bar;");
757 assert
.deepStrictEqual(results
, [
765 message
: "Parsing error: Unexpected token is",
773 fixableErrorCount
: 0,
774 fixableWarningCount
: 0,
775 source
: "var bar = foothis is a syntax error.\n return bar;",
776 usedDeprecatedRules
: []
781 // https://github.com/eslint/eslint/issues/5547
782 it("should respect default ignore rules, even with --no-ignore", async () => {
783 eslint
= new ESLint({
784 cwd
: getFixturePath(),
787 const results
= await eslint
.lintText("var bar = foo;", { filePath
: "node_modules/passing.js", warnIgnored
: true });
788 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
790 assert
.strictEqual(results
.length
, 1);
791 assert
.strictEqual(results
[0].filePath
, getFixturePath("node_modules/passing.js"));
792 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
795 describe('plugin shorthand notation ("@scope" for "@scope/eslint-plugin")', () => {
796 const Module
= require("module");
797 let originalFindPath
= null;
799 /* eslint-disable no-underscore-dangle -- Override Node API */
801 originalFindPath
= Module
._findPath
;
802 Module
._findPath = function(id
, ...otherArgs
) {
803 if (id
=== "@scope/eslint-plugin") {
804 return path
.resolve(__dirname
, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
806 return originalFindPath
.call(this, id
, ...otherArgs
);
810 Module
._findPath
= originalFindPath
;
812 /* eslint-enable no-underscore-dangle -- Override Node API */
814 it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
815 eslint
= new ESLint({ cwd
: getFixturePath("plugin-shorthand/basic") });
816 const [result
] = await eslint
.lintText("var x = 0", { filePath
: "index.js" });
818 assert
.strictEqual(result
.filePath
, getFixturePath("plugin-shorthand/basic/index.js"));
819 assert
.strictEqual(result
.messages
[0].ruleId
, "@scope/rule");
820 assert
.strictEqual(result
.messages
[0].message
, "OK");
823 it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
824 eslint
= new ESLint({ cwd
: getFixturePath("plugin-shorthand/extends") });
825 const [result
] = await eslint
.lintText("var x = 0", { filePath
: "index.js" });
827 assert
.strictEqual(result
.filePath
, getFixturePath("plugin-shorthand/extends/index.js"));
828 assert
.strictEqual(result
.messages
[0].ruleId
, "@scope/rule");
829 assert
.strictEqual(result
.messages
[0].message
, "OK");
833 it("should warn when deprecated rules are found in a config", async () => {
834 eslint
= new ESLint({
837 overrideConfigFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
839 const [result
] = await eslint
.lintText("foo");
841 assert
.deepStrictEqual(
842 result
.usedDeprecatedRules
,
843 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
847 it("should throw if non-string value is given to 'code' parameter", async () => {
848 eslint
= new ESLint();
849 await assert
.rejects(() => eslint
.lintText(100), /'code' must be a string/u);
852 it("should throw if non-object value is given to 'options' parameter", async () => {
853 eslint
= new ESLint();
854 await assert
.rejects(() => eslint
.lintText("var a = 0", "foo.js"), /'options' must be an object, null, or undefined/u);
857 it("should throw if 'options' argument contains unknown key", async () => {
858 eslint
= new ESLint();
859 await assert
.rejects(() => eslint
.lintText("var a = 0", { filename
: "foo.js" }), /'options' must not include the unknown option\(s\): filename/u);
862 it("should throw if non-string value is given to 'options.filePath' option", async () => {
863 eslint
= new ESLint();
864 await assert
.rejects(() => eslint
.lintText("var a = 0", { filePath
: "" }), /'options.filePath' must be a non-empty string or undefined/u);
867 it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
868 eslint
= new ESLint();
869 await assert
.rejects(() => eslint
.lintText("var a = 0", { warnIgnored
: "" }), /'options.warnIgnored' must be a boolean or undefined/u);
873 describe("lintFiles()", () => {
875 /** @type {InstanceType<import("../../../lib/eslint").ESLint>} */
878 it("should use correct parser when custom parser is specified", async () => {
879 eslint
= new ESLint({
883 const filePath
= path
.resolve(__dirname
, "../../fixtures/configurations/parser/custom.js");
884 const results
= await eslint
.lintFiles([filePath
]);
886 assert
.strictEqual(results
.length
, 1);
887 assert
.strictEqual(results
[0].messages
.length
, 1);
888 assert
.strictEqual(results
[0].messages
[0].message
, "Parsing error: Boom!");
891 it("should report zero messages when given a config file and a valid file", async () => {
892 eslint
= new ESLint({
894 overrideConfigFile
: ".eslintrc.js"
896 const results
= await eslint
.lintFiles(["lib/**/cli*.js"]);
898 assert
.strictEqual(results
.length
, 2);
899 assert
.strictEqual(results
[0].messages
.length
, 0);
900 assert
.strictEqual(results
[1].messages
.length
, 0);
903 it("should handle multiple patterns with overlapping files", async () => {
904 eslint
= new ESLint({
906 overrideConfigFile
: ".eslintrc.js"
908 const results
= await eslint
.lintFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
910 assert
.strictEqual(results
.length
, 2);
911 assert
.strictEqual(results
[0].messages
.length
, 0);
912 assert
.strictEqual(results
[1].messages
.length
, 0);
915 it("should report zero messages when given a config file and a valid file and espree as parser", async () => {
916 eslint
= new ESLint({
925 const results
= await eslint
.lintFiles(["lib/cli.js"]);
927 assert
.strictEqual(results
.length
, 1);
928 assert
.strictEqual(results
[0].messages
.length
, 0);
931 it("should report zero messages when given a config file and a valid file and esprima as parser", async () => {
932 eslint
= new ESLint({
939 const results
= await eslint
.lintFiles(["tests/fixtures/passing.js"]);
941 assert
.strictEqual(results
.length
, 1);
942 assert
.strictEqual(results
[0].messages
.length
, 0);
945 it("should throw an error when given a config file and a valid file and invalid parser", async () => {
946 eslint
= new ESLint({
953 await assert
.rejects(async () => await eslint
.lintFiles(["lib/cli.js"]), /Cannot find module
'test11'/u
);
956 it("should report zero messages when given a directory with a .js2 file", async () => {
957 eslint
= new ESLint({
958 cwd
: path
.join(fixtureDir
, ".."),
961 const results
= await eslint
.lintFiles([getFixturePath("files/foo.js2")]);
963 assert
.strictEqual(results
.length
, 1);
964 assert
.strictEqual(results
[0].messages
.length
, 0);
967 it("should fall back to defaults when extensions is set to an empty array", async () => {
968 eslint
= new ESLint({
969 cwd
: getFixturePath("configurations"),
970 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json"),
973 const results
= await eslint
.lintFiles([getFixturePath("single-quoted.js")]);
975 assert
.strictEqual(results
.length
, 1);
976 assert
.strictEqual(results
[0].messages
.length
, 1);
977 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
978 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
979 assert
.strictEqual(results
[0].errorCount
, 1);
980 assert
.strictEqual(results
[0].warningCount
, 0);
981 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
982 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
985 it("should report zero messages when given a directory with a .js and a .js2 file", async () => {
986 eslint
= new ESLint({
987 extensions
: [".js", ".js2"],
989 cwd
: getFixturePath("..")
991 const results
= await eslint
.lintFiles(["fixtures/files/"]);
993 assert
.strictEqual(results
.length
, 2);
994 assert
.strictEqual(results
[0].messages
.length
, 0);
995 assert
.strictEqual(results
[1].messages
.length
, 0);
998 it("should report zero messages when given a '**' pattern with a .js and a .js2 file", async () => {
999 eslint
= new ESLint({
1000 extensions
: [".js", ".js2"],
1002 cwd
: path
.join(fixtureDir
, "..")
1004 const results
= await eslint
.lintFiles(["fixtures/files/*"]);
1006 assert
.strictEqual(results
.length
, 2);
1007 assert
.strictEqual(results
[0].messages
.length
, 0);
1008 assert
.strictEqual(results
[1].messages
.length
, 0);
1011 it("should resolve globs when 'globInputPaths' option is true", async () => {
1012 eslint
= new ESLint({
1013 extensions
: [".js", ".js2"],
1015 cwd
: getFixturePath("..")
1017 const results
= await eslint
.lintFiles(["fixtures/files/*"]);
1019 assert
.strictEqual(results
.length
, 2);
1020 assert
.strictEqual(results
[0].messages
.length
, 0);
1021 assert
.strictEqual(results
[1].messages
.length
, 0);
1024 it("should not resolve globs when 'globInputPaths' option is false", async () => {
1025 eslint
= new ESLint({
1026 extensions
: [".js", ".js2"],
1028 cwd
: getFixturePath(".."),
1029 globInputPaths
: false
1032 await assert
.rejects(async () => {
1033 await eslint
.lintFiles(["fixtures/files/*"]);
1034 }, /No files matching 'fixtures\/files\/\*' were found \(glob was disabled\)\./u);
1037 it("should report on all files passed explicitly, even if ignored by default", async () => {
1038 eslint
= new ESLint({
1039 cwd
: getFixturePath("cli-engine")
1041 const results
= await eslint
.lintFiles(["node_modules/foo.js"]);
1042 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
1044 assert
.strictEqual(results
.length
, 1);
1045 assert
.strictEqual(results
[0].errorCount
, 0);
1046 assert
.strictEqual(results
[0].warningCount
, 1);
1047 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1048 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1049 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1052 it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", async () => {
1053 eslint
= new ESLint({
1054 cwd
: getFixturePath("cli-engine"),
1057 quotes
: [2, "single"]
1061 const results
= await eslint
.lintFiles(["hidden/.hiddenfolder/*.js"]);
1063 assert
.strictEqual(results
.length
, 1);
1064 assert
.strictEqual(results
[0].errorCount
, 1);
1065 assert
.strictEqual(results
[0].warningCount
, 0);
1066 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1067 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1070 it("should not check default ignored files without --no-ignore flag", async () => {
1071 eslint
= new ESLint({
1072 cwd
: getFixturePath("cli-engine")
1075 await assert
.rejects(async () => {
1076 await eslint
.lintFiles(["node_modules"]);
1077 }, /All files matched by 'node_modules' are ignored\./u);
1080 // https://github.com/eslint/eslint/issues/5547
1081 it("should not check node_modules files even with --no-ignore flag", async () => {
1082 eslint
= new ESLint({
1083 cwd
: getFixturePath("cli-engine"),
1087 await assert
.rejects(async () => {
1088 await eslint
.lintFiles(["node_modules"]);
1089 }, /All files matched by 'node_modules' are ignored\./u);
1092 it("should not check .hidden files if they are passed explicitly without --no-ignore flag", async () => {
1093 eslint
= new ESLint({
1094 cwd
: getFixturePath(".."),
1098 quotes
: [2, "single"]
1102 const results
= await eslint
.lintFiles(["fixtures/files/.bar.js"]);
1103 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1105 assert
.strictEqual(results
.length
, 1);
1106 assert
.strictEqual(results
[0].errorCount
, 0);
1107 assert
.strictEqual(results
[0].warningCount
, 1);
1108 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1109 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1110 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1113 // https://github.com/eslint/eslint/issues/12873
1114 it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", async () => {
1115 eslint
= new ESLint({
1116 cwd
: getFixturePath("cli-engine"),
1120 quotes
: [2, "single"]
1124 const results
= await eslint
.lintFiles(["hidden/.hiddenfolder/double-quotes.js"]);
1125 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1127 assert
.strictEqual(results
.length
, 1);
1128 assert
.strictEqual(results
[0].errorCount
, 0);
1129 assert
.strictEqual(results
[0].warningCount
, 1);
1130 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1131 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1132 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1135 it("should check .hidden files if they are passed explicitly with --no-ignore flag", async () => {
1136 eslint
= new ESLint({
1137 cwd
: getFixturePath(".."),
1142 quotes
: [2, "single"]
1146 const results
= await eslint
.lintFiles(["fixtures/files/.bar.js"]);
1148 assert
.strictEqual(results
.length
, 1);
1149 assert
.strictEqual(results
[0].warningCount
, 0);
1150 assert
.strictEqual(results
[0].errorCount
, 1);
1151 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1152 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1153 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1156 it("should check .hidden files if they are unignored with an --ignore-pattern", async () => {
1157 eslint
= new ESLint({
1158 cwd
: getFixturePath("cli-engine"),
1162 ignorePatterns
: "!.hidden*",
1164 quotes
: [2, "single"]
1168 const results
= await eslint
.lintFiles(["hidden/"]);
1170 assert
.strictEqual(results
.length
, 1);
1171 assert
.strictEqual(results
[0].warningCount
, 0);
1172 assert
.strictEqual(results
[0].errorCount
, 1);
1173 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1174 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1175 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1178 it("should report zero messages when given a pattern with a .js and a .js2 file", async () => {
1179 eslint
= new ESLint({
1180 extensions
: [".js", ".js2"],
1182 cwd
: path
.join(fixtureDir
, "..")
1184 const results
= await eslint
.lintFiles(["fixtures/files/*.?s*"]);
1186 assert
.strictEqual(results
.length
, 2);
1187 assert
.strictEqual(results
[0].messages
.length
, 0);
1188 assert
.strictEqual(results
[1].messages
.length
, 0);
1191 it("should return one error message when given a config with rules with options and severity level set to error", async () => {
1192 eslint
= new ESLint({
1193 cwd
: getFixturePath("configurations"),
1194 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json")
1196 const results
= await eslint
.lintFiles([getFixturePath("single-quoted.js")]);
1198 assert
.strictEqual(results
.length
, 1);
1199 assert
.strictEqual(results
[0].messages
.length
, 1);
1200 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1201 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1202 assert
.strictEqual(results
[0].errorCount
, 1);
1203 assert
.strictEqual(results
[0].warningCount
, 0);
1204 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1205 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1208 it("should return 3 messages when given a config file and a directory of 3 valid files", async () => {
1209 eslint
= new ESLint({
1210 cwd
: path
.join(fixtureDir
, ".."),
1211 overrideConfigFile
: getFixturePath("configurations", "semi-error.json")
1213 const results
= await eslint
.lintFiles([getFixturePath("formatters")]);
1215 assert
.strictEqual(results
.length
, 3);
1216 assert
.strictEqual(results
[0].messages
.length
, 0);
1217 assert
.strictEqual(results
[1].messages
.length
, 0);
1218 assert
.strictEqual(results
[2].messages
.length
, 0);
1219 assert
.strictEqual(results
[0].errorCount
, 0);
1220 assert
.strictEqual(results
[0].warningCount
, 0);
1221 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1222 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1223 assert
.strictEqual(results
[1].errorCount
, 0);
1224 assert
.strictEqual(results
[1].warningCount
, 0);
1225 assert
.strictEqual(results
[1].fixableErrorCount
, 0);
1226 assert
.strictEqual(results
[1].fixableWarningCount
, 0);
1227 assert
.strictEqual(results
[2].errorCount
, 0);
1228 assert
.strictEqual(results
[2].warningCount
, 0);
1229 assert
.strictEqual(results
[2].fixableErrorCount
, 0);
1230 assert
.strictEqual(results
[2].fixableWarningCount
, 0);
1233 it("should process when file is given by not specifying extensions", async () => {
1234 eslint
= new ESLint({
1236 cwd
: path
.join(fixtureDir
, "..")
1238 const results
= await eslint
.lintFiles(["fixtures/files/foo.js2"]);
1240 assert
.strictEqual(results
.length
, 1);
1241 assert
.strictEqual(results
[0].messages
.length
, 0);
1244 it("should return zero messages when given a config with environment set to browser", async () => {
1245 eslint
= new ESLint({
1246 cwd
: path
.join(fixtureDir
, ".."),
1247 overrideConfigFile
: getFixturePath("configurations", "env-browser.json")
1249 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1251 assert
.strictEqual(results
.length
, 1);
1252 assert
.strictEqual(results
[0].messages
.length
, 0);
1255 it("should return zero messages when given an option to set environment to browser", async () => {
1256 eslint
= new ESLint({
1257 cwd
: path
.join(fixtureDir
, ".."),
1259 env
: { browser
: true },
1266 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1268 assert
.strictEqual(results
.length
, 1);
1269 assert
.strictEqual(results
[0].messages
.length
, 0);
1272 it("should return zero messages when given a config with environment set to Node.js", async () => {
1273 eslint
= new ESLint({
1274 cwd
: path
.join(fixtureDir
, ".."),
1275 overrideConfigFile
: getFixturePath("configurations", "env-node.json")
1277 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-node.js"))]);
1279 assert
.strictEqual(results
.length
, 1);
1280 assert
.strictEqual(results
[0].messages
.length
, 0);
1283 it("should not return results from previous call when calling more than once", async () => {
1284 eslint
= new ESLint({
1285 cwd
: path
.join(fixtureDir
, ".."),
1293 const failFilePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1294 const passFilePath
= fs
.realpathSync(getFixturePath("passing.js"));
1296 let results
= await eslint
.lintFiles([failFilePath
]);
1298 assert
.strictEqual(results
.length
, 1);
1299 assert
.strictEqual(results
[0].filePath
, failFilePath
);
1300 assert
.strictEqual(results
[0].messages
.length
, 1);
1301 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
1302 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1304 results
= await eslint
.lintFiles([passFilePath
]);
1305 assert
.strictEqual(results
.length
, 1);
1306 assert
.strictEqual(results
[0].filePath
, passFilePath
);
1307 assert
.strictEqual(results
[0].messages
.length
, 0);
1310 it("should throw an error when given a directory with all eslint excluded files in the directory", async () => {
1311 eslint
= new ESLint({
1312 ignorePath
: getFixturePath(".eslintignore")
1315 await assert
.rejects(async () => {
1316 await eslint
.lintFiles([getFixturePath("./cli-engine/")]);
1317 }, new RegExp(escapeStringRegExp(`All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`), "u"));
1320 it("should throw an error when all given files are ignored", async () => {
1321 await assert
.rejects(async () => {
1322 await eslint
.lintFiles(["tests/fixtures/cli-engine/"]);
1323 }, /All files matched by 'tests\/fixtures\/cli-engine\/' are ignored\./u);
1326 it("should throw an error when all given files are ignored even with a `./` prefix", async () => {
1327 eslint
= new ESLint({
1328 ignorePath
: getFixturePath(".eslintignore")
1331 await assert
.rejects(async () => {
1332 await eslint
.lintFiles(["./tests/fixtures/cli-engine/"]);
1333 }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
1336 // https://github.com/eslint/eslint/issues/3788
1337 it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", async () => {
1338 eslint
= new ESLint({
1339 ignorePath
: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
1343 quotes
: [2, "double"]
1346 cwd
: getFixturePath("cli-engine", "nested_node_modules")
1348 const results
= await eslint
.lintFiles(["."]);
1350 assert
.strictEqual(results
.length
, 1);
1351 assert
.strictEqual(results
[0].errorCount
, 0);
1352 assert
.strictEqual(results
[0].warningCount
, 0);
1353 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1354 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1357 // https://github.com/eslint/eslint/issues/3812
1358 it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", async () => {
1359 eslint
= new ESLint({
1360 ignorePath
: getFixturePath("cli-engine/.eslintignore2"),
1364 quotes
: [2, "double"]
1369 await assert
.rejects(async () => {
1370 await eslint
.lintFiles(["./tests/fixtures/cli-engine/"]);
1371 }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
1374 it("should throw an error when all given files are ignored via ignore-pattern", async () => {
1375 eslint
= new ESLint({
1377 ignorePatterns
: "tests/fixtures/single-quoted.js"
1381 await assert
.rejects(async () => {
1382 await eslint
.lintFiles(["tests/fixtures/*-quoted.js"]);
1383 }, /All files matched by 'tests\/fixtures\/\*-quoted\.js' are ignored\./u);
1386 it("should return a warning when an explicitly given file is ignored", async () => {
1387 eslint
= new ESLint({
1388 ignorePath
: getFixturePath(".eslintignore"),
1389 cwd
: getFixturePath()
1391 const filePath
= getFixturePath("passing.js");
1392 const results
= await eslint
.lintFiles([filePath
]);
1394 assert
.strictEqual(results
.length
, 1);
1395 assert
.strictEqual(results
[0].filePath
, filePath
);
1396 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1397 assert
.strictEqual(results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
1398 assert
.strictEqual(results
[0].errorCount
, 0);
1399 assert
.strictEqual(results
[0].warningCount
, 1);
1400 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1401 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1404 it("should return two messages when given a file in excluded files list while ignore is off", async () => {
1405 eslint
= new ESLint({
1406 ignorePath
: getFixturePath(".eslintignore"),
1414 const filePath
= fs
.realpathSync(getFixturePath("undef.js"));
1415 const results
= await eslint
.lintFiles([filePath
]);
1417 assert
.strictEqual(results
.length
, 1);
1418 assert
.strictEqual(results
[0].filePath
, filePath
);
1419 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
1420 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1421 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-undef");
1422 assert
.strictEqual(results
[0].messages
[1].severity
, 2);
1425 it("should return zero messages when executing a file with a shebang", async () => {
1426 eslint
= new ESLint({
1429 const results
= await eslint
.lintFiles([getFixturePath("shebang.js")]);
1431 assert
.strictEqual(results
.length
, 1);
1432 assert
.strictEqual(results
[0].messages
.length
, 0);
1435 it("should give a warning when loading a custom rule that doesn't exist", async () => {
1436 eslint
= new ESLint({
1438 rulePaths
: [getFixturePath("rules", "dir1")],
1439 overrideConfigFile
: getFixturePath("rules", "missing-rule.json")
1441 const results
= await eslint
.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1443 assert
.strictEqual(results
.length
, 1);
1444 assert
.strictEqual(results
[0].messages
.length
, 1);
1445 assert
.strictEqual(results
[0].messages
[0].ruleId
, "missing-rule");
1446 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1447 assert
.strictEqual(results
[0].messages
[0].message
, "Definition for rule 'missing-rule' was not found.");
1450 it("should throw an error when loading a bad custom rule", async () => {
1451 eslint
= new ESLint({
1453 rulePaths
: [getFixturePath("rules", "wrong")],
1454 overrideConfigFile
: getFixturePath("rules", "eslint.json")
1458 await assert
.rejects(async () => {
1459 await eslint
.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1460 }, /Error while loading rule 'custom-rule'/u);
1463 it("should return one message when a custom rule matches a file", async () => {
1464 eslint
= new ESLint({
1467 rulePaths
: [getFixturePath("rules/")],
1468 overrideConfigFile
: getFixturePath("rules", "eslint.json")
1470 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1471 const results
= await eslint
.lintFiles([filePath
]);
1473 assert
.strictEqual(results
.length
, 1);
1474 assert
.strictEqual(results
[0].filePath
, filePath
);
1475 assert
.strictEqual(results
[0].messages
.length
, 2);
1476 assert
.strictEqual(results
[0].messages
[0].ruleId
, "custom-rule");
1477 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1480 it("should load custom rule from the provided cwd", async () => {
1481 const cwd
= path
.resolve(getFixturePath("rules"));
1483 eslint
= new ESLint({
1487 overrideConfigFile
: "eslint.json"
1489 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1490 const results
= await eslint
.lintFiles([filePath
]);
1492 assert
.strictEqual(results
.length
, 1);
1493 assert
.strictEqual(results
[0].filePath
, filePath
);
1494 assert
.strictEqual(results
[0].messages
.length
, 2);
1495 assert
.strictEqual(results
[0].messages
[0].ruleId
, "custom-rule");
1496 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1499 it("should return messages when multiple custom rules match a file", async () => {
1500 eslint
= new ESLint({
1503 getFixturePath("rules", "dir1"),
1504 getFixturePath("rules", "dir2")
1506 overrideConfigFile
: getFixturePath("rules", "multi-rulesdirs.json")
1508 const filePath
= fs
.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.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
.length
, 2);
1514 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-literals");
1515 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1516 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-strings");
1517 assert
.strictEqual(results
[0].messages
[1].severity
, 2);
1520 it("should return zero messages when executing without useEslintrc flag", async () => {
1521 eslint
= new ESLint({
1525 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1526 const results
= await eslint
.lintFiles([filePath
]);
1528 assert
.strictEqual(results
.length
, 1);
1529 assert
.strictEqual(results
[0].filePath
, filePath
);
1530 assert
.strictEqual(results
[0].messages
.length
, 0);
1533 it("should return zero messages when executing without useEslintrc flag in Node.js environment", async () => {
1534 eslint
= new ESLint({
1541 const filePath
= fs
.realpathSync(getFixturePath("process-exit.js"));
1542 const results
= await eslint
.lintFiles([filePath
]);
1544 assert
.strictEqual(results
.length
, 1);
1545 assert
.strictEqual(results
[0].filePath
, filePath
);
1546 assert
.strictEqual(results
[0].messages
.length
, 0);
1549 it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", async () => {
1550 eslint
= new ESLint({
1557 const filePath
= fs
.realpathSync(getFixturePath("eslintrc", "quotes.js"));
1558 const results
= await eslint
.lintFiles([filePath
]);
1560 assert
.strictEqual(results
.length
, 1);
1561 assert
.strictEqual(results
[0].filePath
, filePath
);
1562 assert
.strictEqual(results
[0].messages
.length
, 0);
1565 it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", async () => {
1566 eslint
= new ESLint({
1573 const filePath
= fs
.realpathSync(getFixturePath("packagejson", "quotes.js"));
1574 const results
= await eslint
.lintFiles([filePath
]);
1576 assert
.strictEqual(results
.length
, 1);
1577 assert
.strictEqual(results
[0].filePath
, filePath
);
1578 assert
.strictEqual(results
[0].messages
.length
, 0);
1581 it("should warn when deprecated rules are configured", async () => {
1582 eslint
= new ESLint({
1584 overrideConfigFile
: ".eslintrc.js",
1593 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1595 assert
.deepStrictEqual(
1596 results
[0].usedDeprecatedRules
,
1598 { ruleId
: "indent-legacy", replacedBy
: ["indent"] },
1599 { ruleId
: "require-jsdoc", replacedBy
: [] },
1600 { ruleId
: "valid-jsdoc", replacedBy
: [] }
1605 it("should not warn when deprecated rules are not configured", async () => {
1606 eslint
= new ESLint({
1608 overrideConfigFile
: ".eslintrc.js",
1610 rules
: { indent
: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
1613 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1615 assert
.deepStrictEqual(results
[0].usedDeprecatedRules
, []);
1618 it("should warn when deprecated rules are found in a config", async () => {
1619 eslint
= new ESLint({
1621 overrideConfigFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
1624 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1626 assert
.deepStrictEqual(
1627 results
[0].usedDeprecatedRules
,
1628 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
1632 describe("Fix Mode", () => {
1633 it("should return fixed text on multiple files when in fix mode", async () => {
1636 * Converts CRLF to LF in output.
1637 * This is a workaround for git's autocrlf option on Windows.
1638 * @param {Object} result A result object to convert.
1641 function convertCRLF(result
) {
1642 if (result
&& result
.output
) {
1643 result
.output
= result
.output
.replace(/\r\n/gu, "\n");
1647 eslint
= new ESLint({
1648 cwd
: path
.join(fixtureDir
, ".."),
1654 quotes
: [2, "double"],
1657 "space-infix-ops": 2
1661 const results
= await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1663 results
.forEach(convertCRLF
);
1664 assert
.deepStrictEqual(results
, [
1666 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/multipass.js")),
1671 fixableErrorCount
: 0,
1672 fixableWarningCount
: 0,
1673 output
: "true ? \"yes\" : \"no\";\n",
1674 usedDeprecatedRules
: []
1677 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/ok.js")),
1682 fixableErrorCount
: 0,
1683 fixableWarningCount
: 0,
1684 usedDeprecatedRules
: []
1687 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes-semi-eqeqeq.js")),
1694 message
: "Expected '===' and instead saw '=='.",
1695 messageId
: "unexpected",
1696 nodeType
: "BinaryExpression",
1704 fixableErrorCount
: 0,
1705 fixableWarningCount
: 0,
1706 output
: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n",
1707 usedDeprecatedRules
: []
1710 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes.js")),
1718 message
: "'foo' is not defined.",
1719 nodeType
: "Identifier",
1727 fixableErrorCount
: 0,
1728 fixableWarningCount
: 0,
1729 output
: "var msg = \"hi\" + foo;\n",
1730 usedDeprecatedRules
: []
1735 it("should run autofix even if files are cached without autofix results", async () => {
1736 const baseOptions
= {
1737 cwd
: path
.join(fixtureDir
, ".."),
1742 quotes
: [2, "double"],
1745 "space-infix-ops": 2
1750 eslint
= new ESLint(Object
.assign({}, baseOptions
, { cache
: true, fix
: false }));
1752 // Do initial lint run and populate the cache file
1753 await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1755 eslint
= new ESLint(Object
.assign({}, baseOptions
, { cache
: true, fix
: true }));
1756 const results
= await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1758 assert(results
.some(result
=> result
.output
));
1762 // These tests have to do with https://github.com/eslint/eslint/issues/963
1764 describe("configuration hierarchy", () => {
1766 // Default configuration - blank
1767 it("should return zero messages when executing with no .eslintrc", async () => {
1768 eslint
= new ESLint({
1769 cwd
: path
.join(fixtureDir
, ".."),
1772 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1774 assert
.strictEqual(results
.length
, 1);
1775 assert
.strictEqual(results
[0].messages
.length
, 0);
1778 // No default configuration rules - conf/environments.js (/*eslint-env node*/)
1779 it("should return zero messages when executing with no .eslintrc in the Node.js environment", async () => {
1780 eslint
= new ESLint({
1781 cwd
: path
.join(fixtureDir
, ".."),
1784 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
1786 assert
.strictEqual(results
.length
, 1);
1787 assert
.strictEqual(results
[0].messages
.length
, 0);
1790 // Project configuration - first level .eslintrc
1791 it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
1792 eslint
= new ESLint({
1793 cwd
: path
.join(fixtureDir
, "..")
1795 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1797 assert
.strictEqual(results
.length
, 1);
1798 assert
.strictEqual(results
[0].messages
.length
, 0);
1801 // Project configuration - first level .eslintrc
1802 it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
1803 eslint
= new ESLint({
1804 cwd
: path
.join(fixtureDir
, "..")
1806 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1808 assert
.strictEqual(results
.length
, 1);
1809 assert
.strictEqual(results
[0].messages
.length
, 0);
1812 // Project configuration - first level .eslintrc
1813 it("should return one message when executing with .eslintrc", async () => {
1814 eslint
= new ESLint({
1815 cwd
: path
.join(fixtureDir
, "..")
1817 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1819 assert
.strictEqual(results
.length
, 1);
1820 assert
.strictEqual(results
[0].messages
.length
, 1);
1821 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1822 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1825 // Project configuration - second level .eslintrc
1826 it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", async () => {
1827 eslint
= new ESLint({
1828 cwd
: path
.join(fixtureDir
, "..")
1830 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1832 assert
.strictEqual(results
.length
, 1);
1833 assert
.strictEqual(results
[0].messages
.length
, 1);
1834 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1835 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1838 // Project configuration - third level .eslintrc
1839 it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", async () => {
1840 eslint
= new ESLint({
1841 cwd
: path
.join(fixtureDir
, "..")
1843 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
1845 assert
.strictEqual(results
.length
, 1);
1846 assert
.strictEqual(results
[0].messages
.length
, 1);
1847 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1848 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1851 // Project configuration - first level package.json
1852 it("should return one message when executing with package.json", async () => {
1853 eslint
= new ESLint({
1854 cwd
: path
.join(fixtureDir
, "..")
1856 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
1858 assert
.strictEqual(results
.length
, 1);
1859 assert
.strictEqual(results
[0].messages
.length
, 1);
1860 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1861 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1864 // Project configuration - second level package.json
1865 it("should return zero messages when executing with local package.json that overrides parent package.json", async () => {
1866 eslint
= new ESLint({
1867 cwd
: path
.join(fixtureDir
, "..")
1869 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
1871 assert
.strictEqual(results
.length
, 1);
1872 assert
.strictEqual(results
[0].messages
.length
, 0);
1875 // Project configuration - third level package.json
1876 it("should return one message when executing with local package.json that overrides parent and grandparent package.json", async () => {
1877 eslint
= new ESLint({
1878 cwd
: path
.join(fixtureDir
, "..")
1880 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
1882 assert
.strictEqual(results
.length
, 1);
1883 assert
.strictEqual(results
[0].messages
.length
, 1);
1884 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1885 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1888 // Project configuration - .eslintrc overrides package.json in same directory
1889 it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", async () => {
1890 eslint
= new ESLint({
1891 cwd
: path
.join(fixtureDir
, "..")
1893 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
1895 assert
.strictEqual(results
.length
, 1);
1896 assert
.strictEqual(results
[0].messages
.length
, 1);
1897 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1898 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1901 // Command line configuration - --config with first level .eslintrc
1902 it("should return two messages when executing with config file that adds to local .eslintrc", async () => {
1903 eslint
= new ESLint({
1904 cwd
: path
.join(fixtureDir
, ".."),
1905 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1907 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1909 assert
.strictEqual(results
.length
, 1);
1910 assert
.strictEqual(results
[0].messages
.length
, 2);
1911 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1912 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1913 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi");
1914 assert
.strictEqual(results
[0].messages
[1].severity
, 1);
1917 // Command line configuration - --config with first level .eslintrc
1918 it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
1919 eslint
= new ESLint({
1920 cwd
: path
.join(fixtureDir
, ".."),
1921 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1923 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1925 assert
.strictEqual(results
.length
, 1);
1926 assert
.strictEqual(results
[0].messages
.length
, 0);
1929 // Command line configuration - --config with second level .eslintrc
1930 it("should return two messages when executing with config file that adds to local and parent .eslintrc", async () => {
1931 eslint
= new ESLint({
1932 cwd
: path
.join(fixtureDir
, ".."),
1933 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1935 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1937 assert
.strictEqual(results
.length
, 1);
1938 assert
.strictEqual(results
[0].messages
.length
, 2);
1939 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1940 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1941 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi");
1942 assert
.strictEqual(results
[0].messages
[1].severity
, 1);
1945 // Command line configuration - --config with second level .eslintrc
1946 it("should return one message when executing with config file that overrides local and parent .eslintrc", async () => {
1947 eslint
= new ESLint({
1948 cwd
: path
.join(fixtureDir
, ".."),
1949 overrideConfigFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml")
1951 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1953 assert
.strictEqual(results
.length
, 1);
1954 assert
.strictEqual(results
[0].messages
.length
, 1);
1955 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1956 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1959 // Command line configuration - --config with first level .eslintrc
1960 it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
1961 eslint
= new ESLint({
1962 cwd
: path
.join(fixtureDir
, ".."),
1963 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1965 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1967 assert
.strictEqual(results
.length
, 1);
1968 assert
.strictEqual(results
[0].messages
.length
, 0);
1971 // Command line configuration - --rule with --config and first level .eslintrc
1972 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
1973 eslint
= new ESLint({
1974 cwd
: path
.join(fixtureDir
, ".."),
1975 overrideConfigFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
1978 quotes
: [1, "double"]
1982 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1984 assert
.strictEqual(results
.length
, 1);
1985 assert
.strictEqual(results
[0].messages
.length
, 1);
1986 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1987 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1990 // Command line configuration - --rule with --config and first level .eslintrc
1991 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
1992 eslint
= new ESLint({
1993 cwd
: path
.join(fixtureDir
, ".."),
1994 overrideConfigFile
: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
1997 quotes
: [1, "double"]
2001 const results
= await eslint
.lintFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
2003 assert
.strictEqual(results
.length
, 1);
2004 assert
.strictEqual(results
[0].messages
.length
, 1);
2005 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
2006 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
2010 describe("plugins", () => {
2011 it("should return two messages when executing with config file that specifies a plugin", async () => {
2012 eslint
= eslintWithPlugins({
2013 cwd
: path
.join(fixtureDir
, ".."),
2014 overrideConfigFile
: getFixturePath("configurations", "plugins-with-prefix.json"),
2017 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
2019 assert
.strictEqual(results
.length
, 1);
2020 assert
.strictEqual(results
[0].messages
.length
, 2);
2021 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2024 it("should return two messages when executing with config file that specifies a plugin with namespace", async () => {
2025 eslint
= eslintWithPlugins({
2026 cwd
: path
.join(fixtureDir
, ".."),
2027 overrideConfigFile
: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
2030 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2032 assert
.strictEqual(results
.length
, 1);
2033 assert
.strictEqual(results
[0].messages
.length
, 2);
2034 assert
.strictEqual(results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2037 it("should return two messages when executing with config file that specifies a plugin without prefix", async () => {
2038 eslint
= eslintWithPlugins({
2039 cwd
: path
.join(fixtureDir
, ".."),
2040 overrideConfigFile
: getFixturePath("configurations", "plugins-without-prefix.json"),
2043 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2045 assert
.strictEqual(results
.length
, 1);
2046 assert
.strictEqual(results
[0].messages
.length
, 2);
2047 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2050 it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", async () => {
2051 eslint
= eslintWithPlugins({
2052 cwd
: path
.join(fixtureDir
, ".."),
2053 overrideConfigFile
: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
2056 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2058 assert
.strictEqual(results
.length
, 1);
2059 assert
.strictEqual(results
[0].messages
.length
, 2);
2060 assert
.strictEqual(results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2063 it("should return two messages when executing with cli option that specifies a plugin", async () => {
2064 eslint
= eslintWithPlugins({
2065 cwd
: path
.join(fixtureDir
, ".."),
2068 plugins
: ["example"],
2069 rules
: { "example/example-rule": 1 }
2072 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2074 assert
.strictEqual(results
.length
, 1);
2075 assert
.strictEqual(results
[0].messages
.length
, 2);
2076 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2079 it("should return two messages when executing with cli option that specifies preloaded plugin", async () => {
2080 eslint
= new ESLint({
2081 cwd
: path
.join(fixtureDir
, ".."),
2085 rules
: { "test/example-rule": 1 }
2088 "eslint-plugin-test": { rules
: { "example-rule": require("../../fixtures/rules/custom-rule") } }
2091 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2093 assert
.strictEqual(results
.length
, 1);
2094 assert
.strictEqual(results
[0].messages
.length
, 2);
2095 assert
.strictEqual(results
[0].messages
[0].ruleId
, "test/example-rule");
2098 it("should return two messages when executing with `baseConfig` that extends preloaded plugin config", async () => {
2099 eslint
= new ESLint({
2100 cwd
: path
.join(fixtureDir
, ".."),
2103 extends: ["plugin:test/preset"]
2108 "example-rule": require("../../fixtures/rules/custom-rule")
2113 "test/example-rule": 1
2121 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2123 assert
.strictEqual(results
.length
, 1);
2124 assert
.strictEqual(results
[0].messages
.length
, 2);
2125 assert
.strictEqual(results
[0].messages
[0].ruleId
, "test/example-rule");
2128 it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", async () => {
2129 eslint
= new ESLint({
2130 resolvePluginsRelativeTo
: getFixturePath("plugins"),
2132 plugins
: ["with-rules"],
2133 rules
: { "with-rules/rule1": "error" }
2137 const results
= await eslint
.lintText("foo");
2139 assert
.strictEqual(results
.length
, 1);
2140 assert
.strictEqual(results
[0].messages
.length
, 1);
2141 assert
.strictEqual(results
[0].messages
[0].ruleId
, "with-rules/rule1");
2142 assert
.strictEqual(results
[0].messages
[0].message
, "Rule report from plugin");
2146 describe("cache", () => {
2149 * helper method to delete a file without caring about exceptions
2150 * @param {string} filePath The file path
2153 function doDelete(filePath
) {
2155 fs
.unlinkSync(filePath
);
2159 * we don't care if the file didn't exist, since our
2160 * intention was to remove the file
2166 * helper method to delete the cache files created during testing
2169 function deleteCache() {
2170 doDelete(path
.resolve(".eslintcache"));
2171 doDelete(path
.resolve(".cache/custom-cache"));
2183 describe("when the cacheFile is a directory or looks like a directory", () => {
2186 * helper method to delete the cache files created during testing
2189 function deleteCacheDir() {
2191 fs
.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
2195 * we don't care if the file didn't exist, since our
2196 * intention was to remove the file
2208 it("should create the cache file inside the provided directory", async () => {
2209 assert(!shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2211 eslint
= new ESLint({
2214 // specifying cache true the cache will be created
2216 cacheLocation
: "./tmp/.cacheFileDir/",
2226 const file
= getFixturePath("cache/src", "test-file.js");
2228 await eslint
.lintFiles([file
]);
2230 assert(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2236 it("should create the cache file inside the provided directory using the cacheLocation option", async () => {
2237 assert(!shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2239 eslint
= new ESLint({
2242 // specifying cache true the cache will be created
2244 cacheLocation
: "./tmp/.cacheFileDir/",
2254 const file
= getFixturePath("cache/src", "test-file.js");
2256 await eslint
.lintFiles([file
]);
2258 assert(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2263 it("should create the cache file inside cwd when no cacheLocation provided", async () => {
2264 const cwd
= path
.resolve(getFixturePath("cli-engine"));
2266 eslint
= new ESLint({
2278 const file
= getFixturePath("cli-engine", "console.js");
2280 await eslint
.lintFiles([file
]);
2282 assert(shell
.test("-f", path
.resolve(cwd
, ".eslintcache")), "the cache for eslint was created at provided cwd");
2285 it("should invalidate the cache if the configuration changed between executions", async () => {
2286 assert(!shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2288 eslint
= new ESLint({
2291 // specifying cache true the cache will be created
2303 let spy
= sinon
.spy(fs
, "readFileSync");
2305 let file
= getFixturePath("cache/src", "test-file.js");
2307 file
= fs
.realpathSync(file
);
2308 const results
= await eslint
.lintFiles([file
]);
2310 for (const { errorCount
, warningCount
} of results
) {
2311 assert
.strictEqual(errorCount
+ warningCount
, 0, "the file passed without errors or warnings");
2313 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2314 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2319 eslint
= new ESLint({
2322 // specifying cache true the cache will be created
2335 spy
= sinon
.spy(fs
, "readFileSync");
2337 const [cachedResult
] = await eslint
.lintFiles([file
]);
2339 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed because the config changed");
2340 assert
.strictEqual(cachedResult
.errorCount
, 1, "since configuration changed the cache was not used an one error was reported");
2341 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2344 it("should remember the files from a previous run and do not operate on them if not changed", async () => {
2345 assert(!shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2347 eslint
= new ESLint({
2350 // specifying cache true the cache will be created
2362 let spy
= sinon
.spy(fs
, "readFileSync");
2364 let file
= getFixturePath("cache/src", "test-file.js");
2366 file
= fs
.realpathSync(file
);
2368 const result
= await eslint
.lintFiles([file
]);
2370 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2371 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2376 eslint
= new ESLint({
2379 // specifying cache true the cache will be created
2392 spy
= sinon
.spy(fs
, "readFileSync");
2394 const cachedResult
= await eslint
.lintFiles([file
]);
2396 assert
.deepStrictEqual(result
, cachedResult
, "the result is the same regardless of using cache or not");
2398 // assert the file was not processed because the cache was used
2399 assert(!spy
.calledWith(file
), "the file was not loaded because it used the cache");
2402 it("should remember the files from a previous run and do not operate on then if not changed", async () => {
2403 const cacheLocation
= getFixturePath(".eslintcache");
2404 const eslintOptions
= {
2407 // specifying cache true the cache will be created
2417 cwd
: path
.join(fixtureDir
, "..")
2420 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint does not exist");
2422 eslint
= new ESLint(eslintOptions
);
2424 let file
= getFixturePath("cache/src", "test-file.js");
2426 file
= fs
.realpathSync(file
);
2428 await eslint
.lintFiles([file
]);
2430 assert(shell
.test("-f", cacheLocation
), "the cache for eslint was created");
2432 eslintOptions
.cache
= false;
2433 eslint
= new ESLint(eslintOptions
);
2435 await eslint
.lintFiles([file
]);
2437 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint was deleted since last run did not used the cache");
2440 it("should store in the cache a file that failed the test", async () => {
2441 const cacheLocation
= getFixturePath(".eslintcache");
2443 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint does not exist");
2445 eslint
= new ESLint({
2446 cwd
: path
.join(fixtureDir
, ".."),
2449 // specifying cache true the cache will be created
2460 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2461 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2462 const result
= await eslint
.lintFiles([badFile
, goodFile
]);
2464 assert(shell
.test("-f", cacheLocation
), "the cache for eslint was created");
2465 const fileCache
= fCache
.createFromFile(cacheLocation
);
2466 const { cache
} = fileCache
;
2468 assert
.strictEqual(typeof cache
.getKey(goodFile
), "object", "the entry for the good file is in the cache");
2469 assert
.strictEqual(typeof cache
.getKey(badFile
), "object", "the entry for the bad file is in the cache");
2470 const cachedResult
= await eslint
.lintFiles([badFile
, goodFile
]);
2472 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2475 it("should not contain in the cache a file that was deleted", async () => {
2476 const cacheLocation
= getFixturePath(".eslintcache");
2478 doDelete(cacheLocation
);
2480 eslint
= new ESLint({
2481 cwd
: path
.join(fixtureDir
, ".."),
2484 // specifying cache true the cache will be created
2495 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2496 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2497 const toBeDeletedFile
= fs
.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
2499 await eslint
.lintFiles([badFile
, goodFile
, toBeDeletedFile
]);
2500 const fileCache
= fCache
.createFromFile(cacheLocation
);
2501 let { cache
} = fileCache
;
2503 assert
.strictEqual(typeof cache
.getKey(toBeDeletedFile
), "object", "the entry for the file to be deleted is in the cache");
2505 // delete the file from the file system
2506 fs
.unlinkSync(toBeDeletedFile
);
2509 * file-entry-cache@2.0.0 will remove from the cache deleted files
2510 * even when they were not part of the array of files to be analyzed
2512 await eslint
.lintFiles([badFile
, goodFile
]);
2514 cache
= JSON
.parse(fs
.readFileSync(cacheLocation
));
2516 assert
.strictEqual(typeof cache
[toBeDeletedFile
], "undefined", "the entry for the file to be deleted is not in the cache");
2519 it("should contain files that were not visited in the cache provided they still exist", async () => {
2520 const cacheLocation
= getFixturePath(".eslintcache");
2522 doDelete(cacheLocation
);
2524 eslint
= new ESLint({
2525 cwd
: path
.join(fixtureDir
, ".."),
2528 // specifying cache true the cache will be created
2539 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2540 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2541 const testFile2
= fs
.realpathSync(getFixturePath("cache/src", "test-file2.js"));
2543 await eslint
.lintFiles([badFile
, goodFile
, testFile2
]);
2545 let fileCache
= fCache
.createFromFile(cacheLocation
);
2546 let { cache
} = fileCache
;
2548 assert
.strictEqual(typeof cache
.getKey(testFile2
), "object", "the entry for the test-file2 is in the cache");
2551 * we pass a different set of files minus test-file2
2552 * previous version of file-entry-cache would remove the non visited
2553 * entries. 2.0.0 version will keep them unless they don't exist
2555 await eslint
.lintFiles([badFile
, goodFile
]);
2557 fileCache
= fCache
.createFromFile(cacheLocation
);
2558 cache
= fileCache
.cache
;
2560 assert
.strictEqual(typeof cache
.getKey(testFile2
), "object", "the entry for the test-file2 is in the cache");
2563 it("should not delete cache when executing on text", async () => {
2564 const cacheLocation
= getFixturePath(".eslintcache");
2566 eslint
= new ESLint({
2567 cwd
: path
.join(fixtureDir
, ".."),
2579 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2581 await eslint
.lintText("var foo = 'bar';");
2583 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2586 it("should not delete cache when executing on text with a provided filename", async () => {
2587 const cacheLocation
= getFixturePath(".eslintcache");
2589 eslint
= new ESLint({
2590 cwd
: path
.join(fixtureDir
, ".."),
2602 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2604 await eslint
.lintText("var bar = foo;", { filePath
: "fixtures/passing.js" });
2606 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2609 it("should not delete cache when executing on files with --cache flag", async () => {
2610 const cacheLocation
= getFixturePath(".eslintcache");
2612 eslint
= new ESLint({
2613 cwd
: path
.join(fixtureDir
, ".."),
2625 const file
= getFixturePath("cli-engine", "console.js");
2627 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2629 await eslint
.lintFiles([file
]);
2631 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2634 it("should delete cache when executing on files without --cache flag", async () => {
2635 const cacheLocation
= getFixturePath(".eslintcache");
2637 eslint
= new ESLint({
2638 cwd
: path
.join(fixtureDir
, ".."),
2649 const file
= getFixturePath("cli-engine", "console.js");
2651 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2653 await eslint
.lintFiles([file
]);
2655 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint has been deleted");
2658 describe("cacheFile", () => {
2659 it("should use the specified cache file", async () => {
2660 const customCacheFile
= path
.resolve(".cache/custom-cache");
2662 assert(!shell
.test("-f", customCacheFile
), "the cache for eslint does not exist");
2664 eslint
= new ESLint({
2667 // specify a custom cache file
2668 cacheLocation
: customCacheFile
,
2670 // specifying cache true the cache will be created
2679 cwd
: path
.join(fixtureDir
, "..")
2681 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2682 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2683 const result
= await eslint
.lintFiles([badFile
, goodFile
]);
2685 assert(shell
.test("-f", customCacheFile
), "the cache for eslint was created");
2686 const fileCache
= fCache
.createFromFile(customCacheFile
);
2687 const { cache
} = fileCache
;
2689 assert(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2691 assert(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2692 const cachedResult
= await eslint
.lintFiles([badFile
, goodFile
]);
2694 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2698 describe("cacheStrategy", () => {
2699 it("should detect changes using a file's modification time when set to 'metadata'", async () => {
2700 const cacheLocation
= getFixturePath(".eslintcache");
2702 doDelete(cacheLocation
);
2704 eslint
= new ESLint({
2705 cwd
: path
.join(fixtureDir
, ".."),
2708 // specifying cache true the cache will be created
2711 cacheStrategy
: "metadata",
2720 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2721 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2723 await eslint
.lintFiles([badFile
, goodFile
]);
2724 let fileCache
= fCache
.createFromFile(cacheLocation
);
2725 const entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2727 entries
.forEach(entry
=> {
2728 assert(entry
.changed
=== false, `the entry for ${entry.key} is initially unchanged`);
2731 // this should result in a changed entry
2732 shell
.touch(goodFile
);
2733 fileCache
= fCache
.createFromFile(cacheLocation
);
2734 assert(fileCache
.getFileDescriptor(badFile
).changed
=== false, `the entry for ${badFile} is unchanged`);
2735 assert(fileCache
.getFileDescriptor(goodFile
).changed
=== true, `the entry for ${goodFile} is changed`);
2738 it("should not detect changes using a file's modification time when set to 'content'", async () => {
2739 const cacheLocation
= getFixturePath(".eslintcache");
2741 doDelete(cacheLocation
);
2743 eslint
= new ESLint({
2744 cwd
: path
.join(fixtureDir
, ".."),
2747 // specifying cache true the cache will be created
2750 cacheStrategy
: "content",
2759 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2760 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2762 await eslint
.lintFiles([badFile
, goodFile
]);
2763 let fileCache
= fCache
.createFromFile(cacheLocation
, true);
2764 let entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2766 entries
.forEach(entry
=> {
2767 assert(entry
.changed
=== false, `the entry for ${entry.key} is initially unchanged`);
2770 // this should NOT result in a changed entry
2771 shell
.touch(goodFile
);
2772 fileCache
= fCache
.createFromFile(cacheLocation
, true);
2773 entries
= fileCache
.normalizeEntries([badFile
, goodFile
]);
2774 entries
.forEach(entry
=> {
2775 assert(entry
.changed
=== false, `the entry for ${entry.key} remains unchanged`);
2779 it("should detect changes using a file's contents when set to 'content'", async () => {
2780 const cacheLocation
= getFixturePath(".eslintcache");
2782 doDelete(cacheLocation
);
2784 eslint
= new ESLint({
2785 cwd
: path
.join(fixtureDir
, ".."),
2788 // specifying cache true the cache will be created
2791 cacheStrategy
: "content",
2800 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2801 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2802 const goodFileCopy
= path
.resolve(`${path.dirname(goodFile)}`, "test-file-copy.js");
2804 shell
.cp(goodFile
, goodFileCopy
);
2806 await eslint
.lintFiles([badFile
, goodFileCopy
]);
2807 let fileCache
= fCache
.createFromFile(cacheLocation
, true);
2808 const entries
= fileCache
.normalizeEntries([badFile
, goodFileCopy
]);
2810 entries
.forEach(entry
=> {
2811 assert(entry
.changed
=== false, `the entry for ${entry.key} is initially unchanged`);
2814 // this should result in a changed entry
2815 shell
.sed("-i", "abc", "xzy", goodFileCopy
);
2816 fileCache
= fCache
.createFromFile(cacheLocation
, true);
2817 assert(fileCache
.getFileDescriptor(badFile
).changed
=== false, `the entry for ${badFile} is unchanged`);
2818 assert(fileCache
.getFileDescriptor(goodFileCopy
).changed
=== true, `the entry for ${goodFileCopy} is changed`);
2823 describe("processors", () => {
2824 it("should return two messages when executing with config file that specifies a processor", async () => {
2825 eslint
= eslintWithPlugins({
2826 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2828 extensions
: ["js", "txt"],
2829 cwd
: path
.join(fixtureDir
, "..")
2831 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2833 assert
.strictEqual(results
.length
, 1);
2834 assert
.strictEqual(results
[0].messages
.length
, 2);
2837 it("should return two messages when executing with config file that specifies preloaded processor", async () => {
2838 eslint
= new ESLint({
2841 plugins
: ["test-processor"],
2847 extensions
: ["js", "txt"],
2848 cwd
: path
.join(fixtureDir
, ".."),
2856 postprocess(messages
) {
2864 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2866 assert
.strictEqual(results
.length
, 1);
2867 assert
.strictEqual(results
[0].messages
.length
, 2);
2870 it("should run processors when calling lintFiles with config file that specifies a processor", async () => {
2871 eslint
= eslintWithPlugins({
2872 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2874 extensions
: ["js", "txt"],
2875 cwd
: path
.join(fixtureDir
, "..")
2877 const results
= await eslint
.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2879 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2880 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2883 it("should run processors when calling lintFiles with config file that specifies preloaded processor", async () => {
2884 eslint
= new ESLint({
2887 plugins
: ["test-processor"],
2893 extensions
: ["js", "txt"],
2894 cwd
: path
.join(fixtureDir
, ".."),
2900 return [text
.replace("a()", "b()")];
2902 postprocess(messages
) {
2903 messages
[0][0].ruleId
= "post-processed";
2911 const results
= await eslint
.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2913 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2914 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2917 it("should run processors when calling lintText with config file that specifies a processor", async () => {
2918 eslint
= eslintWithPlugins({
2919 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2921 extensions
: ["js", "txt"],
2924 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
2926 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2927 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2930 it("should run processors when calling lintText with config file that specifies preloaded processor", async () => {
2931 eslint
= new ESLint({
2934 plugins
: ["test-processor"],
2940 extensions
: ["js", "txt"],
2947 return [text
.replace("a()", "b()")];
2949 postprocess(messages
) {
2950 messages
[0][0].ruleId
= "post-processed";
2958 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
2960 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2961 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2964 it("should run processors when calling lintText with processor resolves same extension but different content correctly", async () => {
2967 eslint
= new ESLint({
2970 plugins
: ["test-processor"],
2972 files
: ["**/*.txt/*.txt"],
2979 extensions
: ["txt"],
2990 // it will be run twice, and text will be as-is at the second time, then it will not run third time
2991 text
: text
.replace("a()", "b()"),
2996 postprocess(messages
) {
2997 messages
[0][0].ruleId
= "post-processed";
3005 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
3007 assert
.strictEqual(count
, 2);
3008 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
3009 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
3012 describe("autofixing with processors", () => {
3013 const HTML_PROCESSOR
= Object
.freeze({
3015 return [text
.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
3017 postprocess(problemLists
) {
3018 return problemLists
[0].map(problem
=> {
3020 const updatedFix
= Object
.assign({}, problem
.fix
, {
3021 range
: problem
.fix
.range
.map(index
=> index
+ "<script>".length
)
3024 return Object
.assign({}, problem
, { fix
: updatedFix
});
3032 it("should run in autofix mode when using a processor that supports autofixing", async () => {
3033 eslint
= new ESLint({
3036 plugins
: ["test-processor"],
3041 extensions
: ["js", "txt"],
3047 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
3052 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
3054 assert
.strictEqual(results
[0].messages
.length
, 0);
3055 assert
.strictEqual(results
[0].output
, "<script>foo;</script>");
3058 it("should not run in autofix mode when using a processor that does not support autofixing", async () => {
3059 eslint
= new ESLint({
3062 plugins
: ["test-processor"],
3067 extensions
: ["js", "txt"],
3071 "test-processor": { processors
: { ".html": HTML_PROCESSOR
} }
3074 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
3076 assert
.strictEqual(results
[0].messages
.length
, 1);
3077 assert(!Object
.prototype.hasOwnProperty
.call(results
[0], "output"));
3080 it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", async () => {
3081 eslint
= new ESLint({
3084 plugins
: ["test-processor"],
3089 extensions
: ["js", "txt"],
3094 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
3099 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
3101 assert
.strictEqual(results
[0].messages
.length
, 1);
3102 assert(!Object
.prototype.hasOwnProperty
.call(results
[0], "output"));
3107 describe("Patterns which match no file should throw errors.", () => {
3109 eslint
= new ESLint({
3110 cwd
: getFixturePath("cli-engine"),
3115 it("one file", async () => {
3116 await assert
.rejects(async () => {
3117 await eslint
.lintFiles(["non-exist.js"]);
3118 }, /No files matching 'non-exist\.js' were found\./u);
3121 it("should throw if the directory exists and is empty", async () => {
3122 await assert
.rejects(async () => {
3123 await eslint
.lintFiles(["empty"]);
3124 }, /No files matching 'empty' were found\./u);
3127 it("one glob pattern", async () => {
3128 await assert
.rejects(async () => {
3129 await eslint
.lintFiles(["non-exist/**/*.js"]);
3130 }, /No files matching 'non-exist\/\*\*\/\*\.js' were found\./u);
3133 it("two files", async () => {
3134 await assert
.rejects(async () => {
3135 await eslint
.lintFiles(["aaa.js", "bbb.js"]);
3136 }, /No files matching 'aaa\.js' were found\./u);
3139 it("a mix of an existing file and a non-existing file", async () => {
3140 await assert
.rejects(async () => {
3141 await eslint
.lintFiles(["console.js", "non-exist.js"]);
3142 }, /No files matching 'non-exist\.js' were found\./u);
3146 describe("overrides", () => {
3148 eslint
= new ESLint({
3149 cwd
: getFixturePath("cli-engine/overrides-with-dot"),
3154 it("should recognize dotfiles", async () => {
3155 const ret
= await eslint
.lintFiles([".test-target.js"]);
3157 assert
.strictEqual(ret
.length
, 1);
3158 assert
.strictEqual(ret
[0].messages
.length
, 1);
3159 assert
.strictEqual(ret
[0].messages
[0].ruleId
, "no-unused-vars");
3163 describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
3165 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3166 cwd
: path
.join(os
.tmpdir(), "eslint/11510"),
3168 "no-console-error-in-overrides.json": JSON
.stringify({
3171 rules
: { "no-console": "error" }
3174 ".eslintrc.json": JSON
.stringify({
3175 extends: "./no-console-error-in-overrides.json",
3176 rules
: { "no-console": "off" }
3178 "a.js": "console.log();"
3183 eslint
= new ESLint({ cwd
: getPath() });
3189 it("should not report 'no-console' error.", async () => {
3190 const results
= await eslint
.lintFiles("a.js");
3192 assert
.strictEqual(results
.length
, 1);
3193 assert
.deepStrictEqual(results
[0].messages
, []);
3197 describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
3199 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3200 cwd
: path
.join(os
.tmpdir(), "eslint/11559"),
3202 "node_modules/eslint-plugin-test/index.js": `
3204 recommended: { plugins: ["test"] }
3208 meta: { schema: [{ type: "number" }] },
3209 create() { return {}; }
3213 ".eslintrc.json": JSON
.stringify({
3215 // Import via the recommended config.
3216 extends: "plugin:test/recommended",
3218 // Has invalid option.
3219 rules
: { "test/foo": ["error", "invalid-option"] }
3221 "a.js": "console.log();"
3226 eslint
= new ESLint({ cwd
: getPath() });
3233 it("should throw fatal error.", async () => {
3234 await assert
.rejects(async () => {
3235 await eslint
.lintFiles("a.js");
3236 }, /invalid-option/u);
3240 describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
3241 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3242 cwd
: path
.join(os
.tmpdir(), "cli-engine/11586"),
3244 "node_modules/eslint-plugin-test/index.js": `
3247 meta: { type: "problem", fixable: "code" },
3251 if (node.name === "example") {
3255 fix: fixer => fixer.replaceText(node, "fixed")
3266 rules
: { "test/no-example": "error" }
3273 eslint
= new ESLint({
3276 fixTypes
: ["problem"]
3284 it("should not crash.", async () => {
3285 const results
= await eslint
.lintFiles("a.js");
3287 assert
.strictEqual(results
.length
, 1);
3288 assert
.deepStrictEqual(results
[0].messages
, []);
3289 assert
.deepStrictEqual(results
[0].output
, "fixed;");
3293 describe("multiple processors", () => {
3294 const root
= path
.join(os
.tmpdir(), "eslint/eslint/multiple-processors");
3295 const commonFiles
= {
3296 "node_modules/pattern-processor/index.js": fs
.readFileSync(
3297 require
.resolve("../../fixtures/processors/pattern-processor"),
3300 "node_modules/eslint-plugin-markdown/index.js": `
3301 const { defineProcessor } = require("pattern-processor");
3302 const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
3303 exports.processors = {
3304 ".md": { ...processor, supportsAutofix: true },
3305 "non-fixable": processor
3308 "node_modules/eslint-plugin-html/index.js": `
3309 const { defineProcessor } = require("pattern-processor");
3310 const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
3311 const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
3312 exports.processors = {
3313 ".html": { ...processor, supportsAutofix: true },
3314 "non-fixable": processor,
3315 "legacy": legacyProcessor
3318 "test.md": unIndent
`
3320 console
.log("hello")
3325 console
.log("hello")
3328 console
.log("hello")
3337 cleanup
= () => { };
3340 afterEach(() => cleanup());
3342 it("should lint only JavaScript blocks if '--ext' was not given.", async () => {
3343 const teardown
= createCustomTeardown({
3348 plugins
: ["markdown", "html"],
3349 rules
: { semi
: "error" }
3354 cleanup
= teardown
.cleanup
;
3355 await teardown
.prepare();
3356 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3357 const results
= await eslint
.lintFiles(["test.md"]);
3359 assert
.strictEqual(results
.length
, 1);
3360 assert
.strictEqual(results
[0].messages
.length
, 1);
3361 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3362 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3365 it("should fix only JavaScript blocks if '--ext' was not given.", async () => {
3366 const teardown
= createCustomTeardown({
3371 plugins
: ["markdown", "html"],
3372 rules
: { semi
: "error" }
3377 await teardown
.prepare();
3378 cleanup
= teardown
.cleanup
;
3379 eslint
= new ESLint({ cwd
: teardown
.getPath(), fix
: true });
3380 const results
= await eslint
.lintFiles(["test.md"]);
3382 assert
.strictEqual(results
.length
, 1);
3383 assert
.strictEqual(results
[0].messages
.length
, 0);
3384 assert
.strictEqual(results
[0].output
, unIndent
`
3386 console
.log("hello");${/* ← fixed */""}
3391 console
.log("hello")${/* ← ignored */""}
3394 console
.log("hello")${/* ← ignored */""}
3400 it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3401 const teardown
= createCustomTeardown({
3406 plugins
: ["markdown", "html"],
3407 rules
: { semi
: "error" }
3412 await teardown
.prepare();
3413 cleanup
= teardown
.cleanup
;
3414 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3415 const results
= await eslint
.lintFiles(["test.md"]);
3417 assert
.strictEqual(results
.length
, 1);
3418 assert
.strictEqual(results
[0].messages
.length
, 2);
3419 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3420 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3421 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3422 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3425 it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3426 const teardown
= createCustomTeardown({
3431 plugins
: ["markdown", "html"],
3432 rules
: { semi
: "error" }
3437 await teardown
.prepare();
3438 cleanup
= teardown
.cleanup
;
3439 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"], fix
: true });
3440 const results
= await eslint
.lintFiles(["test.md"]);
3442 assert
.strictEqual(results
.length
, 1);
3443 assert
.strictEqual(results
[0].messages
.length
, 0);
3444 assert
.strictEqual(results
[0].output
, unIndent
`
3446 console
.log("hello");${/* ← fixed */""}
3451 console
.log("hello");${/* ← fixed */""}
3454 console
.log("hello")${/* ← ignored */""}
3460 it("should use overridden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", async () => {
3461 const teardown
= createCustomTeardown({
3466 plugins
: ["markdown", "html"],
3467 rules
: { semi
: "error" },
3471 processor
: "html/non-fixable" // supportsAutofix: false
3478 await teardown
.prepare();
3479 cleanup
= teardown
.cleanup
;
3480 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"], fix
: true });
3481 const results
= await eslint
.lintFiles(["test.md"]);
3483 assert
.strictEqual(results
.length
, 1);
3484 assert
.strictEqual(results
[0].messages
.length
, 1);
3485 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS Block in HTML Block
3486 assert
.strictEqual(results
[0].messages
[0].line
, 7);
3487 assert
.strictEqual(results
[0].messages
[0].fix
, void 0);
3488 assert
.strictEqual(results
[0].output
, unIndent
`
3490 console
.log("hello");${/* ← fixed */""}
3495 console
.log("hello")${/* ← reported but not fixed */""}
3498 console
.log("hello")
3504 it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", async () => {
3505 const teardown
= createCustomTeardown({
3510 plugins
: ["markdown", "html"],
3511 rules
: { semi
: "error" },
3516 // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
3523 files
: "**/*.html/*.js",
3526 "no-console": "error"
3534 await teardown
.prepare();
3535 cleanup
= teardown
.cleanup
;
3536 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3537 const results
= await eslint
.lintFiles(["test.md"]);
3539 assert
.strictEqual(results
.length
, 1);
3540 assert
.strictEqual(results
[0].messages
.length
, 2);
3541 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3542 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3543 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3544 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3547 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 () => {
3548 const teardown
= createCustomTeardown({
3553 plugins
: ["markdown", "html"],
3554 rules
: { semi
: "error" },
3558 processor
: "html/legacy", // this processor returns strings rather than `{text, filename}`
3561 "no-console": "error"
3565 files
: "**/*.html/*.js",
3576 await teardown
.prepare();
3577 cleanup
= teardown
.cleanup
;
3578 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3579 const results
= await eslint
.lintFiles(["test.md"]);
3581 assert
.strictEqual(results
.length
, 1);
3582 assert
.strictEqual(results
[0].messages
.length
, 3);
3583 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3584 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3585 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3586 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3587 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-console");
3588 assert
.strictEqual(results
[0].messages
[2].line
, 10);
3591 it("should throw an error if invalid processor was specified.", async () => {
3592 const teardown
= createCustomTeardown({
3597 plugins
: ["markdown", "html"],
3598 processor
: "markdown/unknown"
3603 await teardown
.prepare();
3604 cleanup
= teardown
.cleanup
;
3605 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3607 await assert
.rejects(async () => {
3608 await eslint
.lintFiles(["test.md"]);
3609 }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
3612 it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", async () => {
3613 const teardown
= createCustomTeardown({
3618 plugins
: ["markdown", "html"],
3619 rules
: { semi
: "error" },
3623 processor
: "html/.html"
3627 processor
: "markdown/.md"
3634 await teardown
.prepare();
3635 cleanup
= teardown
.cleanup
;
3636 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3637 const results
= await eslint
.lintFiles(["test.md"]);
3639 assert
.strictEqual(results
.length
, 1);
3640 assert
.strictEqual(results
[0].messages
.length
, 2);
3641 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3642 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3643 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3644 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3648 describe("MODULE_NOT_FOUND error handling", () => {
3649 const cwd
= getFixturePath("module-not-found");
3652 eslint
= new ESLint({ cwd
});
3655 it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", async () => {
3657 await eslint
.lintText("test", { filePath
: "extends-js/test.js" });
3659 assert
.strictEqual(err
.messageTemplate
, "extend-config-missing");
3660 assert
.deepStrictEqual(err
.messageData
, {
3661 configName
: "nonexistent-config",
3662 importerName
: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
3666 assert
.fail("Expected to throw an error");
3669 it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", async () => {
3671 await eslint
.lintText("test", { filePath
: "extends-plugin/test.js" });
3673 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3674 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3675 assert
.deepStrictEqual(err
.messageData
, {
3676 importerName
: `extends-plugin${path.sep}.eslintrc.yml`,
3677 pluginName
: "eslint-plugin-nonexistent-plugin",
3678 resolvePluginsRelativeTo
: path
.join(cwd
, "extends-plugin") // the directory of the config file.
3682 assert
.fail("Expected to throw an error");
3685 it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", async () => {
3687 await eslint
.lintText("test", { filePath
: "plugins/test.js" });
3689 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3690 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3691 assert
.deepStrictEqual(err
.messageData
, {
3692 importerName
: `plugins${path.sep}.eslintrc.yml`,
3693 pluginName
: "eslint-plugin-nonexistent-plugin",
3694 resolvePluginsRelativeTo
: path
.join(cwd
, "plugins") // the directory of the config file.
3698 assert
.fail("Expected to throw an error");
3701 it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", async () => {
3703 await eslint
.lintText("test", { filePath
: "throw-in-config-itself/test.js" });
3705 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3706 assert
.strictEqual(err
.messageTemplate
, void 0);
3709 assert
.fail("Expected to throw an error");
3712 it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3714 await eslint
.lintText("test", { filePath
: "throw-in-extends-js/test.js" });
3716 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3717 assert
.strictEqual(err
.messageTemplate
, void 0);
3720 assert
.fail("Expected to throw an error");
3723 it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3725 await eslint
.lintText("test", { filePath
: "throw-in-extends-plugin/test.js" });
3727 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3728 assert
.strictEqual(err
.messageTemplate
, void 0);
3731 assert
.fail("Expected to throw an error");
3734 it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3736 await eslint
.lintText("test", { filePath
: "throw-in-plugins/test.js" });
3738 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3739 assert
.strictEqual(err
.messageTemplate
, void 0);
3742 assert
.fail("Expected to throw an error");
3746 describe("with '--rulesdir' option", () => {
3748 const rootPath
= getFixturePath("cli-engine/with-rulesdir");
3749 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3752 "internal-rules/test.js": `
3753 module.exports = context => ({
3754 ExpressionStatement(node) {
3755 context.report({ node, message: "ok" })
3761 rules
: { test
: "error" }
3763 "test.js": "console.log('hello')"
3767 beforeEach(prepare
);
3771 it("should use the configured rules which are defined by '--rulesdir' option.", async () => {
3772 eslint
= new ESLint({
3774 rulePaths
: ["internal-rules"]
3776 const results
= await eslint
.lintFiles(["test.js"]);
3778 assert
.strictEqual(results
.length
, 1);
3779 assert
.strictEqual(results
[0].messages
.length
, 1);
3780 assert
.strictEqual(results
[0].messages
[0].message
, "ok");
3784 describe("glob pattern '[ab].js'", () => {
3785 const root
= getFixturePath("cli-engine/unmatched-glob");
3790 cleanup
= () => { };
3793 afterEach(() => cleanup());
3795 it("should match '[ab].js' if existed.", async () => {
3797 const teardown
= createCustomTeardown({
3804 ".eslintrc.yml": "root: true"
3808 await teardown
.prepare();
3809 cleanup
= teardown
.cleanup
;
3811 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3812 const results
= await eslint
.lintFiles(["[ab].js"]);
3813 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3815 assert
.deepStrictEqual(filenames
, ["[ab].js"]);
3818 it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", async () => {
3819 const teardown
= createCustomTeardown({
3825 ".eslintrc.yml": "root: true"
3829 await teardown
.prepare();
3830 cleanup
= teardown
.cleanup
;
3831 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3832 const results
= await eslint
.lintFiles(["[ab].js"]);
3833 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3835 assert
.deepStrictEqual(filenames
, ["a.js", "b.js"]);
3839 describe("with 'noInlineConfig' setting", () => {
3840 const root
= getFixturePath("cli-engine/noInlineConfig");
3845 cleanup
= () => { };
3848 afterEach(() => cleanup());
3850 it("should warn directive comments if 'noInlineConfig' was given.", async () => {
3851 const teardown
= createCustomTeardown({
3854 "test.js": "/* globals foo */",
3855 ".eslintrc.yml": "noInlineConfig: true"
3859 await teardown
.prepare();
3860 cleanup
= teardown
.cleanup
;
3861 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3863 const results
= await eslint
.lintFiles(["test.js"]);
3864 const messages
= results
[0].messages
;
3866 assert
.strictEqual(messages
.length
, 1);
3867 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
3870 it("should show the config file what the 'noInlineConfig' came from.", async () => {
3871 const teardown
= createCustomTeardown({
3874 "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
3875 "test.js": "/* globals foo */",
3876 ".eslintrc.yml": "extends: foo"
3880 await teardown
.prepare();
3881 cleanup
= teardown
.cleanup
;
3882 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3884 const results
= await eslint
.lintFiles(["test.js"]);
3885 const messages
= results
[0].messages
;
3887 assert
.strictEqual(messages
.length
, 1);
3888 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
3892 describe("with 'reportUnusedDisableDirectives' setting", () => {
3893 const root
= getFixturePath("cli-engine/reportUnusedDisableDirectives");
3898 cleanup
= () => { };
3901 afterEach(() => cleanup());
3903 it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", async () => {
3904 const teardown
= createCustomTeardown({
3907 "test.js": "/* eslint-disable eqeqeq */",
3908 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3913 await teardown
.prepare();
3914 cleanup
= teardown
.cleanup
;
3915 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3917 const results
= await eslint
.lintFiles(["test.js"]);
3918 const messages
= results
[0].messages
;
3920 assert
.strictEqual(messages
.length
, 1);
3921 assert
.strictEqual(messages
[0].severity
, 1);
3922 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3925 describe("the runtime option overrides config files.", () => {
3926 it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", async () => {
3927 const teardown
= createCustomTeardown({
3930 "test.js": "/* eslint-disable eqeqeq */",
3931 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3935 await teardown
.prepare();
3936 cleanup
= teardown
.cleanup
;
3938 eslint
= new ESLint({
3939 cwd
: teardown
.getPath(),
3940 reportUnusedDisableDirectives
: "off"
3943 const results
= await eslint
.lintFiles(["test.js"]);
3944 const messages
= results
[0].messages
;
3946 assert
.strictEqual(messages
.length
, 0);
3949 it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", async () => {
3950 const teardown
= createCustomTeardown({
3953 "test.js": "/* eslint-disable eqeqeq */",
3954 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3958 await teardown
.prepare();
3959 cleanup
= teardown
.cleanup
;
3961 eslint
= new ESLint({
3962 cwd
: teardown
.getPath(),
3963 reportUnusedDisableDirectives
: "error"
3966 const results
= await eslint
.lintFiles(["test.js"]);
3967 const messages
= results
[0].messages
;
3969 assert
.strictEqual(messages
.length
, 1);
3970 assert
.strictEqual(messages
[0].severity
, 2);
3971 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3976 describe("with 'overrides[*].extends' setting on deep locations", () => {
3977 const root
= getFixturePath("cli-engine/deeply-overrides-i-extends");
3978 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3981 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
3982 overrides: [{ files: ["*test*"], extends: "two" }]
3984 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
3985 overrides: [{ files: ["*.js"], extends: "three" }]
3987 "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
3988 rules: { "no-console": "error" }
3990 "test.js": "console.log('hello')",
3991 ".eslintrc.yml": "extends: one"
3995 beforeEach(prepare
);
3998 it("should not throw.", async () => {
3999 eslint
= new ESLint({ cwd
: getPath() });
4000 const results
= await eslint
.lintFiles(["test.js"]);
4001 const messages
= results
[0].messages
;
4003 assert
.strictEqual(messages
.length
, 1);
4004 assert
.strictEqual(messages
[0].ruleId
, "no-console");
4008 describe("don't ignore the entry directory.", () => {
4009 const root
= getFixturePath("cli-engine/dont-ignore-entry-dir");
4014 cleanup
= () => { };
4017 afterEach(async () => {
4020 const configFilePath
= path
.resolve(root
, "../.eslintrc.json");
4022 if (shell
.test("-e", configFilePath
)) {
4023 shell
.rm(configFilePath
);
4027 it("'lintFiles(\".\")' should not load config files from outside of \".\".", async () => {
4028 const teardown
= createCustomTeardown({
4031 "../.eslintrc.json": "BROKEN FILE",
4032 ".eslintrc.json": JSON
.stringify({ root
: true }),
4033 "index.js": "console.log(\"hello\")"
4037 await teardown
.prepare();
4038 cleanup
= teardown
.cleanup
;
4039 eslint
= new ESLint({ cwd
: teardown
.getPath() });
4041 // Don't throw "failed to load config file" error.
4042 await eslint
.lintFiles(".");
4045 it("'lintFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", async () => {
4046 const teardown
= createCustomTeardown({
4049 "../.eslintrc.json": { ignorePatterns
: ["/dont-ignore-entry-dir"] },
4050 ".eslintrc.json": { root
: true },
4051 "index.js": "console.log(\"hello\")"
4055 await teardown
.prepare();
4056 cleanup
= teardown
.cleanup
;
4057 eslint
= new ESLint({ cwd
: teardown
.getPath() });
4059 // Don't throw "file not found" error.
4060 await eslint
.lintFiles(".");
4063 it("'lintFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", async () => {
4064 const teardown
= createCustomTeardown({
4067 ".eslintrc.json": { ignorePatterns
: ["/subdir"] },
4068 "subdir/.eslintrc.json": { root
: true },
4069 "subdir/index.js": "console.log(\"hello\")"
4073 await teardown
.prepare();
4074 cleanup
= teardown
.cleanup
;
4075 eslint
= new ESLint({ cwd
: teardown
.getPath() });
4077 // Don't throw "file not found" error.
4078 await eslint
.lintFiles("subdir");
4082 it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
4083 eslint
= new ESLint();
4084 await assert
.rejects(() => eslint
.lintFiles(777), /'patterns' must be a non-empty string or an array of non-empty strings/u);
4085 await assert
.rejects(() => eslint
.lintFiles([null]), /'patterns' must be a non-empty string or an array of non-empty strings/u);
4089 describe("calculateConfigForFile", () => {
4090 it("should return the info from Config#getConfig when called", async () => {
4092 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json")
4094 const engine
= new ESLint(options
);
4095 const filePath
= getFixturePath("single-quoted.js");
4096 const actualConfig
= await engine
.calculateConfigForFile(filePath
);
4097 const expectedConfig
= new CascadingConfigArrayFactory({ specificConfigPath
: options
.overrideConfigFile
})
4098 .getConfigArrayForFile(filePath
)
4099 .extractConfig(filePath
)
4100 .toCompatibleObjectAsConfigFileContent();
4102 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4105 it("should return the config for a file that doesn't exist", async () => {
4106 const engine
= new ESLint();
4107 const filePath
= getFixturePath("does_not_exist.js");
4108 const existingSiblingFilePath
= getFixturePath("single-quoted.js");
4109 const actualConfig
= await engine
.calculateConfigForFile(filePath
);
4110 const expectedConfig
= await engine
.calculateConfigForFile(existingSiblingFilePath
);
4112 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4115 it("should return the config for a virtual file that is a child of an existing file", async () => {
4116 const engine
= new ESLint();
4117 const parentFileName
= "single-quoted.js";
4118 const filePath
= getFixturePath(parentFileName
, "virtual.js"); // single-quoted.js/virtual.js
4119 const parentFilePath
= getFixturePath(parentFileName
);
4120 const actualConfig
= await engine
.calculateConfigForFile(filePath
);
4121 const expectedConfig
= await engine
.calculateConfigForFile(parentFilePath
);
4123 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4126 it("should return the config when run from within a subdir", async () => {
4128 cwd
: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
4130 const engine
= new ESLint(options
);
4131 const filePath
= getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
4132 const actualConfig
= await engine
.calculateConfigForFile("./.eslintrc");
4133 const expectedConfig
= new CascadingConfigArrayFactory(options
)
4134 .getConfigArrayForFile(filePath
)
4135 .extractConfig(filePath
)
4136 .toCompatibleObjectAsConfigFileContent();
4138 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
4141 it("should throw an error if a directory path was given.", async () => {
4142 const engine
= new ESLint();
4145 await engine
.calculateConfigForFile(".");
4147 assert
.strictEqual(error
.messageTemplate
, "print-config-with-directory-path");
4150 assert
.fail("should throw an error");
4153 it("should throw if non-string value is given to 'filePath' parameter", async () => {
4154 const eslint
= new ESLint();
4156 await assert
.rejects(() => eslint
.calculateConfigForFile(null), /'filePath' must be a non-empty string/u);
4159 // https://github.com/eslint/eslint/issues/13793
4160 it("should throw with an invalid built-in rule config", async () => {
4164 "no-alert": ["error", {
4165 thisDoesNotExist
: true
4170 const engine
= new ESLint(options
);
4171 const filePath
= getFixturePath("single-quoted.js");
4173 await assert
.rejects(
4174 () => engine
.calculateConfigForFile(filePath
),
4175 /Configuration for rule "no-alert" is invalid:/u
4180 describe("isPathIgnored", () => {
4181 it("should check if the given path is ignored", async () => {
4182 const engine
= new ESLint({
4183 ignorePath
: getFixturePath(".eslintignore2"),
4184 cwd
: getFixturePath()
4187 assert(await engine
.isPathIgnored("undef.js"));
4188 assert(!await engine
.isPathIgnored("passing.js"));
4191 it("should return false if ignoring is disabled", async () => {
4192 const engine
= new ESLint({
4194 ignorePath
: getFixturePath(".eslintignore2"),
4195 cwd
: getFixturePath()
4198 assert(!await engine
.isPathIgnored("undef.js"));
4201 // https://github.com/eslint/eslint/issues/5547
4202 it("should return true for default ignores even if ignoring is disabled", async () => {
4203 const engine
= new ESLint({
4205 cwd
: getFixturePath("cli-engine")
4208 assert(await engine
.isPathIgnored("node_modules/foo.js"));
4211 describe("about the default ignore patterns", () => {
4212 it("should always apply defaultPatterns if ignore option is true", async () => {
4213 const cwd
= getFixturePath("ignored-paths");
4214 const engine
= new ESLint({ cwd
});
4216 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
4217 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
4220 it("should still apply defaultPatterns if ignore option is is false", async () => {
4221 const cwd
= getFixturePath("ignored-paths");
4222 const engine
= new ESLint({ ignore
: false, cwd
});
4224 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
4225 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
4228 it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", async () => {
4229 const cwd
= getFixturePath("ignored-paths");
4230 const engine
= new ESLint({
4233 ignorePatterns
: "!/node_modules/package"
4237 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4240 it("should allow subfolders of defaultPatterns to be unignored by ignorePath", async () => {
4241 const cwd
= getFixturePath("ignored-paths");
4242 const engine
= new ESLint({ cwd
, ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
4244 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4247 it("should ignore dotfiles", async () => {
4248 const cwd
= getFixturePath("ignored-paths");
4249 const engine
= new ESLint({ cwd
});
4251 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4252 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4255 it("should ignore directories beginning with a dot", async () => {
4256 const cwd
= getFixturePath("ignored-paths");
4257 const engine
= new ESLint({ cwd
});
4259 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4260 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4263 it("should still ignore dotfiles when ignore option disabled", async () => {
4264 const cwd
= getFixturePath("ignored-paths");
4265 const engine
= new ESLint({ ignore
: false, cwd
});
4267 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4268 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4271 it("should still ignore directories beginning with a dot when ignore option disabled", async () => {
4272 const cwd
= getFixturePath("ignored-paths");
4273 const engine
= new ESLint({ ignore
: false, cwd
});
4275 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4276 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4279 it("should not ignore absolute paths containing '..'", async () => {
4280 const cwd
= getFixturePath("ignored-paths");
4281 const engine
= new ESLint({ cwd
});
4283 assert(!await engine
.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
4286 it("should ignore /node_modules/ relative to .eslintignore when loaded", async () => {
4287 const cwd
= getFixturePath("ignored-paths");
4288 const engine
= new ESLint({ ignorePath
: getFixturePath("ignored-paths", ".eslintignore"), cwd
});
4290 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
4291 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
4294 it("should ignore /node_modules/ relative to cwd without an .eslintignore", async () => {
4295 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4296 const engine
= new ESLint({ cwd
});
4298 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
4299 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
4303 describe("with no .eslintignore file", () => {
4304 it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", async () => {
4305 const cwd
= getFixturePath("ignored-paths", "configurations");
4306 const engine
= new ESLint({ cwd
});
4308 // a .eslintignore in parent directories includes `*.js`, but don't load it.
4309 assert(!await engine
.isPathIgnored("foo.js"));
4310 assert(await engine
.isPathIgnored("node_modules/foo.js"));
4313 it("should return false for files outside of the cwd (with no ignore file provided)", async () => {
4315 // Default ignore patterns should not inadvertently ignore files in parent directories
4316 const engine
= new ESLint({ cwd
: getFixturePath("ignored-paths", "no-ignore-file") });
4318 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4322 describe("with .eslintignore file or package.json file", () => {
4323 it("should load .eslintignore from cwd when explicitly passed", async () => {
4324 const cwd
= getFixturePath("ignored-paths");
4325 const engine
= new ESLint({ cwd
});
4327 // `${cwd}/.eslintignore` includes `sampleignorepattern`.
4328 assert(await engine
.isPathIgnored("sampleignorepattern"));
4331 it("should use package.json's eslintIgnore files if no specified .eslintignore file", async () => {
4332 const cwd
= getFixturePath("ignored-paths", "package-json-ignore");
4333 const engine
= new ESLint({ cwd
});
4335 assert(await engine
.isPathIgnored("hello.js"));
4336 assert(await engine
.isPathIgnored("world.js"));
4339 it("should use correct message template if failed to parse package.json", () => {
4340 const cwd
= getFixturePath("ignored-paths", "broken-package-json");
4342 assert
.throws(() => {
4344 // eslint-disable-next-line no-new -- Check for error
4345 new ESLint({ cwd
});
4347 assert
.strictEqual(error
.messageTemplate
, "failed-to-read-json");
4353 it("should not use package.json's eslintIgnore files if specified .eslintignore file", async () => {
4354 const cwd
= getFixturePath("ignored-paths");
4355 const engine
= new ESLint({ cwd
});
4358 * package.json includes `hello.js` and `world.js`.
4359 * .eslintignore includes `sampleignorepattern`.
4361 assert(!await engine
.isPathIgnored("hello.js"));
4362 assert(!await engine
.isPathIgnored("world.js"));
4363 assert(await engine
.isPathIgnored("sampleignorepattern"));
4366 it("should error if package.json's eslintIgnore is not an array of file paths", () => {
4367 const cwd
= getFixturePath("ignored-paths", "bad-package-json-ignore");
4369 assert
.throws(() => {
4370 // eslint-disable-next-line no-new -- Check for throwing
4371 new ESLint({ cwd
});
4372 }, /Package\.json eslintIgnore property requires an array of paths/u);
4376 describe("with --ignore-pattern option", () => {
4377 it("should accept a string for options.ignorePattern", async () => {
4378 const cwd
= getFixturePath("ignored-paths", "ignore-pattern");
4379 const engine
= new ESLint({
4381 ignorePatterns
: "ignore-me.txt"
4386 assert(await engine
.isPathIgnored("ignore-me.txt"));
4389 it("should accept an array for options.ignorePattern", async () => {
4390 const engine
= new ESLint({
4392 ignorePatterns
: ["a", "b"]
4397 assert(await engine
.isPathIgnored("a"));
4398 assert(await engine
.isPathIgnored("b"));
4399 assert(!await engine
.isPathIgnored("c"));
4402 it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", async () => {
4403 const cwd
= getFixturePath("ignored-paths");
4404 const engine
= new ESLint({
4406 ignorePatterns
: "not-a-file"
4411 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
4414 it("should return true for file matching an ignore pattern exactly", async () => {
4415 const cwd
= getFixturePath("ignored-paths");
4416 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "undef.js" }, cwd
});
4418 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4421 it("should return false for file matching an invalid ignore pattern with leading './'", async () => {
4422 const cwd
= getFixturePath("ignored-paths");
4423 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "./undef.js" }, cwd
});
4425 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4428 it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", async () => {
4429 const cwd
= getFixturePath("ignored-paths");
4430 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "/undef.js" }, cwd
});
4432 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
4435 it("should return true for file matching a child of an ignore pattern", async () => {
4436 const cwd
= getFixturePath("ignored-paths");
4437 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "ignore-pattern" }, cwd
});
4439 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
4442 it("should return true for file matching a grandchild of an ignore pattern", async () => {
4443 const cwd
= getFixturePath("ignored-paths");
4444 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "ignore-pattern" }, cwd
});
4446 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
4449 it("should return false for file not matching any ignore pattern", async () => {
4450 const cwd
= getFixturePath("ignored-paths");
4451 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "failing.js" }, cwd
});
4453 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
4456 it("two globstar '**' ignore pattern should ignore files in nested directories", async () => {
4457 const cwd
= getFixturePath("ignored-paths");
4458 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "**/*.js" }, cwd
});
4460 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4461 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
4462 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
4463 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
4464 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
4465 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
4469 describe("with --ignore-path option", () => {
4470 it("initialization with ignorePath should work when cwd is a parent directory", async () => {
4471 const cwd
= getFixturePath("ignored-paths");
4472 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4473 const engine
= new ESLint({ ignorePath
, cwd
});
4475 assert(await engine
.isPathIgnored("custom-name/foo.js"));
4478 it("initialization with ignorePath should work when the file is in the cwd", async () => {
4479 const cwd
= getFixturePath("ignored-paths", "custom-name");
4480 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4481 const engine
= new ESLint({ ignorePath
, cwd
});
4483 assert(await engine
.isPathIgnored("foo.js"));
4486 it("initialization with ignorePath should work when cwd is a subdirectory", async () => {
4487 const cwd
= getFixturePath("ignored-paths", "custom-name", "subdirectory");
4488 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4489 const engine
= new ESLint({ ignorePath
, cwd
});
4491 assert(await engine
.isPathIgnored("../custom-name/foo.js"));
4494 it("initialization with invalid file should throw error", () => {
4495 const cwd
= getFixturePath("ignored-paths");
4496 const ignorePath
= getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
4498 assert
.throws(() => {
4499 // eslint-disable-next-line no-new -- Check for throwing
4500 new ESLint({ ignorePath
, cwd
});
4501 }, /Cannot read \.eslintignore file/u);
4504 it("should return false for files outside of ignorePath's directory", async () => {
4505 const cwd
= getFixturePath("ignored-paths");
4506 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4507 const engine
= new ESLint({ ignorePath
, cwd
});
4509 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4512 it("should resolve relative paths from CWD", async () => {
4513 const cwd
= getFixturePath("ignored-paths", "subdir");
4514 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4515 const engine
= new ESLint({ ignorePath
, cwd
});
4517 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4518 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4521 it("should resolve relative paths from CWD when it's in a child directory", async () => {
4522 const cwd
= getFixturePath("ignored-paths");
4523 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4524 const engine
= new ESLint({ ignorePath
, cwd
});
4526 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4527 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4528 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4529 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
4531 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
4534 it("should resolve relative paths from CWD when it contains negated globs", async () => {
4535 const cwd
= getFixturePath("ignored-paths");
4536 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4537 const engine
= new ESLint({ ignorePath
, cwd
});
4539 assert(await engine
.isPathIgnored("subdir/blah.txt"));
4540 assert(await engine
.isPathIgnored("blah.txt"));
4541 assert(await engine
.isPathIgnored("subdir/bar.txt"));
4542 assert(!await engine
.isPathIgnored("bar.txt"));
4543 assert(!await engine
.isPathIgnored("subdir/baz.txt"));
4544 assert(!await engine
.isPathIgnored("baz.txt"));
4547 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", async () => {
4548 const cwd
= getFixturePath("ignored-paths");
4549 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4550 const engine
= new ESLint({ ignorePath
, cwd
});
4552 assert(await engine
.isPathIgnored("node_modules/blah.js"));
4555 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", async () => {
4556 const cwd
= getFixturePath("ignored-paths", "subdir");
4557 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4558 const engine
= new ESLint({ ignorePath
, cwd
});
4560 assert(await engine
.isPathIgnored("node_modules/blah.js"));
4563 it("should handle .eslintignore which contains CRLF correctly.", async () => {
4564 const ignoreFileContent
= fs
.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
4566 assert(ignoreFileContent
.includes("\r"), "crlf/.eslintignore should contains CR.");
4567 const cwd
= getFixturePath("ignored-paths");
4568 const ignorePath
= getFixturePath("ignored-paths", "crlf/.eslintignore");
4569 const engine
= new ESLint({ ignorePath
, cwd
});
4571 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
4572 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
4573 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
4576 it("should not include comments in ignore rules", async () => {
4577 const cwd
= getFixturePath("ignored-paths");
4578 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithComments");
4579 const engine
= new ESLint({ ignorePath
, cwd
});
4581 assert(!await engine
.isPathIgnored("# should be ignored"));
4582 assert(await engine
.isPathIgnored("this_one_not"));
4585 it("should ignore a non-negated pattern", async () => {
4586 const cwd
= getFixturePath("ignored-paths");
4587 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4588 const engine
= new ESLint({ ignorePath
, cwd
});
4590 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
4593 it("should not ignore a negated pattern", async () => {
4594 const cwd
= getFixturePath("ignored-paths");
4595 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4596 const engine
= new ESLint({ ignorePath
, cwd
});
4598 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
4602 describe("with --ignore-path option and --ignore-pattern option", () => {
4603 it("should return false for ignored file when unignored with ignore pattern", async () => {
4604 const cwd
= getFixturePath("ignored-paths");
4605 const engine
= new ESLint({
4606 ignorePath
: getFixturePath("ignored-paths", ".eslintignore"),
4608 ignorePatterns
: "!sampleignorepattern"
4613 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
4617 it("should throw if non-string value is given to 'filePath' parameter", async () => {
4618 const eslint
= new ESLint();
4620 await assert
.rejects(() => eslint
.isPathIgnored(null), /'filePath' must be a non-empty string/u);
4624 describe("loadFormatter()", () => {
4625 it("should return a formatter object when a bundled formatter is requested", async () => {
4626 const engine
= new ESLint();
4627 const formatter
= await engine
.loadFormatter("compact");
4629 assert
.strictEqual(typeof formatter
, "object");
4630 assert
.strictEqual(typeof formatter
.format
, "function");
4633 it("should return a formatter object when no argument is passed", async () => {
4634 const engine
= new ESLint();
4635 const formatter
= await engine
.loadFormatter();
4637 assert
.strictEqual(typeof formatter
, "object");
4638 assert
.strictEqual(typeof formatter
.format
, "function");
4641 it("should return a formatter object when a custom formatter is requested", async () => {
4642 const engine
= new ESLint();
4643 const formatter
= await engine
.loadFormatter(getFixturePath("formatters", "simple.js"));
4645 assert
.strictEqual(typeof formatter
, "object");
4646 assert
.strictEqual(typeof formatter
.format
, "function");
4649 it("should return a formatter object when a custom formatter is requested, also if the path has backslashes", async () => {
4650 const engine
= new ESLint({
4651 cwd
: path
.join(fixtureDir
, "..")
4653 const formatter
= await engine
.loadFormatter(".\\fixtures\\formatters\\simple.js");
4655 assert
.strictEqual(typeof formatter
, "object");
4656 assert
.strictEqual(typeof formatter
.format
, "function");
4659 it("should return a formatter object when a formatter prefixed with eslint-formatter is requested", async () => {
4660 const engine
= new ESLint({
4661 cwd
: getFixturePath("cli-engine")
4663 const formatter
= await engine
.loadFormatter("bar");
4665 assert
.strictEqual(typeof formatter
, "object");
4666 assert
.strictEqual(typeof formatter
.format
, "function");
4669 it("should return a formatter object when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", async () => {
4670 const engine
= new ESLint({
4671 cwd
: getFixturePath("cli-engine")
4673 const formatter
= await engine
.loadFormatter("eslint-formatter-bar");
4675 assert
.strictEqual(typeof formatter
, "object");
4676 assert
.strictEqual(typeof formatter
.format
, "function");
4679 it("should return a formatter object when a formatter is requested within a scoped npm package", async () => {
4680 const engine
= new ESLint({
4681 cwd
: getFixturePath("cli-engine")
4683 const formatter
= await engine
.loadFormatter("@somenamespace/foo");
4685 assert
.strictEqual(typeof formatter
, "object");
4686 assert
.strictEqual(typeof formatter
.format
, "function");
4689 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 () => {
4690 const engine
= new ESLint({
4691 cwd
: getFixturePath("cli-engine")
4693 const formatter
= await engine
.loadFormatter("@somenamespace/eslint-formatter-foo");
4695 assert
.strictEqual(typeof formatter
, "object");
4696 assert
.strictEqual(typeof formatter
.format
, "function");
4699 it("should throw if a custom formatter doesn't exist", async () => {
4700 const engine
= new ESLint();
4701 const formatterPath
= getFixturePath("formatters", "doesntexist.js");
4702 const fullFormatterPath
= path
.resolve(formatterPath
);
4704 await assert
.rejects(async () => {
4705 await engine
.loadFormatter(formatterPath
);
4706 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
4709 it("should throw if a built-in formatter doesn't exist", async () => {
4710 const engine
= new ESLint();
4711 const fullFormatterPath
= path
.resolve(__dirname
, "../../../lib/cli-engine/formatters/special");
4713 await assert
.rejects(async () => {
4714 await engine
.loadFormatter("special");
4715 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
4718 it("should throw if the required formatter exists but has an error", async () => {
4719 const engine
= new ESLint();
4720 const formatterPath
= getFixturePath("formatters", "broken.js");
4722 await assert
.rejects(async () => {
4723 await engine
.loadFormatter(formatterPath
);
4724 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`), "u"));
4727 it("should throw if a non-string formatter name is passed", async () => {
4728 const engine
= new ESLint();
4730 await assert
.rejects(async () => {
4731 await engine
.loadFormatter(5);
4732 }, /'name' must be a string/u);
4736 describe("getErrorResults()", () => {
4737 it("should report 5 error messages when looking for errors only", async () => {
4738 process
.chdir(originalDir
);
4739 const engine
= new ESLint();
4740 const results
= await engine
.lintText("var foo = 'bar';");
4741 const errorResults
= ESLint
.getErrorResults(results
);
4743 assert
.strictEqual(errorResults
[0].messages
.length
, 5);
4744 assert
.strictEqual(errorResults
[0].errorCount
, 5);
4745 assert
.strictEqual(errorResults
[0].fixableErrorCount
, 3);
4746 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4747 assert
.strictEqual(errorResults
[0].messages
[0].ruleId
, "strict");
4748 assert
.strictEqual(errorResults
[0].messages
[0].severity
, 2);
4749 assert
.strictEqual(errorResults
[0].messages
[1].ruleId
, "no-var");
4750 assert
.strictEqual(errorResults
[0].messages
[1].severity
, 2);
4751 assert
.strictEqual(errorResults
[0].messages
[2].ruleId
, "no-unused-vars");
4752 assert
.strictEqual(errorResults
[0].messages
[2].severity
, 2);
4753 assert
.strictEqual(errorResults
[0].messages
[3].ruleId
, "quotes");
4754 assert
.strictEqual(errorResults
[0].messages
[3].severity
, 2);
4755 assert
.strictEqual(errorResults
[0].messages
[4].ruleId
, "eol-last");
4756 assert
.strictEqual(errorResults
[0].messages
[4].severity
, 2);
4759 it("should not mutate passed report parameter", async () => {
4760 process
.chdir(originalDir
);
4761 const engine
= new ESLint({
4763 rules
: { quotes
: [1, "double"] }
4766 const results
= await engine
.lintText("var foo = 'bar';");
4767 const reportResultsLength
= results
[0].messages
.length
;
4769 ESLint
.getErrorResults(results
);
4771 assert
.strictEqual(results
[0].messages
.length
, reportResultsLength
);
4774 it("should report a warningCount of 0 when looking for errors only", async () => {
4775 process
.chdir(originalDir
);
4776 const engine
= new ESLint();
4777 const results
= await engine
.lintText("var foo = 'bar';");
4778 const errorResults
= ESLint
.getErrorResults(results
);
4780 assert
.strictEqual(errorResults
[0].warningCount
, 0);
4781 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4784 it("should return 0 error or warning messages even when the file has warnings", async () => {
4785 const engine
= new ESLint({
4786 ignorePath
: path
.join(fixtureDir
, ".eslintignore"),
4787 cwd
: path
.join(fixtureDir
, "..")
4790 filePath
: "fixtures/passing.js",
4793 const results
= await engine
.lintText("var bar = foo;", options
);
4794 const errorReport
= ESLint
.getErrorResults(results
);
4796 assert
.strictEqual(errorReport
.length
, 0);
4797 assert
.strictEqual(results
.length
, 1);
4798 assert
.strictEqual(results
[0].errorCount
, 0);
4799 assert
.strictEqual(results
[0].warningCount
, 1);
4802 it("should return source code of file in the `source` property", async () => {
4803 process
.chdir(originalDir
);
4804 const engine
= new ESLint({
4807 rules
: { quotes
: [2, "double"] }
4810 const results
= await engine
.lintText("var foo = 'bar';");
4811 const errorResults
= ESLint
.getErrorResults(results
);
4813 assert
.strictEqual(errorResults
[0].messages
.length
, 1);
4814 assert
.strictEqual(errorResults
[0].source
, "var foo = 'bar';");
4817 it("should contain `output` property after fixes", async () => {
4818 process
.chdir(originalDir
);
4819 const engine
= new ESLint({
4829 const results
= await engine
.lintText("console.log('foo')");
4830 const errorResults
= ESLint
.getErrorResults(results
);
4832 assert
.strictEqual(errorResults
[0].messages
.length
, 1);
4833 assert
.strictEqual(errorResults
[0].output
, "console.log('foo');");
4837 describe("getRulesMetaForResults()", () => {
4838 it("should return empty object when there are no linting errors", async () => {
4839 const engine
= new ESLint({
4843 const rulesMeta
= engine
.getRulesMetaForResults([]);
4845 assert
.strictEqual(Object
.keys(rulesMeta
).length
, 0);
4848 it("should return one rule meta when there is a linting error", async () => {
4849 const engine
= new ESLint({
4858 const results
= await engine
.lintText("a");
4859 const rulesMeta
= engine
.getRulesMetaForResults(results
);
4861 assert
.strictEqual(rulesMeta
.semi
, coreRules
.get("semi").meta
);
4864 it("should return multiple rule meta when there are multiple linting errors", async () => {
4865 const engine
= new ESLint({
4870 quotes
: [2, "double"]
4875 const results
= await engine
.lintText("'a'");
4876 const rulesMeta
= engine
.getRulesMetaForResults(results
);
4878 assert
.strictEqual(rulesMeta
.semi
, coreRules
.get("semi").meta
);
4879 assert
.strictEqual(rulesMeta
.quotes
, coreRules
.get("quotes").meta
);
4882 it("should return multiple rule meta when there are multiple linting errors from a plugin", async () => {
4883 const nodePlugin
= require("eslint-plugin-node");
4884 const engine
= new ESLint({
4892 "node/no-new-require": 2,
4894 quotes
: [2, "double"]
4899 const results
= await engine
.lintText("new require('hi')");
4900 const rulesMeta
= engine
.getRulesMetaForResults(results
);
4902 assert
.strictEqual(rulesMeta
.semi
, coreRules
.get("semi").meta
);
4903 assert
.strictEqual(rulesMeta
.quotes
, coreRules
.get("quotes").meta
);
4905 rulesMeta
["node/no-new-require"],
4906 nodePlugin
.rules
["no-new-require"].meta
4911 describe("outputFixes()", () => {
4913 sinon
.verifyAndRestore();
4916 it("should call fs.writeFile() for each result with output", async () => {
4918 writeFile
: sinon
.spy(callLastArgument
)
4920 const spy
= fakeFS
.writeFile
;
4921 const { ESLint
: localESLint
} = proxyquire("../../../lib/eslint/eslint", {
4927 filePath
: path
.resolve("foo.js"),
4931 filePath
: path
.resolve("bar.js"),
4936 await localESLint
.outputFixes(results
);
4938 assert
.strictEqual(spy
.callCount
, 2);
4939 assert(spy
.firstCall
.calledWithExactly(path
.resolve("foo.js"), "bar", sinon
.match
.func
), "First call was incorrect.");
4940 assert(spy
.secondCall
.calledWithExactly(path
.resolve("bar.js"), "baz", sinon
.match
.func
), "Second call was incorrect.");
4943 it("should call fs.writeFile() for each result with output and not at all for a result without output", async () => {
4945 writeFile
: sinon
.spy(callLastArgument
)
4947 const spy
= fakeFS
.writeFile
;
4948 const { ESLint
: localESLint
} = proxyquire("../../../lib/eslint/eslint", {
4953 filePath
: path
.resolve("foo.js"),
4957 filePath
: path
.resolve("abc.js")
4960 filePath
: path
.resolve("bar.js"),
4965 await localESLint
.outputFixes(results
);
4967 assert
.strictEqual(spy
.callCount
, 2);
4968 assert(spy
.firstCall
.calledWithExactly(path
.resolve("foo.js"), "bar", sinon
.match
.func
), "First call was incorrect.");
4969 assert(spy
.secondCall
.calledWithExactly(path
.resolve("bar.js"), "baz", sinon
.match
.func
), "Second call was incorrect.");
4972 it("should throw if non object array is given to 'results' parameter", async () => {
4973 await assert
.rejects(() => ESLint
.outputFixes(null), /'results' must be an array/u);
4974 await assert
.rejects(() => ESLint
.outputFixes([null]), /'results' must include only objects/u);
4978 describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
4979 it("should report a violation for disabling rules", async () => {
4981 "alert('test'); // eslint-disable-line no-alert"
4986 allowInlineConfig
: false,
4988 env
: { browser
: true },
4992 "no-trailing-spaces": 0,
4998 const eslintCLI
= new ESLint(config
);
4999 const results
= await eslintCLI
.lintText(code
);
5000 const messages
= results
[0].messages
;
5002 assert
.strictEqual(messages
.length
, 1);
5003 assert
.strictEqual(messages
[0].ruleId
, "no-alert");
5006 it("should not report a violation by default", async () => {
5008 "alert('test'); // eslint-disable-line no-alert"
5013 allowInlineConfig
: true,
5015 env
: { browser
: true },
5019 "no-trailing-spaces": 0,
5025 const eslintCLI
= new ESLint(config
);
5026 const results
= await eslintCLI
.lintText(code
);
5027 const messages
= results
[0].messages
;
5029 assert
.strictEqual(messages
.length
, 0);
5033 describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
5034 it("should report problems for unused eslint-disable directives", async () => {
5035 const eslint
= new ESLint({ useEslintrc
: false, reportUnusedDisableDirectives
: "error" });
5037 assert
.deepStrictEqual(
5038 await eslint
.lintText("/* eslint-disable */"),
5045 message
: "Unused eslint-disable directive (no problems were reported).",
5059 fixableErrorCount
: 1,
5060 fixableWarningCount
: 0,
5061 source
: "/* eslint-disable */",
5062 usedDeprecatedRules
: []
5069 describe("when retreiving version number", () => {
5070 it("should return current version number", () => {
5071 const eslintCLI
= require("../../../lib/eslint").ESLint
;
5072 const version
= eslintCLI
.version
;
5074 assert
.strictEqual(typeof version
, "string");
5075 assert(parseInt(version
[0], 10) >= 3);
5079 describe("mutability", () => {
5080 describe("plugins", () => {
5081 it("Loading plugin in one instance doesn't mutate to another instance", async () => {
5082 const filePath
= getFixturePath("single-quoted.js");
5083 const engine1
= eslintWithPlugins({
5084 cwd
: path
.join(fixtureDir
, ".."),
5087 plugins
: ["example"],
5088 rules
: { "example/example-rule": 1 }
5091 const engine2
= new ESLint({
5092 cwd
: path
.join(fixtureDir
, ".."),
5095 const fileConfig1
= await engine1
.calculateConfigForFile(filePath
);
5096 const fileConfig2
= await engine2
.calculateConfigForFile(filePath
);
5099 assert
.deepStrictEqual(fileConfig1
.plugins
, ["example"], "Plugin is present for engine 1");
5100 assert
.deepStrictEqual(fileConfig2
.plugins
, [], "Plugin is not present for engine 2");
5104 describe("rules", () => {
5105 it("Loading rules in one instance doesn't mutate to another instance", async () => {
5106 const filePath
= getFixturePath("single-quoted.js");
5107 const engine1
= new ESLint({
5108 cwd
: path
.join(fixtureDir
, ".."),
5110 overrideConfig
: { rules
: { "example/example-rule": 1 } }
5112 const engine2
= new ESLint({
5113 cwd
: path
.join(fixtureDir
, ".."),
5116 const fileConfig1
= await engine1
.calculateConfigForFile(filePath
);
5117 const fileConfig2
= await engine2
.calculateConfigForFile(filePath
);
5120 assert
.deepStrictEqual(fileConfig1
.rules
["example/example-rule"], [1], "example is present for engine 1");
5121 assert
.strictEqual(fileConfig2
.rules
["example/example-rule"], void 0, "example is not present for engine 2");
5126 describe("with ignorePatterns config", () => {
5127 const root
= getFixturePath("cli-engine/ignore-patterns");
5129 describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
5130 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5134 ignorePatterns
: "foo.js"
5138 "subdir/foo.js": "",
5143 beforeEach(prepare
);
5146 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5147 const engine
= new ESLint({ cwd
: getPath() });
5149 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5150 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5153 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5154 const engine
= new ESLint({ cwd
: getPath() });
5156 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5157 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), false);
5160 it("'lintFiles()' should not verify 'foo.js'.", async () => {
5161 const engine
= new ESLint({ cwd
: getPath() });
5162 const filePaths
= (await engine
.lintFiles("**/*.js"))
5163 .map(r
=> r
.filePath
)
5166 assert
.deepStrictEqual(filePaths
, [
5167 path
.join(root
, "bar.js"),
5168 path
.join(root
, "subdir/bar.js")
5173 describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
5174 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5178 ignorePatterns
: ["foo.js", "/bar.js"]
5183 "subdir/foo.js": "",
5184 "subdir/bar.js": "",
5189 beforeEach(prepare
);
5192 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5193 const engine
= new ESLint({ cwd
: getPath() });
5195 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5196 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5199 it("'isPathIgnored()' should return 'true' for '/bar.js'.", async () => {
5200 const engine
= new ESLint({ cwd
: getPath() });
5202 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), true);
5203 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), false);
5206 it("'lintFiles()' should not verify 'foo.js' and '/bar.js'.", async () => {
5207 const engine
= new ESLint({ cwd
: getPath() });
5208 const filePaths
= (await engine
.lintFiles("**/*.js"))
5209 .map(r
=> r
.filePath
)
5212 assert
.deepStrictEqual(filePaths
, [
5213 path
.join(root
, "baz.js"),
5214 path
.join(root
, "subdir/bar.js"),
5215 path
.join(root
, "subdir/baz.js")
5220 describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
5222 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5226 ignorePatterns
: "!/node_modules/foo"
5228 "node_modules/foo/index.js": "",
5229 "node_modules/foo/.dot.js": "",
5230 "node_modules/bar/index.js": "",
5235 beforeEach(prepare
);
5238 it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", async () => {
5239 const engine
= new ESLint({ cwd
: getPath() });
5241 assert
.strictEqual(await engine
.isPathIgnored("node_modules/foo/index.js"), false);
5244 it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", async () => {
5245 const engine
= new ESLint({ cwd
: getPath() });
5247 assert
.strictEqual(await engine
.isPathIgnored("node_modules/foo/.dot.js"), true);
5250 it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", async () => {
5251 const engine
= new ESLint({ cwd
: getPath() });
5253 assert
.strictEqual(await engine
.isPathIgnored("node_modules/bar/index.js"), true);
5256 it("'lintFiles()' should verify 'node_modules/foo/index.js'.", async () => {
5257 const engine
= new ESLint({ cwd
: getPath() });
5258 const filePaths
= (await engine
.lintFiles("**/*.js"))
5259 .map(r
=> r
.filePath
)
5262 assert
.deepStrictEqual(filePaths
, [
5263 path
.join(root
, "foo.js"),
5264 path
.join(root
, "node_modules/foo/index.js")
5269 describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
5271 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5274 ".eslintrc.js": `module.exports = ${JSON.stringify({
5275 ignorePatterns: "!.eslintrc.js"
5281 beforeEach(prepare
);
5284 it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", async () => {
5285 const engine
= new ESLint({ cwd
: getPath() });
5287 assert
.strictEqual(await engine
.isPathIgnored(".eslintrc.js"), false);
5290 it("'lintFiles()' should verify '.eslintrc.js'.", async () => {
5291 const engine
= new ESLint({ cwd
: getPath() });
5292 const filePaths
= (await engine
.lintFiles("**/*.js"))
5293 .map(r
=> r
.filePath
)
5296 assert
.deepStrictEqual(filePaths
, [
5297 path
.join(root
, ".eslintrc.js"),
5298 path
.join(root
, "foo.js")
5303 describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
5304 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5307 ".eslintrc.js": `module.exports = ${JSON.stringify({
5308 ignorePatterns: "!.*"
5310 ".eslintignore": ".foo*",
5316 beforeEach(prepare
);
5319 it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", async () => {
5320 const engine
= new ESLint({ cwd
: getPath() });
5322 assert
.strictEqual(await engine
.isPathIgnored(".foo.js"), true);
5325 it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", async () => {
5326 const engine
= new ESLint({ cwd
: getPath() });
5328 assert
.strictEqual(await engine
.isPathIgnored(".bar.js"), false);
5331 it("'lintFiles()' should not verify re-ignored '.foo.js'.", async () => {
5332 const engine
= new ESLint({ cwd
: getPath() });
5333 const filePaths
= (await engine
.lintFiles("**/*.js"))
5334 .map(r
=> r
.filePath
)
5337 assert
.deepStrictEqual(filePaths
, [
5338 path
.join(root
, ".bar.js"),
5339 path
.join(root
, ".eslintrc.js")
5344 describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
5345 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5348 ".eslintrc.js": `module.exports = ${JSON.stringify({
5349 ignorePatterns: "*.js"
5351 ".eslintignore": "!foo.js",
5357 beforeEach(prepare
);
5360 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
5361 const engine
= new ESLint({ cwd
: getPath() });
5363 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5366 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
5367 const engine
= new ESLint({ cwd
: getPath() });
5369 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), true);
5372 it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
5373 const engine
= new ESLint({ cwd
: getPath() });
5374 const filePaths
= (await engine
.lintFiles("**/*.js"))
5375 .map(r
=> r
.filePath
)
5378 assert
.deepStrictEqual(filePaths
, [
5379 path
.join(root
, "foo.js")
5384 describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
5385 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5388 ".eslintrc.json": JSON
.stringify({
5389 ignorePatterns
: "foo.js"
5391 "subdir/.eslintrc.json": JSON
.stringify({
5392 ignorePatterns
: "bar.js"
5396 "subdir/foo.js": "",
5397 "subdir/bar.js": "",
5398 "subdir/subsubdir/foo.js": "",
5399 "subdir/subsubdir/bar.js": ""
5404 beforeEach(prepare
);
5407 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5408 const engine
= new ESLint({ cwd
: getPath() });
5410 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5411 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5412 assert
.strictEqual(await engine
.isPathIgnored("subdir/subsubdir/foo.js"), true);
5415 it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", async () => {
5416 const engine
= new ESLint({ cwd
: getPath() });
5418 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5419 assert
.strictEqual(await engine
.isPathIgnored("subdir/subsubdir/bar.js"), true);
5422 it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", async () => {
5423 const engine
= new ESLint({ cwd
: getPath() });
5425 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5428 it("'lintFiles()' should verify 'bar.js' in the outside of 'subdir'.", async () => {
5429 const engine
= new ESLint({ cwd
: getPath() });
5430 const filePaths
= (await engine
.lintFiles("**/*.js"))
5431 .map(r
=> r
.filePath
)
5434 assert
.deepStrictEqual(filePaths
, [
5435 path
.join(root
, "bar.js")
5440 describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
5441 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5444 ".eslintrc.json": JSON
.stringify({
5445 ignorePatterns
: "foo.js"
5447 "subdir/.eslintrc.json": JSON
.stringify({
5448 ignorePatterns
: "!foo.js"
5455 beforeEach(prepare
);
5458 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
5459 const engine
= new ESLint({ cwd
: getPath() });
5461 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5464 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
5465 const engine
= new ESLint({ cwd
: getPath() });
5467 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5470 it("'lintFiles()' should verify 'foo.js' in the child directory.", async () => {
5471 const engine
= new ESLint({ cwd
: getPath() });
5472 const filePaths
= (await engine
.lintFiles("**/*.js"))
5473 .map(r
=> r
.filePath
)
5476 assert
.deepStrictEqual(filePaths
, [
5477 path
.join(root
, "subdir/foo.js")
5482 describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
5483 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5486 ".eslintrc.json": JSON
.stringify({}),
5487 "subdir/.eslintrc.json": JSON
.stringify({
5488 ignorePatterns
: "*.js"
5490 ".eslintignore": "!foo.js",
5492 "subdir/foo.js": "",
5497 beforeEach(prepare
);
5500 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
5501 const engine
= new ESLint({ cwd
: getPath() });
5503 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5504 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5507 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
5508 const engine
= new ESLint({ cwd
: getPath() });
5510 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5513 it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
5514 const engine
= new ESLint({ cwd
: getPath() });
5515 const filePaths
= (await engine
.lintFiles("**/*.js"))
5516 .map(r
=> r
.filePath
)
5519 assert
.deepStrictEqual(filePaths
, [
5520 path
.join(root
, "foo.js"),
5521 path
.join(root
, "subdir/foo.js")
5526 describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
5527 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5530 ".eslintrc.json": JSON
.stringify({
5531 ignorePatterns
: "foo.js"
5533 "subdir/.eslintrc.json": JSON
.stringify({
5535 ignorePatterns
: "bar.js"
5539 "subdir/foo.js": "",
5544 beforeEach(prepare
);
5547 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
5548 const engine
= new ESLint({ cwd
: getPath() });
5550 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5553 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
5554 const engine
= new ESLint({ cwd
: getPath() });
5556 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5559 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
5560 const engine
= new ESLint({ cwd
: getPath() });
5562 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5565 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
5566 const engine
= new ESLint({ cwd
: getPath() });
5568 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5571 it("'lintFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", async () => {
5572 const engine
= new ESLint({ cwd
: getPath() });
5573 const filePaths
= (await engine
.lintFiles("**/*.js"))
5574 .map(r
=> r
.filePath
)
5577 assert
.deepStrictEqual(filePaths
, [
5578 path
.join(root
, "bar.js"),
5579 path
.join(root
, "subdir/foo.js")
5584 describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
5585 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5588 ".eslintrc.json": JSON
.stringify({}),
5589 "subdir/.eslintrc.json": JSON
.stringify({
5591 ignorePatterns
: "bar.js"
5593 ".eslintignore": "foo.js",
5596 "subdir/foo.js": "",
5601 beforeEach(prepare
);
5604 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5605 const engine
= new ESLint({ cwd
: getPath() });
5607 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5608 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5611 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
5612 const engine
= new ESLint({ cwd
: getPath() });
5614 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5617 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
5618 const engine
= new ESLint({ cwd
: getPath() });
5620 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5623 it("'lintFiles()' should verify 'bar.js' in the root directory.", async () => {
5624 const engine
= new ESLint({ cwd
: getPath() });
5625 const filePaths
= (await engine
.lintFiles("**/*.js"))
5626 .map(r
=> r
.filePath
)
5629 assert
.deepStrictEqual(filePaths
, [
5630 path
.join(root
, "bar.js")
5635 describe("ignorePatterns in the shareable config should be used.", () => {
5636 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5639 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5640 ignorePatterns: "foo.js"
5642 ".eslintrc.json": JSON
.stringify({
5650 beforeEach(prepare
);
5653 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5654 const engine
= new ESLint({ cwd
: getPath() });
5656 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5659 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5660 const engine
= new ESLint({ cwd
: getPath() });
5662 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5665 it("'lintFiles()' should verify 'bar.js'.", async () => {
5666 const engine
= new ESLint({ cwd
: getPath() });
5667 const filePaths
= (await engine
.lintFiles("**/*.js"))
5668 .map(r
=> r
.filePath
)
5671 assert
.deepStrictEqual(filePaths
, [
5672 path
.join(root
, "bar.js")
5677 describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
5679 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5682 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5683 ignorePatterns: "/foo.js"
5685 ".eslintrc.json": JSON
.stringify({
5693 beforeEach(prepare
);
5696 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5697 const engine
= new ESLint({ cwd
: getPath() });
5699 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5702 it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", async () => {
5703 const engine
= new ESLint({ cwd
: getPath() });
5705 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5708 it("'lintFiles()' should verify 'subdir/foo.js'.", async () => {
5709 const engine
= new ESLint({ cwd
: getPath() });
5710 const filePaths
= (await engine
.lintFiles("**/*.js"))
5711 .map(r
=> r
.filePath
)
5714 assert
.deepStrictEqual(filePaths
, [
5715 path
.join(root
, "subdir/foo.js")
5720 describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
5721 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5724 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5725 ignorePatterns: "*.js"
5727 ".eslintrc.json": JSON
.stringify({
5729 ignorePatterns
: "!bar.js"
5736 beforeEach(prepare
);
5739 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5740 const engine
= new ESLint({ cwd
: getPath() });
5742 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5745 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5746 const engine
= new ESLint({ cwd
: getPath() });
5748 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5751 it("'lintFiles()' should verify 'bar.js'.", async () => {
5752 const engine
= new ESLint({ cwd
: getPath() });
5753 const filePaths
= (await engine
.lintFiles("**/*.js"))
5754 .map(r
=> r
.filePath
)
5757 assert
.deepStrictEqual(filePaths
, [
5758 path
.join(root
, "bar.js")
5763 describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
5765 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5768 ".eslintrc.json": JSON
.stringify({
5769 ignorePatterns
: "*.js"
5775 beforeEach(prepare
);
5778 it("'isPathIgnored()' should return 'false' for 'foo.js'.", async () => {
5779 const engine
= new ESLint({ cwd
: getPath(), ignore
: false });
5781 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5784 it("'lintFiles()' should verify 'foo.js'.", async () => {
5785 const engine
= new ESLint({ cwd
: getPath(), ignore
: false });
5786 const filePaths
= (await engine
.lintFiles("**/*.js"))
5787 .map(r
=> r
.filePath
)
5790 assert
.deepStrictEqual(filePaths
, [
5791 path
.join(root
, "foo.js")
5796 describe("ignorePatterns in overrides section is not allowed.", () => {
5798 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5801 ".eslintrc.js": `module.exports = ${JSON.stringify({
5805 ignorePatterns: "foo.js"
5813 beforeEach(prepare
);
5816 it("should throw a configuration error.", async () => {
5817 await assert
.rejects(async () => {
5818 const engine
= new ESLint({ cwd
: getPath() });
5820 await engine
.lintFiles("*.js");
5821 }, /Unexpected top-level property "overrides\[0\]\.ignorePatterns"/u);
5826 describe("'overrides[].files' adds lint targets", () => {
5827 const root
= getFixturePath("cli-engine/additional-lint-targets");
5830 describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
5831 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5834 ".eslintrc.json": JSON
.stringify({
5838 excludedFiles
: "**/ignore.txt"
5842 "foo/nested/test.txt": "",
5845 "foo/ignore.txt": "",
5848 "bar/ignore.txt": "",
5855 beforeEach(prepare
);
5858 it("'lintFiles()' with a directory path should contain 'foo/test.txt'.", async () => {
5859 const engine
= new ESLint({ cwd
: getPath() });
5860 const filePaths
= (await engine
.lintFiles("."))
5861 .map(r
=> r
.filePath
)
5864 assert
.deepStrictEqual(filePaths
, [
5865 path
.join(root
, "bar/test.js"),
5866 path
.join(root
, "foo/test.js"),
5867 path
.join(root
, "foo/test.txt"),
5868 path
.join(root
, "test.js")
5872 it("'lintFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", async () => {
5873 const engine
= new ESLint({ cwd
: getPath() });
5874 const filePaths
= (await engine
.lintFiles("**/*.js"))
5875 .map(r
=> r
.filePath
)
5878 assert
.deepStrictEqual(filePaths
, [
5879 path
.join(root
, "bar/test.js"),
5880 path
.join(root
, "foo/test.js"),
5881 path
.join(root
, "test.js")
5886 describe("if { files: 'foo/**/*.txt' } is present,", () => {
5888 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5891 ".eslintrc.json": JSON
.stringify({
5894 files
: "foo/**/*.txt"
5898 "foo/nested/test.txt": "",
5908 beforeEach(prepare
);
5911 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5912 const engine
= new ESLint({ cwd
: getPath() });
5913 const filePaths
= (await engine
.lintFiles("."))
5914 .map(r
=> r
.filePath
)
5917 assert
.deepStrictEqual(filePaths
, [
5918 path
.join(root
, "bar/test.js"),
5919 path
.join(root
, "foo/nested/test.txt"),
5920 path
.join(root
, "foo/test.js"),
5921 path
.join(root
, "foo/test.txt"),
5922 path
.join(root
, "test.js")
5927 describe("if { files: 'foo/**/*' } is present,", () => {
5929 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5932 ".eslintrc.json": JSON
.stringify({
5939 "foo/nested/test.txt": "",
5949 beforeEach(prepare
);
5952 it("'lintFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5953 const engine
= new ESLint({ cwd
: getPath() });
5954 const filePaths
= (await engine
.lintFiles("."))
5955 .map(r
=> r
.filePath
)
5958 assert
.deepStrictEqual(filePaths
, [
5959 path
.join(root
, "bar/test.js"),
5960 path
.join(root
, "foo/test.js"),
5961 path
.join(root
, "test.js")
5966 describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
5968 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5971 "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
5974 files: "foo/**/*.txt"
5978 ".eslintrc.json": JSON
.stringify({
5981 "foo/nested/test.txt": "",
5991 beforeEach(prepare
);
5994 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5995 const engine
= new ESLint({ cwd
: getPath() });
5996 const filePaths
= (await engine
.lintFiles("."))
5997 .map(r
=> r
.filePath
)
6000 assert
.deepStrictEqual(filePaths
, [
6001 path
.join(root
, "bar/test.js"),
6002 path
.join(root
, "foo/nested/test.txt"),
6003 path
.join(root
, "foo/test.js"),
6004 path
.join(root
, "foo/test.txt"),
6005 path
.join(root
, "test.js")
6010 describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
6012 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6015 "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
6019 files: "foo/**/*.txt"
6024 ".eslintrc.json": JSON
.stringify({
6025 extends: "plugin:foo/bar"
6027 "foo/nested/test.txt": "",
6037 beforeEach(prepare
);
6040 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
6041 const engine
= new ESLint({ cwd
: getPath() });
6042 const filePaths
= (await engine
.lintFiles("."))
6043 .map(r
=> r
.filePath
)
6046 assert
.deepStrictEqual(filePaths
, [
6047 path
.join(root
, "bar/test.js"),
6048 path
.join(root
, "foo/nested/test.txt"),
6049 path
.join(root
, "foo/test.js"),
6050 path
.join(root
, "foo/test.txt"),
6051 path
.join(root
, "test.js")
6057 describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
6058 const root
= getFixturePath("cli-engine/config-and-overrides-files");
6060 describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6061 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6064 "node_modules/myconf/.eslintrc.json": {
6074 "node_modules/myconf/foo/test.js": "a == b",
6075 "foo/test.js": "a == b"
6079 beforeEach(prepare
);
6082 it("'lintFiles()' with 'foo/test.js' should use the override entry.", async () => {
6083 const engine
= new ESLint({
6084 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6089 const results
= await engine
.lintFiles("foo/test.js");
6091 // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
6092 assert
.deepStrictEqual(results
, [
6095 filePath
: path
.join(getPath(), "foo/test.js"),
6096 fixableErrorCount
: 0,
6097 fixableWarningCount
: 0,
6104 message
: "Expected '===' and instead saw '=='.",
6105 messageId
: "unexpected",
6106 nodeType
: "BinaryExpression",
6112 usedDeprecatedRules
: [],
6119 it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", async () => {
6120 const engine
= new ESLint({
6121 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6126 const results
= await engine
.lintFiles("node_modules/myconf/foo/test.js");
6128 // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
6129 assert
.deepStrictEqual(results
, [
6132 filePath
: path
.join(getPath(), "node_modules/myconf/foo/test.js"),
6133 fixableErrorCount
: 0,
6134 fixableWarningCount
: 0,
6136 usedDeprecatedRules
: [],
6144 describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6145 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6148 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6152 excludedFiles
: "foo/*.js",
6159 "node_modules/myconf/foo/test.js": "a == b",
6160 "foo/test.js": "a == b"
6164 beforeEach(prepare
);
6167 it("'lintFiles()' with 'foo/test.js' should NOT use the override entry.", async () => {
6168 const engine
= new ESLint({
6169 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6174 const results
= await engine
.lintFiles("foo/test.js");
6176 // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
6177 assert
.deepStrictEqual(results
, [
6180 filePath
: path
.join(getPath(), "foo/test.js"),
6181 fixableErrorCount
: 0,
6182 fixableWarningCount
: 0,
6184 usedDeprecatedRules
: [],
6191 it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", async () => {
6192 const engine
= new ESLint({
6193 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6198 const results
= await engine
.lintFiles("node_modules/myconf/foo/test.js");
6200 // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
6201 assert
.deepStrictEqual(results
, [
6204 filePath
: path
.join(getPath(), "node_modules/myconf/foo/test.js"),
6205 fixableErrorCount
: 0,
6206 fixableWarningCount
: 0,
6213 message
: "Expected '===' and instead saw '=='.",
6214 messageId
: "unexpected",
6215 nodeType
: "BinaryExpression",
6221 usedDeprecatedRules
: [],
6229 describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
6230 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6233 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
6234 ignorePatterns
: ["!/node_modules/myconf", "foo/*.js"],
6239 "node_modules/myconf/foo/test.js": "a == b",
6240 "foo/test.js": "a == b"
6244 beforeEach(prepare
);
6247 it("'lintFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", async () => {
6248 const engine
= new ESLint({
6249 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
6253 const files
= (await engine
.lintFiles("**/*.js"))
6254 .map(r
=> r
.filePath
)
6257 assert
.deepStrictEqual(files
, [
6258 path
.join(root
, "node_modules/myconf/foo/test.js")
6264 describe("plugin conflicts", () => {
6266 const root
= getFixturePath("cli-engine/plugin-conflicts-");
6269 * Verify thrown errors.
6270 * @param {() => Promise<any>} f The function to run and throw.
6271 * @param {Record<string, any>} props The properties to verify.
6272 * @returns {Promise<void>} void
6274 async
function assertThrows(f
, props
) {
6278 for (const [key
, value
] of Object
.entries(props
)) {
6279 assert
.deepStrictEqual(error
[key
], value
, key
);
6284 assert
.fail("Function should throw an error, but not.");
6287 describe("between a config file and linear extendees.", () => {
6289 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6290 cwd
: `${root}${++uid}`,
6292 "node_modules/eslint-plugin-foo/index.js": "",
6293 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6294 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6298 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6299 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6302 ".eslintrc.json": JSON
.stringify({
6310 beforeEach(prepare
);
6313 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
6314 const engine
= new ESLint({ cwd
: getPath() });
6316 await engine
.lintFiles("test.js");
6320 describe("between a config file and same-depth extendees.", () => {
6322 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6323 cwd
: `${root}${++uid}`,
6325 "node_modules/eslint-plugin-foo/index.js": "",
6326 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6327 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6330 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6331 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6334 ".eslintrc.json": JSON
.stringify({
6335 extends: ["one", "two"],
6342 beforeEach(prepare
);
6345 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
6346 const engine
= new ESLint({ cwd
: getPath() });
6348 await engine
.lintFiles("test.js");
6352 describe("between two config files in different directories, with single node_modules.", () => {
6354 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6355 cwd
: `${root}${++uid}`,
6357 "node_modules/eslint-plugin-foo/index.js": "",
6358 ".eslintrc.json": JSON
.stringify({
6361 "subdir/.eslintrc.json": JSON
.stringify({
6364 "subdir/test.js": ""
6368 beforeEach(prepare
);
6371 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 () => {
6372 const engine
= new ESLint({ cwd
: getPath() });
6374 await engine
.lintFiles("subdir/test.js");
6378 describe("between two config files in different directories, with multiple node_modules.", () => {
6380 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6381 cwd
: `${root}${++uid}`,
6383 "node_modules/eslint-plugin-foo/index.js": "",
6384 ".eslintrc.json": JSON
.stringify({
6387 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6388 "subdir/.eslintrc.json": JSON
.stringify({
6391 "subdir/test.js": ""
6395 beforeEach(prepare
);
6398 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 () => {
6399 const engine
= new ESLint({ cwd
: getPath() });
6402 () => engine
.lintFiles("subdir/test.js"),
6404 message
: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
6405 messageTemplate
: "plugin-conflict",
6410 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6411 importerName
: `subdir${path.sep}.eslintrc.json`
6414 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6415 importerName
: ".eslintrc.json"
6424 describe("between '--config' option and a regular config file, with single node_modules.", () => {
6426 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6427 cwd
: `${root}${++uid}`,
6429 "node_modules/eslint-plugin-foo/index.js": "",
6430 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6433 ".eslintrc.json": JSON
.stringify({
6440 beforeEach(prepare
);
6443 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 () => {
6444 const engine
= new ESLint({
6446 overrideConfigFile
: "node_modules/mine/.eslintrc.json"
6449 await engine
.lintFiles("test.js");
6453 describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
6455 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6456 cwd
: `${root}${++uid}`,
6458 "node_modules/eslint-plugin-foo/index.js": "",
6459 "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
6460 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6463 ".eslintrc.json": JSON
.stringify({
6470 beforeEach(prepare
);
6473 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 () => {
6474 const engine
= new ESLint({
6476 overrideConfigFile
: "node_modules/mine/.eslintrc.json"
6480 () => engine
.lintFiles("test.js"),
6482 message
: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
6483 messageTemplate
: "plugin-conflict",
6488 filePath
: path
.join(getPath(), "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
6489 importerName
: "--config"
6492 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6493 importerName
: ".eslintrc.json"
6502 describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
6504 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6505 cwd
: `${root}${++uid}`,
6507 "node_modules/eslint-plugin-foo/index.js": "",
6508 "subdir/.eslintrc.json": JSON
.stringify({
6511 "subdir/test.js": ""
6516 beforeEach(prepare
);
6519 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 () => {
6520 const engine
= new ESLint({
6522 overrideConfig
: { plugins
: ["foo"] }
6525 await engine
.lintFiles("subdir/test.js");
6529 describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
6531 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6532 cwd
: `${root}${++uid}`,
6534 "node_modules/eslint-plugin-foo/index.js": "",
6535 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6536 "subdir/.eslintrc.json": JSON
.stringify({
6539 "subdir/test.js": ""
6543 beforeEach(prepare
);
6546 it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", async () => {
6547 const engine
= new ESLint({
6549 overrideConfig
: { plugins
: ["foo"] }
6553 () => engine
.lintFiles("subdir/test.js"),
6555 message
: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
6556 messageTemplate
: "plugin-conflict",
6561 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6562 importerName
: "CLIOptions"
6565 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6566 importerName
: `subdir${path.sep}.eslintrc.json`
6575 describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
6577 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6578 cwd
: `${root}${++uid}`,
6580 "node_modules/eslint-plugin-foo/index.js": "",
6581 ".eslintrc.json": JSON
.stringify({
6584 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6585 "subdir/.eslintrc.json": JSON
.stringify({
6588 "subdir/test.js": ""
6592 beforeEach(prepare
);
6595 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", async () => {
6596 const engine
= new ESLint({
6598 resolvePluginsRelativeTo
: getPath()
6601 await engine
.lintFiles("subdir/test.js");
6605 describe("between two config files with different target files.", () => {
6607 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6608 cwd
: `${root}${++uid}`,
6610 "one/node_modules/eslint-plugin-foo/index.js": "",
6611 "one/.eslintrc.json": JSON
.stringify({
6615 "two/node_modules/eslint-plugin-foo/index.js": "",
6616 "two/.eslintrc.json": JSON
.stringify({
6623 beforeEach(prepare
);
6626 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 () => {
6627 const engine
= new ESLint({ cwd
: getPath() });
6628 const results
= await engine
.lintFiles("*/test.js");
6630 assert
.strictEqual(results
.length
, 2);