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 leche
= require("leche");
20 const sinon
= require("sinon");
21 const proxyquire
= require("proxyquire").noCallThru().noPreserveCache();
22 const shell
= require("shelljs");
23 const { CascadingConfigArrayFactory
} = require("../../../lib/cli-engine/cascading-config-array-factory");
24 const hash
= require("../../../lib/cli-engine/hash");
25 const { unIndent
, defineESLintWithInMemoryFileSystem
} = require("../../_utils");
27 //------------------------------------------------------------------------------
29 //------------------------------------------------------------------------------
31 describe("ESLint", () => {
32 const examplePluginName
= "eslint-plugin-example";
33 const examplePluginNameWithNamespace
= "@eslint/eslint-plugin-example";
34 const examplePlugin
= {
36 "example-rule": require("../../fixtures/rules/custom-rule"),
37 "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
40 const examplePreprocessorName
= "eslint-plugin-processor";
41 const originalDir
= process
.cwd();
42 const fixtureDir
= path
.resolve(fs
.realpathSync(os
.tmpdir()), "eslint/fixtures");
44 /** @type {import("../../../lib/eslint")["ESLint"]} */
48 * Returns the path inside of the fixture directory.
49 * @param {...string} args file path segments.
50 * @returns {string} The path inside the fixture directory.
53 function getFixturePath(...args
) {
54 const filepath
= path
.join(fixtureDir
, ...args
);
57 return fs
.realpathSync(filepath
);
64 * Create the ESLint object by mocking some of the plugins
65 * @param {Object} options options for ESLint
66 * @returns {ESLint} engine object
69 function eslintWithPlugins(options
) {
73 [examplePluginName
]: examplePlugin
,
74 [examplePluginNameWithNamespace
]: examplePlugin
,
75 [examplePreprocessorName
]: require("../../fixtures/processors/custom-processor")
81 * Call the last argument.
82 * @param {any[]} args Arguments
85 function callLastArgument(...args
) {
86 process
.nextTick(args
[args
.length
- 1], null);
89 // copy into clean area so as not to get "infected" by this project's .eslintrc files
91 shell
.mkdir("-p", fixtureDir
);
92 shell
.cp("-r", "./tests/fixtures/.", fixtureDir
);
96 ({ ESLint
} = require("../../../lib/eslint/eslint"));
100 shell
.rm("-r", fixtureDir
);
103 describe("ESLint constructor function", () => {
104 it("the default value of 'options.cwd' should be the current working directory.", async () => {
105 process
.chdir(__dirname
);
107 const engine
= new ESLint();
108 const results
= await engine
.lintFiles("eslint.js");
110 assert
.strictEqual(path
.dirname(results
[0].filePath
), __dirname
);
112 process
.chdir(originalDir
);
116 it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
117 assert
.throws(() => {
118 // eslint-disable-next-line no-new
119 new ESLint({ ignorePath
: fixtureDir
});
120 }, new RegExp(escapeStringRegExp(`Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`), "u"));
123 // https://github.com/eslint/eslint/issues/2380
124 it("should not modify baseConfig when format is specified", () => {
125 const customBaseConfig
= { root
: true };
127 new ESLint({ baseConfig
: customBaseConfig
}); // eslint-disable-line no-new
129 assert
.deepStrictEqual(customBaseConfig
, { root
: true });
132 it("should throw readable messages if removed options are present", () => {
145 new RegExp(escapeStringRegExp([
147 "- Unknown options: cacheFile, configFile, envs, globals, ignorePattern, parser, parserOptions, rules",
148 "- 'cacheFile' has been removed. Please use the 'cacheLocation' option instead.",
149 "- 'configFile' has been removed. Please use the 'overrideConfigFile' option instead.",
150 "- 'envs' has been removed. Please use the 'overrideConfig.env' option instead.",
151 "- 'globals' has been removed. Please use the 'overrideConfig.globals' option instead.",
152 "- 'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.",
153 "- 'parser' has been removed. Please use the 'overrideConfig.parser' option instead.",
154 "- 'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead.",
155 "- 'rules' has been removed. Please use the 'overrideConfig.rules' option instead.",
156 "- 'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead."
161 it("should throw readable messages if wrong type values are given to options", () => {
164 allowInlineConfig
: "",
169 errorOnUnmatchedPattern
: "",
177 overrideConfigFile
: "",
179 reportUnusedDisableDirectives
: "",
180 resolvePluginsRelativeTo
: "",
184 new RegExp(escapeStringRegExp([
186 "- 'allowInlineConfig' must be a boolean.",
187 "- 'baseConfig' must be an object or null.",
188 "- 'cache' must be a boolean.",
189 "- 'cacheLocation' must be a non-empty string.",
190 "- 'cwd' must be an absolute path.",
191 "- 'errorOnUnmatchedPattern' must be a boolean.",
192 "- 'extensions' must be an array of non-empty strings or null.",
193 "- 'fix' must be a boolean or a function.",
194 "- 'fixTypes' must be an array of any of \"problem\", \"suggestion\", and \"layout\".",
195 "- 'globInputPaths' must be a boolean.",
196 "- 'ignore' must be a boolean.",
197 "- 'ignorePath' must be a non-empty string or null.",
198 "- 'overrideConfig' must be an object or null.",
199 "- 'overrideConfigFile' must be a non-empty string or null.",
200 "- 'plugins' must be an object or null.",
201 "- 'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.",
202 "- 'resolvePluginsRelativeTo' must be a non-empty string or null.",
203 "- 'rulePaths' must be an array of non-empty strings.",
204 "- 'useElintrc' must be a boolean."
209 it("should throw readable messages if 'plugins' option contains empty key", () => {
213 "eslint-plugin-foo": {},
214 "eslint-plugin-bar": {},
218 new RegExp(escapeStringRegExp([
220 "- 'plugins' must not include an empty string."
226 describe("lintText()", () => {
229 it("should report the total and per file errors when using local cwd .eslintrc", async () => {
230 eslint
= new ESLint();
231 const results
= await eslint
.lintText("var foo = 'bar';");
233 assert
.strictEqual(results
.length
, 1);
234 assert
.strictEqual(results
[0].messages
.length
, 5);
235 assert
.strictEqual(results
[0].messages
[0].ruleId
, "strict");
236 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-var");
237 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-unused-vars");
238 assert
.strictEqual(results
[0].messages
[3].ruleId
, "quotes");
239 assert
.strictEqual(results
[0].messages
[4].ruleId
, "eol-last");
240 assert
.strictEqual(results
[0].fixableErrorCount
, 3);
241 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
242 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
245 it("should report the total and per file warnings when using local cwd .eslintrc", async () => {
246 eslint
= new ESLint({
257 const results
= await eslint
.lintText("var foo = 'bar';");
259 assert
.strictEqual(results
.length
, 1);
260 assert
.strictEqual(results
[0].messages
.length
, 5);
261 assert
.strictEqual(results
[0].messages
[0].ruleId
, "strict");
262 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-var");
263 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-unused-vars");
264 assert
.strictEqual(results
[0].messages
[3].ruleId
, "quotes");
265 assert
.strictEqual(results
[0].messages
[4].ruleId
, "eol-last");
266 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
267 assert
.strictEqual(results
[0].fixableWarningCount
, 3);
268 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
271 it("should report one message when using specific config file", async () => {
272 eslint
= new ESLint({
273 overrideConfigFile
: "fixtures/configurations/quotes-error.json",
275 cwd
: getFixturePath("..")
277 const results
= await eslint
.lintText("var foo = 'bar';");
279 assert
.strictEqual(results
.length
, 1);
280 assert
.strictEqual(results
[0].messages
.length
, 1);
281 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
282 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
283 assert
.strictEqual(results
[0].errorCount
, 1);
284 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
285 assert
.strictEqual(results
[0].warningCount
, 0);
286 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
289 it("should report the filename when passed in", async () => {
290 eslint
= new ESLint({
292 cwd
: getFixturePath()
294 const options
= { filePath
: "test.js" };
295 const results
= await eslint
.lintText("var foo = 'bar';", options
);
297 assert
.strictEqual(results
[0].filePath
, getFixturePath("test.js"));
300 it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", async () => {
301 eslint
= new ESLint({
302 ignorePath
: getFixturePath(".eslintignore"),
303 cwd
: getFixturePath("..")
305 const options
= { filePath
: "fixtures/passing.js", warnIgnored
: true };
306 const results
= await eslint
.lintText("var bar = foo;", options
);
308 assert
.strictEqual(results
.length
, 1);
309 assert
.strictEqual(results
[0].filePath
, getFixturePath("passing.js"));
310 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
311 assert
.strictEqual(results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
312 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
313 assert
.strictEqual(results
[0].errorCount
, 0);
314 assert
.strictEqual(results
[0].warningCount
, 1);
315 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
316 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
317 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
320 it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", async () => {
321 eslint
= new ESLint({
322 ignorePath
: getFixturePath(".eslintignore"),
323 cwd
: getFixturePath("..")
326 filePath
: "fixtures/passing.js",
330 // intentional parsing error
331 const results
= await eslint
.lintText("va r bar = foo;", options
);
333 // should not report anything because the file is ignored
334 assert
.strictEqual(results
.length
, 0);
337 it("should suppress excluded file warnings by default", async () => {
338 eslint
= new ESLint({
339 ignorePath
: getFixturePath(".eslintignore"),
340 cwd
: getFixturePath("..")
342 const options
= { filePath
: "fixtures/passing.js" };
343 const results
= await eslint
.lintText("var bar = foo;", options
);
345 // should not report anything because there are no errors
346 assert
.strictEqual(results
.length
, 0);
349 it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", async () => {
350 eslint
= new ESLint({
351 ignorePath
: "fixtures/.eslintignore",
352 cwd
: getFixturePath(".."),
361 const options
= { filePath
: "fixtures/passing.js" };
362 const results
= await eslint
.lintText("var bar = foo;", options
);
364 assert
.strictEqual(results
.length
, 1);
365 assert
.strictEqual(results
[0].filePath
, getFixturePath("passing.js"));
366 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
367 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
368 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
371 it("should return a message and fixed text when in fix mode", async () => {
372 eslint
= new ESLint({
381 cwd
: getFixturePath()
383 const options
= { filePath
: "passing.js" };
384 const results
= await eslint
.lintText("var bar = foo", options
);
386 assert
.deepStrictEqual(results
, [
388 filePath
: getFixturePath("passing.js"),
392 fixableErrorCount
: 0,
393 fixableWarningCount
: 0,
394 output
: "var bar = foo;",
395 usedDeprecatedRules
: []
400 it("correctly autofixes semicolon-conflicting-fixes", async () => {
401 eslint
= new ESLint({
402 cwd
: path
.join(fixtureDir
, ".."),
406 const inputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.js");
407 const outputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
408 const results
= await eslint
.lintFiles([inputPath
]);
409 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
411 assert
.strictEqual(results
[0].output
, expectedOutput
);
414 it("correctly autofixes return-conflicting-fixes", async () => {
415 eslint
= new ESLint({
416 cwd
: path
.join(fixtureDir
, ".."),
420 const inputPath
= getFixturePath("autofix/return-conflicting-fixes.js");
421 const outputPath
= getFixturePath("autofix/return-conflicting-fixes.expected.js");
422 const results
= await eslint
.lintFiles([inputPath
]);
423 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
425 assert
.strictEqual(results
[0].output
, expectedOutput
);
428 describe("Fix Types", () => {
429 it("should throw an error when an invalid fix type is specified", () => {
430 assert
.throws(() => {
431 eslint
= new ESLint({
432 cwd
: path
.join(fixtureDir
, ".."),
437 }, /'fixTypes' must be an array of any of "problem", "suggestion", and "layout"\./iu);
440 it("should not fix any rules when fixTypes is used without fix", async () => {
441 eslint
= new ESLint({
442 cwd
: path
.join(fixtureDir
, ".."),
447 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
448 const results
= await eslint
.lintFiles([inputPath
]);
450 assert
.strictEqual(results
[0].output
, void 0);
453 it("should not fix non-style rules when fixTypes has only 'layout'", async () => {
454 eslint
= new ESLint({
455 cwd
: path
.join(fixtureDir
, ".."),
460 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
461 const outputPath
= getFixturePath("fix-types/fix-only-semi.expected.js");
462 const results
= await eslint
.lintFiles([inputPath
]);
463 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
465 assert
.strictEqual(results
[0].output
, expectedOutput
);
468 it("should not fix style or problem rules when fixTypes has only 'suggestion'", async () => {
469 eslint
= new ESLint({
470 cwd
: path
.join(fixtureDir
, ".."),
473 fixTypes
: ["suggestion"]
475 const inputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
476 const outputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
477 const results
= await eslint
.lintFiles([inputPath
]);
478 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
480 assert
.strictEqual(results
[0].output
, expectedOutput
);
483 it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", async () => {
484 eslint
= new ESLint({
485 cwd
: path
.join(fixtureDir
, ".."),
488 fixTypes
: ["suggestion", "layout"]
490 const inputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
491 const outputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
492 const results
= await eslint
.lintFiles([inputPath
]);
493 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
495 assert
.strictEqual(results
[0].output
, expectedOutput
);
498 it("should not throw an error when a rule doesn't have a 'meta' property", async () => {
499 eslint
= new ESLint({
500 cwd
: path
.join(fixtureDir
, ".."),
503 fixTypes
: ["layout"],
504 rulePaths
: [getFixturePath("rules", "fix-types-test")]
506 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
507 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
508 const results
= await eslint
.lintFiles([inputPath
]);
509 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
511 assert
.strictEqual(results
[0].output
, expectedOutput
);
514 it("should not throw an error when a rule is loaded after initialization with lintFiles()", async () => {
515 eslint
= new ESLint({
516 cwd
: path
.join(fixtureDir
, ".."),
519 fixTypes
: ["layout"],
523 "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
528 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
529 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
530 const results
= await eslint
.lintFiles([inputPath
]);
531 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
533 assert
.strictEqual(results
[0].output
, expectedOutput
);
536 it("should not throw an error when a rule is loaded after initialization with lintText()", async () => {
537 eslint
= new ESLint({
538 cwd
: path
.join(fixtureDir
, ".."),
541 fixTypes
: ["layout"],
545 "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
550 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
551 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
552 const results
= await eslint
.lintText(fs
.readFileSync(inputPath
, { encoding
: "utf8" }), { filePath
: inputPath
});
553 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
555 assert
.strictEqual(results
[0].output
, expectedOutput
);
559 it("should return a message and omit fixed text when in fix mode and fixes aren't done", async () => {
560 eslint
= new ESLint({
569 cwd
: getFixturePath()
571 const options
= { filePath
: "passing.js" };
572 const results
= await eslint
.lintText("var bar = foo", options
);
574 assert
.deepStrictEqual(results
, [
576 filePath
: getFixturePath("passing.js"),
582 message
: "'foo' is not defined.",
587 nodeType
: "Identifier"
592 fixableErrorCount
: 0,
593 fixableWarningCount
: 0,
594 source
: "var bar = foo",
595 usedDeprecatedRules
: []
600 it("should not delete code if there is a syntax error after trying to autofix.", async () => {
601 eslint
= eslintWithPlugins({
605 plugins
: ["example"],
607 "example/make-syntax-error": "error"
611 cwd
: getFixturePath()
613 const options
= { filePath
: "test.js" };
614 const results
= await eslint
.lintText("var bar = foo", options
);
616 assert
.deepStrictEqual(results
, [
618 filePath
: getFixturePath("test.js"),
624 message
: "Parsing error: Unexpected token is",
631 fixableErrorCount
: 0,
632 fixableWarningCount
: 0,
633 output
: "var bar = foothis is a syntax error.",
634 usedDeprecatedRules
: []
639 it("should not crash even if there are any syntax error since the first time.", async () => {
640 eslint
= new ESLint({
645 "example/make-syntax-error": "error"
649 cwd
: getFixturePath()
651 const options
= { filePath
: "test.js" };
652 const results
= await eslint
.lintText("var bar =", options
);
654 assert
.deepStrictEqual(results
, [
656 filePath
: getFixturePath("test.js"),
662 message
: "Parsing error: Unexpected token",
669 fixableErrorCount
: 0,
670 fixableWarningCount
: 0,
672 usedDeprecatedRules
: []
677 it("should return source code of file in `source` property when errors are present", async () => {
678 eslint
= new ESLint({
684 const results
= await eslint
.lintText("var foo = 'bar'");
686 assert
.strictEqual(results
[0].source
, "var foo = 'bar'");
689 it("should return source code of file in `source` property when warnings are present", async () => {
690 eslint
= new ESLint({
696 const results
= await eslint
.lintText("var foo = 'bar'");
698 assert
.strictEqual(results
[0].source
, "var foo = 'bar'");
702 it("should not return a `source` property when no errors or warnings are present", async () => {
703 eslint
= new ESLint({
709 const results
= await eslint
.lintText("var foo = 'bar';");
711 assert
.strictEqual(results
[0].messages
.length
, 0);
712 assert
.strictEqual(results
[0].source
, void 0);
715 it("should not return a `source` property when fixes are applied", async () => {
716 eslint
= new ESLint({
726 const results
= await eslint
.lintText("var msg = 'hi' + foo\n");
728 assert
.strictEqual(results
[0].source
, void 0);
729 assert
.strictEqual(results
[0].output
, "var msg = 'hi' + foo;\n");
732 it("should return a `source` property when a parsing error has occurred", async () => {
733 eslint
= new ESLint({
739 const results
= await eslint
.lintText("var bar = foothis is a syntax error.\n return bar;");
741 assert
.deepStrictEqual(results
, [
749 message
: "Parsing error: Unexpected token is",
756 fixableErrorCount
: 0,
757 fixableWarningCount
: 0,
758 source
: "var bar = foothis is a syntax error.\n return bar;",
759 usedDeprecatedRules
: []
764 // https://github.com/eslint/eslint/issues/5547
765 it("should respect default ignore rules, even with --no-ignore", async () => {
766 eslint
= new ESLint({
767 cwd
: getFixturePath(),
770 const results
= await eslint
.lintText("var bar = foo;", { filePath
: "node_modules/passing.js", warnIgnored
: true });
771 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
773 assert
.strictEqual(results
.length
, 1);
774 assert
.strictEqual(results
[0].filePath
, getFixturePath("node_modules/passing.js"));
775 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
778 describe('plugin shorthand notation ("@scope" for "@scope/eslint-plugin")', () => {
779 const Module
= require("module");
780 let originalFindPath
= null;
782 /* eslint-disable no-underscore-dangle */
784 originalFindPath
= Module
._findPath
;
785 Module
._findPath = function(id
, ...otherArgs
) {
786 if (id
=== "@scope/eslint-plugin") {
787 return path
.resolve(__dirname
, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
789 return originalFindPath
.call(this, id
, ...otherArgs
);
793 Module
._findPath
= originalFindPath
;
795 /* eslint-enable no-underscore-dangle */
797 it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
798 eslint
= new ESLint({ cwd
: getFixturePath("plugin-shorthand/basic") });
799 const [result
] = await eslint
.lintText("var x = 0", { filePath
: "index.js" });
801 assert
.strictEqual(result
.filePath
, getFixturePath("plugin-shorthand/basic/index.js"));
802 assert
.strictEqual(result
.messages
[0].ruleId
, "@scope/rule");
803 assert
.strictEqual(result
.messages
[0].message
, "OK");
806 it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
807 eslint
= new ESLint({ cwd
: getFixturePath("plugin-shorthand/extends") });
808 const [result
] = await eslint
.lintText("var x = 0", { filePath
: "index.js" });
810 assert
.strictEqual(result
.filePath
, getFixturePath("plugin-shorthand/extends/index.js"));
811 assert
.strictEqual(result
.messages
[0].ruleId
, "@scope/rule");
812 assert
.strictEqual(result
.messages
[0].message
, "OK");
816 it("should warn when deprecated rules are found in a config", async () => {
817 eslint
= new ESLint({
820 overrideConfigFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
822 const [result
] = await eslint
.lintText("foo");
824 assert
.deepStrictEqual(
825 result
.usedDeprecatedRules
,
826 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
830 it("should throw if non-string value is given to 'code' parameter", async () => {
831 eslint
= new ESLint();
832 await assert
.rejects(() => eslint
.lintText(100), /'code' must be a string/u);
835 it("should throw if non-object value is given to 'options' parameter", async () => {
836 eslint
= new ESLint();
837 await assert
.rejects(() => eslint
.lintText("var a = 0", "foo.js"), /'options' must be an object, null, or undefined/u);
840 it("should throw if 'options' argument contains unknown key", async () => {
841 eslint
= new ESLint();
842 await assert
.rejects(() => eslint
.lintText("var a = 0", { filename
: "foo.js" }), /'options' must not include the unknown option 'filename'/u);
845 it("should throw if non-string value is given to 'options.filePath' option", async () => {
846 eslint
= new ESLint();
847 await assert
.rejects(() => eslint
.lintText("var a = 0", { filePath
: "" }), /'options.filePath' must be a non-empty string or undefined/u);
850 it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
851 eslint
= new ESLint();
852 await assert
.rejects(() => eslint
.lintText("var a = 0", { warnIgnored
: "" }), /'options.warnIgnored' must be a boolean or undefined/u);
856 describe("lintFiles()", () => {
858 /** @type {InstanceType<import("../../../lib/eslint")["ESLint"]>} */
861 it("should use correct parser when custom parser is specified", async () => {
862 eslint
= new ESLint({
866 const filePath
= path
.resolve(__dirname
, "../../fixtures/configurations/parser/custom.js");
867 const results
= await eslint
.lintFiles([filePath
]);
869 assert
.strictEqual(results
.length
, 1);
870 assert
.strictEqual(results
[0].messages
.length
, 1);
871 assert
.strictEqual(results
[0].messages
[0].message
, "Parsing error: Boom!");
874 it("should report zero messages when given a config file and a valid file", async () => {
875 eslint
= new ESLint({
877 overrideConfigFile
: ".eslintrc.js"
879 const results
= await eslint
.lintFiles(["lib/**/cli*.js"]);
881 assert
.strictEqual(results
.length
, 2);
882 assert
.strictEqual(results
[0].messages
.length
, 0);
883 assert
.strictEqual(results
[1].messages
.length
, 0);
886 it("should handle multiple patterns with overlapping files", async () => {
887 eslint
= new ESLint({
889 overrideConfigFile
: ".eslintrc.js"
891 const results
= await eslint
.lintFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
893 assert
.strictEqual(results
.length
, 2);
894 assert
.strictEqual(results
[0].messages
.length
, 0);
895 assert
.strictEqual(results
[1].messages
.length
, 0);
898 it("should report zero messages when given a config file and a valid file and espree as parser", async () => {
899 eslint
= new ESLint({
908 const results
= await eslint
.lintFiles(["lib/cli.js"]);
910 assert
.strictEqual(results
.length
, 1);
911 assert
.strictEqual(results
[0].messages
.length
, 0);
914 it("should report zero messages when given a config file and a valid file and esprima as parser", async () => {
915 eslint
= new ESLint({
922 const results
= await eslint
.lintFiles(["tests/fixtures/passing.js"]);
924 assert
.strictEqual(results
.length
, 1);
925 assert
.strictEqual(results
[0].messages
.length
, 0);
928 it("should throw an error when given a config file and a valid file and invalid parser", async () => {
929 eslint
= new ESLint({
936 await assert
.rejects(async () => await eslint
.lintFiles(["lib/cli.js"]), /Cannot find module
'test11'/u
);
939 it("should report zero messages when given a directory with a .js2 file", async () => {
940 eslint
= new ESLint({
941 cwd
: path
.join(fixtureDir
, ".."),
944 const results
= await eslint
.lintFiles([getFixturePath("files/foo.js2")]);
946 assert
.strictEqual(results
.length
, 1);
947 assert
.strictEqual(results
[0].messages
.length
, 0);
950 it("should fall back to defaults when extensions is set to an empty array", async () => {
951 eslint
= new ESLint({
952 cwd
: getFixturePath("configurations"),
953 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json"),
956 const results
= await eslint
.lintFiles([getFixturePath("single-quoted.js")]);
958 assert
.strictEqual(results
.length
, 1);
959 assert
.strictEqual(results
[0].messages
.length
, 1);
960 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
961 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
962 assert
.strictEqual(results
[0].errorCount
, 1);
963 assert
.strictEqual(results
[0].warningCount
, 0);
964 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
965 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
968 it("should report zero messages when given a directory with a .js and a .js2 file", async () => {
969 eslint
= new ESLint({
970 extensions
: [".js", ".js2"],
972 cwd
: getFixturePath("..")
974 const results
= await eslint
.lintFiles(["fixtures/files/"]);
976 assert
.strictEqual(results
.length
, 2);
977 assert
.strictEqual(results
[0].messages
.length
, 0);
978 assert
.strictEqual(results
[1].messages
.length
, 0);
981 it("should report zero messages when given a '**' pattern with a .js and a .js2 file", async () => {
982 eslint
= new ESLint({
983 extensions
: [".js", ".js2"],
985 cwd
: path
.join(fixtureDir
, "..")
987 const results
= await eslint
.lintFiles(["fixtures/files/*"]);
989 assert
.strictEqual(results
.length
, 2);
990 assert
.strictEqual(results
[0].messages
.length
, 0);
991 assert
.strictEqual(results
[1].messages
.length
, 0);
994 it("should resolve globs when 'globInputPaths' option is true", async () => {
995 eslint
= new ESLint({
996 extensions
: [".js", ".js2"],
998 cwd
: getFixturePath("..")
1000 const results
= await eslint
.lintFiles(["fixtures/files/*"]);
1002 assert
.strictEqual(results
.length
, 2);
1003 assert
.strictEqual(results
[0].messages
.length
, 0);
1004 assert
.strictEqual(results
[1].messages
.length
, 0);
1007 it("should not resolve globs when 'globInputPaths' option is false", async () => {
1008 eslint
= new ESLint({
1009 extensions
: [".js", ".js2"],
1011 cwd
: getFixturePath(".."),
1012 globInputPaths
: false
1015 await assert
.rejects(async () => {
1016 await eslint
.lintFiles(["fixtures/files/*"]);
1017 }, /No files matching 'fixtures\/files\/\*' were found \(glob was disabled\)\./u);
1020 it("should report on all files passed explicitly, even if ignored by default", async () => {
1021 eslint
= new ESLint({
1022 cwd
: getFixturePath("cli-engine")
1024 const results
= await eslint
.lintFiles(["node_modules/foo.js"]);
1025 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
1027 assert
.strictEqual(results
.length
, 1);
1028 assert
.strictEqual(results
[0].errorCount
, 0);
1029 assert
.strictEqual(results
[0].warningCount
, 1);
1030 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1031 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1032 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1035 it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", async () => {
1036 eslint
= new ESLint({
1037 cwd
: getFixturePath("cli-engine"),
1040 quotes
: [2, "single"]
1044 const results
= await eslint
.lintFiles(["hidden/.hiddenfolder/*.js"]);
1046 assert
.strictEqual(results
.length
, 1);
1047 assert
.strictEqual(results
[0].errorCount
, 1);
1048 assert
.strictEqual(results
[0].warningCount
, 0);
1049 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1050 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1053 it("should not check default ignored files without --no-ignore flag", async () => {
1054 eslint
= new ESLint({
1055 cwd
: getFixturePath("cli-engine")
1058 await assert
.rejects(async () => {
1059 await eslint
.lintFiles(["node_modules"]);
1060 }, /All files matched by 'node_modules' are ignored\./u);
1063 // https://github.com/eslint/eslint/issues/5547
1064 it("should not check node_modules files even with --no-ignore flag", async () => {
1065 eslint
= new ESLint({
1066 cwd
: getFixturePath("cli-engine"),
1070 await assert
.rejects(async () => {
1071 await eslint
.lintFiles(["node_modules"]);
1072 }, /All files matched by 'node_modules' are ignored\./u);
1075 it("should not check .hidden files if they are passed explicitly without --no-ignore flag", async () => {
1076 eslint
= new ESLint({
1077 cwd
: getFixturePath(".."),
1081 quotes
: [2, "single"]
1085 const results
= await eslint
.lintFiles(["fixtures/files/.bar.js"]);
1086 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1088 assert
.strictEqual(results
.length
, 1);
1089 assert
.strictEqual(results
[0].errorCount
, 0);
1090 assert
.strictEqual(results
[0].warningCount
, 1);
1091 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1092 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1093 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1096 // https://github.com/eslint/eslint/issues/12873
1097 it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", async () => {
1098 eslint
= new ESLint({
1099 cwd
: getFixturePath("cli-engine"),
1103 quotes
: [2, "single"]
1107 const results
= await eslint
.lintFiles(["hidden/.hiddenfolder/double-quotes.js"]);
1108 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1110 assert
.strictEqual(results
.length
, 1);
1111 assert
.strictEqual(results
[0].errorCount
, 0);
1112 assert
.strictEqual(results
[0].warningCount
, 1);
1113 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1114 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1115 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1118 it("should check .hidden files if they are passed explicitly with --no-ignore flag", async () => {
1119 eslint
= new ESLint({
1120 cwd
: getFixturePath(".."),
1125 quotes
: [2, "single"]
1129 const results
= await eslint
.lintFiles(["fixtures/files/.bar.js"]);
1131 assert
.strictEqual(results
.length
, 1);
1132 assert
.strictEqual(results
[0].warningCount
, 0);
1133 assert
.strictEqual(results
[0].errorCount
, 1);
1134 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1135 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1136 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1139 it("should check .hidden files if they are unignored with an --ignore-pattern", async () => {
1140 eslint
= new ESLint({
1141 cwd
: getFixturePath("cli-engine"),
1145 ignorePatterns
: "!.hidden*",
1147 quotes
: [2, "single"]
1151 const results
= await eslint
.lintFiles(["hidden/"]);
1153 assert
.strictEqual(results
.length
, 1);
1154 assert
.strictEqual(results
[0].warningCount
, 0);
1155 assert
.strictEqual(results
[0].errorCount
, 1);
1156 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1157 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1158 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1161 it("should report zero messages when given a pattern with a .js and a .js2 file", async () => {
1162 eslint
= new ESLint({
1163 extensions
: [".js", ".js2"],
1165 cwd
: path
.join(fixtureDir
, "..")
1167 const results
= await eslint
.lintFiles(["fixtures/files/*.?s*"]);
1169 assert
.strictEqual(results
.length
, 2);
1170 assert
.strictEqual(results
[0].messages
.length
, 0);
1171 assert
.strictEqual(results
[1].messages
.length
, 0);
1174 it("should return one error message when given a config with rules with options and severity level set to error", async () => {
1175 eslint
= new ESLint({
1176 cwd
: getFixturePath("configurations"),
1177 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json")
1179 const results
= await eslint
.lintFiles([getFixturePath("single-quoted.js")]);
1181 assert
.strictEqual(results
.length
, 1);
1182 assert
.strictEqual(results
[0].messages
.length
, 1);
1183 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1184 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1185 assert
.strictEqual(results
[0].errorCount
, 1);
1186 assert
.strictEqual(results
[0].warningCount
, 0);
1187 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1188 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1191 it("should return 3 messages when given a config file and a directory of 3 valid files", async () => {
1192 eslint
= new ESLint({
1193 cwd
: path
.join(fixtureDir
, ".."),
1194 overrideConfigFile
: getFixturePath("configurations", "semi-error.json")
1196 const results
= await eslint
.lintFiles([getFixturePath("formatters")]);
1198 assert
.strictEqual(results
.length
, 3);
1199 assert
.strictEqual(results
[0].messages
.length
, 0);
1200 assert
.strictEqual(results
[1].messages
.length
, 0);
1201 assert
.strictEqual(results
[2].messages
.length
, 0);
1202 assert
.strictEqual(results
[0].errorCount
, 0);
1203 assert
.strictEqual(results
[0].warningCount
, 0);
1204 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1205 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1206 assert
.strictEqual(results
[1].errorCount
, 0);
1207 assert
.strictEqual(results
[1].warningCount
, 0);
1208 assert
.strictEqual(results
[1].fixableErrorCount
, 0);
1209 assert
.strictEqual(results
[1].fixableWarningCount
, 0);
1210 assert
.strictEqual(results
[2].errorCount
, 0);
1211 assert
.strictEqual(results
[2].warningCount
, 0);
1212 assert
.strictEqual(results
[2].fixableErrorCount
, 0);
1213 assert
.strictEqual(results
[2].fixableWarningCount
, 0);
1216 it("should process when file is given by not specifying extensions", async () => {
1217 eslint
= new ESLint({
1219 cwd
: path
.join(fixtureDir
, "..")
1221 const results
= await eslint
.lintFiles(["fixtures/files/foo.js2"]);
1223 assert
.strictEqual(results
.length
, 1);
1224 assert
.strictEqual(results
[0].messages
.length
, 0);
1227 it("should return zero messages when given a config with environment set to browser", async () => {
1228 eslint
= new ESLint({
1229 cwd
: path
.join(fixtureDir
, ".."),
1230 overrideConfigFile
: getFixturePath("configurations", "env-browser.json")
1232 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1234 assert
.strictEqual(results
.length
, 1);
1235 assert
.strictEqual(results
[0].messages
.length
, 0);
1238 it("should return zero messages when given an option to set environment to browser", async () => {
1239 eslint
= new ESLint({
1240 cwd
: path
.join(fixtureDir
, ".."),
1242 env
: { browser
: true },
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 a config with environment set to Node.js", async () => {
1256 eslint
= new ESLint({
1257 cwd
: path
.join(fixtureDir
, ".."),
1258 overrideConfigFile
: getFixturePath("configurations", "env-node.json")
1260 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-node.js"))]);
1262 assert
.strictEqual(results
.length
, 1);
1263 assert
.strictEqual(results
[0].messages
.length
, 0);
1266 it("should not return results from previous call when calling more than once", async () => {
1267 eslint
= new ESLint({
1268 cwd
: path
.join(fixtureDir
, ".."),
1276 const failFilePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1277 const passFilePath
= fs
.realpathSync(getFixturePath("passing.js"));
1279 let results
= await eslint
.lintFiles([failFilePath
]);
1281 assert
.strictEqual(results
.length
, 1);
1282 assert
.strictEqual(results
[0].filePath
, failFilePath
);
1283 assert
.strictEqual(results
[0].messages
.length
, 1);
1284 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
1285 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1287 results
= await eslint
.lintFiles([passFilePath
]);
1288 assert
.strictEqual(results
.length
, 1);
1289 assert
.strictEqual(results
[0].filePath
, passFilePath
);
1290 assert
.strictEqual(results
[0].messages
.length
, 0);
1293 it("should throw an error when given a directory with all eslint excluded files in the directory", async () => {
1294 eslint
= new ESLint({
1295 ignorePath
: getFixturePath(".eslintignore")
1298 await assert
.rejects(async () => {
1299 await eslint
.lintFiles([getFixturePath("./cli-engine/")]);
1300 }, new RegExp(escapeStringRegExp(`All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`), "u"));
1303 it("should throw an error when all given files are ignored", async () => {
1304 await assert
.rejects(async () => {
1305 await eslint
.lintFiles(["tests/fixtures/cli-engine/"]);
1306 }, /All files matched by 'tests\/fixtures\/cli-engine\/' are ignored\./u);
1309 it("should throw an error when all given files are ignored even with a `./` prefix", async () => {
1310 eslint
= new ESLint({
1311 ignorePath
: getFixturePath(".eslintignore")
1314 await assert
.rejects(async () => {
1315 await eslint
.lintFiles(["./tests/fixtures/cli-engine/"]);
1316 }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
1319 // https://github.com/eslint/eslint/issues/3788
1320 it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", async () => {
1321 eslint
= new ESLint({
1322 ignorePath
: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
1326 quotes
: [2, "double"]
1329 cwd
: getFixturePath("cli-engine", "nested_node_modules")
1331 const results
= await eslint
.lintFiles(["."]);
1333 assert
.strictEqual(results
.length
, 1);
1334 assert
.strictEqual(results
[0].errorCount
, 0);
1335 assert
.strictEqual(results
[0].warningCount
, 0);
1336 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1337 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1340 // https://github.com/eslint/eslint/issues/3812
1341 it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", async () => {
1342 eslint
= new ESLint({
1343 ignorePath
: getFixturePath("cli-engine/.eslintignore2"),
1347 quotes
: [2, "double"]
1352 await assert
.rejects(async () => {
1353 await eslint
.lintFiles(["./tests/fixtures/cli-engine/"]);
1354 }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
1357 it("should throw an error when all given files are ignored via ignore-pattern", async () => {
1358 eslint
= new ESLint({
1360 ignorePatterns
: "tests/fixtures/single-quoted.js"
1364 await assert
.rejects(async () => {
1365 await eslint
.lintFiles(["tests/fixtures/*-quoted.js"]);
1366 }, /All files matched by 'tests\/fixtures\/\*-quoted\.js' are ignored\./u);
1369 it("should return a warning when an explicitly given file is ignored", async () => {
1370 eslint
= new ESLint({
1371 ignorePath
: getFixturePath(".eslintignore"),
1372 cwd
: getFixturePath()
1374 const filePath
= getFixturePath("passing.js");
1375 const results
= await eslint
.lintFiles([filePath
]);
1377 assert
.strictEqual(results
.length
, 1);
1378 assert
.strictEqual(results
[0].filePath
, filePath
);
1379 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1380 assert
.strictEqual(results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
1381 assert
.strictEqual(results
[0].errorCount
, 0);
1382 assert
.strictEqual(results
[0].warningCount
, 1);
1383 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1384 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1387 it("should return two messages when given a file in excluded files list while ignore is off", async () => {
1388 eslint
= new ESLint({
1389 ignorePath
: getFixturePath(".eslintignore"),
1397 const filePath
= fs
.realpathSync(getFixturePath("undef.js"));
1398 const results
= await eslint
.lintFiles([filePath
]);
1400 assert
.strictEqual(results
.length
, 1);
1401 assert
.strictEqual(results
[0].filePath
, filePath
);
1402 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
1403 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1404 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-undef");
1405 assert
.strictEqual(results
[0].messages
[1].severity
, 2);
1408 it("should return zero messages when executing a file with a shebang", async () => {
1409 eslint
= new ESLint({
1412 const results
= await eslint
.lintFiles([getFixturePath("shebang.js")]);
1414 assert
.strictEqual(results
.length
, 1);
1415 assert
.strictEqual(results
[0].messages
.length
, 0);
1418 it("should give a warning when loading a custom rule that doesn't exist", async () => {
1419 eslint
= new ESLint({
1421 rulePaths
: [getFixturePath("rules", "dir1")],
1422 overrideConfigFile
: getFixturePath("rules", "missing-rule.json")
1424 const results
= await eslint
.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1426 assert
.strictEqual(results
.length
, 1);
1427 assert
.strictEqual(results
[0].messages
.length
, 1);
1428 assert
.strictEqual(results
[0].messages
[0].ruleId
, "missing-rule");
1429 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1430 assert
.strictEqual(results
[0].messages
[0].message
, "Definition for rule 'missing-rule' was not found.");
1433 it("should throw an error when loading a bad custom rule", async () => {
1434 eslint
= new ESLint({
1436 rulePaths
: [getFixturePath("rules", "wrong")],
1437 overrideConfigFile
: getFixturePath("rules", "eslint.json")
1441 await assert
.rejects(async () => {
1442 await eslint
.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1443 }, /Error while loading rule 'custom-rule'/u);
1446 it("should return one message when a custom rule matches a file", async () => {
1447 eslint
= new ESLint({
1450 rulePaths
: [getFixturePath("rules/")],
1451 overrideConfigFile
: getFixturePath("rules", "eslint.json")
1453 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1454 const results
= await eslint
.lintFiles([filePath
]);
1456 assert
.strictEqual(results
.length
, 1);
1457 assert
.strictEqual(results
[0].filePath
, filePath
);
1458 assert
.strictEqual(results
[0].messages
.length
, 2);
1459 assert
.strictEqual(results
[0].messages
[0].ruleId
, "custom-rule");
1460 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1463 it("should load custom rule from the provided cwd", async () => {
1464 const cwd
= path
.resolve(getFixturePath("rules"));
1466 eslint
= new ESLint({
1470 overrideConfigFile
: "eslint.json"
1472 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1473 const results
= await eslint
.lintFiles([filePath
]);
1475 assert
.strictEqual(results
.length
, 1);
1476 assert
.strictEqual(results
[0].filePath
, filePath
);
1477 assert
.strictEqual(results
[0].messages
.length
, 2);
1478 assert
.strictEqual(results
[0].messages
[0].ruleId
, "custom-rule");
1479 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1482 it("should return messages when multiple custom rules match a file", async () => {
1483 eslint
= new ESLint({
1486 getFixturePath("rules", "dir1"),
1487 getFixturePath("rules", "dir2")
1489 overrideConfigFile
: getFixturePath("rules", "multi-rulesdirs.json")
1491 const filePath
= fs
.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.js"));
1492 const results
= await eslint
.lintFiles([filePath
]);
1494 assert
.strictEqual(results
.length
, 1);
1495 assert
.strictEqual(results
[0].filePath
, filePath
);
1496 assert
.strictEqual(results
[0].messages
.length
, 2);
1497 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-literals");
1498 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1499 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-strings");
1500 assert
.strictEqual(results
[0].messages
[1].severity
, 2);
1503 it("should return zero messages when executing without useEslintrc flag", async () => {
1504 eslint
= new ESLint({
1508 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.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
, 0);
1516 it("should return zero messages when executing without useEslintrc flag in Node.js environment", async () => {
1517 eslint
= new ESLint({
1524 const filePath
= fs
.realpathSync(getFixturePath("process-exit.js"));
1525 const results
= await eslint
.lintFiles([filePath
]);
1527 assert
.strictEqual(results
.length
, 1);
1528 assert
.strictEqual(results
[0].filePath
, filePath
);
1529 assert
.strictEqual(results
[0].messages
.length
, 0);
1532 it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", async () => {
1533 eslint
= new ESLint({
1540 const filePath
= fs
.realpathSync(getFixturePath("eslintrc", "quotes.js"));
1541 const results
= await eslint
.lintFiles([filePath
]);
1543 assert
.strictEqual(results
.length
, 1);
1544 assert
.strictEqual(results
[0].filePath
, filePath
);
1545 assert
.strictEqual(results
[0].messages
.length
, 0);
1548 it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", async () => {
1549 eslint
= new ESLint({
1556 const filePath
= fs
.realpathSync(getFixturePath("packagejson", "quotes.js"));
1557 const results
= await eslint
.lintFiles([filePath
]);
1559 assert
.strictEqual(results
.length
, 1);
1560 assert
.strictEqual(results
[0].filePath
, filePath
);
1561 assert
.strictEqual(results
[0].messages
.length
, 0);
1564 it("should warn when deprecated rules are configured", async () => {
1565 eslint
= new ESLint({
1567 overrideConfigFile
: ".eslintrc.js",
1576 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1578 assert
.deepStrictEqual(
1579 results
[0].usedDeprecatedRules
,
1581 { ruleId
: "indent-legacy", replacedBy
: ["indent"] },
1582 { ruleId
: "require-jsdoc", replacedBy
: [] },
1583 { ruleId
: "valid-jsdoc", replacedBy
: [] }
1588 it("should not warn when deprecated rules are not configured", async () => {
1589 eslint
= new ESLint({
1591 overrideConfigFile
: ".eslintrc.js",
1593 rules
: { indent
: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
1596 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1598 assert
.deepStrictEqual(results
[0].usedDeprecatedRules
, []);
1601 it("should warn when deprecated rules are found in a config", async () => {
1602 eslint
= new ESLint({
1604 overrideConfigFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
1607 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1609 assert
.deepStrictEqual(
1610 results
[0].usedDeprecatedRules
,
1611 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
1615 describe("Fix Mode", () => {
1616 it("should return fixed text on multiple files when in fix mode", async () => {
1619 * Converts CRLF to LF in output.
1620 * This is a workaround for git's autocrlf option on Windows.
1621 * @param {Object} result A result object to convert.
1624 function convertCRLF(result
) {
1625 if (result
&& result
.output
) {
1626 result
.output
= result
.output
.replace(/\r\n/gu, "\n");
1630 eslint
= new ESLint({
1631 cwd
: path
.join(fixtureDir
, ".."),
1637 quotes
: [2, "double"],
1640 "space-infix-ops": 2
1644 const results
= await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1646 results
.forEach(convertCRLF
);
1647 assert
.deepStrictEqual(results
, [
1649 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/multipass.js")),
1653 fixableErrorCount
: 0,
1654 fixableWarningCount
: 0,
1655 output
: "true ? \"yes\" : \"no\";\n",
1656 usedDeprecatedRules
: []
1659 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/ok.js")),
1663 fixableErrorCount
: 0,
1664 fixableWarningCount
: 0,
1665 usedDeprecatedRules
: []
1668 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes-semi-eqeqeq.js")),
1675 message
: "Expected '===' and instead saw '=='.",
1676 messageId
: "unexpected",
1677 nodeType
: "BinaryExpression",
1684 fixableErrorCount
: 0,
1685 fixableWarningCount
: 0,
1686 output
: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n",
1687 usedDeprecatedRules
: []
1690 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes.js")),
1698 message
: "'foo' is not defined.",
1699 nodeType
: "Identifier",
1706 fixableErrorCount
: 0,
1707 fixableWarningCount
: 0,
1708 output
: "var msg = \"hi\" + foo;\n",
1709 usedDeprecatedRules
: []
1714 it("should run autofix even if files are cached without autofix results", async () => {
1715 const baseOptions
= {
1716 cwd
: path
.join(fixtureDir
, ".."),
1721 quotes
: [2, "double"],
1724 "space-infix-ops": 2
1729 eslint
= new ESLint(Object
.assign({}, baseOptions
, { cache
: true, fix
: false }));
1731 // Do initial lint run and populate the cache file
1732 await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1734 eslint
= new ESLint(Object
.assign({}, baseOptions
, { cache
: true, fix
: true }));
1735 const results
= await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1737 assert(results
.some(result
=> result
.output
));
1741 // These tests have to do with https://github.com/eslint/eslint/issues/963
1743 describe("configuration hierarchy", () => {
1745 // Default configuration - blank
1746 it("should return zero messages when executing with no .eslintrc", async () => {
1747 eslint
= new ESLint({
1748 cwd
: path
.join(fixtureDir
, ".."),
1751 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1753 assert
.strictEqual(results
.length
, 1);
1754 assert
.strictEqual(results
[0].messages
.length
, 0);
1757 // No default configuration rules - conf/environments.js (/*eslint-env node*/)
1758 it("should return zero messages when executing with no .eslintrc in the Node.js environment", async () => {
1759 eslint
= new ESLint({
1760 cwd
: path
.join(fixtureDir
, ".."),
1763 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
1765 assert
.strictEqual(results
.length
, 1);
1766 assert
.strictEqual(results
[0].messages
.length
, 0);
1769 // Project configuration - first level .eslintrc
1770 it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
1771 eslint
= new ESLint({
1772 cwd
: path
.join(fixtureDir
, "..")
1774 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1776 assert
.strictEqual(results
.length
, 1);
1777 assert
.strictEqual(results
[0].messages
.length
, 0);
1780 // Project configuration - first level .eslintrc
1781 it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
1782 eslint
= new ESLint({
1783 cwd
: path
.join(fixtureDir
, "..")
1785 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1787 assert
.strictEqual(results
.length
, 1);
1788 assert
.strictEqual(results
[0].messages
.length
, 0);
1791 // Project configuration - first level .eslintrc
1792 it("should return one message when executing with .eslintrc", async () => {
1793 eslint
= new ESLint({
1794 cwd
: path
.join(fixtureDir
, "..")
1796 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1798 assert
.strictEqual(results
.length
, 1);
1799 assert
.strictEqual(results
[0].messages
.length
, 1);
1800 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1801 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1804 // Project configuration - second level .eslintrc
1805 it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", async () => {
1806 eslint
= new ESLint({
1807 cwd
: path
.join(fixtureDir
, "..")
1809 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1811 assert
.strictEqual(results
.length
, 1);
1812 assert
.strictEqual(results
[0].messages
.length
, 1);
1813 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1814 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1817 // Project configuration - third level .eslintrc
1818 it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", async () => {
1819 eslint
= new ESLint({
1820 cwd
: path
.join(fixtureDir
, "..")
1822 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
1824 assert
.strictEqual(results
.length
, 1);
1825 assert
.strictEqual(results
[0].messages
.length
, 1);
1826 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1827 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1830 // Project configuration - first level package.json
1831 it("should return one message when executing with package.json", async () => {
1832 eslint
= new ESLint({
1833 cwd
: path
.join(fixtureDir
, "..")
1835 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
1837 assert
.strictEqual(results
.length
, 1);
1838 assert
.strictEqual(results
[0].messages
.length
, 1);
1839 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1840 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1843 // Project configuration - second level package.json
1844 it("should return zero messages when executing with local package.json that overrides parent package.json", async () => {
1845 eslint
= new ESLint({
1846 cwd
: path
.join(fixtureDir
, "..")
1848 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
1850 assert
.strictEqual(results
.length
, 1);
1851 assert
.strictEqual(results
[0].messages
.length
, 0);
1854 // Project configuration - third level package.json
1855 it("should return one message when executing with local package.json that overrides parent and grandparent package.json", async () => {
1856 eslint
= new ESLint({
1857 cwd
: path
.join(fixtureDir
, "..")
1859 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
1861 assert
.strictEqual(results
.length
, 1);
1862 assert
.strictEqual(results
[0].messages
.length
, 1);
1863 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1864 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1867 // Project configuration - .eslintrc overrides package.json in same directory
1868 it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", async () => {
1869 eslint
= new ESLint({
1870 cwd
: path
.join(fixtureDir
, "..")
1872 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
1874 assert
.strictEqual(results
.length
, 1);
1875 assert
.strictEqual(results
[0].messages
.length
, 1);
1876 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1877 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1880 // Command line configuration - --config with first level .eslintrc
1881 it("should return two messages when executing with config file that adds to local .eslintrc", async () => {
1882 eslint
= new ESLint({
1883 cwd
: path
.join(fixtureDir
, ".."),
1884 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1886 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1888 assert
.strictEqual(results
.length
, 1);
1889 assert
.strictEqual(results
[0].messages
.length
, 2);
1890 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1891 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1892 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi");
1893 assert
.strictEqual(results
[0].messages
[1].severity
, 1);
1896 // Command line configuration - --config with first level .eslintrc
1897 it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
1898 eslint
= new ESLint({
1899 cwd
: path
.join(fixtureDir
, ".."),
1900 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1902 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1904 assert
.strictEqual(results
.length
, 1);
1905 assert
.strictEqual(results
[0].messages
.length
, 0);
1908 // Command line configuration - --config with second level .eslintrc
1909 it("should return two messages when executing with config file that adds to local and parent .eslintrc", async () => {
1910 eslint
= new ESLint({
1911 cwd
: path
.join(fixtureDir
, ".."),
1912 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1914 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1916 assert
.strictEqual(results
.length
, 1);
1917 assert
.strictEqual(results
[0].messages
.length
, 2);
1918 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1919 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1920 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi");
1921 assert
.strictEqual(results
[0].messages
[1].severity
, 1);
1924 // Command line configuration - --config with second level .eslintrc
1925 it("should return one message when executing with config file that overrides local and parent .eslintrc", async () => {
1926 eslint
= new ESLint({
1927 cwd
: path
.join(fixtureDir
, ".."),
1928 overrideConfigFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml")
1930 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1932 assert
.strictEqual(results
.length
, 1);
1933 assert
.strictEqual(results
[0].messages
.length
, 1);
1934 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1935 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1938 // Command line configuration - --config with first level .eslintrc
1939 it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
1940 eslint
= new ESLint({
1941 cwd
: path
.join(fixtureDir
, ".."),
1942 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1944 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1946 assert
.strictEqual(results
.length
, 1);
1947 assert
.strictEqual(results
[0].messages
.length
, 0);
1950 // Command line configuration - --rule with --config and first level .eslintrc
1951 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
1952 eslint
= new ESLint({
1953 cwd
: path
.join(fixtureDir
, ".."),
1954 overrideConfigFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
1957 quotes
: [1, "double"]
1961 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1963 assert
.strictEqual(results
.length
, 1);
1964 assert
.strictEqual(results
[0].messages
.length
, 1);
1965 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1966 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1969 // Command line configuration - --rule with --config and first level .eslintrc
1970 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
1971 eslint
= new ESLint({
1972 cwd
: path
.join(fixtureDir
, ".."),
1973 overrideConfigFile
: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
1976 quotes
: [1, "double"]
1980 const results
= await eslint
.lintFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
1982 assert
.strictEqual(results
.length
, 1);
1983 assert
.strictEqual(results
[0].messages
.length
, 1);
1984 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1985 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1989 describe("plugins", () => {
1990 it("should return two messages when executing with config file that specifies a plugin", async () => {
1991 eslint
= eslintWithPlugins({
1992 cwd
: path
.join(fixtureDir
, ".."),
1993 overrideConfigFile
: getFixturePath("configurations", "plugins-with-prefix.json"),
1996 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
1998 assert
.strictEqual(results
.length
, 1);
1999 assert
.strictEqual(results
[0].messages
.length
, 2);
2000 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2003 it("should return two messages when executing with config file that specifies a plugin with namespace", async () => {
2004 eslint
= eslintWithPlugins({
2005 cwd
: path
.join(fixtureDir
, ".."),
2006 overrideConfigFile
: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
2009 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2011 assert
.strictEqual(results
.length
, 1);
2012 assert
.strictEqual(results
[0].messages
.length
, 2);
2013 assert
.strictEqual(results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2016 it("should return two messages when executing with config file that specifies a plugin without prefix", async () => {
2017 eslint
= eslintWithPlugins({
2018 cwd
: path
.join(fixtureDir
, ".."),
2019 overrideConfigFile
: getFixturePath("configurations", "plugins-without-prefix.json"),
2022 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2024 assert
.strictEqual(results
.length
, 1);
2025 assert
.strictEqual(results
[0].messages
.length
, 2);
2026 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2029 it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", async () => {
2030 eslint
= eslintWithPlugins({
2031 cwd
: path
.join(fixtureDir
, ".."),
2032 overrideConfigFile
: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
2035 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2037 assert
.strictEqual(results
.length
, 1);
2038 assert
.strictEqual(results
[0].messages
.length
, 2);
2039 assert
.strictEqual(results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2042 it("should return two messages when executing with cli option that specifies a plugin", async () => {
2043 eslint
= eslintWithPlugins({
2044 cwd
: path
.join(fixtureDir
, ".."),
2047 plugins
: ["example"],
2048 rules
: { "example/example-rule": 1 }
2051 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2053 assert
.strictEqual(results
.length
, 1);
2054 assert
.strictEqual(results
[0].messages
.length
, 2);
2055 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2058 it("should return two messages when executing with cli option that specifies preloaded plugin", async () => {
2059 eslint
= new ESLint({
2060 cwd
: path
.join(fixtureDir
, ".."),
2064 rules
: { "test/example-rule": 1 }
2067 "eslint-plugin-test": { rules
: { "example-rule": require("../../fixtures/rules/custom-rule") } }
2070 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2072 assert
.strictEqual(results
.length
, 1);
2073 assert
.strictEqual(results
[0].messages
.length
, 2);
2074 assert
.strictEqual(results
[0].messages
[0].ruleId
, "test/example-rule");
2077 it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", async () => {
2078 eslint
= new ESLint({
2079 resolvePluginsRelativeTo
: getFixturePath("plugins"),
2081 plugins
: ["with-rules"],
2082 rules
: { "with-rules/rule1": "error" }
2086 const results
= await eslint
.lintText("foo");
2088 assert
.strictEqual(results
.length
, 1);
2089 assert
.strictEqual(results
[0].messages
.length
, 1);
2090 assert
.strictEqual(results
[0].messages
[0].ruleId
, "with-rules/rule1");
2091 assert
.strictEqual(results
[0].messages
[0].message
, "Rule report from plugin");
2095 describe("cache", () => {
2098 * helper method to delete a file without caring about exceptions
2099 * @param {string} filePath The file path
2102 function doDelete(filePath
) {
2104 fs
.unlinkSync(filePath
);
2108 * we don't care if the file didn't exist, since our
2109 * intention was to remove the file
2115 * helper method to delete the cache files created during testing
2118 function deleteCache() {
2119 doDelete(path
.resolve(".eslintcache"));
2120 doDelete(path
.resolve(".cache/custom-cache"));
2132 describe("when the cacheFile is a directory or looks like a directory", () => {
2135 * helper method to delete the cache files created during testing
2138 function deleteCacheDir() {
2140 fs
.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
2144 * we don't care if the file didn't exist, since our
2145 * intention was to remove the file
2157 it("should create the cache file inside the provided directory", async () => {
2158 assert(!shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2160 eslint
= new ESLint({
2163 // specifying cache true the cache will be created
2165 cacheLocation
: "./tmp/.cacheFileDir/",
2175 const file
= getFixturePath("cache/src", "test-file.js");
2177 await eslint
.lintFiles([file
]);
2179 assert(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2185 it("should create the cache file inside the provided directory using the cacheLocation option", async () => {
2186 assert(!shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2188 eslint
= new ESLint({
2191 // specifying cache true the cache will be created
2193 cacheLocation
: "./tmp/.cacheFileDir/",
2203 const file
= getFixturePath("cache/src", "test-file.js");
2205 await eslint
.lintFiles([file
]);
2207 assert(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2212 it("should create the cache file inside cwd when no cacheLocation provided", async () => {
2213 const cwd
= path
.resolve(getFixturePath("cli-engine"));
2215 eslint
= new ESLint({
2227 const file
= getFixturePath("cli-engine", "console.js");
2229 await eslint
.lintFiles([file
]);
2231 assert(shell
.test("-f", path
.resolve(cwd
, ".eslintcache")), "the cache for eslint was created at provided cwd");
2234 it("should invalidate the cache if the configuration changed between executions", async () => {
2235 assert(!shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2237 eslint
= new ESLint({
2240 // specifying cache true the cache will be created
2252 let spy
= sinon
.spy(fs
, "readFileSync");
2254 let file
= getFixturePath("cache/src", "test-file.js");
2256 file
= fs
.realpathSync(file
);
2257 const results
= await eslint
.lintFiles([file
]);
2259 for (const { errorCount
, warningCount
} of results
) {
2260 assert
.strictEqual(errorCount
+ warningCount
, 0, "the file passed without errors or warnings");
2262 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2263 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2268 eslint
= new ESLint({
2271 // specifying cache true the cache will be created
2284 spy
= sinon
.spy(fs
, "readFileSync");
2286 const [cachedResult
] = await eslint
.lintFiles([file
]);
2288 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed because the config changed");
2289 assert
.strictEqual(cachedResult
.errorCount
, 1, "since configuration changed the cache was not used an one error was reported");
2290 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2293 it("should remember the files from a previous run and do not operate on them if not changed", async () => {
2294 assert(!shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2296 eslint
= new ESLint({
2299 // specifying cache true the cache will be created
2311 let spy
= sinon
.spy(fs
, "readFileSync");
2313 let file
= getFixturePath("cache/src", "test-file.js");
2315 file
= fs
.realpathSync(file
);
2317 const result
= await eslint
.lintFiles([file
]);
2319 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2320 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2325 eslint
= new ESLint({
2328 // specifying cache true the cache will be created
2341 spy
= sinon
.spy(fs
, "readFileSync");
2343 const cachedResult
= await eslint
.lintFiles([file
]);
2345 assert
.deepStrictEqual(result
, cachedResult
, "the result is the same regardless of using cache or not");
2347 // assert the file was not processed because the cache was used
2348 assert(!spy
.calledWith(file
), "the file was not loaded because it used the cache");
2351 it("should remember the files from a previous run and do not operate on then if not changed", async () => {
2352 const cacheLocation
= getFixturePath(".eslintcache");
2353 const eslintOptions
= {
2356 // specifying cache true the cache will be created
2366 cwd
: path
.join(fixtureDir
, "..")
2369 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint does not exist");
2371 eslint
= new ESLint(eslintOptions
);
2373 let file
= getFixturePath("cache/src", "test-file.js");
2375 file
= fs
.realpathSync(file
);
2377 await eslint
.lintFiles([file
]);
2379 assert(shell
.test("-f", cacheLocation
), "the cache for eslint was created");
2381 eslintOptions
.cache
= false;
2382 eslint
= new ESLint(eslintOptions
);
2384 await eslint
.lintFiles([file
]);
2386 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint was deleted since last run did not used the cache");
2389 it("should store in the cache a file that failed the test", async () => {
2390 const cacheLocation
= getFixturePath(".eslintcache");
2392 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint does not exist");
2394 eslint
= new ESLint({
2395 cwd
: path
.join(fixtureDir
, ".."),
2398 // specifying cache true the cache will be created
2409 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2410 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2411 const result
= await eslint
.lintFiles([badFile
, goodFile
]);
2413 assert(shell
.test("-f", cacheLocation
), "the cache for eslint was created");
2414 const fileCache
= fCache
.createFromFile(cacheLocation
);
2415 const { cache
} = fileCache
;
2417 assert
.strictEqual(typeof cache
.getKey(goodFile
), "object", "the entry for the good file is in the cache");
2418 assert
.strictEqual(typeof cache
.getKey(badFile
), "object", "the entry for the bad file is in the cache");
2419 const cachedResult
= await eslint
.lintFiles([badFile
, goodFile
]);
2421 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2424 it("should not contain in the cache a file that was deleted", async () => {
2425 const cacheLocation
= getFixturePath(".eslintcache");
2427 doDelete(cacheLocation
);
2429 eslint
= new ESLint({
2430 cwd
: path
.join(fixtureDir
, ".."),
2433 // specifying cache true the cache will be created
2444 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2445 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2446 const toBeDeletedFile
= fs
.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
2448 await eslint
.lintFiles([badFile
, goodFile
, toBeDeletedFile
]);
2449 const fileCache
= fCache
.createFromFile(cacheLocation
);
2450 let { cache
} = fileCache
;
2452 assert
.strictEqual(typeof cache
.getKey(toBeDeletedFile
), "object", "the entry for the file to be deleted is in the cache");
2454 // delete the file from the file system
2455 fs
.unlinkSync(toBeDeletedFile
);
2458 * file-entry-cache@2.0.0 will remove from the cache deleted files
2459 * even when they were not part of the array of files to be analyzed
2461 await eslint
.lintFiles([badFile
, goodFile
]);
2463 cache
= JSON
.parse(fs
.readFileSync(cacheLocation
));
2465 assert
.strictEqual(typeof cache
[toBeDeletedFile
], "undefined", "the entry for the file to be deleted is not in the cache");
2468 it("should contain files that were not visited in the cache provided they still exist", async () => {
2469 const cacheLocation
= getFixturePath(".eslintcache");
2471 doDelete(cacheLocation
);
2473 eslint
= new ESLint({
2474 cwd
: path
.join(fixtureDir
, ".."),
2477 // specifying cache true the cache will be created
2488 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2489 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2490 const testFile2
= fs
.realpathSync(getFixturePath("cache/src", "test-file2.js"));
2492 await eslint
.lintFiles([badFile
, goodFile
, testFile2
]);
2494 let fileCache
= fCache
.createFromFile(cacheLocation
);
2495 let { cache
} = fileCache
;
2497 assert
.strictEqual(typeof cache
.getKey(testFile2
), "object", "the entry for the test-file2 is in the cache");
2500 * we pass a different set of files minus test-file2
2501 * previous version of file-entry-cache would remove the non visited
2502 * entries. 2.0.0 version will keep them unless they don't exist
2504 await eslint
.lintFiles([badFile
, goodFile
]);
2506 fileCache
= fCache
.createFromFile(cacheLocation
);
2507 cache
= fileCache
.cache
;
2509 assert
.strictEqual(typeof cache
.getKey(testFile2
), "object", "the entry for the test-file2 is in the cache");
2512 it("should not delete cache when executing on text", async () => {
2513 const cacheLocation
= getFixturePath(".eslintcache");
2515 eslint
= new ESLint({
2516 cwd
: path
.join(fixtureDir
, ".."),
2528 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2530 await eslint
.lintText("var foo = 'bar';");
2532 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2535 it("should not delete cache when executing on text with a provided filename", async () => {
2536 const cacheLocation
= getFixturePath(".eslintcache");
2538 eslint
= new ESLint({
2539 cwd
: path
.join(fixtureDir
, ".."),
2551 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2553 await eslint
.lintText("var bar = foo;", { filePath
: "fixtures/passing.js" });
2555 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2558 it("should not delete cache when executing on files with --cache flag", async () => {
2559 const cacheLocation
= getFixturePath(".eslintcache");
2561 eslint
= new ESLint({
2562 cwd
: path
.join(fixtureDir
, ".."),
2574 const file
= getFixturePath("cli-engine", "console.js");
2576 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2578 await eslint
.lintFiles([file
]);
2580 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2583 it("should delete cache when executing on files without --cache flag", async () => {
2584 const cacheLocation
= getFixturePath(".eslintcache");
2586 eslint
= new ESLint({
2587 cwd
: path
.join(fixtureDir
, ".."),
2598 const file
= getFixturePath("cli-engine", "console.js");
2600 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2602 await eslint
.lintFiles([file
]);
2604 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint has been deleted");
2607 describe("cacheFile", () => {
2608 it("should use the specified cache file", async () => {
2609 const customCacheFile
= path
.resolve(".cache/custom-cache");
2611 assert(!shell
.test("-f", customCacheFile
), "the cache for eslint does not exist");
2613 eslint
= new ESLint({
2616 // specify a custom cache file
2617 cacheLocation
: customCacheFile
,
2619 // specifying cache true the cache will be created
2628 cwd
: path
.join(fixtureDir
, "..")
2630 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2631 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2632 const result
= await eslint
.lintFiles([badFile
, goodFile
]);
2634 assert(shell
.test("-f", customCacheFile
), "the cache for eslint was created");
2635 const fileCache
= fCache
.createFromFile(customCacheFile
);
2636 const { cache
} = fileCache
;
2638 assert(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2640 assert(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2641 const cachedResult
= await eslint
.lintFiles([badFile
, goodFile
]);
2643 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2648 describe("processors", () => {
2649 it("should return two messages when executing with config file that specifies a processor", async () => {
2650 eslint
= eslintWithPlugins({
2651 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2653 extensions
: ["js", "txt"],
2654 cwd
: path
.join(fixtureDir
, "..")
2656 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2658 assert
.strictEqual(results
.length
, 1);
2659 assert
.strictEqual(results
[0].messages
.length
, 2);
2662 it("should return two messages when executing with config file that specifies preloaded processor", async () => {
2663 eslint
= new ESLint({
2666 plugins
: ["test-processor"],
2672 extensions
: ["js", "txt"],
2673 cwd
: path
.join(fixtureDir
, ".."),
2681 postprocess(messages
) {
2689 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2691 assert
.strictEqual(results
.length
, 1);
2692 assert
.strictEqual(results
[0].messages
.length
, 2);
2695 it("should run processors when calling lintFiles with config file that specifies a processor", async () => {
2696 eslint
= eslintWithPlugins({
2697 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2699 extensions
: ["js", "txt"],
2700 cwd
: path
.join(fixtureDir
, "..")
2702 const results
= await eslint
.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2704 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2705 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2708 it("should run processors when calling lintFiles with config file that specifies preloaded processor", async () => {
2709 eslint
= new ESLint({
2712 plugins
: ["test-processor"],
2718 extensions
: ["js", "txt"],
2719 cwd
: path
.join(fixtureDir
, ".."),
2725 return [text
.replace("a()", "b()")];
2727 postprocess(messages
) {
2728 messages
[0][0].ruleId
= "post-processed";
2736 const results
= await eslint
.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2738 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2739 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2742 it("should run processors when calling lintText with config file that specifies a processor", async () => {
2743 eslint
= eslintWithPlugins({
2744 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2746 extensions
: ["js", "txt"],
2749 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
2751 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2752 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2755 it("should run processors when calling lintText with config file that specifies preloaded processor", async () => {
2756 eslint
= new ESLint({
2759 plugins
: ["test-processor"],
2765 extensions
: ["js", "txt"],
2772 return [text
.replace("a()", "b()")];
2774 postprocess(messages
) {
2775 messages
[0][0].ruleId
= "post-processed";
2783 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
2785 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2786 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2789 describe("autofixing with processors", () => {
2790 const HTML_PROCESSOR
= Object
.freeze({
2792 return [text
.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
2794 postprocess(problemLists
) {
2795 return problemLists
[0].map(problem
=> {
2797 const updatedFix
= Object
.assign({}, problem
.fix
, {
2798 range
: problem
.fix
.range
.map(index
=> index
+ "<script>".length
)
2801 return Object
.assign({}, problem
, { fix
: updatedFix
});
2809 it("should run in autofix mode when using a processor that supports autofixing", async () => {
2810 eslint
= new ESLint({
2813 plugins
: ["test-processor"],
2818 extensions
: ["js", "txt"],
2824 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2829 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
2831 assert
.strictEqual(results
[0].messages
.length
, 0);
2832 assert
.strictEqual(results
[0].output
, "<script>foo;</script>");
2835 it("should not run in autofix mode when using a processor that does not support autofixing", async () => {
2836 eslint
= new ESLint({
2839 plugins
: ["test-processor"],
2844 extensions
: ["js", "txt"],
2848 "test-processor": { processors
: { ".html": HTML_PROCESSOR
} }
2851 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
2853 assert
.strictEqual(results
[0].messages
.length
, 1);
2854 assert(!Object
.prototype.hasOwnProperty
.call(results
[0], "output"));
2857 it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", async () => {
2858 eslint
= new ESLint({
2861 plugins
: ["test-processor"],
2866 extensions
: ["js", "txt"],
2871 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2876 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
2878 assert
.strictEqual(results
[0].messages
.length
, 1);
2879 assert(!Object
.prototype.hasOwnProperty
.call(results
[0], "output"));
2884 describe("Patterns which match no file should throw errors.", () => {
2886 eslint
= new ESLint({
2887 cwd
: getFixturePath("cli-engine"),
2892 it("one file", async () => {
2893 await assert
.rejects(async () => {
2894 await eslint
.lintFiles(["non-exist.js"]);
2895 }, /No files matching 'non-exist\.js' were found\./u);
2898 it("should throw if the directory exists and is empty", async () => {
2899 await assert
.rejects(async () => {
2900 await eslint
.lintFiles(["empty"]);
2901 }, /No files matching 'empty' were found\./u);
2904 it("one glob pattern", async () => {
2905 await assert
.rejects(async () => {
2906 await eslint
.lintFiles(["non-exist/**/*.js"]);
2907 }, /No files matching 'non-exist\/\*\*\/\*\.js' were found\./u);
2910 it("two files", async () => {
2911 await assert
.rejects(async () => {
2912 await eslint
.lintFiles(["aaa.js", "bbb.js"]);
2913 }, /No files matching 'aaa\.js' were found\./u);
2916 it("a mix of an existing file and a non-existing file", async () => {
2917 await assert
.rejects(async () => {
2918 await eslint
.lintFiles(["console.js", "non-exist.js"]);
2919 }, /No files matching 'non-exist\.js' were found\./u);
2923 describe("overrides", () => {
2925 eslint
= new ESLint({
2926 cwd
: getFixturePath("cli-engine/overrides-with-dot"),
2931 it("should recognize dotfiles", async () => {
2932 const ret
= await eslint
.lintFiles([".test-target.js"]);
2934 assert
.strictEqual(ret
.length
, 1);
2935 assert
.strictEqual(ret
[0].messages
.length
, 1);
2936 assert
.strictEqual(ret
[0].messages
[0].ruleId
, "no-unused-vars");
2940 describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
2942 ({ ESLint
} = defineESLintWithInMemoryFileSystem({
2943 cwd
: () => path
.join(os
.tmpdir(), "eslint/11510"),
2945 "no-console-error-in-overrides.json": JSON
.stringify({
2948 rules
: { "no-console": "error" }
2951 ".eslintrc.json": JSON
.stringify({
2952 extends: "./no-console-error-in-overrides.json",
2953 rules
: { "no-console": "off" }
2955 "a.js": "console.log();"
2958 eslint
= new ESLint();
2961 it("should not report 'no-console' error.", async () => {
2962 const results
= await eslint
.lintFiles("a.js");
2964 assert
.strictEqual(results
.length
, 1);
2965 assert
.deepStrictEqual(results
[0].messages
, []);
2969 describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
2971 ({ ESLint
} = defineESLintWithInMemoryFileSystem({
2972 cwd
: () => path
.join(os
.tmpdir(), "eslint/11559"),
2974 "node_modules/eslint-plugin-test/index.js": `
2976 recommended: { plugins: ["test"] }
2980 meta: { schema: [{ type: "number" }] },
2981 create() { return {}; }
2985 ".eslintrc.json": JSON
.stringify({
2987 // Import via the recommended config.
2988 extends: "plugin:test/recommended",
2990 // Has invalid option.
2991 rules
: { "test/foo": ["error", "invalid-option"] }
2993 "a.js": "console.log();"
2996 eslint
= new ESLint();
2999 it("should throw fatal error.", async () => {
3000 await assert
.rejects(async () => {
3001 await eslint
.lintFiles("a.js");
3002 }, /invalid-option/u);
3006 describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
3008 ({ ESLint
} = defineESLintWithInMemoryFileSystem({
3009 cwd
: () => path
.join(os
.tmpdir(), "eslint/11586"),
3011 "node_modules/eslint-plugin-test/index.js": `
3014 meta: { type: "problem", fixable: "code" },
3018 if (node.name === "example") {
3022 fix: fixer => fixer.replaceText(node, "fixed")
3031 ".eslintrc.json": JSON
.stringify({
3033 rules
: { "test/no-example": "error" }
3038 eslint
= new ESLint({ fix
: true, fixTypes
: ["problem"] });
3041 it("should not crash.", async () => {
3042 const results
= await eslint
.lintFiles("a.js");
3044 assert
.strictEqual(results
.length
, 1);
3045 assert
.deepStrictEqual(results
[0].messages
, []);
3046 assert
.deepStrictEqual(results
[0].output
, "fixed;");
3050 describe("multiple processors", () => {
3051 const root
= path
.join(os
.tmpdir(), "eslint/eslint/multiple-processors");
3052 const commonFiles
= {
3053 "node_modules/pattern-processor/index.js": fs
.readFileSync(
3054 require
.resolve("../../fixtures/processors/pattern-processor"),
3057 "node_modules/eslint-plugin-markdown/index.js": `
3058 const { defineProcessor } = require("pattern-processor");
3059 const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
3060 exports.processors = {
3061 ".md": { ...processor, supportsAutofix: true },
3062 "non-fixable": processor
3065 "node_modules/eslint-plugin-html/index.js": `
3066 const { defineProcessor } = require("pattern-processor");
3067 const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
3068 const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
3069 exports.processors = {
3070 ".html": { ...processor, supportsAutofix: true },
3071 "non-fixable": processor,
3072 "legacy": legacyProcessor
3075 "test.md": unIndent
`
3077 console
.log("hello")
3082 console
.log("hello")
3085 console
.log("hello")
3091 it("should lint only JavaScript blocks if '--ext' was not given.", async () => {
3092 ESLint
= defineESLintWithInMemoryFileSystem({
3096 ".eslintrc.json": JSON
.stringify({
3097 plugins
: ["markdown", "html"],
3098 rules
: { semi
: "error" }
3102 eslint
= new ESLint({ cwd
: root
});
3103 const results
= await eslint
.lintFiles(["test.md"]);
3105 assert
.strictEqual(results
.length
, 1);
3106 assert
.strictEqual(results
[0].messages
.length
, 1);
3107 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3108 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3111 it("should fix only JavaScript blocks if '--ext' was not given.", async () => {
3112 ESLint
= defineESLintWithInMemoryFileSystem({
3116 ".eslintrc.json": JSON
.stringify({
3117 plugins
: ["markdown", "html"],
3118 rules
: { semi
: "error" }
3122 eslint
= new ESLint({ cwd
: root
, fix
: true });
3123 const results
= await eslint
.lintFiles(["test.md"]);
3125 assert
.strictEqual(results
.length
, 1);
3126 assert
.strictEqual(results
[0].messages
.length
, 0);
3127 assert
.strictEqual(results
[0].output
, unIndent
`
3129 console
.log("hello");${/* ← fixed */""}
3134 console
.log("hello")${/* ← ignored */""}
3137 console
.log("hello")${/* ← ignored */""}
3143 it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3144 ESLint
= defineESLintWithInMemoryFileSystem({
3148 ".eslintrc.json": JSON
.stringify({
3149 plugins
: ["markdown", "html"],
3150 rules
: { semi
: "error" }
3154 eslint
= new ESLint({ cwd
: root
, extensions
: ["js", "html"] });
3155 const results
= await eslint
.lintFiles(["test.md"]);
3157 assert
.strictEqual(results
.length
, 1);
3158 assert
.strictEqual(results
[0].messages
.length
, 2);
3159 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3160 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3161 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3162 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3165 it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3166 ESLint
= defineESLintWithInMemoryFileSystem({
3170 ".eslintrc.json": JSON
.stringify({
3171 plugins
: ["markdown", "html"],
3172 rules
: { semi
: "error" }
3176 eslint
= new ESLint({ cwd
: root
, extensions
: ["js", "html"], fix
: true });
3177 const results
= await eslint
.lintFiles(["test.md"]);
3179 assert
.strictEqual(results
.length
, 1);
3180 assert
.strictEqual(results
[0].messages
.length
, 0);
3181 assert
.strictEqual(results
[0].output
, unIndent
`
3183 console
.log("hello");${/* ← fixed */""}
3188 console
.log("hello");${/* ← fixed */""}
3191 console
.log("hello")${/* ← ignored */""}
3197 it("should use overriden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", async () => {
3198 ESLint
= defineESLintWithInMemoryFileSystem({
3202 ".eslintrc.json": JSON
.stringify({
3203 plugins
: ["markdown", "html"],
3204 rules
: { semi
: "error" },
3208 processor
: "html/non-fixable" // supportsAutofix: false
3214 eslint
= new ESLint({ cwd
: root
, extensions
: ["js", "html"], fix
: true });
3215 const results
= await eslint
.lintFiles(["test.md"]);
3217 assert
.strictEqual(results
.length
, 1);
3218 assert
.strictEqual(results
[0].messages
.length
, 1);
3219 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS Block in HTML Block
3220 assert
.strictEqual(results
[0].messages
[0].line
, 7);
3221 assert
.strictEqual(results
[0].messages
[0].fix
, void 0);
3222 assert
.strictEqual(results
[0].output
, unIndent
`
3224 console
.log("hello");${/* ← fixed */""}
3229 console
.log("hello")${/* ← reported but not fixed */""}
3232 console
.log("hello")
3238 it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", async () => {
3239 ESLint
= defineESLintWithInMemoryFileSystem({
3243 ".eslintrc.json": JSON
.stringify({
3244 plugins
: ["markdown", "html"],
3245 rules
: { semi
: "error" },
3250 // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
3257 files
: "**/*.html/*.js",
3260 "no-console": "error"
3267 eslint
= new ESLint({ cwd
: root
, extensions
: ["js", "html"] });
3268 const results
= await eslint
.lintFiles(["test.md"]);
3270 assert
.strictEqual(results
.length
, 1);
3271 assert
.strictEqual(results
[0].messages
.length
, 2);
3272 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3273 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3274 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3275 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3278 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 () => {
3279 ESLint
= defineESLintWithInMemoryFileSystem({
3283 ".eslintrc.json": JSON
.stringify({
3284 plugins
: ["markdown", "html"],
3285 rules
: { semi
: "error" },
3289 processor
: "html/legacy", // this processor returns strings rather than `{text, filename}`
3292 "no-console": "error"
3296 files
: "**/*.html/*.js",
3306 eslint
= new ESLint({ cwd
: root
, extensions
: ["js", "html"] });
3307 const results
= await eslint
.lintFiles(["test.md"]);
3309 assert
.strictEqual(results
.length
, 1);
3310 assert
.strictEqual(results
[0].messages
.length
, 3);
3311 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3312 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3313 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3314 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3315 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-console");
3316 assert
.strictEqual(results
[0].messages
[2].line
, 10);
3319 it("should throw an error if invalid processor was specified.", async () => {
3320 ESLint
= defineESLintWithInMemoryFileSystem({
3324 ".eslintrc.json": JSON
.stringify({
3325 plugins
: ["markdown", "html"],
3326 processor
: "markdown/unknown"
3330 eslint
= new ESLint({ cwd
: root
});
3332 await assert
.rejects(async () => {
3333 await eslint
.lintFiles(["test.md"]);
3334 }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
3337 it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", async () => {
3338 ESLint
= defineESLintWithInMemoryFileSystem({
3342 ".eslintrc.json": JSON
.stringify({
3343 plugins
: ["markdown", "html"],
3344 rules
: { semi
: "error" },
3348 processor
: "html/.html"
3352 processor
: "markdown/.md"
3358 eslint
= new ESLint({ cwd
: root
});
3359 const results
= await eslint
.lintFiles(["test.md"]);
3361 assert
.strictEqual(results
.length
, 1);
3362 assert
.strictEqual(results
[0].messages
.length
, 2);
3363 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3364 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3365 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3366 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3370 describe("MODULE_NOT_FOUND error handling", () => {
3371 const cwd
= getFixturePath("module-not-found");
3374 eslint
= new ESLint({ cwd
});
3377 it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", async () => {
3379 await eslint
.lintText("test", { filePath
: "extends-js/test.js" });
3381 assert
.strictEqual(err
.messageTemplate
, "extend-config-missing");
3382 assert
.deepStrictEqual(err
.messageData
, {
3383 configName
: "nonexistent-config",
3384 importerName
: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
3388 assert
.fail("Expected to throw an error");
3391 it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", async () => {
3393 await eslint
.lintText("test", { filePath
: "extends-plugin/test.js" });
3395 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3396 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3397 assert
.deepStrictEqual(err
.messageData
, {
3398 importerName
: `extends-plugin${path.sep}.eslintrc.yml`,
3399 pluginName
: "eslint-plugin-nonexistent-plugin",
3400 resolvePluginsRelativeTo
: path
.join(cwd
, "extends-plugin") // the directory of the config file.
3404 assert
.fail("Expected to throw an error");
3407 it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", async () => {
3409 await eslint
.lintText("test", { filePath
: "plugins/test.js" });
3411 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3412 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3413 assert
.deepStrictEqual(err
.messageData
, {
3414 importerName
: `plugins${path.sep}.eslintrc.yml`,
3415 pluginName
: "eslint-plugin-nonexistent-plugin",
3416 resolvePluginsRelativeTo
: path
.join(cwd
, "plugins") // the directory of the config file.
3420 assert
.fail("Expected to throw an error");
3423 it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", async () => {
3425 await eslint
.lintText("test", { filePath
: "throw-in-config-itself/test.js" });
3427 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3428 assert
.strictEqual(err
.messageTemplate
, void 0);
3431 assert
.fail("Expected to throw an error");
3434 it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3436 await eslint
.lintText("test", { filePath
: "throw-in-extends-js/test.js" });
3438 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3439 assert
.strictEqual(err
.messageTemplate
, void 0);
3442 assert
.fail("Expected to throw an error");
3445 it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3447 await eslint
.lintText("test", { filePath
: "throw-in-extends-plugin/test.js" });
3449 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3450 assert
.strictEqual(err
.messageTemplate
, void 0);
3453 assert
.fail("Expected to throw an error");
3456 it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3458 await eslint
.lintText("test", { filePath
: "throw-in-plugins/test.js" });
3460 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3461 assert
.strictEqual(err
.messageTemplate
, void 0);
3464 assert
.fail("Expected to throw an error");
3468 describe("with '--rulesdir' option", () => {
3469 it("should use the configured rules which are defined by '--rulesdir' option.", async () => {
3470 const rootPath
= getFixturePath("cli-engine/with-rulesdir");
3471 const StubbedESLint
= defineESLintWithInMemoryFileSystem({
3472 cwd
: () => rootPath
,
3474 "internal-rules/test.js": `
3475 module.exports = context => ({
3476 ExpressionStatement(node) {
3477 context.report({ node, message: "ok" })
3481 ".eslintrc.json": JSON
.stringify({
3483 rules
: { test
: "error" }
3485 "test.js": "console.log('hello')"
3489 eslint
= new StubbedESLint({
3490 rulePaths
: ["internal-rules"]
3492 const results
= await eslint
.lintFiles(["test.js"]);
3494 assert
.strictEqual(results
.length
, 1);
3495 assert
.strictEqual(results
[0].messages
.length
, 1);
3496 assert
.strictEqual(results
[0].messages
[0].message
, "ok");
3500 describe("glob pattern '[ab].js'", () => {
3501 const root
= getFixturePath("cli-engine/unmatched-glob");
3503 it("should match '[ab].js' if existed.", async () => {
3504 ESLint
= defineESLintWithInMemoryFileSystem({
3511 ".eslintrc.yml": "root: true"
3514 eslint
= new ESLint();
3515 const results
= await eslint
.lintFiles(["[ab].js"]);
3516 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3518 assert
.deepStrictEqual(filenames
, ["[ab].js"]);
3521 it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", async () => {
3522 ESLint
= defineESLintWithInMemoryFileSystem({
3528 ".eslintrc.yml": "root: true"
3531 eslint
= new ESLint();
3532 const results
= await eslint
.lintFiles(["[ab].js"]);
3533 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3535 assert
.deepStrictEqual(filenames
, ["a.js", "b.js"]);
3539 describe("with 'noInlineConfig' setting", () => {
3540 const root
= getFixturePath("cli-engine/noInlineConfig");
3542 it("should warn directive comments if 'noInlineConfig' was given.", async () => {
3543 ESLint
= defineESLintWithInMemoryFileSystem({
3546 "test.js": "/* globals foo */",
3547 ".eslintrc.yml": "noInlineConfig: true"
3550 eslint
= new ESLint();
3551 const results
= await eslint
.lintFiles(["test.js"]);
3552 const messages
= results
[0].messages
;
3554 assert
.strictEqual(messages
.length
, 1);
3555 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
3558 it("should show the config file what the 'noInlineConfig' came from.", async () => {
3559 ESLint
= defineESLintWithInMemoryFileSystem({
3562 "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
3563 "test.js": "/* globals foo */",
3564 ".eslintrc.yml": "extends: foo"
3567 eslint
= new ESLint();
3568 const results
= await eslint
.lintFiles(["test.js"]);
3569 const messages
= results
[0].messages
;
3571 assert
.strictEqual(messages
.length
, 1);
3572 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
3576 describe("with 'reportUnusedDisableDirectives' setting", () => {
3577 const root
= getFixturePath("cli-engine/reportUnusedDisableDirectives");
3579 it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", async () => {
3580 ESLint
= defineESLintWithInMemoryFileSystem({
3583 "test.js": "/* eslint-disable eqeqeq */",
3584 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3587 eslint
= new ESLint();
3588 const results
= await eslint
.lintFiles(["test.js"]);
3589 const messages
= results
[0].messages
;
3591 assert
.strictEqual(messages
.length
, 1);
3592 assert
.strictEqual(messages
[0].severity
, 1);
3593 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3596 describe("the runtime option overrides config files.", () => {
3597 it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", async () => {
3598 ESLint
= defineESLintWithInMemoryFileSystem({
3601 "test.js": "/* eslint-disable eqeqeq */",
3602 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3605 eslint
= new ESLint({ reportUnusedDisableDirectives
: "off" });
3606 const results
= await eslint
.lintFiles(["test.js"]);
3607 const messages
= results
[0].messages
;
3609 assert
.strictEqual(messages
.length
, 0);
3612 it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", async () => {
3613 ESLint
= defineESLintWithInMemoryFileSystem({
3616 "test.js": "/* eslint-disable eqeqeq */",
3617 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3620 eslint
= new ESLint({ reportUnusedDisableDirectives
: "error" });
3621 const results
= await eslint
.lintFiles(["test.js"]);
3622 const messages
= results
[0].messages
;
3624 assert
.strictEqual(messages
.length
, 1);
3625 assert
.strictEqual(messages
[0].severity
, 2);
3626 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3631 describe("with 'overrides[*].extends' setting on deep locations", () => {
3632 const root
= getFixturePath("cli-engine/deeply-overrides-i-extends");
3634 it("should not throw.", async () => {
3635 ESLint
= defineESLintWithInMemoryFileSystem({
3638 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
3639 overrides: [{ files: ["*test*"], extends: "two" }]
3641 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
3642 overrides: [{ files: ["*.js"], extends: "three" }]
3644 "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
3645 rules: { "no-console": "error" }
3647 "test.js": "console.log('hello')",
3648 ".eslintrc.yml": "extends: one"
3651 eslint
= new ESLint();
3652 const results
= await eslint
.lintFiles(["test.js"]);
3653 const messages
= results
[0].messages
;
3655 assert
.strictEqual(messages
.length
, 1);
3656 assert
.strictEqual(messages
[0].ruleId
, "no-console");
3660 describe("don't ignore the entry directory.", () => {
3661 const root
= getFixturePath("cli-engine/dont-ignore-entry-dir");
3663 it("'lintFiles(\".\")' should not load config files from outside of \".\".", async () => {
3664 ESLint
= defineESLintWithInMemoryFileSystem({
3667 "../.eslintrc.json": "BROKEN FILE",
3668 ".eslintrc.json": JSON
.stringify({ root
: true }),
3669 "index.js": "console.log(\"hello\")"
3672 eslint
= new ESLint();
3674 // Don't throw "failed to load config file" error.
3675 await eslint
.lintFiles(".");
3678 it("'lintFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", async () => {
3679 ESLint
= defineESLintWithInMemoryFileSystem({
3682 "../.eslintrc.json": JSON
.stringify({ ignorePatterns
: ["/dont-ignore-entry-dir"] }),
3683 ".eslintrc.json": JSON
.stringify({ root
: true }),
3684 "index.js": "console.log(\"hello\")"
3687 eslint
= new ESLint();
3689 // Don't throw "file not found" error.
3690 await eslint
.lintFiles(".");
3693 it("'lintFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", async () => {
3694 ESLint
= defineESLintWithInMemoryFileSystem({
3697 ".eslintrc.json": JSON
.stringify({ ignorePatterns
: ["/subdir"] }),
3698 "subdir/.eslintrc.json": JSON
.stringify({ root
: true }),
3699 "subdir/index.js": "console.log(\"hello\")"
3702 eslint
= new ESLint();
3704 // Don't throw "file not found" error.
3705 await eslint
.lintFiles("subdir");
3709 it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
3710 eslint
= new ESLint();
3711 await assert
.rejects(() => eslint
.lintFiles(777), /'patterns' must be a non-empty string or an array of non-empty strings/u);
3712 await assert
.rejects(() => eslint
.lintFiles([null]), /'patterns' must be a non-empty string or an array of non-empty strings/u);
3716 describe("calculateConfigForFile", () => {
3717 it("should return the info from Config#getConfig when called", async () => {
3719 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json")
3721 const engine
= new ESLint(options
);
3722 const filePath
= getFixturePath("single-quoted.js");
3723 const actualConfig
= await engine
.calculateConfigForFile(filePath
);
3724 const expectedConfig
= new CascadingConfigArrayFactory({ specificConfigPath
: options
.overrideConfigFile
})
3725 .getConfigArrayForFile(filePath
)
3726 .extractConfig(filePath
)
3727 .toCompatibleObjectAsConfigFileContent();
3729 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3733 it("should return the config when run from within a subdir", async () => {
3735 cwd
: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
3737 const engine
= new ESLint(options
);
3738 const filePath
= getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
3739 const actualConfig
= await engine
.calculateConfigForFile("./.eslintrc");
3740 const expectedConfig
= new CascadingConfigArrayFactory(options
)
3741 .getConfigArrayForFile(filePath
)
3742 .extractConfig(filePath
)
3743 .toCompatibleObjectAsConfigFileContent();
3745 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3748 it("should throw an error if a directory path was given.", async () => {
3749 const engine
= new ESLint();
3752 await engine
.calculateConfigForFile(".");
3754 assert
.strictEqual(error
.messageTemplate
, "print-config-with-directory-path");
3757 assert
.fail("should throw an error");
3760 it("should throw if non-string value is given to 'filePath' parameter", async () => {
3761 const eslint
= new ESLint();
3763 await assert
.rejects(() => eslint
.calculateConfigForFile(null), /'filePath' must be a non-empty string/u);
3767 describe("isPathIgnored", () => {
3768 it("should check if the given path is ignored", async () => {
3769 const engine
= new ESLint({
3770 ignorePath
: getFixturePath(".eslintignore2"),
3771 cwd
: getFixturePath()
3774 assert(await engine
.isPathIgnored("undef.js"));
3775 assert(!await engine
.isPathIgnored("passing.js"));
3778 it("should return false if ignoring is disabled", async () => {
3779 const engine
= new ESLint({
3781 ignorePath
: getFixturePath(".eslintignore2"),
3782 cwd
: getFixturePath()
3785 assert(!await engine
.isPathIgnored("undef.js"));
3788 // https://github.com/eslint/eslint/issues/5547
3789 it("should return true for default ignores even if ignoring is disabled", async () => {
3790 const engine
= new ESLint({
3792 cwd
: getFixturePath("cli-engine")
3795 assert(await engine
.isPathIgnored("node_modules/foo.js"));
3798 describe("about the default ignore patterns", () => {
3799 it("should always apply defaultPatterns if ignore option is true", async () => {
3800 const cwd
= getFixturePath("ignored-paths");
3801 const engine
= new ESLint({ cwd
});
3803 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
3804 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
3807 it("should still apply defaultPatterns if ignore option is is false", async () => {
3808 const cwd
= getFixturePath("ignored-paths");
3809 const engine
= new ESLint({ ignore
: false, cwd
});
3811 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
3812 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
3815 it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", async () => {
3816 const cwd
= getFixturePath("ignored-paths");
3817 const engine
= new ESLint({
3820 ignorePatterns
: "!/node_modules/package"
3824 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
3827 it("should allow subfolders of defaultPatterns to be unignored by ignorePath", async () => {
3828 const cwd
= getFixturePath("ignored-paths");
3829 const engine
= new ESLint({ cwd
, ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
3831 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
3834 it("should ignore dotfiles", async () => {
3835 const cwd
= getFixturePath("ignored-paths");
3836 const engine
= new ESLint({ cwd
});
3838 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
3839 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
3842 it("should ignore directories beginning with a dot", async () => {
3843 const cwd
= getFixturePath("ignored-paths");
3844 const engine
= new ESLint({ cwd
});
3846 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
3847 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
3850 it("should still ignore dotfiles when ignore option disabled", async () => {
3851 const cwd
= getFixturePath("ignored-paths");
3852 const engine
= new ESLint({ ignore
: false, cwd
});
3854 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
3855 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
3858 it("should still ignore directories beginning with a dot when ignore option disabled", async () => {
3859 const cwd
= getFixturePath("ignored-paths");
3860 const engine
= new ESLint({ ignore
: false, cwd
});
3862 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
3863 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
3866 it("should not ignore absolute paths containing '..'", async () => {
3867 const cwd
= getFixturePath("ignored-paths");
3868 const engine
= new ESLint({ cwd
});
3870 assert(!await engine
.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
3873 it("should ignore /node_modules/ relative to .eslintignore when loaded", async () => {
3874 const cwd
= getFixturePath("ignored-paths");
3875 const engine
= new ESLint({ ignorePath
: getFixturePath("ignored-paths", ".eslintignore"), cwd
});
3877 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
3878 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
3881 it("should ignore /node_modules/ relative to cwd without an .eslintignore", async () => {
3882 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
3883 const engine
= new ESLint({ cwd
});
3885 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
3886 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
3890 describe("with no .eslintignore file", () => {
3891 it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", async () => {
3892 const cwd
= getFixturePath("ignored-paths", "configurations");
3893 const engine
= new ESLint({ cwd
});
3895 // a .eslintignore in parent directories includes `*.js`, but don't load it.
3896 assert(!await engine
.isPathIgnored("foo.js"));
3897 assert(await engine
.isPathIgnored("node_modules/foo.js"));
3900 it("should return false for files outside of the cwd (with no ignore file provided)", async () => {
3902 // Default ignore patterns should not inadvertently ignore files in parent directories
3903 const engine
= new ESLint({ cwd
: getFixturePath("ignored-paths", "no-ignore-file") });
3905 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
3909 describe("with .eslintignore file or package.json file", () => {
3910 it("should load .eslintignore from cwd when explicitly passed", async () => {
3911 const cwd
= getFixturePath("ignored-paths");
3912 const engine
= new ESLint({ cwd
});
3914 // `${cwd}/.eslintignore` includes `sampleignorepattern`.
3915 assert(await engine
.isPathIgnored("sampleignorepattern"));
3918 it("should use package.json's eslintIgnore files if no specified .eslintignore file", async () => {
3919 const cwd
= getFixturePath("ignored-paths", "package-json-ignore");
3920 const engine
= new ESLint({ cwd
});
3922 assert(await engine
.isPathIgnored("hello.js"));
3923 assert(await engine
.isPathIgnored("world.js"));
3926 it("should use correct message template if failed to parse package.json", () => {
3927 const cwd
= getFixturePath("ignored-paths", "broken-package-json");
3929 assert
.throws(() => {
3931 // eslint-disable-next-line no-new
3932 new ESLint({ cwd
});
3934 assert
.strictEqual(error
.messageTemplate
, "failed-to-read-json");
3940 it("should not use package.json's eslintIgnore files if specified .eslintignore file", async () => {
3941 const cwd
= getFixturePath("ignored-paths");
3942 const engine
= new ESLint({ cwd
});
3945 * package.json includes `hello.js` and `world.js`.
3946 * .eslintignore includes `sampleignorepattern`.
3948 assert(!await engine
.isPathIgnored("hello.js"));
3949 assert(!await engine
.isPathIgnored("world.js"));
3950 assert(await engine
.isPathIgnored("sampleignorepattern"));
3953 it("should error if package.json's eslintIgnore is not an array of file paths", () => {
3954 const cwd
= getFixturePath("ignored-paths", "bad-package-json-ignore");
3956 assert
.throws(() => {
3957 // eslint-disable-next-line no-new
3958 new ESLint({ cwd
});
3959 }, /Package\.json eslintIgnore property requires an array of paths/u);
3963 describe("with --ignore-pattern option", () => {
3964 it("should accept a string for options.ignorePattern", async () => {
3965 const cwd
= getFixturePath("ignored-paths", "ignore-pattern");
3966 const engine
= new ESLint({
3968 ignorePatterns
: "ignore-me.txt"
3973 assert(await engine
.isPathIgnored("ignore-me.txt"));
3976 it("should accept an array for options.ignorePattern", async () => {
3977 const engine
= new ESLint({
3979 ignorePatterns
: ["a", "b"]
3984 assert(await engine
.isPathIgnored("a"));
3985 assert(await engine
.isPathIgnored("b"));
3986 assert(!await engine
.isPathIgnored("c"));
3989 it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", async () => {
3990 const cwd
= getFixturePath("ignored-paths");
3991 const engine
= new ESLint({
3993 ignorePatterns
: "not-a-file"
3998 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
4001 it("should return true for file matching an ignore pattern exactly", async () => {
4002 const cwd
= getFixturePath("ignored-paths");
4003 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "undef.js" }, cwd
});
4005 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4008 it("should return false for file matching an invalid ignore pattern with leading './'", async () => {
4009 const cwd
= getFixturePath("ignored-paths");
4010 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "./undef.js" }, cwd
});
4012 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4015 it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", async () => {
4016 const cwd
= getFixturePath("ignored-paths");
4017 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "/undef.js" }, cwd
});
4019 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
4022 it("should return true for file matching a child of an ignore pattern", async () => {
4023 const cwd
= getFixturePath("ignored-paths");
4024 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "ignore-pattern" }, cwd
});
4026 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
4029 it("should return true for file matching a grandchild of an ignore pattern", async () => {
4030 const cwd
= getFixturePath("ignored-paths");
4031 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "ignore-pattern" }, cwd
});
4033 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
4036 it("should return false for file not matching any ignore pattern", async () => {
4037 const cwd
= getFixturePath("ignored-paths");
4038 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "failing.js" }, cwd
});
4040 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
4043 it("two globstar '**' ignore pattern should ignore files in nested directories", async () => {
4044 const cwd
= getFixturePath("ignored-paths");
4045 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "**/*.js" }, cwd
});
4047 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4048 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
4049 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
4050 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
4051 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
4052 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
4056 describe("with --ignore-path option", () => {
4057 it("initialization with ignorePath should work when cwd is a parent directory", async () => {
4058 const cwd
= getFixturePath("ignored-paths");
4059 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4060 const engine
= new ESLint({ ignorePath
, cwd
});
4062 assert(await engine
.isPathIgnored("custom-name/foo.js"));
4065 it("initialization with ignorePath should work when the file is in the cwd", async () => {
4066 const cwd
= getFixturePath("ignored-paths", "custom-name");
4067 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4068 const engine
= new ESLint({ ignorePath
, cwd
});
4070 assert(await engine
.isPathIgnored("foo.js"));
4073 it("initialization with ignorePath should work when cwd is a subdirectory", async () => {
4074 const cwd
= getFixturePath("ignored-paths", "custom-name", "subdirectory");
4075 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4076 const engine
= new ESLint({ ignorePath
, cwd
});
4078 assert(await engine
.isPathIgnored("../custom-name/foo.js"));
4081 it("initialization with invalid file should throw error", () => {
4082 const cwd
= getFixturePath("ignored-paths");
4083 const ignorePath
= getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
4085 assert
.throws(() => {
4086 // eslint-disable-next-line no-new
4087 new ESLint({ ignorePath
, cwd
});
4088 }, /Cannot read \.eslintignore file/u);
4091 it("should return false for files outside of ignorePath's directory", async () => {
4092 const cwd
= getFixturePath("ignored-paths");
4093 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4094 const engine
= new ESLint({ ignorePath
, cwd
});
4096 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4099 it("should resolve relative paths from CWD", async () => {
4100 const cwd
= getFixturePath("ignored-paths", "subdir");
4101 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4102 const engine
= new ESLint({ ignorePath
, cwd
});
4104 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4105 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4108 it("should resolve relative paths from CWD when it's in a child directory", async () => {
4109 const cwd
= getFixturePath("ignored-paths");
4110 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4111 const engine
= new ESLint({ ignorePath
, cwd
});
4113 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4114 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4115 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4116 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
4118 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
4121 it("should resolve relative paths from CWD when it contains negated globs", async () => {
4122 const cwd
= getFixturePath("ignored-paths");
4123 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4124 const engine
= new ESLint({ ignorePath
, cwd
});
4126 assert(await engine
.isPathIgnored("subdir/blah.txt"));
4127 assert(await engine
.isPathIgnored("blah.txt"));
4128 assert(await engine
.isPathIgnored("subdir/bar.txt"));
4129 assert(!await engine
.isPathIgnored("bar.txt"));
4130 assert(!await engine
.isPathIgnored("subdir/baz.txt"));
4131 assert(!await engine
.isPathIgnored("baz.txt"));
4134 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", async () => {
4135 const cwd
= getFixturePath("ignored-paths");
4136 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4137 const engine
= new ESLint({ ignorePath
, cwd
});
4139 assert(await engine
.isPathIgnored("node_modules/blah.js"));
4142 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", async () => {
4143 const cwd
= getFixturePath("ignored-paths", "subdir");
4144 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4145 const engine
= new ESLint({ ignorePath
, cwd
});
4147 assert(await engine
.isPathIgnored("node_modules/blah.js"));
4150 it("should handle .eslintignore which contains CRLF correctly.", async () => {
4151 const ignoreFileContent
= fs
.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
4153 assert(ignoreFileContent
.includes("\r"), "crlf/.eslintignore should contains CR.");
4154 const cwd
= getFixturePath("ignored-paths");
4155 const ignorePath
= getFixturePath("ignored-paths", "crlf/.eslintignore");
4156 const engine
= new ESLint({ ignorePath
, cwd
});
4158 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
4159 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
4160 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
4163 it("should not include comments in ignore rules", async () => {
4164 const cwd
= getFixturePath("ignored-paths");
4165 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithComments");
4166 const engine
= new ESLint({ ignorePath
, cwd
});
4168 assert(!await engine
.isPathIgnored("# should be ignored"));
4169 assert(await engine
.isPathIgnored("this_one_not"));
4172 it("should ignore a non-negated pattern", async () => {
4173 const cwd
= getFixturePath("ignored-paths");
4174 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4175 const engine
= new ESLint({ ignorePath
, cwd
});
4177 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
4180 it("should not ignore a negated pattern", async () => {
4181 const cwd
= getFixturePath("ignored-paths");
4182 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4183 const engine
= new ESLint({ ignorePath
, cwd
});
4185 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
4189 describe("with --ignore-path option and --ignore-pattern option", () => {
4190 it("should return false for ignored file when unignored with ignore pattern", async () => {
4191 const cwd
= getFixturePath("ignored-paths");
4192 const engine
= new ESLint({
4193 ignorePath
: getFixturePath("ignored-paths", ".eslintignore"),
4195 ignorePatterns
: "!sampleignorepattern"
4200 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
4204 it("should throw if non-string value is given to 'filePath' parameter", async () => {
4205 const eslint
= new ESLint();
4207 await assert
.rejects(() => eslint
.isPathIgnored(null), /'filePath' must be a non-empty string/u);
4211 describe("loadFormatter()", () => {
4212 it("should return a formatter object when a bundled formatter is requested", async () => {
4213 const engine
= new ESLint();
4214 const formatter
= await engine
.loadFormatter("compact");
4216 assert
.strictEqual(typeof formatter
, "object");
4217 assert
.strictEqual(typeof formatter
.format
, "function");
4220 it("should return a formatter object when no argument is passed", async () => {
4221 const engine
= new ESLint();
4222 const formatter
= await engine
.loadFormatter();
4224 assert
.strictEqual(typeof formatter
, "object");
4225 assert
.strictEqual(typeof formatter
.format
, "function");
4228 it("should return a formatter object when a custom formatter is requested", async () => {
4229 const engine
= new ESLint();
4230 const formatter
= await engine
.loadFormatter(getFixturePath("formatters", "simple.js"));
4232 assert
.strictEqual(typeof formatter
, "object");
4233 assert
.strictEqual(typeof formatter
.format
, "function");
4236 it("should return a formatter object when a custom formatter is requested, also if the path has backslashes", async () => {
4237 const engine
= new ESLint({
4238 cwd
: path
.join(fixtureDir
, "..")
4240 const formatter
= await engine
.loadFormatter(".\\fixtures\\formatters\\simple.js");
4242 assert
.strictEqual(typeof formatter
, "object");
4243 assert
.strictEqual(typeof formatter
.format
, "function");
4246 it("should return a formatter object when a formatter prefixed with eslint-formatter is requested", async () => {
4247 const engine
= new ESLint({
4248 cwd
: getFixturePath("cli-engine")
4250 const formatter
= await engine
.loadFormatter("bar");
4252 assert
.strictEqual(typeof formatter
, "object");
4253 assert
.strictEqual(typeof formatter
.format
, "function");
4256 it("should return a formatter object when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", async () => {
4257 const engine
= new ESLint({
4258 cwd
: getFixturePath("cli-engine")
4260 const formatter
= await engine
.loadFormatter("eslint-formatter-bar");
4262 assert
.strictEqual(typeof formatter
, "object");
4263 assert
.strictEqual(typeof formatter
.format
, "function");
4266 it("should return a formatter object when a formatter is requested within a scoped npm package", async () => {
4267 const engine
= new ESLint({
4268 cwd
: getFixturePath("cli-engine")
4270 const formatter
= await engine
.loadFormatter("@somenamespace/foo");
4272 assert
.strictEqual(typeof formatter
, "object");
4273 assert
.strictEqual(typeof formatter
.format
, "function");
4276 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 () => {
4277 const engine
= new ESLint({
4278 cwd
: getFixturePath("cli-engine")
4280 const formatter
= await engine
.loadFormatter("@somenamespace/eslint-formatter-foo");
4282 assert
.strictEqual(typeof formatter
, "object");
4283 assert
.strictEqual(typeof formatter
.format
, "function");
4286 it("should throw if a customer formatter doesn't exist", async () => {
4287 const engine
= new ESLint();
4288 const formatterPath
= getFixturePath("formatters", "doesntexist.js");
4289 const fullFormatterPath
= path
.resolve(formatterPath
);
4291 await assert
.rejects(async () => {
4292 await engine
.loadFormatter(formatterPath
);
4293 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
4296 it("should throw if a built-in formatter doesn't exist", async () => {
4297 const engine
= new ESLint();
4298 const fullFormatterPath
= path
.resolve(__dirname
, "../../../lib/cli-engine/formatters/special");
4300 await assert
.rejects(async () => {
4301 await engine
.loadFormatter("special");
4302 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
4305 it("should throw if the required formatter exists but has an error", async () => {
4306 const engine
= new ESLint();
4307 const formatterPath
= getFixturePath("formatters", "broken.js");
4309 await assert
.rejects(async () => {
4310 await engine
.loadFormatter(formatterPath
);
4311 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`), "u"));
4314 it("should throw if a non-string formatter name is passed", async () => {
4315 const engine
= new ESLint();
4317 await assert
.rejects(async () => {
4318 await engine
.loadFormatter(5);
4319 }, /'name' must be a string/u);
4323 describe("getErrorResults()", () => {
4324 it("should report 5 error messages when looking for errors only", async () => {
4325 process
.chdir(originalDir
);
4326 const engine
= new ESLint();
4327 const results
= await engine
.lintText("var foo = 'bar';");
4328 const errorResults
= ESLint
.getErrorResults(results
);
4330 assert
.strictEqual(errorResults
[0].messages
.length
, 5);
4331 assert
.strictEqual(errorResults
[0].errorCount
, 5);
4332 assert
.strictEqual(errorResults
[0].fixableErrorCount
, 3);
4333 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4334 assert
.strictEqual(errorResults
[0].messages
[0].ruleId
, "strict");
4335 assert
.strictEqual(errorResults
[0].messages
[0].severity
, 2);
4336 assert
.strictEqual(errorResults
[0].messages
[1].ruleId
, "no-var");
4337 assert
.strictEqual(errorResults
[0].messages
[1].severity
, 2);
4338 assert
.strictEqual(errorResults
[0].messages
[2].ruleId
, "no-unused-vars");
4339 assert
.strictEqual(errorResults
[0].messages
[2].severity
, 2);
4340 assert
.strictEqual(errorResults
[0].messages
[3].ruleId
, "quotes");
4341 assert
.strictEqual(errorResults
[0].messages
[3].severity
, 2);
4342 assert
.strictEqual(errorResults
[0].messages
[4].ruleId
, "eol-last");
4343 assert
.strictEqual(errorResults
[0].messages
[4].severity
, 2);
4346 it("should not mutate passed report parameter", async () => {
4347 process
.chdir(originalDir
);
4348 const engine
= new ESLint({
4350 rules
: { quotes
: [1, "double"] }
4353 const results
= await engine
.lintText("var foo = 'bar';");
4354 const reportResultsLength
= results
[0].messages
.length
;
4356 ESLint
.getErrorResults(results
);
4358 assert
.strictEqual(results
[0].messages
.length
, reportResultsLength
);
4361 it("should report a warningCount of 0 when looking for errors only", async () => {
4362 process
.chdir(originalDir
);
4363 const engine
= new ESLint();
4364 const results
= await engine
.lintText("var foo = 'bar';");
4365 const errorResults
= ESLint
.getErrorResults(results
);
4367 assert
.strictEqual(errorResults
[0].warningCount
, 0);
4368 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4371 it("should return 0 error or warning messages even when the file has warnings", async () => {
4372 const engine
= new ESLint({
4373 ignorePath
: path
.join(fixtureDir
, ".eslintignore"),
4374 cwd
: path
.join(fixtureDir
, "..")
4377 filePath
: "fixtures/passing.js",
4380 const results
= await engine
.lintText("var bar = foo;", options
);
4381 const errorReport
= ESLint
.getErrorResults(results
);
4383 assert
.strictEqual(errorReport
.length
, 0);
4384 assert
.strictEqual(results
.length
, 1);
4385 assert
.strictEqual(results
[0].errorCount
, 0);
4386 assert
.strictEqual(results
[0].warningCount
, 1);
4389 it("should return source code of file in the `source` property", async () => {
4390 process
.chdir(originalDir
);
4391 const engine
= new ESLint({
4394 rules
: { quotes
: [2, "double"] }
4397 const results
= await engine
.lintText("var foo = 'bar';");
4398 const errorResults
= ESLint
.getErrorResults(results
);
4400 assert
.strictEqual(errorResults
[0].messages
.length
, 1);
4401 assert
.strictEqual(errorResults
[0].source
, "var foo = 'bar';");
4404 it("should contain `output` property after fixes", async () => {
4405 process
.chdir(originalDir
);
4406 const engine
= new ESLint({
4416 const results
= await engine
.lintText("console.log('foo')");
4417 const errorResults
= ESLint
.getErrorResults(results
);
4419 assert
.strictEqual(errorResults
[0].messages
.length
, 1);
4420 assert
.strictEqual(errorResults
[0].output
, "console.log('foo');");
4424 describe("outputFixes()", () => {
4426 sinon
.verifyAndRestore();
4429 it("should call fs.writeFile() for each result with output", async () => {
4430 const fakeFS
= leche
.fake(fs
);
4431 const spy
= fakeFS
.writeFile
= sinon
.spy(callLastArgument
);
4432 const localESLint
= proxyquire("../../../lib/eslint/eslint", {
4437 filePath
: path
.resolve("foo.js"),
4441 filePath
: path
.resolve("bar.js"),
4446 await localESLint
.outputFixes(results
);
4448 assert
.strictEqual(spy
.callCount
, 2);
4449 assert(spy
.firstCall
.calledWithExactly(path
.resolve("foo.js"), "bar", sinon
.match
.func
), "First call was incorrect.");
4450 assert(spy
.secondCall
.calledWithExactly(path
.resolve("bar.js"), "baz", sinon
.match
.func
), "Second call was incorrect.");
4453 it("should call fs.writeFile() for each result with output and not at all for a result without output", async () => {
4454 const fakeFS
= leche
.fake(fs
);
4455 const spy
= fakeFS
.writeFile
= sinon
.spy(callLastArgument
);
4456 const localESLint
= proxyquire("../../../lib/eslint/eslint", {
4461 filePath
: path
.resolve("foo.js"),
4465 filePath
: path
.resolve("abc.js")
4468 filePath
: path
.resolve("bar.js"),
4473 await localESLint
.outputFixes(results
);
4475 assert
.strictEqual(spy
.callCount
, 2);
4476 assert(spy
.firstCall
.calledWithExactly(path
.resolve("foo.js"), "bar", sinon
.match
.func
), "First call was incorrect.");
4477 assert(spy
.secondCall
.calledWithExactly(path
.resolve("bar.js"), "baz", sinon
.match
.func
), "Second call was incorrect.");
4480 it("should throw if non object array is given to 'results' parameter", async () => {
4481 await assert
.rejects(() => ESLint
.outputFixes(null), /'results' must be an array/u);
4482 await assert
.rejects(() => ESLint
.outputFixes([null]), /'results' must include only objects/u);
4486 describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
4487 it("should report a violation for disabling rules", async () => {
4489 "alert('test'); // eslint-disable-line no-alert"
4493 allowInlineConfig
: false,
4495 env
: { browser
: true },
4499 "no-trailing-spaces": 0,
4505 const eslintCLI
= new ESLint(config
);
4506 const results
= await eslintCLI
.lintText(code
);
4507 const messages
= results
[0].messages
;
4509 assert
.strictEqual(messages
.length
, 1);
4510 assert
.strictEqual(messages
[0].ruleId
, "no-alert");
4513 it("should not report a violation by default", async () => {
4515 "alert('test'); // eslint-disable-line no-alert"
4519 allowInlineConfig
: true,
4521 env
: { browser
: true },
4525 "no-trailing-spaces": 0,
4531 const eslintCLI
= new ESLint(config
);
4532 const results
= await eslintCLI
.lintText(code
);
4533 const messages
= results
[0].messages
;
4535 assert
.strictEqual(messages
.length
, 0);
4539 describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
4540 it("should report problems for unused eslint-disable directives", async () => {
4541 const eslint
= new ESLint({ useEslintrc
: false, reportUnusedDisableDirectives
: "error" });
4543 assert
.deepStrictEqual(
4544 await eslint
.lintText("/* eslint-disable */"),
4551 message
: "Unused eslint-disable directive (no problems were reported).",
4560 fixableErrorCount
: 0,
4561 fixableWarningCount
: 0,
4562 source
: "/* eslint-disable */",
4563 usedDeprecatedRules
: []
4570 describe("when retreiving version number", () => {
4571 it("should return current version number", () => {
4572 const eslintCLI
= require("../../../lib/eslint").ESLint
;
4573 const version
= eslintCLI
.version
;
4575 assert
.strictEqual(typeof version
, "string");
4576 assert(parseInt(version
[0], 10) >= 3);
4580 describe("mutability", () => {
4581 describe("plugins", () => {
4582 it("Loading plugin in one instance doesn't mutate to another instance", async () => {
4583 const filePath
= getFixturePath("single-quoted.js");
4584 const engine1
= eslintWithPlugins({
4585 cwd
: path
.join(fixtureDir
, ".."),
4588 plugins
: ["example"],
4589 rules
: { "example/example-rule": 1 }
4592 const engine2
= new ESLint({
4593 cwd
: path
.join(fixtureDir
, ".."),
4596 const fileConfig1
= await engine1
.calculateConfigForFile(filePath
);
4597 const fileConfig2
= await engine2
.calculateConfigForFile(filePath
);
4600 assert
.deepStrictEqual(fileConfig1
.plugins
, ["example"], "Plugin is present for engine 1");
4601 assert
.deepStrictEqual(fileConfig2
.plugins
, [], "Plugin is not present for engine 2");
4605 describe("rules", () => {
4606 it("Loading rules in one instance doesn't mutate to another instance", async () => {
4607 const filePath
= getFixturePath("single-quoted.js");
4608 const engine1
= new ESLint({
4609 cwd
: path
.join(fixtureDir
, ".."),
4611 overrideConfig
: { rules
: { "example/example-rule": 1 } }
4613 const engine2
= new ESLint({
4614 cwd
: path
.join(fixtureDir
, ".."),
4617 const fileConfig1
= await engine1
.calculateConfigForFile(filePath
);
4618 const fileConfig2
= await engine2
.calculateConfigForFile(filePath
);
4621 assert
.deepStrictEqual(fileConfig1
.rules
["example/example-rule"], [1], "example is present for engine 1");
4622 assert
.strictEqual(fileConfig2
.rules
["example/example-rule"], void 0, "example is not present for engine 2");
4627 describe("with ignorePatterns config", () => {
4628 const root
= getFixturePath("cli-engine/ignore-patterns");
4630 /** @type {typeof ESLint} */
4633 describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
4635 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4638 ".eslintrc.json": JSON
.stringify({
4639 ignorePatterns
: "foo.js"
4643 "subdir/foo.js": "",
4649 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
4650 const engine
= new InMemoryESLint();
4652 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
4653 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
4656 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
4657 const engine
= new InMemoryESLint();
4659 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
4660 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), false);
4663 it("'lintFiles()' should not verify 'foo.js'.", async () => {
4664 const engine
= new InMemoryESLint();
4665 const filePaths
= (await engine
.lintFiles("**/*.js"))
4666 .map(r
=> r
.filePath
)
4669 assert
.deepStrictEqual(filePaths
, [
4670 path
.join(root
, "bar.js"),
4671 path
.join(root
, "subdir/bar.js")
4676 describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
4678 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4681 ".eslintrc.json": JSON
.stringify({
4682 ignorePatterns
: ["foo.js", "/bar.js"]
4687 "subdir/foo.js": "",
4688 "subdir/bar.js": "",
4694 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
4695 const engine
= new InMemoryESLint();
4697 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
4698 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
4701 it("'isPathIgnored()' should return 'true' for '/bar.js'.", async () => {
4702 const engine
= new InMemoryESLint();
4704 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), true);
4705 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), false);
4708 it("'lintFiles()' should not verify 'foo.js' and '/bar.js'.", async () => {
4709 const engine
= new InMemoryESLint();
4710 const filePaths
= (await engine
.lintFiles("**/*.js"))
4711 .map(r
=> r
.filePath
)
4714 assert
.deepStrictEqual(filePaths
, [
4715 path
.join(root
, "baz.js"),
4716 path
.join(root
, "subdir/bar.js"),
4717 path
.join(root
, "subdir/baz.js")
4722 describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
4724 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4727 ".eslintrc.json": JSON
.stringify({
4728 ignorePatterns
: "!/node_modules/foo"
4730 "node_modules/foo/index.js": "",
4731 "node_modules/foo/.dot.js": "",
4732 "node_modules/bar/index.js": "",
4738 it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", async () => {
4739 const engine
= new InMemoryESLint();
4741 assert
.strictEqual(await engine
.isPathIgnored("node_modules/foo/index.js"), false);
4744 it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", async () => {
4745 const engine
= new InMemoryESLint();
4747 assert
.strictEqual(await engine
.isPathIgnored("node_modules/foo/.dot.js"), true);
4750 it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", async () => {
4751 const engine
= new InMemoryESLint();
4753 assert
.strictEqual(await engine
.isPathIgnored("node_modules/bar/index.js"), true);
4756 it("'lintFiles()' should verify 'node_modules/foo/index.js'.", async () => {
4757 const engine
= new InMemoryESLint();
4758 const filePaths
= (await engine
.lintFiles("**/*.js"))
4759 .map(r
=> r
.filePath
)
4762 assert
.deepStrictEqual(filePaths
, [
4763 path
.join(root
, "foo.js"),
4764 path
.join(root
, "node_modules/foo/index.js")
4769 describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
4771 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4774 ".eslintrc.js": `module.exports = ${JSON.stringify({
4775 ignorePatterns: "!.eslintrc.js"
4782 it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", async () => {
4783 const engine
= new InMemoryESLint();
4785 assert
.strictEqual(await engine
.isPathIgnored(".eslintrc.js"), false);
4788 it("'lintFiles()' should verify '.eslintrc.js'.", async () => {
4789 const engine
= new InMemoryESLint();
4790 const filePaths
= (await engine
.lintFiles("**/*.js"))
4791 .map(r
=> r
.filePath
)
4794 assert
.deepStrictEqual(filePaths
, [
4795 path
.join(root
, ".eslintrc.js"),
4796 path
.join(root
, "foo.js")
4801 describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
4803 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4806 ".eslintrc.js": `module.exports = ${JSON.stringify({
4807 ignorePatterns: "!.*"
4809 ".eslintignore": ".foo*",
4816 it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", async () => {
4817 const engine
= new InMemoryESLint();
4819 assert
.strictEqual(await engine
.isPathIgnored(".foo.js"), true);
4822 it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", async () => {
4823 const engine
= new InMemoryESLint();
4825 assert
.strictEqual(await engine
.isPathIgnored(".bar.js"), false);
4828 it("'lintFiles()' should not verify re-ignored '.foo.js'.", async () => {
4829 const engine
= new InMemoryESLint();
4830 const filePaths
= (await engine
.lintFiles("**/*.js"))
4831 .map(r
=> r
.filePath
)
4834 assert
.deepStrictEqual(filePaths
, [
4835 path
.join(root
, ".bar.js"),
4836 path
.join(root
, ".eslintrc.js")
4841 describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
4843 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4846 ".eslintrc.js": `module.exports = ${JSON.stringify({
4847 ignorePatterns: "*.js"
4849 ".eslintignore": "!foo.js",
4856 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
4857 const engine
= new InMemoryESLint();
4859 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
4862 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
4863 const engine
= new InMemoryESLint();
4865 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), true);
4868 it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
4869 const engine
= new InMemoryESLint();
4870 const filePaths
= (await engine
.lintFiles("**/*.js"))
4871 .map(r
=> r
.filePath
)
4874 assert
.deepStrictEqual(filePaths
, [
4875 path
.join(root
, "foo.js")
4880 describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
4882 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4885 ".eslintrc.json": JSON
.stringify({
4886 ignorePatterns
: "foo.js"
4888 "subdir/.eslintrc.json": JSON
.stringify({
4889 ignorePatterns
: "bar.js"
4893 "subdir/foo.js": "",
4894 "subdir/bar.js": "",
4895 "subdir/subsubdir/foo.js": "",
4896 "subdir/subsubdir/bar.js": ""
4901 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
4902 const engine
= new InMemoryESLint();
4904 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
4905 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
4906 assert
.strictEqual(await engine
.isPathIgnored("subdir/subsubdir/foo.js"), true);
4909 it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", async () => {
4910 const engine
= new InMemoryESLint();
4912 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
4913 assert
.strictEqual(await engine
.isPathIgnored("subdir/subsubdir/bar.js"), true);
4916 it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", async () => {
4917 const engine
= new InMemoryESLint();
4919 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
4922 it("'lintFiles()' should verify 'bar.js' in the outside of 'subdir'.", async () => {
4923 const engine
= new InMemoryESLint();
4924 const filePaths
= (await engine
.lintFiles("**/*.js"))
4925 .map(r
=> r
.filePath
)
4928 assert
.deepStrictEqual(filePaths
, [
4929 path
.join(root
, "bar.js")
4934 describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
4936 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4939 ".eslintrc.json": JSON
.stringify({
4940 ignorePatterns
: "foo.js"
4942 "subdir/.eslintrc.json": JSON
.stringify({
4943 ignorePatterns
: "!foo.js"
4951 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
4952 const engine
= new InMemoryESLint();
4954 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
4957 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
4958 const engine
= new InMemoryESLint();
4960 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
4963 it("'lintFiles()' should verify 'foo.js' in the child directory.", async () => {
4964 const engine
= new InMemoryESLint();
4965 const filePaths
= (await engine
.lintFiles("**/*.js"))
4966 .map(r
=> r
.filePath
)
4969 assert
.deepStrictEqual(filePaths
, [
4970 path
.join(root
, "subdir/foo.js")
4975 describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
4977 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
4980 ".eslintrc.json": JSON
.stringify({}),
4981 "subdir/.eslintrc.json": JSON
.stringify({
4982 ignorePatterns
: "*.js"
4984 ".eslintignore": "!foo.js",
4986 "subdir/foo.js": "",
4992 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
4993 const engine
= new InMemoryESLint();
4995 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
4996 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
4999 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
5000 const engine
= new InMemoryESLint();
5002 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5005 it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
5006 const engine
= new InMemoryESLint();
5007 const filePaths
= (await engine
.lintFiles("**/*.js"))
5008 .map(r
=> r
.filePath
)
5011 assert
.deepStrictEqual(filePaths
, [
5012 path
.join(root
, "foo.js"),
5013 path
.join(root
, "subdir/foo.js")
5018 describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
5020 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5023 ".eslintrc.json": JSON
.stringify({
5024 ignorePatterns
: "foo.js"
5026 "subdir/.eslintrc.json": JSON
.stringify({
5028 ignorePatterns
: "bar.js"
5032 "subdir/foo.js": "",
5038 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
5039 const engine
= new InMemoryESLint();
5041 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5044 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
5045 const engine
= new InMemoryESLint();
5047 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5050 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
5051 const engine
= new InMemoryESLint();
5053 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5056 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
5057 const engine
= new InMemoryESLint();
5059 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5062 it("'lintFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", async () => {
5063 const engine
= new InMemoryESLint();
5064 const filePaths
= (await engine
.lintFiles("**/*.js"))
5065 .map(r
=> r
.filePath
)
5068 assert
.deepStrictEqual(filePaths
, [
5069 path
.join(root
, "bar.js"),
5070 path
.join(root
, "subdir/foo.js")
5075 describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
5077 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5080 ".eslintrc.json": JSON
.stringify({}),
5081 "subdir/.eslintrc.json": JSON
.stringify({
5083 ignorePatterns
: "bar.js"
5085 ".eslintignore": "foo.js",
5088 "subdir/foo.js": "",
5094 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5095 const engine
= new InMemoryESLint();
5097 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5098 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5101 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
5102 const engine
= new InMemoryESLint();
5104 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5107 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
5108 const engine
= new InMemoryESLint();
5110 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5113 it("'lintFiles()' should verify 'bar.js' in the root directory.", async () => {
5114 const engine
= new InMemoryESLint();
5115 const filePaths
= (await engine
.lintFiles("**/*.js"))
5116 .map(r
=> r
.filePath
)
5119 assert
.deepStrictEqual(filePaths
, [
5120 path
.join(root
, "bar.js")
5125 describe("ignorePatterns in the shareable config should be used.", () => {
5127 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5130 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5131 ignorePatterns: "foo.js"
5133 ".eslintrc.json": JSON
.stringify({
5142 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5143 const engine
= new InMemoryESLint();
5145 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5148 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5149 const engine
= new InMemoryESLint();
5151 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5154 it("'lintFiles()' should verify 'bar.js'.", async () => {
5155 const engine
= new InMemoryESLint();
5156 const filePaths
= (await engine
.lintFiles("**/*.js"))
5157 .map(r
=> r
.filePath
)
5160 assert
.deepStrictEqual(filePaths
, [
5161 path
.join(root
, "bar.js")
5166 describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
5168 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5171 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5172 ignorePatterns: "/foo.js"
5174 ".eslintrc.json": JSON
.stringify({
5183 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5184 const engine
= new InMemoryESLint();
5186 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5189 it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", async () => {
5190 const engine
= new InMemoryESLint();
5192 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5195 it("'lintFiles()' should verify 'subdir/foo.js'.", async () => {
5196 const engine
= new InMemoryESLint();
5197 const filePaths
= (await engine
.lintFiles("**/*.js"))
5198 .map(r
=> r
.filePath
)
5201 assert
.deepStrictEqual(filePaths
, [
5202 path
.join(root
, "subdir/foo.js")
5207 describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
5209 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5212 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5213 ignorePatterns: "*.js"
5215 ".eslintrc.json": JSON
.stringify({
5217 ignorePatterns
: "!bar.js"
5225 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5226 const engine
= new InMemoryESLint();
5228 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5231 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5232 const engine
= new InMemoryESLint();
5234 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5237 it("'lintFiles()' should verify 'bar.js'.", async () => {
5238 const engine
= new InMemoryESLint();
5239 const filePaths
= (await engine
.lintFiles("**/*.js"))
5240 .map(r
=> r
.filePath
)
5243 assert
.deepStrictEqual(filePaths
, [
5244 path
.join(root
, "bar.js")
5249 describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
5251 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5254 ".eslintrc.json": JSON
.stringify({
5255 ignorePatterns
: "*.js"
5262 it("'isPathIgnored()' should return 'false' for 'foo.js'.", async () => {
5263 const engine
= new InMemoryESLint({ ignore
: false });
5265 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5268 it("'lintFiles()' should verify 'foo.js'.", async () => {
5269 const engine
= new InMemoryESLint({ ignore
: false });
5270 const filePaths
= (await engine
.lintFiles("**/*.js"))
5271 .map(r
=> r
.filePath
)
5274 assert
.deepStrictEqual(filePaths
, [
5275 path
.join(root
, "foo.js")
5280 describe("ignorePatterns in overrides section is not allowed.", () => {
5282 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5285 ".eslintrc.js": `module.exports = ${JSON.stringify({
5289 ignorePatterns: "foo.js"
5298 it("should throw a configuration error.", async () => {
5299 await assert
.rejects(async () => {
5300 const engine
= new InMemoryESLint();
5302 await engine
.lintFiles("*.js");
5303 }, /Unexpected top-level property "overrides\[0\]\.ignorePatterns"/u);
5308 describe("'overrides[].files' adds lint targets", () => {
5309 const root
= getFixturePath("cli-engine/additional-lint-targets");
5312 describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
5314 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5317 ".eslintrc.json": JSON
.stringify({
5321 excludedFiles
: "**/ignore.txt"
5325 "foo/nested/test.txt": "",
5328 "foo/ignore.txt": "",
5331 "bar/ignore.txt": "",
5339 it("'lintFiles()' with a directory path should contain 'foo/test.txt'.", async () => {
5340 const engine
= new InMemoryESLint();
5341 const filePaths
= (await engine
.lintFiles("."))
5342 .map(r
=> r
.filePath
)
5345 assert
.deepStrictEqual(filePaths
, [
5346 path
.join(root
, "bar/test.js"),
5347 path
.join(root
, "foo/test.js"),
5348 path
.join(root
, "foo/test.txt"),
5349 path
.join(root
, "test.js")
5353 it("'lintFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", async () => {
5354 const engine
= new InMemoryESLint();
5355 const filePaths
= (await engine
.lintFiles("**/*.js"))
5356 .map(r
=> r
.filePath
)
5359 assert
.deepStrictEqual(filePaths
, [
5360 path
.join(root
, "bar/test.js"),
5361 path
.join(root
, "foo/test.js"),
5362 path
.join(root
, "test.js")
5367 describe("if { files: 'foo/**/*.txt' } is present,", () => {
5369 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5372 ".eslintrc.json": JSON
.stringify({
5375 files
: "foo/**/*.txt"
5379 "foo/nested/test.txt": "",
5390 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5391 const engine
= new InMemoryESLint();
5392 const filePaths
= (await engine
.lintFiles("."))
5393 .map(r
=> r
.filePath
)
5396 assert
.deepStrictEqual(filePaths
, [
5397 path
.join(root
, "bar/test.js"),
5398 path
.join(root
, "foo/nested/test.txt"),
5399 path
.join(root
, "foo/test.js"),
5400 path
.join(root
, "foo/test.txt"),
5401 path
.join(root
, "test.js")
5406 describe("if { files: 'foo/**/*' } is present,", () => {
5408 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5411 ".eslintrc.json": JSON
.stringify({
5418 "foo/nested/test.txt": "",
5429 it("'lintFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5430 const engine
= new InMemoryESLint();
5431 const filePaths
= (await engine
.lintFiles("."))
5432 .map(r
=> r
.filePath
)
5435 assert
.deepStrictEqual(filePaths
, [
5436 path
.join(root
, "bar/test.js"),
5437 path
.join(root
, "foo/test.js"),
5438 path
.join(root
, "test.js")
5443 describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
5445 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5448 "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
5451 files: "foo/**/*.txt"
5455 ".eslintrc.json": JSON
.stringify({
5458 "foo/nested/test.txt": "",
5469 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5470 const engine
= new InMemoryESLint();
5471 const filePaths
= (await engine
.lintFiles("."))
5472 .map(r
=> r
.filePath
)
5475 assert
.deepStrictEqual(filePaths
, [
5476 path
.join(root
, "bar/test.js"),
5477 path
.join(root
, "foo/nested/test.txt"),
5478 path
.join(root
, "foo/test.js"),
5479 path
.join(root
, "foo/test.txt"),
5480 path
.join(root
, "test.js")
5485 describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
5487 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5490 "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
5494 files: "foo/**/*.txt"
5499 ".eslintrc.json": JSON
.stringify({
5500 extends: "plugin:foo/bar"
5502 "foo/nested/test.txt": "",
5513 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5514 const engine
= new InMemoryESLint();
5515 const filePaths
= (await engine
.lintFiles("."))
5516 .map(r
=> r
.filePath
)
5519 assert
.deepStrictEqual(filePaths
, [
5520 path
.join(root
, "bar/test.js"),
5521 path
.join(root
, "foo/nested/test.txt"),
5522 path
.join(root
, "foo/test.js"),
5523 path
.join(root
, "foo/test.txt"),
5524 path
.join(root
, "test.js")
5530 describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
5531 const root
= getFixturePath("cli-engine/config-and-overrides-files");
5533 /** @type {ESLint} */
5536 describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5538 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5541 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5551 "node_modules/myconf/foo/test.js": "a == b",
5552 "foo/test.js": "a == b"
5557 it("'lintFiles()' with 'foo/test.js' should use the override entry.", async () => {
5558 const engine
= new InMemoryESLint({
5559 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5564 const results
= await engine
.lintFiles("foo/test.js");
5566 // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
5567 assert
.deepStrictEqual(results
, [
5570 filePath
: path
.join(root
, "foo/test.js"),
5571 fixableErrorCount
: 0,
5572 fixableWarningCount
: 0,
5579 message
: "Expected '===' and instead saw '=='.",
5580 messageId
: "unexpected",
5581 nodeType
: "BinaryExpression",
5587 usedDeprecatedRules
: [],
5593 it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", async () => {
5594 const engine
= new InMemoryESLint({
5595 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5600 const results
= await engine
.lintFiles("node_modules/myconf/foo/test.js");
5602 // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
5603 assert
.deepStrictEqual(results
, [
5606 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
5607 fixableErrorCount
: 0,
5608 fixableWarningCount
: 0,
5610 usedDeprecatedRules
: [],
5617 describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5619 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5622 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5626 excludedFiles
: "foo/*.js",
5633 "node_modules/myconf/foo/test.js": "a == b",
5634 "foo/test.js": "a == b"
5639 it("'lintFiles()' with 'foo/test.js' should NOT use the override entry.", async () => {
5640 const engine
= new InMemoryESLint({
5641 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5646 const results
= await engine
.lintFiles("foo/test.js");
5648 // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
5649 assert
.deepStrictEqual(results
, [
5652 filePath
: path
.join(root
, "foo/test.js"),
5653 fixableErrorCount
: 0,
5654 fixableWarningCount
: 0,
5656 usedDeprecatedRules
: [],
5662 it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", async () => {
5663 const engine
= new InMemoryESLint({
5664 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5669 const results
= await engine
.lintFiles("node_modules/myconf/foo/test.js");
5671 // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
5672 assert
.deepStrictEqual(results
, [
5675 filePath
: path
.join(root
, "node_modules/myconf/foo/test.js"),
5676 fixableErrorCount
: 0,
5677 fixableWarningCount
: 0,
5684 message
: "Expected '===' and instead saw '=='.",
5685 messageId
: "unexpected",
5686 nodeType
: "BinaryExpression",
5692 usedDeprecatedRules
: [],
5699 describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5701 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5704 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5705 ignorePatterns
: ["!/node_modules/myconf", "foo/*.js"],
5710 "node_modules/myconf/foo/test.js": "a == b",
5711 "foo/test.js": "a == b"
5716 it("'lintFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", async () => {
5717 const engine
= new InMemoryESLint({
5718 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5722 const files
= (await engine
.lintFiles("**/*.js"))
5723 .map(r
=> r
.filePath
)
5726 assert
.deepStrictEqual(files
, [
5727 path
.join(root
, "node_modules/myconf/foo/test.js")
5733 describe("plugin conflicts", () => {
5738 root
= getFixturePath(`eslint/plugin-conflicts-${++uid}`);
5741 /** @type {typeof ESLint} */
5745 * Verify thrown errors.
5746 * @param {() => Promise<any>} f The function to run and throw.
5747 * @param {Record<string, any>} props The properties to verify.
5748 * @returns {Promise<void>} void
5750 async
function assertThrows(f
, props
) {
5754 for (const [key
, value
] of Object
.entries(props
)) {
5755 assert
.deepStrictEqual(error
[key
], value
, key
);
5760 assert
.fail("Function should throw an error, but not.");
5763 describe("between a config file and linear extendees.", () => {
5765 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5768 "node_modules/eslint-plugin-foo/index.js": "",
5769 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
5770 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5774 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
5775 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
5778 ".eslintrc.json": JSON
.stringify({
5787 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
5788 const engine
= new InMemoryESLint({ cwd
: root
});
5790 await engine
.lintFiles("test.js");
5794 describe("between a config file and same-depth extendees.", () => {
5796 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5799 "node_modules/eslint-plugin-foo/index.js": "",
5800 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
5801 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5804 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
5805 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
5808 ".eslintrc.json": JSON
.stringify({
5809 extends: ["one", "two"],
5817 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
5818 const engine
= new InMemoryESLint({ cwd
: root
});
5820 await engine
.lintFiles("test.js");
5824 describe("between two config files in different directories, with single node_modules.", () => {
5826 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5829 "node_modules/eslint-plugin-foo/index.js": "",
5830 ".eslintrc.json": JSON
.stringify({
5833 "subdir/.eslintrc.json": JSON
.stringify({
5836 "subdir/test.js": ""
5841 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 () => {
5842 const engine
= new InMemoryESLint({ cwd
: root
});
5844 await engine
.lintFiles("subdir/test.js");
5848 describe("between two config files in different directories, with multiple node_modules.", () => {
5850 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5853 "node_modules/eslint-plugin-foo/index.js": "",
5854 ".eslintrc.json": JSON
.stringify({
5857 "subdir/node_modules/eslint-plugin-foo/index.js": "",
5858 "subdir/.eslintrc.json": JSON
.stringify({
5861 "subdir/test.js": ""
5866 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 () => {
5867 const engine
= new InMemoryESLint({ cwd
: root
});
5870 () => engine
.lintFiles("subdir/test.js"),
5872 message
: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
5873 messageTemplate
: "plugin-conflict",
5878 filePath
: path
.join(root
, "subdir/node_modules/eslint-plugin-foo/index.js"),
5879 importerName
: `subdir${path.sep}.eslintrc.json`
5882 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
5883 importerName
: ".eslintrc.json"
5892 describe("between '--config' option and a regular config file, with single node_modules.", () => {
5894 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5897 "node_modules/eslint-plugin-foo/index.js": "",
5898 "node_modules/mine/.eslintrc.json": JSON
.stringify({
5901 ".eslintrc.json": JSON
.stringify({
5909 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 () => {
5910 const engine
= new InMemoryESLint({
5912 overrideConfigFile
: "node_modules/mine/.eslintrc.json"
5915 await engine
.lintFiles("test.js");
5919 describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
5921 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5924 "node_modules/eslint-plugin-foo/index.js": "",
5925 "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
5926 "node_modules/mine/.eslintrc.json": JSON
.stringify({
5929 ".eslintrc.json": JSON
.stringify({
5937 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 () => {
5938 const engine
= new InMemoryESLint({
5940 overrideConfigFile
: "node_modules/mine/.eslintrc.json"
5944 () => engine
.lintFiles("test.js"),
5946 message
: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
5947 messageTemplate
: "plugin-conflict",
5952 filePath
: path
.join(root
, "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
5953 importerName
: "--config"
5956 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
5957 importerName
: ".eslintrc.json"
5966 describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
5968 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5971 "node_modules/eslint-plugin-foo/index.js": "",
5972 "subdir/.eslintrc.json": JSON
.stringify({
5975 "subdir/test.js": ""
5980 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 () => {
5981 const engine
= new InMemoryESLint({
5983 overrideConfig
: { plugins
: ["foo"] }
5986 await engine
.lintFiles("subdir/test.js");
5990 describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
5992 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
5995 "node_modules/eslint-plugin-foo/index.js": "",
5996 "subdir/node_modules/eslint-plugin-foo/index.js": "",
5997 "subdir/.eslintrc.json": JSON
.stringify({
6000 "subdir/test.js": ""
6005 it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", async () => {
6006 const engine
= new InMemoryESLint({
6008 overrideConfig
: { plugins
: ["foo"] }
6012 () => engine
.lintFiles("subdir/test.js"),
6014 message
: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
6015 messageTemplate
: "plugin-conflict",
6020 filePath
: path
.join(root
, "node_modules/eslint-plugin-foo/index.js"),
6021 importerName
: "CLIOptions"
6024 filePath
: path
.join(root
, "subdir/node_modules/eslint-plugin-foo/index.js"),
6025 importerName
: `subdir${path.sep}.eslintrc.json`
6034 describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
6036 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
6039 "node_modules/eslint-plugin-foo/index.js": "",
6040 ".eslintrc.json": JSON
.stringify({
6043 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6044 "subdir/.eslintrc.json": JSON
.stringify({
6047 "subdir/test.js": ""
6052 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", async () => {
6053 const engine
= new InMemoryESLint({
6055 resolvePluginsRelativeTo
: root
6058 await engine
.lintFiles("subdir/test.js");
6062 describe("between two config files with different target files.", () => {
6064 InMemoryESLint
= defineESLintWithInMemoryFileSystem({
6067 "one/node_modules/eslint-plugin-foo/index.js": "",
6068 "one/.eslintrc.json": JSON
.stringify({
6072 "two/node_modules/eslint-plugin-foo/index.js": "",
6073 "two/.eslintrc.json": JSON
.stringify({
6081 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 () => {
6082 const engine
= new InMemoryESLint({ cwd
: root
});
6083 const results
= await engine
.lintFiles("*/test.js");
6085 assert
.strictEqual(results
.length
, 2);