2 * @fileoverview Tests for the ESLint class.
4 * @author Toru Nagashima
9 //------------------------------------------------------------------------------
11 //------------------------------------------------------------------------------
13 const assert
= require("assert");
14 const fs
= require("fs");
15 const os
= require("os");
16 const path
= require("path");
17 const escapeStringRegExp
= require("escape-string-regexp");
18 const fCache
= require("file-entry-cache");
19 const sinon
= require("sinon");
20 const proxyquire
= require("proxyquire").noCallThru().noPreserveCache();
21 const shell
= require("shelljs");
22 const { CascadingConfigArrayFactory
} = require("@eslint/eslintrc/lib/cascading-config-array-factory");
23 const hash
= require("../../../lib/cli-engine/hash");
24 const { unIndent
, createCustomTeardown
} = require("../../_utils");
26 //------------------------------------------------------------------------------
28 //------------------------------------------------------------------------------
30 describe("ESLint", () => {
31 const examplePluginName
= "eslint-plugin-example";
32 const examplePluginNameWithNamespace
= "@eslint/eslint-plugin-example";
33 const examplePlugin
= {
35 "example-rule": require("../../fixtures/rules/custom-rule"),
36 "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
39 const examplePreprocessorName
= "eslint-plugin-processor";
40 const originalDir
= process
.cwd();
41 const fixtureDir
= path
.resolve(fs
.realpathSync(os
.tmpdir()), "eslint/fixtures");
43 /** @type {import("../../../lib/eslint")["ESLint"]} */
47 * Returns the path inside of the fixture directory.
48 * @param {...string} args file path segments.
49 * @returns {string} The path inside the fixture directory.
52 function getFixturePath(...args
) {
53 const filepath
= path
.join(fixtureDir
, ...args
);
56 return fs
.realpathSync(filepath
);
63 * Create the ESLint object by mocking some of the plugins
64 * @param {Object} options options for ESLint
65 * @returns {ESLint} engine object
68 function eslintWithPlugins(options
) {
72 [examplePluginName
]: examplePlugin
,
73 [examplePluginNameWithNamespace
]: examplePlugin
,
74 [examplePreprocessorName
]: require("../../fixtures/processors/custom-processor")
80 * Call the last argument.
81 * @param {any[]} args Arguments
84 function callLastArgument(...args
) {
85 process
.nextTick(args
[args
.length
- 1], null);
88 // copy into clean area so as not to get "infected" by this project's .eslintrc files
92 * GitHub Actions Windows and macOS runners occasionally exhibit
93 * extremely slow filesystem operations, during which copying fixtures
94 * exceeds the default test timeout, so raise it just for this hook.
95 * Mocha uses `this` to set timeouts on an individual hook level.
97 this.timeout(60 * 1000); // eslint-disable-line no-invalid-this
98 shell
.mkdir("-p", fixtureDir
);
99 shell
.cp("-r", "./tests/fixtures/.", fixtureDir
);
103 ({ ESLint
} = require("../../../lib/eslint/eslint"));
107 shell
.rm("-r", fixtureDir
);
110 describe("ESLint constructor function", () => {
111 it("the default value of 'options.cwd' should be the current working directory.", async () => {
112 process
.chdir(__dirname
);
114 const engine
= new ESLint();
115 const results
= await engine
.lintFiles("eslint.js");
117 assert
.strictEqual(path
.dirname(results
[0].filePath
), __dirname
);
119 process
.chdir(originalDir
);
123 it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
124 assert
.throws(() => {
125 // eslint-disable-next-line no-new
126 new ESLint({ ignorePath
: fixtureDir
});
127 }, new RegExp(escapeStringRegExp(`Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`), "u"));
130 // https://github.com/eslint/eslint/issues/2380
131 it("should not modify baseConfig when format is specified", () => {
132 const customBaseConfig
= { root
: true };
134 new ESLint({ baseConfig
: customBaseConfig
}); // eslint-disable-line no-new
136 assert
.deepStrictEqual(customBaseConfig
, { root
: true });
139 it("should throw readable messages if removed options are present", () => {
152 new RegExp(escapeStringRegExp([
154 "- Unknown options: cacheFile, configFile, envs, globals, ignorePattern, parser, parserOptions, rules",
155 "- 'cacheFile' has been removed. Please use the 'cacheLocation' option instead.",
156 "- 'configFile' has been removed. Please use the 'overrideConfigFile' option instead.",
157 "- 'envs' has been removed. Please use the 'overrideConfig.env' option instead.",
158 "- 'globals' has been removed. Please use the 'overrideConfig.globals' option instead.",
159 "- 'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.",
160 "- 'parser' has been removed. Please use the 'overrideConfig.parser' option instead.",
161 "- 'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead.",
162 "- 'rules' has been removed. Please use the 'overrideConfig.rules' option instead.",
163 "- 'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead."
168 it("should throw readable messages if wrong type values are given to options", () => {
171 allowInlineConfig
: "",
176 errorOnUnmatchedPattern
: "",
184 overrideConfigFile
: "",
186 reportUnusedDisableDirectives
: "",
187 resolvePluginsRelativeTo
: "",
191 new RegExp(escapeStringRegExp([
193 "- 'allowInlineConfig' must be a boolean.",
194 "- 'baseConfig' must be an object or null.",
195 "- 'cache' must be a boolean.",
196 "- 'cacheLocation' must be a non-empty string.",
197 "- 'cwd' must be an absolute path.",
198 "- 'errorOnUnmatchedPattern' must be a boolean.",
199 "- 'extensions' must be an array of non-empty strings or null.",
200 "- 'fix' must be a boolean or a function.",
201 "- 'fixTypes' must be an array of any of \"problem\", \"suggestion\", and \"layout\".",
202 "- 'globInputPaths' must be a boolean.",
203 "- 'ignore' must be a boolean.",
204 "- 'ignorePath' must be a non-empty string or null.",
205 "- 'overrideConfig' must be an object or null.",
206 "- 'overrideConfigFile' must be a non-empty string or null.",
207 "- 'plugins' must be an object or null.",
208 "- 'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.",
209 "- 'resolvePluginsRelativeTo' must be a non-empty string or null.",
210 "- 'rulePaths' must be an array of non-empty strings.",
211 "- 'useEslintrc' must be a boolean."
216 it("should throw readable messages if 'plugins' option contains empty key", () => {
220 "eslint-plugin-foo": {},
221 "eslint-plugin-bar": {},
225 new RegExp(escapeStringRegExp([
227 "- 'plugins' must not include an empty string."
233 describe("lintText()", () => {
236 it("should report the total and per file errors when using local cwd .eslintrc", async () => {
237 eslint
= new ESLint();
238 const results
= await eslint
.lintText("var foo = 'bar';");
240 assert
.strictEqual(results
.length
, 1);
241 assert
.strictEqual(results
[0].messages
.length
, 5);
242 assert
.strictEqual(results
[0].messages
[0].ruleId
, "strict");
243 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-var");
244 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-unused-vars");
245 assert
.strictEqual(results
[0].messages
[3].ruleId
, "quotes");
246 assert
.strictEqual(results
[0].messages
[4].ruleId
, "eol-last");
247 assert
.strictEqual(results
[0].fixableErrorCount
, 3);
248 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
249 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
252 it("should report the total and per file warnings when using local cwd .eslintrc", async () => {
253 eslint
= new ESLint({
264 const results
= await eslint
.lintText("var foo = 'bar';");
266 assert
.strictEqual(results
.length
, 1);
267 assert
.strictEqual(results
[0].messages
.length
, 5);
268 assert
.strictEqual(results
[0].messages
[0].ruleId
, "strict");
269 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-var");
270 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-unused-vars");
271 assert
.strictEqual(results
[0].messages
[3].ruleId
, "quotes");
272 assert
.strictEqual(results
[0].messages
[4].ruleId
, "eol-last");
273 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
274 assert
.strictEqual(results
[0].fixableWarningCount
, 3);
275 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
278 it("should report one message when using specific config file", async () => {
279 eslint
= new ESLint({
280 overrideConfigFile
: "fixtures/configurations/quotes-error.json",
282 cwd
: getFixturePath("..")
284 const results
= await eslint
.lintText("var foo = 'bar';");
286 assert
.strictEqual(results
.length
, 1);
287 assert
.strictEqual(results
[0].messages
.length
, 1);
288 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
289 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
290 assert
.strictEqual(results
[0].errorCount
, 1);
291 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
292 assert
.strictEqual(results
[0].warningCount
, 0);
293 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
296 it("should report the filename when passed in", async () => {
297 eslint
= new ESLint({
299 cwd
: getFixturePath()
301 const options
= { filePath
: "test.js" };
302 const results
= await eslint
.lintText("var foo = 'bar';", options
);
304 assert
.strictEqual(results
[0].filePath
, getFixturePath("test.js"));
307 it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", async () => {
308 eslint
= new ESLint({
309 ignorePath
: getFixturePath(".eslintignore"),
310 cwd
: getFixturePath("..")
312 const options
= { filePath
: "fixtures/passing.js", warnIgnored
: true };
313 const results
= await eslint
.lintText("var bar = foo;", options
);
315 assert
.strictEqual(results
.length
, 1);
316 assert
.strictEqual(results
[0].filePath
, getFixturePath("passing.js"));
317 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
318 assert
.strictEqual(results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
319 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
320 assert
.strictEqual(results
[0].errorCount
, 0);
321 assert
.strictEqual(results
[0].warningCount
, 1);
322 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
323 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
324 assert
.strictEqual(results
[0].usedDeprecatedRules
.length
, 0);
327 it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", async () => {
328 eslint
= new ESLint({
329 ignorePath
: getFixturePath(".eslintignore"),
330 cwd
: getFixturePath("..")
333 filePath
: "fixtures/passing.js",
337 // intentional parsing error
338 const results
= await eslint
.lintText("va r bar = foo;", options
);
340 // should not report anything because the file is ignored
341 assert
.strictEqual(results
.length
, 0);
344 it("should suppress excluded file warnings by default", async () => {
345 eslint
= new ESLint({
346 ignorePath
: getFixturePath(".eslintignore"),
347 cwd
: getFixturePath("..")
349 const options
= { filePath
: "fixtures/passing.js" };
350 const results
= await eslint
.lintText("var bar = foo;", options
);
352 // should not report anything because there are no errors
353 assert
.strictEqual(results
.length
, 0);
356 it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", async () => {
357 eslint
= new ESLint({
358 ignorePath
: "fixtures/.eslintignore",
359 cwd
: getFixturePath(".."),
368 const options
= { filePath
: "fixtures/passing.js" };
369 const results
= await eslint
.lintText("var bar = foo;", options
);
371 assert
.strictEqual(results
.length
, 1);
372 assert
.strictEqual(results
[0].filePath
, getFixturePath("passing.js"));
373 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
374 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
375 assert
.strictEqual(results
[0].messages
[0].output
, void 0);
378 it("should return a message and fixed text when in fix mode", async () => {
379 eslint
= new ESLint({
388 cwd
: getFixturePath()
390 const options
= { filePath
: "passing.js" };
391 const results
= await eslint
.lintText("var bar = foo", options
);
393 assert
.deepStrictEqual(results
, [
395 filePath
: getFixturePath("passing.js"),
399 fixableErrorCount
: 0,
400 fixableWarningCount
: 0,
401 output
: "var bar = foo;",
402 usedDeprecatedRules
: []
407 it("correctly autofixes semicolon-conflicting-fixes", async () => {
408 eslint
= new ESLint({
409 cwd
: path
.join(fixtureDir
, ".."),
413 const inputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.js");
414 const outputPath
= getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
415 const results
= await eslint
.lintFiles([inputPath
]);
416 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
418 assert
.strictEqual(results
[0].output
, expectedOutput
);
421 it("correctly autofixes return-conflicting-fixes", async () => {
422 eslint
= new ESLint({
423 cwd
: path
.join(fixtureDir
, ".."),
427 const inputPath
= getFixturePath("autofix/return-conflicting-fixes.js");
428 const outputPath
= getFixturePath("autofix/return-conflicting-fixes.expected.js");
429 const results
= await eslint
.lintFiles([inputPath
]);
430 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
432 assert
.strictEqual(results
[0].output
, expectedOutput
);
435 describe("Fix Types", () => {
436 it("should throw an error when an invalid fix type is specified", () => {
437 assert
.throws(() => {
438 eslint
= new ESLint({
439 cwd
: path
.join(fixtureDir
, ".."),
444 }, /'fixTypes' must be an array of any of "problem", "suggestion", and "layout"\./iu);
447 it("should not fix any rules when fixTypes is used without fix", async () => {
448 eslint
= new ESLint({
449 cwd
: path
.join(fixtureDir
, ".."),
454 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
455 const results
= await eslint
.lintFiles([inputPath
]);
457 assert
.strictEqual(results
[0].output
, void 0);
460 it("should not fix non-style rules when fixTypes has only 'layout'", async () => {
461 eslint
= new ESLint({
462 cwd
: path
.join(fixtureDir
, ".."),
467 const inputPath
= getFixturePath("fix-types/fix-only-semi.js");
468 const outputPath
= getFixturePath("fix-types/fix-only-semi.expected.js");
469 const results
= await eslint
.lintFiles([inputPath
]);
470 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
472 assert
.strictEqual(results
[0].output
, expectedOutput
);
475 it("should not fix style or problem rules when fixTypes has only 'suggestion'", async () => {
476 eslint
= new ESLint({
477 cwd
: path
.join(fixtureDir
, ".."),
480 fixTypes
: ["suggestion"]
482 const inputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
483 const outputPath
= getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
484 const results
= await eslint
.lintFiles([inputPath
]);
485 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
487 assert
.strictEqual(results
[0].output
, expectedOutput
);
490 it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", async () => {
491 eslint
= new ESLint({
492 cwd
: path
.join(fixtureDir
, ".."),
495 fixTypes
: ["suggestion", "layout"]
497 const inputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
498 const outputPath
= getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
499 const results
= await eslint
.lintFiles([inputPath
]);
500 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
502 assert
.strictEqual(results
[0].output
, expectedOutput
);
505 it("should not throw an error when a rule doesn't have a 'meta' property", async () => {
506 eslint
= new ESLint({
507 cwd
: path
.join(fixtureDir
, ".."),
510 fixTypes
: ["layout"],
511 rulePaths
: [getFixturePath("rules", "fix-types-test")]
513 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
514 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
515 const results
= await eslint
.lintFiles([inputPath
]);
516 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
518 assert
.strictEqual(results
[0].output
, expectedOutput
);
521 it("should not throw an error when a rule is loaded after initialization with lintFiles()", async () => {
522 eslint
= new ESLint({
523 cwd
: path
.join(fixtureDir
, ".."),
526 fixTypes
: ["layout"],
530 "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
535 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
536 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
537 const results
= await eslint
.lintFiles([inputPath
]);
538 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
540 assert
.strictEqual(results
[0].output
, expectedOutput
);
543 it("should not throw an error when a rule is loaded after initialization with lintText()", async () => {
544 eslint
= new ESLint({
545 cwd
: path
.join(fixtureDir
, ".."),
548 fixTypes
: ["layout"],
552 "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
557 const inputPath
= getFixturePath("fix-types/ignore-missing-meta.js");
558 const outputPath
= getFixturePath("fix-types/ignore-missing-meta.expected.js");
559 const results
= await eslint
.lintText(fs
.readFileSync(inputPath
, { encoding
: "utf8" }), { filePath
: inputPath
});
560 const expectedOutput
= fs
.readFileSync(outputPath
, "utf8");
562 assert
.strictEqual(results
[0].output
, expectedOutput
);
566 it("should return a message and omit fixed text when in fix mode and fixes aren't done", async () => {
567 eslint
= new ESLint({
576 cwd
: getFixturePath()
578 const options
= { filePath
: "passing.js" };
579 const results
= await eslint
.lintText("var bar = foo", options
);
581 assert
.deepStrictEqual(results
, [
583 filePath
: getFixturePath("passing.js"),
589 message
: "'foo' is not defined.",
594 nodeType
: "Identifier"
599 fixableErrorCount
: 0,
600 fixableWarningCount
: 0,
601 source
: "var bar = foo",
602 usedDeprecatedRules
: []
607 it("should not delete code if there is a syntax error after trying to autofix.", async () => {
608 eslint
= eslintWithPlugins({
612 plugins
: ["example"],
614 "example/make-syntax-error": "error"
618 cwd
: getFixturePath()
620 const options
= { filePath
: "test.js" };
621 const results
= await eslint
.lintText("var bar = foo", options
);
623 assert
.deepStrictEqual(results
, [
625 filePath
: getFixturePath("test.js"),
631 message
: "Parsing error: Unexpected token is",
638 fixableErrorCount
: 0,
639 fixableWarningCount
: 0,
640 output
: "var bar = foothis is a syntax error.",
641 usedDeprecatedRules
: []
646 it("should not crash even if there are any syntax error since the first time.", async () => {
647 eslint
= new ESLint({
652 "example/make-syntax-error": "error"
656 cwd
: getFixturePath()
658 const options
= { filePath
: "test.js" };
659 const results
= await eslint
.lintText("var bar =", options
);
661 assert
.deepStrictEqual(results
, [
663 filePath
: getFixturePath("test.js"),
669 message
: "Parsing error: Unexpected token",
676 fixableErrorCount
: 0,
677 fixableWarningCount
: 0,
679 usedDeprecatedRules
: []
684 it("should return source code of file in `source` property when errors are present", async () => {
685 eslint
= new ESLint({
691 const results
= await eslint
.lintText("var foo = 'bar'");
693 assert
.strictEqual(results
[0].source
, "var foo = 'bar'");
696 it("should return source code of file in `source` property when warnings are present", async () => {
697 eslint
= new ESLint({
703 const results
= await eslint
.lintText("var foo = 'bar'");
705 assert
.strictEqual(results
[0].source
, "var foo = 'bar'");
709 it("should not return a `source` property when no errors or warnings are present", async () => {
710 eslint
= new ESLint({
716 const results
= await eslint
.lintText("var foo = 'bar';");
718 assert
.strictEqual(results
[0].messages
.length
, 0);
719 assert
.strictEqual(results
[0].source
, void 0);
722 it("should not return a `source` property when fixes are applied", async () => {
723 eslint
= new ESLint({
733 const results
= await eslint
.lintText("var msg = 'hi' + foo\n");
735 assert
.strictEqual(results
[0].source
, void 0);
736 assert
.strictEqual(results
[0].output
, "var msg = 'hi' + foo;\n");
739 it("should return a `source` property when a parsing error has occurred", async () => {
740 eslint
= new ESLint({
746 const results
= await eslint
.lintText("var bar = foothis is a syntax error.\n return bar;");
748 assert
.deepStrictEqual(results
, [
756 message
: "Parsing error: Unexpected token is",
763 fixableErrorCount
: 0,
764 fixableWarningCount
: 0,
765 source
: "var bar = foothis is a syntax error.\n return bar;",
766 usedDeprecatedRules
: []
771 // https://github.com/eslint/eslint/issues/5547
772 it("should respect default ignore rules, even with --no-ignore", async () => {
773 eslint
= new ESLint({
774 cwd
: getFixturePath(),
777 const results
= await eslint
.lintText("var bar = foo;", { filePath
: "node_modules/passing.js", warnIgnored
: true });
778 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
780 assert
.strictEqual(results
.length
, 1);
781 assert
.strictEqual(results
[0].filePath
, getFixturePath("node_modules/passing.js"));
782 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
785 describe('plugin shorthand notation ("@scope" for "@scope/eslint-plugin")', () => {
786 const Module
= require("module");
787 let originalFindPath
= null;
789 /* eslint-disable no-underscore-dangle */
791 originalFindPath
= Module
._findPath
;
792 Module
._findPath = function(id
, ...otherArgs
) {
793 if (id
=== "@scope/eslint-plugin") {
794 return path
.resolve(__dirname
, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
796 return originalFindPath
.call(this, id
, ...otherArgs
);
800 Module
._findPath
= originalFindPath
;
802 /* eslint-enable no-underscore-dangle */
804 it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
805 eslint
= new ESLint({ cwd
: getFixturePath("plugin-shorthand/basic") });
806 const [result
] = await eslint
.lintText("var x = 0", { filePath
: "index.js" });
808 assert
.strictEqual(result
.filePath
, getFixturePath("plugin-shorthand/basic/index.js"));
809 assert
.strictEqual(result
.messages
[0].ruleId
, "@scope/rule");
810 assert
.strictEqual(result
.messages
[0].message
, "OK");
813 it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
814 eslint
= new ESLint({ cwd
: getFixturePath("plugin-shorthand/extends") });
815 const [result
] = await eslint
.lintText("var x = 0", { filePath
: "index.js" });
817 assert
.strictEqual(result
.filePath
, getFixturePath("plugin-shorthand/extends/index.js"));
818 assert
.strictEqual(result
.messages
[0].ruleId
, "@scope/rule");
819 assert
.strictEqual(result
.messages
[0].message
, "OK");
823 it("should warn when deprecated rules are found in a config", async () => {
824 eslint
= new ESLint({
827 overrideConfigFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
829 const [result
] = await eslint
.lintText("foo");
831 assert
.deepStrictEqual(
832 result
.usedDeprecatedRules
,
833 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
837 it("should throw if non-string value is given to 'code' parameter", async () => {
838 eslint
= new ESLint();
839 await assert
.rejects(() => eslint
.lintText(100), /'code' must be a string/u);
842 it("should throw if non-object value is given to 'options' parameter", async () => {
843 eslint
= new ESLint();
844 await assert
.rejects(() => eslint
.lintText("var a = 0", "foo.js"), /'options' must be an object, null, or undefined/u);
847 it("should throw if 'options' argument contains unknown key", async () => {
848 eslint
= new ESLint();
849 await assert
.rejects(() => eslint
.lintText("var a = 0", { filename
: "foo.js" }), /'options' must not include the unknown option 'filename'/u);
852 it("should throw if non-string value is given to 'options.filePath' option", async () => {
853 eslint
= new ESLint();
854 await assert
.rejects(() => eslint
.lintText("var a = 0", { filePath
: "" }), /'options.filePath' must be a non-empty string or undefined/u);
857 it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
858 eslint
= new ESLint();
859 await assert
.rejects(() => eslint
.lintText("var a = 0", { warnIgnored
: "" }), /'options.warnIgnored' must be a boolean or undefined/u);
863 describe("lintFiles()", () => {
865 /** @type {InstanceType<import("../../../lib/eslint")["ESLint"]>} */
868 it("should use correct parser when custom parser is specified", async () => {
869 eslint
= new ESLint({
873 const filePath
= path
.resolve(__dirname
, "../../fixtures/configurations/parser/custom.js");
874 const results
= await eslint
.lintFiles([filePath
]);
876 assert
.strictEqual(results
.length
, 1);
877 assert
.strictEqual(results
[0].messages
.length
, 1);
878 assert
.strictEqual(results
[0].messages
[0].message
, "Parsing error: Boom!");
881 it("should report zero messages when given a config file and a valid file", async () => {
882 eslint
= new ESLint({
884 overrideConfigFile
: ".eslintrc.js"
886 const results
= await eslint
.lintFiles(["lib/**/cli*.js"]);
888 assert
.strictEqual(results
.length
, 2);
889 assert
.strictEqual(results
[0].messages
.length
, 0);
890 assert
.strictEqual(results
[1].messages
.length
, 0);
893 it("should handle multiple patterns with overlapping files", async () => {
894 eslint
= new ESLint({
896 overrideConfigFile
: ".eslintrc.js"
898 const results
= await eslint
.lintFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
900 assert
.strictEqual(results
.length
, 2);
901 assert
.strictEqual(results
[0].messages
.length
, 0);
902 assert
.strictEqual(results
[1].messages
.length
, 0);
905 it("should report zero messages when given a config file and a valid file and espree as parser", async () => {
906 eslint
= new ESLint({
915 const results
= await eslint
.lintFiles(["lib/cli.js"]);
917 assert
.strictEqual(results
.length
, 1);
918 assert
.strictEqual(results
[0].messages
.length
, 0);
921 it("should report zero messages when given a config file and a valid file and esprima as parser", async () => {
922 eslint
= new ESLint({
929 const results
= await eslint
.lintFiles(["tests/fixtures/passing.js"]);
931 assert
.strictEqual(results
.length
, 1);
932 assert
.strictEqual(results
[0].messages
.length
, 0);
935 it("should throw an error when given a config file and a valid file and invalid parser", async () => {
936 eslint
= new ESLint({
943 await assert
.rejects(async () => await eslint
.lintFiles(["lib/cli.js"]), /Cannot find module
'test11'/u
);
946 it("should report zero messages when given a directory with a .js2 file", async () => {
947 eslint
= new ESLint({
948 cwd
: path
.join(fixtureDir
, ".."),
951 const results
= await eslint
.lintFiles([getFixturePath("files/foo.js2")]);
953 assert
.strictEqual(results
.length
, 1);
954 assert
.strictEqual(results
[0].messages
.length
, 0);
957 it("should fall back to defaults when extensions is set to an empty array", async () => {
958 eslint
= new ESLint({
959 cwd
: getFixturePath("configurations"),
960 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json"),
963 const results
= await eslint
.lintFiles([getFixturePath("single-quoted.js")]);
965 assert
.strictEqual(results
.length
, 1);
966 assert
.strictEqual(results
[0].messages
.length
, 1);
967 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
968 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
969 assert
.strictEqual(results
[0].errorCount
, 1);
970 assert
.strictEqual(results
[0].warningCount
, 0);
971 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
972 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
975 it("should report zero messages when given a directory with a .js and a .js2 file", async () => {
976 eslint
= new ESLint({
977 extensions
: [".js", ".js2"],
979 cwd
: getFixturePath("..")
981 const results
= await eslint
.lintFiles(["fixtures/files/"]);
983 assert
.strictEqual(results
.length
, 2);
984 assert
.strictEqual(results
[0].messages
.length
, 0);
985 assert
.strictEqual(results
[1].messages
.length
, 0);
988 it("should report zero messages when given a '**' pattern with a .js and a .js2 file", async () => {
989 eslint
= new ESLint({
990 extensions
: [".js", ".js2"],
992 cwd
: path
.join(fixtureDir
, "..")
994 const results
= await eslint
.lintFiles(["fixtures/files/*"]);
996 assert
.strictEqual(results
.length
, 2);
997 assert
.strictEqual(results
[0].messages
.length
, 0);
998 assert
.strictEqual(results
[1].messages
.length
, 0);
1001 it("should resolve globs when 'globInputPaths' option is true", async () => {
1002 eslint
= new ESLint({
1003 extensions
: [".js", ".js2"],
1005 cwd
: getFixturePath("..")
1007 const results
= await eslint
.lintFiles(["fixtures/files/*"]);
1009 assert
.strictEqual(results
.length
, 2);
1010 assert
.strictEqual(results
[0].messages
.length
, 0);
1011 assert
.strictEqual(results
[1].messages
.length
, 0);
1014 it("should not resolve globs when 'globInputPaths' option is false", async () => {
1015 eslint
= new ESLint({
1016 extensions
: [".js", ".js2"],
1018 cwd
: getFixturePath(".."),
1019 globInputPaths
: false
1022 await assert
.rejects(async () => {
1023 await eslint
.lintFiles(["fixtures/files/*"]);
1024 }, /No files matching 'fixtures\/files\/\*' were found \(glob was disabled\)\./u);
1027 it("should report on all files passed explicitly, even if ignored by default", async () => {
1028 eslint
= new ESLint({
1029 cwd
: getFixturePath("cli-engine")
1031 const results
= await eslint
.lintFiles(["node_modules/foo.js"]);
1032 const expectedMsg
= "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
1034 assert
.strictEqual(results
.length
, 1);
1035 assert
.strictEqual(results
[0].errorCount
, 0);
1036 assert
.strictEqual(results
[0].warningCount
, 1);
1037 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1038 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1039 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1042 it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", async () => {
1043 eslint
= new ESLint({
1044 cwd
: getFixturePath("cli-engine"),
1047 quotes
: [2, "single"]
1051 const results
= await eslint
.lintFiles(["hidden/.hiddenfolder/*.js"]);
1053 assert
.strictEqual(results
.length
, 1);
1054 assert
.strictEqual(results
[0].errorCount
, 1);
1055 assert
.strictEqual(results
[0].warningCount
, 0);
1056 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1057 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1060 it("should not check default ignored files without --no-ignore flag", async () => {
1061 eslint
= new ESLint({
1062 cwd
: getFixturePath("cli-engine")
1065 await assert
.rejects(async () => {
1066 await eslint
.lintFiles(["node_modules"]);
1067 }, /All files matched by 'node_modules' are ignored\./u);
1070 // https://github.com/eslint/eslint/issues/5547
1071 it("should not check node_modules files even with --no-ignore flag", async () => {
1072 eslint
= new ESLint({
1073 cwd
: getFixturePath("cli-engine"),
1077 await assert
.rejects(async () => {
1078 await eslint
.lintFiles(["node_modules"]);
1079 }, /All files matched by 'node_modules' are ignored\./u);
1082 it("should not check .hidden files if they are passed explicitly without --no-ignore flag", async () => {
1083 eslint
= new ESLint({
1084 cwd
: getFixturePath(".."),
1088 quotes
: [2, "single"]
1092 const results
= await eslint
.lintFiles(["fixtures/files/.bar.js"]);
1093 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1095 assert
.strictEqual(results
.length
, 1);
1096 assert
.strictEqual(results
[0].errorCount
, 0);
1097 assert
.strictEqual(results
[0].warningCount
, 1);
1098 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1099 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1100 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1103 // https://github.com/eslint/eslint/issues/12873
1104 it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", async () => {
1105 eslint
= new ESLint({
1106 cwd
: getFixturePath("cli-engine"),
1110 quotes
: [2, "single"]
1114 const results
= await eslint
.lintFiles(["hidden/.hiddenfolder/double-quotes.js"]);
1115 const expectedMsg
= "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
1117 assert
.strictEqual(results
.length
, 1);
1118 assert
.strictEqual(results
[0].errorCount
, 0);
1119 assert
.strictEqual(results
[0].warningCount
, 1);
1120 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1121 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1122 assert
.strictEqual(results
[0].messages
[0].message
, expectedMsg
);
1125 it("should check .hidden files if they are passed explicitly with --no-ignore flag", async () => {
1126 eslint
= new ESLint({
1127 cwd
: getFixturePath(".."),
1132 quotes
: [2, "single"]
1136 const results
= await eslint
.lintFiles(["fixtures/files/.bar.js"]);
1138 assert
.strictEqual(results
.length
, 1);
1139 assert
.strictEqual(results
[0].warningCount
, 0);
1140 assert
.strictEqual(results
[0].errorCount
, 1);
1141 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1142 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1143 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1146 it("should check .hidden files if they are unignored with an --ignore-pattern", async () => {
1147 eslint
= new ESLint({
1148 cwd
: getFixturePath("cli-engine"),
1152 ignorePatterns
: "!.hidden*",
1154 quotes
: [2, "single"]
1158 const results
= await eslint
.lintFiles(["hidden/"]);
1160 assert
.strictEqual(results
.length
, 1);
1161 assert
.strictEqual(results
[0].warningCount
, 0);
1162 assert
.strictEqual(results
[0].errorCount
, 1);
1163 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1164 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1165 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1168 it("should report zero messages when given a pattern with a .js and a .js2 file", async () => {
1169 eslint
= new ESLint({
1170 extensions
: [".js", ".js2"],
1172 cwd
: path
.join(fixtureDir
, "..")
1174 const results
= await eslint
.lintFiles(["fixtures/files/*.?s*"]);
1176 assert
.strictEqual(results
.length
, 2);
1177 assert
.strictEqual(results
[0].messages
.length
, 0);
1178 assert
.strictEqual(results
[1].messages
.length
, 0);
1181 it("should return one error message when given a config with rules with options and severity level set to error", async () => {
1182 eslint
= new ESLint({
1183 cwd
: getFixturePath("configurations"),
1184 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json")
1186 const results
= await eslint
.lintFiles([getFixturePath("single-quoted.js")]);
1188 assert
.strictEqual(results
.length
, 1);
1189 assert
.strictEqual(results
[0].messages
.length
, 1);
1190 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1191 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1192 assert
.strictEqual(results
[0].errorCount
, 1);
1193 assert
.strictEqual(results
[0].warningCount
, 0);
1194 assert
.strictEqual(results
[0].fixableErrorCount
, 1);
1195 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1198 it("should return 3 messages when given a config file and a directory of 3 valid files", async () => {
1199 eslint
= new ESLint({
1200 cwd
: path
.join(fixtureDir
, ".."),
1201 overrideConfigFile
: getFixturePath("configurations", "semi-error.json")
1203 const results
= await eslint
.lintFiles([getFixturePath("formatters")]);
1205 assert
.strictEqual(results
.length
, 3);
1206 assert
.strictEqual(results
[0].messages
.length
, 0);
1207 assert
.strictEqual(results
[1].messages
.length
, 0);
1208 assert
.strictEqual(results
[2].messages
.length
, 0);
1209 assert
.strictEqual(results
[0].errorCount
, 0);
1210 assert
.strictEqual(results
[0].warningCount
, 0);
1211 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1212 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1213 assert
.strictEqual(results
[1].errorCount
, 0);
1214 assert
.strictEqual(results
[1].warningCount
, 0);
1215 assert
.strictEqual(results
[1].fixableErrorCount
, 0);
1216 assert
.strictEqual(results
[1].fixableWarningCount
, 0);
1217 assert
.strictEqual(results
[2].errorCount
, 0);
1218 assert
.strictEqual(results
[2].warningCount
, 0);
1219 assert
.strictEqual(results
[2].fixableErrorCount
, 0);
1220 assert
.strictEqual(results
[2].fixableWarningCount
, 0);
1223 it("should process when file is given by not specifying extensions", async () => {
1224 eslint
= new ESLint({
1226 cwd
: path
.join(fixtureDir
, "..")
1228 const results
= await eslint
.lintFiles(["fixtures/files/foo.js2"]);
1230 assert
.strictEqual(results
.length
, 1);
1231 assert
.strictEqual(results
[0].messages
.length
, 0);
1234 it("should return zero messages when given a config with environment set to browser", async () => {
1235 eslint
= new ESLint({
1236 cwd
: path
.join(fixtureDir
, ".."),
1237 overrideConfigFile
: getFixturePath("configurations", "env-browser.json")
1239 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1241 assert
.strictEqual(results
.length
, 1);
1242 assert
.strictEqual(results
[0].messages
.length
, 0);
1245 it("should return zero messages when given an option to set environment to browser", async () => {
1246 eslint
= new ESLint({
1247 cwd
: path
.join(fixtureDir
, ".."),
1249 env
: { browser
: true },
1256 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-browser.js"))]);
1258 assert
.strictEqual(results
.length
, 1);
1259 assert
.strictEqual(results
[0].messages
.length
, 0);
1262 it("should return zero messages when given a config with environment set to Node.js", async () => {
1263 eslint
= new ESLint({
1264 cwd
: path
.join(fixtureDir
, ".."),
1265 overrideConfigFile
: getFixturePath("configurations", "env-node.json")
1267 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("globals-node.js"))]);
1269 assert
.strictEqual(results
.length
, 1);
1270 assert
.strictEqual(results
[0].messages
.length
, 0);
1273 it("should not return results from previous call when calling more than once", async () => {
1274 eslint
= new ESLint({
1275 cwd
: path
.join(fixtureDir
, ".."),
1283 const failFilePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1284 const passFilePath
= fs
.realpathSync(getFixturePath("passing.js"));
1286 let results
= await eslint
.lintFiles([failFilePath
]);
1288 assert
.strictEqual(results
.length
, 1);
1289 assert
.strictEqual(results
[0].filePath
, failFilePath
);
1290 assert
.strictEqual(results
[0].messages
.length
, 1);
1291 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
1292 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1294 results
= await eslint
.lintFiles([passFilePath
]);
1295 assert
.strictEqual(results
.length
, 1);
1296 assert
.strictEqual(results
[0].filePath
, passFilePath
);
1297 assert
.strictEqual(results
[0].messages
.length
, 0);
1300 it("should throw an error when given a directory with all eslint excluded files in the directory", async () => {
1301 eslint
= new ESLint({
1302 ignorePath
: getFixturePath(".eslintignore")
1305 await assert
.rejects(async () => {
1306 await eslint
.lintFiles([getFixturePath("./cli-engine/")]);
1307 }, new RegExp(escapeStringRegExp(`All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`), "u"));
1310 it("should throw an error when all given files are ignored", async () => {
1311 await assert
.rejects(async () => {
1312 await eslint
.lintFiles(["tests/fixtures/cli-engine/"]);
1313 }, /All files matched by 'tests\/fixtures\/cli-engine\/' are ignored\./u);
1316 it("should throw an error when all given files are ignored even with a `./` prefix", async () => {
1317 eslint
= new ESLint({
1318 ignorePath
: getFixturePath(".eslintignore")
1321 await assert
.rejects(async () => {
1322 await eslint
.lintFiles(["./tests/fixtures/cli-engine/"]);
1323 }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
1326 // https://github.com/eslint/eslint/issues/3788
1327 it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", async () => {
1328 eslint
= new ESLint({
1329 ignorePath
: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
1333 quotes
: [2, "double"]
1336 cwd
: getFixturePath("cli-engine", "nested_node_modules")
1338 const results
= await eslint
.lintFiles(["."]);
1340 assert
.strictEqual(results
.length
, 1);
1341 assert
.strictEqual(results
[0].errorCount
, 0);
1342 assert
.strictEqual(results
[0].warningCount
, 0);
1343 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1344 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1347 // https://github.com/eslint/eslint/issues/3812
1348 it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", async () => {
1349 eslint
= new ESLint({
1350 ignorePath
: getFixturePath("cli-engine/.eslintignore2"),
1354 quotes
: [2, "double"]
1359 await assert
.rejects(async () => {
1360 await eslint
.lintFiles(["./tests/fixtures/cli-engine/"]);
1361 }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
1364 it("should throw an error when all given files are ignored via ignore-pattern", async () => {
1365 eslint
= new ESLint({
1367 ignorePatterns
: "tests/fixtures/single-quoted.js"
1371 await assert
.rejects(async () => {
1372 await eslint
.lintFiles(["tests/fixtures/*-quoted.js"]);
1373 }, /All files matched by 'tests\/fixtures\/\*-quoted\.js' are ignored\./u);
1376 it("should return a warning when an explicitly given file is ignored", async () => {
1377 eslint
= new ESLint({
1378 ignorePath
: getFixturePath(".eslintignore"),
1379 cwd
: getFixturePath()
1381 const filePath
= getFixturePath("passing.js");
1382 const results
= await eslint
.lintFiles([filePath
]);
1384 assert
.strictEqual(results
.length
, 1);
1385 assert
.strictEqual(results
[0].filePath
, filePath
);
1386 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1387 assert
.strictEqual(results
[0].messages
[0].message
, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
1388 assert
.strictEqual(results
[0].errorCount
, 0);
1389 assert
.strictEqual(results
[0].warningCount
, 1);
1390 assert
.strictEqual(results
[0].fixableErrorCount
, 0);
1391 assert
.strictEqual(results
[0].fixableWarningCount
, 0);
1394 it("should return two messages when given a file in excluded files list while ignore is off", async () => {
1395 eslint
= new ESLint({
1396 ignorePath
: getFixturePath(".eslintignore"),
1404 const filePath
= fs
.realpathSync(getFixturePath("undef.js"));
1405 const results
= await eslint
.lintFiles([filePath
]);
1407 assert
.strictEqual(results
.length
, 1);
1408 assert
.strictEqual(results
[0].filePath
, filePath
);
1409 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-undef");
1410 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1411 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-undef");
1412 assert
.strictEqual(results
[0].messages
[1].severity
, 2);
1415 it("should return zero messages when executing a file with a shebang", async () => {
1416 eslint
= new ESLint({
1419 const results
= await eslint
.lintFiles([getFixturePath("shebang.js")]);
1421 assert
.strictEqual(results
.length
, 1);
1422 assert
.strictEqual(results
[0].messages
.length
, 0);
1425 it("should give a warning when loading a custom rule that doesn't exist", async () => {
1426 eslint
= new ESLint({
1428 rulePaths
: [getFixturePath("rules", "dir1")],
1429 overrideConfigFile
: getFixturePath("rules", "missing-rule.json")
1431 const results
= await eslint
.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1433 assert
.strictEqual(results
.length
, 1);
1434 assert
.strictEqual(results
[0].messages
.length
, 1);
1435 assert
.strictEqual(results
[0].messages
[0].ruleId
, "missing-rule");
1436 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1437 assert
.strictEqual(results
[0].messages
[0].message
, "Definition for rule 'missing-rule' was not found.");
1440 it("should throw an error when loading a bad custom rule", async () => {
1441 eslint
= new ESLint({
1443 rulePaths
: [getFixturePath("rules", "wrong")],
1444 overrideConfigFile
: getFixturePath("rules", "eslint.json")
1448 await assert
.rejects(async () => {
1449 await eslint
.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
1450 }, /Error while loading rule 'custom-rule'/u);
1453 it("should return one message when a custom rule matches a file", async () => {
1454 eslint
= new ESLint({
1457 rulePaths
: [getFixturePath("rules/")],
1458 overrideConfigFile
: getFixturePath("rules", "eslint.json")
1460 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1461 const results
= await eslint
.lintFiles([filePath
]);
1463 assert
.strictEqual(results
.length
, 1);
1464 assert
.strictEqual(results
[0].filePath
, filePath
);
1465 assert
.strictEqual(results
[0].messages
.length
, 2);
1466 assert
.strictEqual(results
[0].messages
[0].ruleId
, "custom-rule");
1467 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1470 it("should load custom rule from the provided cwd", async () => {
1471 const cwd
= path
.resolve(getFixturePath("rules"));
1473 eslint
= new ESLint({
1477 overrideConfigFile
: "eslint.json"
1479 const filePath
= fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
1480 const results
= await eslint
.lintFiles([filePath
]);
1482 assert
.strictEqual(results
.length
, 1);
1483 assert
.strictEqual(results
[0].filePath
, filePath
);
1484 assert
.strictEqual(results
[0].messages
.length
, 2);
1485 assert
.strictEqual(results
[0].messages
[0].ruleId
, "custom-rule");
1486 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1489 it("should return messages when multiple custom rules match a file", async () => {
1490 eslint
= new ESLint({
1493 getFixturePath("rules", "dir1"),
1494 getFixturePath("rules", "dir2")
1496 overrideConfigFile
: getFixturePath("rules", "multi-rulesdirs.json")
1498 const filePath
= fs
.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.js"));
1499 const results
= await eslint
.lintFiles([filePath
]);
1501 assert
.strictEqual(results
.length
, 1);
1502 assert
.strictEqual(results
[0].filePath
, filePath
);
1503 assert
.strictEqual(results
[0].messages
.length
, 2);
1504 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-literals");
1505 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1506 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-strings");
1507 assert
.strictEqual(results
[0].messages
[1].severity
, 2);
1510 it("should return zero messages when executing without useEslintrc flag", async () => {
1511 eslint
= new ESLint({
1515 const filePath
= fs
.realpathSync(getFixturePath("missing-semicolon.js"));
1516 const results
= await eslint
.lintFiles([filePath
]);
1518 assert
.strictEqual(results
.length
, 1);
1519 assert
.strictEqual(results
[0].filePath
, filePath
);
1520 assert
.strictEqual(results
[0].messages
.length
, 0);
1523 it("should return zero messages when executing without useEslintrc flag in Node.js environment", async () => {
1524 eslint
= new ESLint({
1531 const filePath
= fs
.realpathSync(getFixturePath("process-exit.js"));
1532 const results
= await eslint
.lintFiles([filePath
]);
1534 assert
.strictEqual(results
.length
, 1);
1535 assert
.strictEqual(results
[0].filePath
, filePath
);
1536 assert
.strictEqual(results
[0].messages
.length
, 0);
1539 it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", async () => {
1540 eslint
= new ESLint({
1547 const filePath
= fs
.realpathSync(getFixturePath("eslintrc", "quotes.js"));
1548 const results
= await eslint
.lintFiles([filePath
]);
1550 assert
.strictEqual(results
.length
, 1);
1551 assert
.strictEqual(results
[0].filePath
, filePath
);
1552 assert
.strictEqual(results
[0].messages
.length
, 0);
1555 it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", async () => {
1556 eslint
= new ESLint({
1563 const filePath
= fs
.realpathSync(getFixturePath("packagejson", "quotes.js"));
1564 const results
= await eslint
.lintFiles([filePath
]);
1566 assert
.strictEqual(results
.length
, 1);
1567 assert
.strictEqual(results
[0].filePath
, filePath
);
1568 assert
.strictEqual(results
[0].messages
.length
, 0);
1571 it("should warn when deprecated rules are configured", async () => {
1572 eslint
= new ESLint({
1574 overrideConfigFile
: ".eslintrc.js",
1583 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1585 assert
.deepStrictEqual(
1586 results
[0].usedDeprecatedRules
,
1588 { ruleId
: "indent-legacy", replacedBy
: ["indent"] },
1589 { ruleId
: "require-jsdoc", replacedBy
: [] },
1590 { ruleId
: "valid-jsdoc", replacedBy
: [] }
1595 it("should not warn when deprecated rules are not configured", async () => {
1596 eslint
= new ESLint({
1598 overrideConfigFile
: ".eslintrc.js",
1600 rules
: { indent
: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
1603 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1605 assert
.deepStrictEqual(results
[0].usedDeprecatedRules
, []);
1608 it("should warn when deprecated rules are found in a config", async () => {
1609 eslint
= new ESLint({
1611 overrideConfigFile
: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
1614 const results
= await eslint
.lintFiles(["lib/cli*.js"]);
1616 assert
.deepStrictEqual(
1617 results
[0].usedDeprecatedRules
,
1618 [{ ruleId
: "indent-legacy", replacedBy
: ["indent"] }]
1622 describe("Fix Mode", () => {
1623 it("should return fixed text on multiple files when in fix mode", async () => {
1626 * Converts CRLF to LF in output.
1627 * This is a workaround for git's autocrlf option on Windows.
1628 * @param {Object} result A result object to convert.
1631 function convertCRLF(result
) {
1632 if (result
&& result
.output
) {
1633 result
.output
= result
.output
.replace(/\r\n/gu, "\n");
1637 eslint
= new ESLint({
1638 cwd
: path
.join(fixtureDir
, ".."),
1644 quotes
: [2, "double"],
1647 "space-infix-ops": 2
1651 const results
= await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1653 results
.forEach(convertCRLF
);
1654 assert
.deepStrictEqual(results
, [
1656 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/multipass.js")),
1660 fixableErrorCount
: 0,
1661 fixableWarningCount
: 0,
1662 output
: "true ? \"yes\" : \"no\";\n",
1663 usedDeprecatedRules
: []
1666 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/ok.js")),
1670 fixableErrorCount
: 0,
1671 fixableWarningCount
: 0,
1672 usedDeprecatedRules
: []
1675 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes-semi-eqeqeq.js")),
1682 message
: "Expected '===' and instead saw '=='.",
1683 messageId
: "unexpected",
1684 nodeType
: "BinaryExpression",
1691 fixableErrorCount
: 0,
1692 fixableWarningCount
: 0,
1693 output
: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n",
1694 usedDeprecatedRules
: []
1697 filePath
: fs
.realpathSync(path
.resolve(fixtureDir
, "fixmode/quotes.js")),
1705 message
: "'foo' is not defined.",
1706 nodeType
: "Identifier",
1713 fixableErrorCount
: 0,
1714 fixableWarningCount
: 0,
1715 output
: "var msg = \"hi\" + foo;\n",
1716 usedDeprecatedRules
: []
1721 it("should run autofix even if files are cached without autofix results", async () => {
1722 const baseOptions
= {
1723 cwd
: path
.join(fixtureDir
, ".."),
1728 quotes
: [2, "double"],
1731 "space-infix-ops": 2
1736 eslint
= new ESLint(Object
.assign({}, baseOptions
, { cache
: true, fix
: false }));
1738 // Do initial lint run and populate the cache file
1739 await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1741 eslint
= new ESLint(Object
.assign({}, baseOptions
, { cache
: true, fix
: true }));
1742 const results
= await eslint
.lintFiles([path
.resolve(fixtureDir
, `${fixtureDir}/fixmode`)]);
1744 assert(results
.some(result
=> result
.output
));
1748 // These tests have to do with https://github.com/eslint/eslint/issues/963
1750 describe("configuration hierarchy", () => {
1752 // Default configuration - blank
1753 it("should return zero messages when executing with no .eslintrc", async () => {
1754 eslint
= new ESLint({
1755 cwd
: path
.join(fixtureDir
, ".."),
1758 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1760 assert
.strictEqual(results
.length
, 1);
1761 assert
.strictEqual(results
[0].messages
.length
, 0);
1764 // No default configuration rules - conf/environments.js (/*eslint-env node*/)
1765 it("should return zero messages when executing with no .eslintrc in the Node.js environment", async () => {
1766 eslint
= new ESLint({
1767 cwd
: path
.join(fixtureDir
, ".."),
1770 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
1772 assert
.strictEqual(results
.length
, 1);
1773 assert
.strictEqual(results
[0].messages
.length
, 0);
1776 // Project configuration - first level .eslintrc
1777 it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
1778 eslint
= new ESLint({
1779 cwd
: path
.join(fixtureDir
, "..")
1781 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1783 assert
.strictEqual(results
.length
, 1);
1784 assert
.strictEqual(results
[0].messages
.length
, 0);
1787 // Project configuration - first level .eslintrc
1788 it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
1789 eslint
= new ESLint({
1790 cwd
: path
.join(fixtureDir
, "..")
1792 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
1794 assert
.strictEqual(results
.length
, 1);
1795 assert
.strictEqual(results
[0].messages
.length
, 0);
1798 // Project configuration - first level .eslintrc
1799 it("should return one message when executing with .eslintrc", async () => {
1800 eslint
= new ESLint({
1801 cwd
: path
.join(fixtureDir
, "..")
1803 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1805 assert
.strictEqual(results
.length
, 1);
1806 assert
.strictEqual(results
[0].messages
.length
, 1);
1807 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1808 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1811 // Project configuration - second level .eslintrc
1812 it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", async () => {
1813 eslint
= new ESLint({
1814 cwd
: path
.join(fixtureDir
, "..")
1816 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1818 assert
.strictEqual(results
.length
, 1);
1819 assert
.strictEqual(results
[0].messages
.length
, 1);
1820 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1821 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1824 // Project configuration - third level .eslintrc
1825 it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", async () => {
1826 eslint
= new ESLint({
1827 cwd
: path
.join(fixtureDir
, "..")
1829 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
1831 assert
.strictEqual(results
.length
, 1);
1832 assert
.strictEqual(results
[0].messages
.length
, 1);
1833 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1834 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1837 // Project configuration - first level package.json
1838 it("should return one message when executing with package.json", async () => {
1839 eslint
= new ESLint({
1840 cwd
: path
.join(fixtureDir
, "..")
1842 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
1844 assert
.strictEqual(results
.length
, 1);
1845 assert
.strictEqual(results
[0].messages
.length
, 1);
1846 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1847 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1850 // Project configuration - second level package.json
1851 it("should return zero messages when executing with local package.json that overrides parent package.json", async () => {
1852 eslint
= new ESLint({
1853 cwd
: path
.join(fixtureDir
, "..")
1855 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
1857 assert
.strictEqual(results
.length
, 1);
1858 assert
.strictEqual(results
[0].messages
.length
, 0);
1861 // Project configuration - third level package.json
1862 it("should return one message when executing with local package.json that overrides parent and grandparent package.json", async () => {
1863 eslint
= new ESLint({
1864 cwd
: path
.join(fixtureDir
, "..")
1866 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
1868 assert
.strictEqual(results
.length
, 1);
1869 assert
.strictEqual(results
[0].messages
.length
, 1);
1870 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1871 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1874 // Project configuration - .eslintrc overrides package.json in same directory
1875 it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", async () => {
1876 eslint
= new ESLint({
1877 cwd
: path
.join(fixtureDir
, "..")
1879 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
1881 assert
.strictEqual(results
.length
, 1);
1882 assert
.strictEqual(results
[0].messages
.length
, 1);
1883 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1884 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1887 // Command line configuration - --config with first level .eslintrc
1888 it("should return two messages when executing with config file that adds to local .eslintrc", async () => {
1889 eslint
= new ESLint({
1890 cwd
: path
.join(fixtureDir
, ".."),
1891 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1893 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1895 assert
.strictEqual(results
.length
, 1);
1896 assert
.strictEqual(results
[0].messages
.length
, 2);
1897 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1898 assert
.strictEqual(results
[0].messages
[0].severity
, 2);
1899 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi");
1900 assert
.strictEqual(results
[0].messages
[1].severity
, 1);
1903 // Command line configuration - --config with first level .eslintrc
1904 it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
1905 eslint
= new ESLint({
1906 cwd
: path
.join(fixtureDir
, ".."),
1907 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1909 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1911 assert
.strictEqual(results
.length
, 1);
1912 assert
.strictEqual(results
[0].messages
.length
, 0);
1915 // Command line configuration - --config with second level .eslintrc
1916 it("should return two messages when executing with config file that adds to local and parent .eslintrc", async () => {
1917 eslint
= new ESLint({
1918 cwd
: path
.join(fixtureDir
, ".."),
1919 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
1921 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1923 assert
.strictEqual(results
.length
, 1);
1924 assert
.strictEqual(results
[0].messages
.length
, 2);
1925 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1926 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1927 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi");
1928 assert
.strictEqual(results
[0].messages
[1].severity
, 1);
1931 // Command line configuration - --config with second level .eslintrc
1932 it("should return one message when executing with config file that overrides local and parent .eslintrc", async () => {
1933 eslint
= new ESLint({
1934 cwd
: path
.join(fixtureDir
, ".."),
1935 overrideConfigFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml")
1937 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
1939 assert
.strictEqual(results
.length
, 1);
1940 assert
.strictEqual(results
[0].messages
.length
, 1);
1941 assert
.strictEqual(results
[0].messages
[0].ruleId
, "no-console");
1942 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1945 // Command line configuration - --config with first level .eslintrc
1946 it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
1947 eslint
= new ESLint({
1948 cwd
: path
.join(fixtureDir
, ".."),
1949 overrideConfigFile
: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
1951 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1953 assert
.strictEqual(results
.length
, 1);
1954 assert
.strictEqual(results
[0].messages
.length
, 0);
1957 // Command line configuration - --rule with --config and first level .eslintrc
1958 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
1959 eslint
= new ESLint({
1960 cwd
: path
.join(fixtureDir
, ".."),
1961 overrideConfigFile
: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
1964 quotes
: [1, "double"]
1968 const results
= await eslint
.lintFiles([fs
.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
1970 assert
.strictEqual(results
.length
, 1);
1971 assert
.strictEqual(results
[0].messages
.length
, 1);
1972 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1973 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1976 // Command line configuration - --rule with --config and first level .eslintrc
1977 it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
1978 eslint
= new ESLint({
1979 cwd
: path
.join(fixtureDir
, ".."),
1980 overrideConfigFile
: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
1983 quotes
: [1, "double"]
1987 const results
= await eslint
.lintFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
1989 assert
.strictEqual(results
.length
, 1);
1990 assert
.strictEqual(results
[0].messages
.length
, 1);
1991 assert
.strictEqual(results
[0].messages
[0].ruleId
, "quotes");
1992 assert
.strictEqual(results
[0].messages
[0].severity
, 1);
1996 describe("plugins", () => {
1997 it("should return two messages when executing with config file that specifies a plugin", async () => {
1998 eslint
= eslintWithPlugins({
1999 cwd
: path
.join(fixtureDir
, ".."),
2000 overrideConfigFile
: getFixturePath("configurations", "plugins-with-prefix.json"),
2003 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
2005 assert
.strictEqual(results
.length
, 1);
2006 assert
.strictEqual(results
[0].messages
.length
, 2);
2007 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2010 it("should return two messages when executing with config file that specifies a plugin with namespace", async () => {
2011 eslint
= eslintWithPlugins({
2012 cwd
: path
.join(fixtureDir
, ".."),
2013 overrideConfigFile
: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
2016 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2018 assert
.strictEqual(results
.length
, 1);
2019 assert
.strictEqual(results
[0].messages
.length
, 2);
2020 assert
.strictEqual(results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2023 it("should return two messages when executing with config file that specifies a plugin without prefix", async () => {
2024 eslint
= eslintWithPlugins({
2025 cwd
: path
.join(fixtureDir
, ".."),
2026 overrideConfigFile
: getFixturePath("configurations", "plugins-without-prefix.json"),
2029 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2031 assert
.strictEqual(results
.length
, 1);
2032 assert
.strictEqual(results
[0].messages
.length
, 2);
2033 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2036 it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", async () => {
2037 eslint
= eslintWithPlugins({
2038 cwd
: path
.join(fixtureDir
, ".."),
2039 overrideConfigFile
: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
2042 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2044 assert
.strictEqual(results
.length
, 1);
2045 assert
.strictEqual(results
[0].messages
.length
, 2);
2046 assert
.strictEqual(results
[0].messages
[0].ruleId
, "@eslint/example/example-rule");
2049 it("should return two messages when executing with cli option that specifies a plugin", async () => {
2050 eslint
= eslintWithPlugins({
2051 cwd
: path
.join(fixtureDir
, ".."),
2054 plugins
: ["example"],
2055 rules
: { "example/example-rule": 1 }
2058 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2060 assert
.strictEqual(results
.length
, 1);
2061 assert
.strictEqual(results
[0].messages
.length
, 2);
2062 assert
.strictEqual(results
[0].messages
[0].ruleId
, "example/example-rule");
2065 it("should return two messages when executing with cli option that specifies preloaded plugin", async () => {
2066 eslint
= new ESLint({
2067 cwd
: path
.join(fixtureDir
, ".."),
2071 rules
: { "test/example-rule": 1 }
2074 "eslint-plugin-test": { rules
: { "example-rule": require("../../fixtures/rules/custom-rule") } }
2077 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
2079 assert
.strictEqual(results
.length
, 1);
2080 assert
.strictEqual(results
[0].messages
.length
, 2);
2081 assert
.strictEqual(results
[0].messages
[0].ruleId
, "test/example-rule");
2084 it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", async () => {
2085 eslint
= new ESLint({
2086 resolvePluginsRelativeTo
: getFixturePath("plugins"),
2088 plugins
: ["with-rules"],
2089 rules
: { "with-rules/rule1": "error" }
2093 const results
= await eslint
.lintText("foo");
2095 assert
.strictEqual(results
.length
, 1);
2096 assert
.strictEqual(results
[0].messages
.length
, 1);
2097 assert
.strictEqual(results
[0].messages
[0].ruleId
, "with-rules/rule1");
2098 assert
.strictEqual(results
[0].messages
[0].message
, "Rule report from plugin");
2102 describe("cache", () => {
2105 * helper method to delete a file without caring about exceptions
2106 * @param {string} filePath The file path
2109 function doDelete(filePath
) {
2111 fs
.unlinkSync(filePath
);
2115 * we don't care if the file didn't exist, since our
2116 * intention was to remove the file
2122 * helper method to delete the cache files created during testing
2125 function deleteCache() {
2126 doDelete(path
.resolve(".eslintcache"));
2127 doDelete(path
.resolve(".cache/custom-cache"));
2139 describe("when the cacheFile is a directory or looks like a directory", () => {
2142 * helper method to delete the cache files created during testing
2145 function deleteCacheDir() {
2147 fs
.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
2151 * we don't care if the file didn't exist, since our
2152 * intention was to remove the file
2164 it("should create the cache file inside the provided directory", async () => {
2165 assert(!shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2167 eslint
= new ESLint({
2170 // specifying cache true the cache will be created
2172 cacheLocation
: "./tmp/.cacheFileDir/",
2182 const file
= getFixturePath("cache/src", "test-file.js");
2184 await eslint
.lintFiles([file
]);
2186 assert(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2192 it("should create the cache file inside the provided directory using the cacheLocation option", async () => {
2193 assert(!shell
.test("-d", path
.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
2195 eslint
= new ESLint({
2198 // specifying cache true the cache will be created
2200 cacheLocation
: "./tmp/.cacheFileDir/",
2210 const file
= getFixturePath("cache/src", "test-file.js");
2212 await eslint
.lintFiles([file
]);
2214 assert(shell
.test("-f", path
.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
2219 it("should create the cache file inside cwd when no cacheLocation provided", async () => {
2220 const cwd
= path
.resolve(getFixturePath("cli-engine"));
2222 eslint
= new ESLint({
2234 const file
= getFixturePath("cli-engine", "console.js");
2236 await eslint
.lintFiles([file
]);
2238 assert(shell
.test("-f", path
.resolve(cwd
, ".eslintcache")), "the cache for eslint was created at provided cwd");
2241 it("should invalidate the cache if the configuration changed between executions", async () => {
2242 assert(!shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2244 eslint
= new ESLint({
2247 // specifying cache true the cache will be created
2259 let spy
= sinon
.spy(fs
, "readFileSync");
2261 let file
= getFixturePath("cache/src", "test-file.js");
2263 file
= fs
.realpathSync(file
);
2264 const results
= await eslint
.lintFiles([file
]);
2266 for (const { errorCount
, warningCount
} of results
) {
2267 assert
.strictEqual(errorCount
+ warningCount
, 0, "the file passed without errors or warnings");
2269 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2270 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2275 eslint
= new ESLint({
2278 // specifying cache true the cache will be created
2291 spy
= sinon
.spy(fs
, "readFileSync");
2293 const [cachedResult
] = await eslint
.lintFiles([file
]);
2295 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed because the config changed");
2296 assert
.strictEqual(cachedResult
.errorCount
, 1, "since configuration changed the cache was not used an one error was reported");
2297 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2300 it("should remember the files from a previous run and do not operate on them if not changed", async () => {
2301 assert(!shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint does not exist");
2303 eslint
= new ESLint({
2306 // specifying cache true the cache will be created
2318 let spy
= sinon
.spy(fs
, "readFileSync");
2320 let file
= getFixturePath("cache/src", "test-file.js");
2322 file
= fs
.realpathSync(file
);
2324 const result
= await eslint
.lintFiles([file
]);
2326 assert
.strictEqual(spy
.getCall(0).args
[0], file
, "the module read the file because is considered changed");
2327 assert(shell
.test("-f", path
.resolve(".eslintcache")), "the cache for eslint was created");
2332 eslint
= new ESLint({
2335 // specifying cache true the cache will be created
2348 spy
= sinon
.spy(fs
, "readFileSync");
2350 const cachedResult
= await eslint
.lintFiles([file
]);
2352 assert
.deepStrictEqual(result
, cachedResult
, "the result is the same regardless of using cache or not");
2354 // assert the file was not processed because the cache was used
2355 assert(!spy
.calledWith(file
), "the file was not loaded because it used the cache");
2358 it("should remember the files from a previous run and do not operate on then if not changed", async () => {
2359 const cacheLocation
= getFixturePath(".eslintcache");
2360 const eslintOptions
= {
2363 // specifying cache true the cache will be created
2373 cwd
: path
.join(fixtureDir
, "..")
2376 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint does not exist");
2378 eslint
= new ESLint(eslintOptions
);
2380 let file
= getFixturePath("cache/src", "test-file.js");
2382 file
= fs
.realpathSync(file
);
2384 await eslint
.lintFiles([file
]);
2386 assert(shell
.test("-f", cacheLocation
), "the cache for eslint was created");
2388 eslintOptions
.cache
= false;
2389 eslint
= new ESLint(eslintOptions
);
2391 await eslint
.lintFiles([file
]);
2393 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint was deleted since last run did not used the cache");
2396 it("should store in the cache a file that failed the test", async () => {
2397 const cacheLocation
= getFixturePath(".eslintcache");
2399 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint does not exist");
2401 eslint
= new ESLint({
2402 cwd
: path
.join(fixtureDir
, ".."),
2405 // specifying cache true the cache will be created
2416 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2417 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2418 const result
= await eslint
.lintFiles([badFile
, goodFile
]);
2420 assert(shell
.test("-f", cacheLocation
), "the cache for eslint was created");
2421 const fileCache
= fCache
.createFromFile(cacheLocation
);
2422 const { cache
} = fileCache
;
2424 assert
.strictEqual(typeof cache
.getKey(goodFile
), "object", "the entry for the good file is in the cache");
2425 assert
.strictEqual(typeof cache
.getKey(badFile
), "object", "the entry for the bad file is in the cache");
2426 const cachedResult
= await eslint
.lintFiles([badFile
, goodFile
]);
2428 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2431 it("should not contain in the cache a file that was deleted", async () => {
2432 const cacheLocation
= getFixturePath(".eslintcache");
2434 doDelete(cacheLocation
);
2436 eslint
= new ESLint({
2437 cwd
: path
.join(fixtureDir
, ".."),
2440 // specifying cache true the cache will be created
2451 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2452 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2453 const toBeDeletedFile
= fs
.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
2455 await eslint
.lintFiles([badFile
, goodFile
, toBeDeletedFile
]);
2456 const fileCache
= fCache
.createFromFile(cacheLocation
);
2457 let { cache
} = fileCache
;
2459 assert
.strictEqual(typeof cache
.getKey(toBeDeletedFile
), "object", "the entry for the file to be deleted is in the cache");
2461 // delete the file from the file system
2462 fs
.unlinkSync(toBeDeletedFile
);
2465 * file-entry-cache@2.0.0 will remove from the cache deleted files
2466 * even when they were not part of the array of files to be analyzed
2468 await eslint
.lintFiles([badFile
, goodFile
]);
2470 cache
= JSON
.parse(fs
.readFileSync(cacheLocation
));
2472 assert
.strictEqual(typeof cache
[toBeDeletedFile
], "undefined", "the entry for the file to be deleted is not in the cache");
2475 it("should contain files that were not visited in the cache provided they still exist", async () => {
2476 const cacheLocation
= getFixturePath(".eslintcache");
2478 doDelete(cacheLocation
);
2480 eslint
= new ESLint({
2481 cwd
: path
.join(fixtureDir
, ".."),
2484 // specifying cache true the cache will be created
2495 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2496 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2497 const testFile2
= fs
.realpathSync(getFixturePath("cache/src", "test-file2.js"));
2499 await eslint
.lintFiles([badFile
, goodFile
, testFile2
]);
2501 let fileCache
= fCache
.createFromFile(cacheLocation
);
2502 let { cache
} = fileCache
;
2504 assert
.strictEqual(typeof cache
.getKey(testFile2
), "object", "the entry for the test-file2 is in the cache");
2507 * we pass a different set of files minus test-file2
2508 * previous version of file-entry-cache would remove the non visited
2509 * entries. 2.0.0 version will keep them unless they don't exist
2511 await eslint
.lintFiles([badFile
, goodFile
]);
2513 fileCache
= fCache
.createFromFile(cacheLocation
);
2514 cache
= fileCache
.cache
;
2516 assert
.strictEqual(typeof cache
.getKey(testFile2
), "object", "the entry for the test-file2 is in the cache");
2519 it("should not delete cache when executing on text", async () => {
2520 const cacheLocation
= getFixturePath(".eslintcache");
2522 eslint
= new ESLint({
2523 cwd
: path
.join(fixtureDir
, ".."),
2535 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2537 await eslint
.lintText("var foo = 'bar';");
2539 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2542 it("should not delete cache when executing on text with a provided filename", async () => {
2543 const cacheLocation
= getFixturePath(".eslintcache");
2545 eslint
= new ESLint({
2546 cwd
: path
.join(fixtureDir
, ".."),
2558 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2560 await eslint
.lintText("var bar = foo;", { filePath
: "fixtures/passing.js" });
2562 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2565 it("should not delete cache when executing on files with --cache flag", async () => {
2566 const cacheLocation
= getFixturePath(".eslintcache");
2568 eslint
= new ESLint({
2569 cwd
: path
.join(fixtureDir
, ".."),
2581 const file
= getFixturePath("cli-engine", "console.js");
2583 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2585 await eslint
.lintFiles([file
]);
2587 assert(shell
.test("-f", cacheLocation
), "the cache for eslint still exists");
2590 it("should delete cache when executing on files without --cache flag", async () => {
2591 const cacheLocation
= getFixturePath(".eslintcache");
2593 eslint
= new ESLint({
2594 cwd
: path
.join(fixtureDir
, ".."),
2605 const file
= getFixturePath("cli-engine", "console.js");
2607 assert(shell
.test("-f", cacheLocation
), "the cache for eslint exists");
2609 await eslint
.lintFiles([file
]);
2611 assert(!shell
.test("-f", cacheLocation
), "the cache for eslint has been deleted");
2614 describe("cacheFile", () => {
2615 it("should use the specified cache file", async () => {
2616 const customCacheFile
= path
.resolve(".cache/custom-cache");
2618 assert(!shell
.test("-f", customCacheFile
), "the cache for eslint does not exist");
2620 eslint
= new ESLint({
2623 // specify a custom cache file
2624 cacheLocation
: customCacheFile
,
2626 // specifying cache true the cache will be created
2635 cwd
: path
.join(fixtureDir
, "..")
2637 const badFile
= fs
.realpathSync(getFixturePath("cache/src", "fail-file.js"));
2638 const goodFile
= fs
.realpathSync(getFixturePath("cache/src", "test-file.js"));
2639 const result
= await eslint
.lintFiles([badFile
, goodFile
]);
2641 assert(shell
.test("-f", customCacheFile
), "the cache for eslint was created");
2642 const fileCache
= fCache
.createFromFile(customCacheFile
);
2643 const { cache
} = fileCache
;
2645 assert(typeof cache
.getKey(goodFile
) === "object", "the entry for the good file is in the cache");
2647 assert(typeof cache
.getKey(badFile
) === "object", "the entry for the bad file is in the cache");
2648 const cachedResult
= await eslint
.lintFiles([badFile
, goodFile
]);
2650 assert
.deepStrictEqual(result
, cachedResult
, "result is the same with or without cache");
2655 describe("processors", () => {
2656 it("should return two messages when executing with config file that specifies a processor", async () => {
2657 eslint
= eslintWithPlugins({
2658 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2660 extensions
: ["js", "txt"],
2661 cwd
: path
.join(fixtureDir
, "..")
2663 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2665 assert
.strictEqual(results
.length
, 1);
2666 assert
.strictEqual(results
[0].messages
.length
, 2);
2669 it("should return two messages when executing with config file that specifies preloaded processor", async () => {
2670 eslint
= new ESLint({
2673 plugins
: ["test-processor"],
2679 extensions
: ["js", "txt"],
2680 cwd
: path
.join(fixtureDir
, ".."),
2688 postprocess(messages
) {
2696 const results
= await eslint
.lintFiles([fs
.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
2698 assert
.strictEqual(results
.length
, 1);
2699 assert
.strictEqual(results
[0].messages
.length
, 2);
2702 it("should run processors when calling lintFiles with config file that specifies a processor", async () => {
2703 eslint
= eslintWithPlugins({
2704 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2706 extensions
: ["js", "txt"],
2707 cwd
: path
.join(fixtureDir
, "..")
2709 const results
= await eslint
.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2711 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2712 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2715 it("should run processors when calling lintFiles with config file that specifies preloaded processor", async () => {
2716 eslint
= new ESLint({
2719 plugins
: ["test-processor"],
2725 extensions
: ["js", "txt"],
2726 cwd
: path
.join(fixtureDir
, ".."),
2732 return [text
.replace("a()", "b()")];
2734 postprocess(messages
) {
2735 messages
[0][0].ruleId
= "post-processed";
2743 const results
= await eslint
.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
2745 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2746 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2749 it("should run processors when calling lintText with config file that specifies a processor", async () => {
2750 eslint
= eslintWithPlugins({
2751 overrideConfigFile
: getFixturePath("configurations", "processors.json"),
2753 extensions
: ["js", "txt"],
2756 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
2758 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2759 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2762 it("should run processors when calling lintText with config file that specifies preloaded processor", async () => {
2763 eslint
= new ESLint({
2766 plugins
: ["test-processor"],
2772 extensions
: ["js", "txt"],
2779 return [text
.replace("a()", "b()")];
2781 postprocess(messages
) {
2782 messages
[0][0].ruleId
= "post-processed";
2790 const results
= await eslint
.lintText("function a() {console.log(\"Test\");}", { filePath
: "tests/fixtures/processors/test/test-processor.txt" });
2792 assert
.strictEqual(results
[0].messages
[0].message
, "'b' is defined but never used.");
2793 assert
.strictEqual(results
[0].messages
[0].ruleId
, "post-processed");
2796 describe("autofixing with processors", () => {
2797 const HTML_PROCESSOR
= Object
.freeze({
2799 return [text
.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
2801 postprocess(problemLists
) {
2802 return problemLists
[0].map(problem
=> {
2804 const updatedFix
= Object
.assign({}, problem
.fix
, {
2805 range
: problem
.fix
.range
.map(index
=> index
+ "<script>".length
)
2808 return Object
.assign({}, problem
, { fix
: updatedFix
});
2816 it("should run in autofix mode when using a processor that supports autofixing", async () => {
2817 eslint
= new ESLint({
2820 plugins
: ["test-processor"],
2825 extensions
: ["js", "txt"],
2831 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2836 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
2838 assert
.strictEqual(results
[0].messages
.length
, 0);
2839 assert
.strictEqual(results
[0].output
, "<script>foo;</script>");
2842 it("should not run in autofix mode when using a processor that does not support autofixing", async () => {
2843 eslint
= new ESLint({
2846 plugins
: ["test-processor"],
2851 extensions
: ["js", "txt"],
2855 "test-processor": { processors
: { ".html": HTML_PROCESSOR
} }
2858 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
2860 assert
.strictEqual(results
[0].messages
.length
, 1);
2861 assert(!Object
.prototype.hasOwnProperty
.call(results
[0], "output"));
2864 it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", async () => {
2865 eslint
= new ESLint({
2868 plugins
: ["test-processor"],
2873 extensions
: ["js", "txt"],
2878 ".html": Object
.assign({ supportsAutofix
: true }, HTML_PROCESSOR
)
2883 const results
= await eslint
.lintText("<script>foo</script>", { filePath
: "foo.html" });
2885 assert
.strictEqual(results
[0].messages
.length
, 1);
2886 assert(!Object
.prototype.hasOwnProperty
.call(results
[0], "output"));
2891 describe("Patterns which match no file should throw errors.", () => {
2893 eslint
= new ESLint({
2894 cwd
: getFixturePath("cli-engine"),
2899 it("one file", async () => {
2900 await assert
.rejects(async () => {
2901 await eslint
.lintFiles(["non-exist.js"]);
2902 }, /No files matching 'non-exist\.js' were found\./u);
2905 it("should throw if the directory exists and is empty", async () => {
2906 await assert
.rejects(async () => {
2907 await eslint
.lintFiles(["empty"]);
2908 }, /No files matching 'empty' were found\./u);
2911 it("one glob pattern", async () => {
2912 await assert
.rejects(async () => {
2913 await eslint
.lintFiles(["non-exist/**/*.js"]);
2914 }, /No files matching 'non-exist\/\*\*\/\*\.js' were found\./u);
2917 it("two files", async () => {
2918 await assert
.rejects(async () => {
2919 await eslint
.lintFiles(["aaa.js", "bbb.js"]);
2920 }, /No files matching 'aaa\.js' were found\./u);
2923 it("a mix of an existing file and a non-existing file", async () => {
2924 await assert
.rejects(async () => {
2925 await eslint
.lintFiles(["console.js", "non-exist.js"]);
2926 }, /No files matching 'non-exist\.js' were found\./u);
2930 describe("overrides", () => {
2932 eslint
= new ESLint({
2933 cwd
: getFixturePath("cli-engine/overrides-with-dot"),
2938 it("should recognize dotfiles", async () => {
2939 const ret
= await eslint
.lintFiles([".test-target.js"]);
2941 assert
.strictEqual(ret
.length
, 1);
2942 assert
.strictEqual(ret
[0].messages
.length
, 1);
2943 assert
.strictEqual(ret
[0].messages
[0].ruleId
, "no-unused-vars");
2947 describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
2949 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
2950 cwd
: path
.join(os
.tmpdir(), "eslint/11510"),
2952 "no-console-error-in-overrides.json": JSON
.stringify({
2955 rules
: { "no-console": "error" }
2958 ".eslintrc.json": JSON
.stringify({
2959 extends: "./no-console-error-in-overrides.json",
2960 rules
: { "no-console": "off" }
2962 "a.js": "console.log();"
2967 eslint
= new ESLint({ cwd
: getPath() });
2973 it("should not report 'no-console' error.", async () => {
2974 const results
= await eslint
.lintFiles("a.js");
2976 assert
.strictEqual(results
.length
, 1);
2977 assert
.deepStrictEqual(results
[0].messages
, []);
2981 describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
2983 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
2984 cwd
: path
.join(os
.tmpdir(), "eslint/11559"),
2986 "node_modules/eslint-plugin-test/index.js": `
2988 recommended: { plugins: ["test"] }
2992 meta: { schema: [{ type: "number" }] },
2993 create() { return {}; }
2997 ".eslintrc.json": JSON
.stringify({
2999 // Import via the recommended config.
3000 extends: "plugin:test/recommended",
3002 // Has invalid option.
3003 rules
: { "test/foo": ["error", "invalid-option"] }
3005 "a.js": "console.log();"
3010 eslint
= new ESLint({ cwd
: getPath() });
3017 it("should throw fatal error.", async () => {
3018 await assert
.rejects(async () => {
3019 await eslint
.lintFiles("a.js");
3020 }, /invalid-option/u);
3024 describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
3025 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3026 cwd
: path
.join(os
.tmpdir(), "cli-engine/11586"),
3028 "node_modules/eslint-plugin-test/index.js": `
3031 meta: { type: "problem", fixable: "code" },
3035 if (node.name === "example") {
3039 fix: fixer => fixer.replaceText(node, "fixed")
3050 rules
: { "test/no-example": "error" }
3057 eslint
= new ESLint({
3060 fixTypes
: ["problem"]
3068 it("should not crash.", async () => {
3069 const results
= await eslint
.lintFiles("a.js");
3071 assert
.strictEqual(results
.length
, 1);
3072 assert
.deepStrictEqual(results
[0].messages
, []);
3073 assert
.deepStrictEqual(results
[0].output
, "fixed;");
3077 describe("multiple processors", () => {
3078 const root
= path
.join(os
.tmpdir(), "eslint/eslint/multiple-processors");
3079 const commonFiles
= {
3080 "node_modules/pattern-processor/index.js": fs
.readFileSync(
3081 require
.resolve("../../fixtures/processors/pattern-processor"),
3084 "node_modules/eslint-plugin-markdown/index.js": `
3085 const { defineProcessor } = require("pattern-processor");
3086 const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
3087 exports.processors = {
3088 ".md": { ...processor, supportsAutofix: true },
3089 "non-fixable": processor
3092 "node_modules/eslint-plugin-html/index.js": `
3093 const { defineProcessor } = require("pattern-processor");
3094 const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
3095 const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
3096 exports.processors = {
3097 ".html": { ...processor, supportsAutofix: true },
3098 "non-fixable": processor,
3099 "legacy": legacyProcessor
3102 "test.md": unIndent
`
3104 console
.log("hello")
3109 console
.log("hello")
3112 console
.log("hello")
3121 cleanup
= () => { };
3124 afterEach(() => cleanup());
3126 it("should lint only JavaScript blocks if '--ext' was not given.", async () => {
3127 const teardown
= createCustomTeardown({
3132 plugins
: ["markdown", "html"],
3133 rules
: { semi
: "error" }
3138 cleanup
= teardown
.cleanup
;
3139 await teardown
.prepare();
3140 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3141 const results
= await eslint
.lintFiles(["test.md"]);
3143 assert
.strictEqual(results
.length
, 1);
3144 assert
.strictEqual(results
[0].messages
.length
, 1);
3145 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3146 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3149 it("should fix only JavaScript blocks if '--ext' was not given.", async () => {
3150 const teardown
= createCustomTeardown({
3155 plugins
: ["markdown", "html"],
3156 rules
: { semi
: "error" }
3161 await teardown
.prepare();
3162 cleanup
= teardown
.cleanup
;
3163 eslint
= new ESLint({ cwd
: teardown
.getPath(), fix
: true });
3164 const results
= await eslint
.lintFiles(["test.md"]);
3166 assert
.strictEqual(results
.length
, 1);
3167 assert
.strictEqual(results
[0].messages
.length
, 0);
3168 assert
.strictEqual(results
[0].output
, unIndent
`
3170 console
.log("hello");${/* ← fixed */""}
3175 console
.log("hello")${/* ← ignored */""}
3178 console
.log("hello")${/* ← ignored */""}
3184 it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3185 const teardown
= createCustomTeardown({
3190 plugins
: ["markdown", "html"],
3191 rules
: { semi
: "error" }
3196 await teardown
.prepare();
3197 cleanup
= teardown
.cleanup
;
3198 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3199 const results
= await eslint
.lintFiles(["test.md"]);
3201 assert
.strictEqual(results
.length
, 1);
3202 assert
.strictEqual(results
[0].messages
.length
, 2);
3203 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3204 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3205 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3206 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3209 it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
3210 const teardown
= createCustomTeardown({
3215 plugins
: ["markdown", "html"],
3216 rules
: { semi
: "error" }
3221 await teardown
.prepare();
3222 cleanup
= teardown
.cleanup
;
3223 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"], fix
: true });
3224 const results
= await eslint
.lintFiles(["test.md"]);
3226 assert
.strictEqual(results
.length
, 1);
3227 assert
.strictEqual(results
[0].messages
.length
, 0);
3228 assert
.strictEqual(results
[0].output
, unIndent
`
3230 console
.log("hello");${/* ← fixed */""}
3235 console
.log("hello");${/* ← fixed */""}
3238 console
.log("hello")${/* ← ignored */""}
3244 it("should use overridden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", async () => {
3245 const teardown
= createCustomTeardown({
3250 plugins
: ["markdown", "html"],
3251 rules
: { semi
: "error" },
3255 processor
: "html/non-fixable" // supportsAutofix: false
3262 await teardown
.prepare();
3263 cleanup
= teardown
.cleanup
;
3264 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"], fix
: true });
3265 const results
= await eslint
.lintFiles(["test.md"]);
3267 assert
.strictEqual(results
.length
, 1);
3268 assert
.strictEqual(results
[0].messages
.length
, 1);
3269 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS Block in HTML Block
3270 assert
.strictEqual(results
[0].messages
[0].line
, 7);
3271 assert
.strictEqual(results
[0].messages
[0].fix
, void 0);
3272 assert
.strictEqual(results
[0].output
, unIndent
`
3274 console
.log("hello");${/* ← fixed */""}
3279 console
.log("hello")${/* ← reported but not fixed */""}
3282 console
.log("hello")
3288 it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", async () => {
3289 const teardown
= createCustomTeardown({
3294 plugins
: ["markdown", "html"],
3295 rules
: { semi
: "error" },
3300 // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
3307 files
: "**/*.html/*.js",
3310 "no-console": "error"
3318 await teardown
.prepare();
3319 cleanup
= teardown
.cleanup
;
3320 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3321 const results
= await eslint
.lintFiles(["test.md"]);
3323 assert
.strictEqual(results
.length
, 1);
3324 assert
.strictEqual(results
[0].messages
.length
, 2);
3325 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3326 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3327 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3328 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3331 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 () => {
3332 const teardown
= createCustomTeardown({
3337 plugins
: ["markdown", "html"],
3338 rules
: { semi
: "error" },
3342 processor
: "html/legacy", // this processor returns strings rather than `{text, filename}`
3345 "no-console": "error"
3349 files
: "**/*.html/*.js",
3360 await teardown
.prepare();
3361 cleanup
= teardown
.cleanup
;
3362 eslint
= new ESLint({ cwd
: teardown
.getPath(), extensions
: ["js", "html"] });
3363 const results
= await eslint
.lintFiles(["test.md"]);
3365 assert
.strictEqual(results
.length
, 1);
3366 assert
.strictEqual(results
[0].messages
.length
, 3);
3367 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi");
3368 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3369 assert
.strictEqual(results
[0].messages
[1].ruleId
, "no-console");
3370 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3371 assert
.strictEqual(results
[0].messages
[2].ruleId
, "no-console");
3372 assert
.strictEqual(results
[0].messages
[2].line
, 10);
3375 it("should throw an error if invalid processor was specified.", async () => {
3376 const teardown
= createCustomTeardown({
3381 plugins
: ["markdown", "html"],
3382 processor
: "markdown/unknown"
3387 await teardown
.prepare();
3388 cleanup
= teardown
.cleanup
;
3389 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3391 await assert
.rejects(async () => {
3392 await eslint
.lintFiles(["test.md"]);
3393 }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
3396 it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", async () => {
3397 const teardown
= createCustomTeardown({
3402 plugins
: ["markdown", "html"],
3403 rules
: { semi
: "error" },
3407 processor
: "html/.html"
3411 processor
: "markdown/.md"
3418 await teardown
.prepare();
3419 cleanup
= teardown
.cleanup
;
3420 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3421 const results
= await eslint
.lintFiles(["test.md"]);
3423 assert
.strictEqual(results
.length
, 1);
3424 assert
.strictEqual(results
[0].messages
.length
, 2);
3425 assert
.strictEqual(results
[0].messages
[0].ruleId
, "semi"); // JS block
3426 assert
.strictEqual(results
[0].messages
[0].line
, 2);
3427 assert
.strictEqual(results
[0].messages
[1].ruleId
, "semi"); // JS block in HTML block
3428 assert
.strictEqual(results
[0].messages
[1].line
, 7);
3432 describe("MODULE_NOT_FOUND error handling", () => {
3433 const cwd
= getFixturePath("module-not-found");
3436 eslint
= new ESLint({ cwd
});
3439 it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", async () => {
3441 await eslint
.lintText("test", { filePath
: "extends-js/test.js" });
3443 assert
.strictEqual(err
.messageTemplate
, "extend-config-missing");
3444 assert
.deepStrictEqual(err
.messageData
, {
3445 configName
: "nonexistent-config",
3446 importerName
: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
3450 assert
.fail("Expected to throw an error");
3453 it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", async () => {
3455 await eslint
.lintText("test", { filePath
: "extends-plugin/test.js" });
3457 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3458 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3459 assert
.deepStrictEqual(err
.messageData
, {
3460 importerName
: `extends-plugin${path.sep}.eslintrc.yml`,
3461 pluginName
: "eslint-plugin-nonexistent-plugin",
3462 resolvePluginsRelativeTo
: path
.join(cwd
, "extends-plugin") // the directory of the config file.
3466 assert
.fail("Expected to throw an error");
3469 it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", async () => {
3471 await eslint
.lintText("test", { filePath
: "plugins/test.js" });
3473 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3474 assert
.strictEqual(err
.messageTemplate
, "plugin-missing");
3475 assert
.deepStrictEqual(err
.messageData
, {
3476 importerName
: `plugins${path.sep}.eslintrc.yml`,
3477 pluginName
: "eslint-plugin-nonexistent-plugin",
3478 resolvePluginsRelativeTo
: path
.join(cwd
, "plugins") // the directory of the config file.
3482 assert
.fail("Expected to throw an error");
3485 it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", async () => {
3487 await eslint
.lintText("test", { filePath
: "throw-in-config-itself/test.js" });
3489 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3490 assert
.strictEqual(err
.messageTemplate
, void 0);
3493 assert
.fail("Expected to throw an error");
3496 it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3498 await eslint
.lintText("test", { filePath
: "throw-in-extends-js/test.js" });
3500 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3501 assert
.strictEqual(err
.messageTemplate
, void 0);
3504 assert
.fail("Expected to throw an error");
3507 it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3509 await eslint
.lintText("test", { filePath
: "throw-in-extends-plugin/test.js" });
3511 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3512 assert
.strictEqual(err
.messageTemplate
, void 0);
3515 assert
.fail("Expected to throw an error");
3518 it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
3520 await eslint
.lintText("test", { filePath
: "throw-in-plugins/test.js" });
3522 assert
.strictEqual(err
.code
, "MODULE_NOT_FOUND");
3523 assert
.strictEqual(err
.messageTemplate
, void 0);
3526 assert
.fail("Expected to throw an error");
3530 describe("with '--rulesdir' option", () => {
3532 const rootPath
= getFixturePath("cli-engine/with-rulesdir");
3533 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3536 "internal-rules/test.js": `
3537 module.exports = context => ({
3538 ExpressionStatement(node) {
3539 context.report({ node, message: "ok" })
3545 rules
: { test
: "error" }
3547 "test.js": "console.log('hello')"
3551 beforeEach(prepare
);
3555 it("should use the configured rules which are defined by '--rulesdir' option.", async () => {
3556 eslint
= new ESLint({
3558 rulePaths
: ["internal-rules"]
3560 const results
= await eslint
.lintFiles(["test.js"]);
3562 assert
.strictEqual(results
.length
, 1);
3563 assert
.strictEqual(results
[0].messages
.length
, 1);
3564 assert
.strictEqual(results
[0].messages
[0].message
, "ok");
3568 describe("glob pattern '[ab].js'", () => {
3569 const root
= getFixturePath("cli-engine/unmatched-glob");
3574 cleanup
= () => { };
3577 afterEach(() => cleanup());
3579 it("should match '[ab].js' if existed.", async () => {
3581 const teardown
= createCustomTeardown({
3588 ".eslintrc.yml": "root: true"
3592 await teardown
.prepare();
3593 cleanup
= teardown
.cleanup
;
3595 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3596 const results
= await eslint
.lintFiles(["[ab].js"]);
3597 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3599 assert
.deepStrictEqual(filenames
, ["[ab].js"]);
3602 it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", async () => {
3603 const teardown
= createCustomTeardown({
3609 ".eslintrc.yml": "root: true"
3613 await teardown
.prepare();
3614 cleanup
= teardown
.cleanup
;
3615 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3616 const results
= await eslint
.lintFiles(["[ab].js"]);
3617 const filenames
= results
.map(r
=> path
.basename(r
.filePath
));
3619 assert
.deepStrictEqual(filenames
, ["a.js", "b.js"]);
3623 describe("with 'noInlineConfig' setting", () => {
3624 const root
= getFixturePath("cli-engine/noInlineConfig");
3629 cleanup
= () => { };
3632 afterEach(() => cleanup());
3634 it("should warn directive comments if 'noInlineConfig' was given.", async () => {
3635 const teardown
= createCustomTeardown({
3638 "test.js": "/* globals foo */",
3639 ".eslintrc.yml": "noInlineConfig: true"
3643 await teardown
.prepare();
3644 cleanup
= teardown
.cleanup
;
3645 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3647 const results
= await eslint
.lintFiles(["test.js"]);
3648 const messages
= results
[0].messages
;
3650 assert
.strictEqual(messages
.length
, 1);
3651 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
3654 it("should show the config file what the 'noInlineConfig' came from.", async () => {
3655 const teardown
= createCustomTeardown({
3658 "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
3659 "test.js": "/* globals foo */",
3660 ".eslintrc.yml": "extends: foo"
3664 await teardown
.prepare();
3665 cleanup
= teardown
.cleanup
;
3666 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3668 const results
= await eslint
.lintFiles(["test.js"]);
3669 const messages
= results
[0].messages
;
3671 assert
.strictEqual(messages
.length
, 1);
3672 assert
.strictEqual(messages
[0].message
, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
3676 describe("with 'reportUnusedDisableDirectives' setting", () => {
3677 const root
= getFixturePath("cli-engine/reportUnusedDisableDirectives");
3682 cleanup
= () => { };
3685 afterEach(() => cleanup());
3687 it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", async () => {
3688 const teardown
= createCustomTeardown({
3691 "test.js": "/* eslint-disable eqeqeq */",
3692 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3697 await teardown
.prepare();
3698 cleanup
= teardown
.cleanup
;
3699 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3701 const results
= await eslint
.lintFiles(["test.js"]);
3702 const messages
= results
[0].messages
;
3704 assert
.strictEqual(messages
.length
, 1);
3705 assert
.strictEqual(messages
[0].severity
, 1);
3706 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3709 describe("the runtime option overrides config files.", () => {
3710 it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", async () => {
3711 const teardown
= createCustomTeardown({
3714 "test.js": "/* eslint-disable eqeqeq */",
3715 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3719 await teardown
.prepare();
3720 cleanup
= teardown
.cleanup
;
3722 eslint
= new ESLint({
3723 cwd
: teardown
.getPath(),
3724 reportUnusedDisableDirectives
: "off"
3727 const results
= await eslint
.lintFiles(["test.js"]);
3728 const messages
= results
[0].messages
;
3730 assert
.strictEqual(messages
.length
, 0);
3733 it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", async () => {
3734 const teardown
= createCustomTeardown({
3737 "test.js": "/* eslint-disable eqeqeq */",
3738 ".eslintrc.yml": "reportUnusedDisableDirectives: true"
3742 await teardown
.prepare();
3743 cleanup
= teardown
.cleanup
;
3745 eslint
= new ESLint({
3746 cwd
: teardown
.getPath(),
3747 reportUnusedDisableDirectives
: "error"
3750 const results
= await eslint
.lintFiles(["test.js"]);
3751 const messages
= results
[0].messages
;
3753 assert
.strictEqual(messages
.length
, 1);
3754 assert
.strictEqual(messages
[0].severity
, 2);
3755 assert
.strictEqual(messages
[0].message
, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
3760 describe("with 'overrides[*].extends' setting on deep locations", () => {
3761 const root
= getFixturePath("cli-engine/deeply-overrides-i-extends");
3762 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
3765 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
3766 overrides: [{ files: ["*test*"], extends: "two" }]
3768 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
3769 overrides: [{ files: ["*.js"], extends: "three" }]
3771 "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
3772 rules: { "no-console": "error" }
3774 "test.js": "console.log('hello')",
3775 ".eslintrc.yml": "extends: one"
3779 beforeEach(prepare
);
3782 it("should not throw.", async () => {
3783 eslint
= new ESLint({ cwd
: getPath() });
3784 const results
= await eslint
.lintFiles(["test.js"]);
3785 const messages
= results
[0].messages
;
3787 assert
.strictEqual(messages
.length
, 1);
3788 assert
.strictEqual(messages
[0].ruleId
, "no-console");
3792 describe("don't ignore the entry directory.", () => {
3793 const root
= getFixturePath("cli-engine/dont-ignore-entry-dir");
3798 cleanup
= () => { };
3801 afterEach(async () => {
3804 const configFilePath
= path
.resolve(root
, "../.eslintrc.json");
3806 if (shell
.test("-e", configFilePath
)) {
3807 shell
.rm(configFilePath
);
3811 it("'lintFiles(\".\")' should not load config files from outside of \".\".", async () => {
3812 const teardown
= createCustomTeardown({
3815 "../.eslintrc.json": "BROKEN FILE",
3816 ".eslintrc.json": JSON
.stringify({ root
: true }),
3817 "index.js": "console.log(\"hello\")"
3821 await teardown
.prepare();
3822 cleanup
= teardown
.cleanup
;
3823 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3825 // Don't throw "failed to load config file" error.
3826 await eslint
.lintFiles(".");
3829 it("'lintFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", async () => {
3830 const teardown
= createCustomTeardown({
3833 "../.eslintrc.json": { ignorePatterns
: ["/dont-ignore-entry-dir"] },
3834 ".eslintrc.json": { root
: true },
3835 "index.js": "console.log(\"hello\")"
3839 await teardown
.prepare();
3840 cleanup
= teardown
.cleanup
;
3841 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3843 // Don't throw "file not found" error.
3844 await eslint
.lintFiles(".");
3847 it("'lintFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", async () => {
3848 const teardown
= createCustomTeardown({
3851 ".eslintrc.json": { ignorePatterns
: ["/subdir"] },
3852 "subdir/.eslintrc.json": { root
: true },
3853 "subdir/index.js": "console.log(\"hello\")"
3857 await teardown
.prepare();
3858 cleanup
= teardown
.cleanup
;
3859 eslint
= new ESLint({ cwd
: teardown
.getPath() });
3861 // Don't throw "file not found" error.
3862 await eslint
.lintFiles("subdir");
3866 it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
3867 eslint
= new ESLint();
3868 await assert
.rejects(() => eslint
.lintFiles(777), /'patterns' must be a non-empty string or an array of non-empty strings/u);
3869 await assert
.rejects(() => eslint
.lintFiles([null]), /'patterns' must be a non-empty string or an array of non-empty strings/u);
3873 describe("calculateConfigForFile", () => {
3874 it("should return the info from Config#getConfig when called", async () => {
3876 overrideConfigFile
: getFixturePath("configurations", "quotes-error.json")
3878 const engine
= new ESLint(options
);
3879 const filePath
= getFixturePath("single-quoted.js");
3880 const actualConfig
= await engine
.calculateConfigForFile(filePath
);
3881 const expectedConfig
= new CascadingConfigArrayFactory({ specificConfigPath
: options
.overrideConfigFile
})
3882 .getConfigArrayForFile(filePath
)
3883 .extractConfig(filePath
)
3884 .toCompatibleObjectAsConfigFileContent();
3886 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3890 it("should return the config when run from within a subdir", async () => {
3892 cwd
: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
3894 const engine
= new ESLint(options
);
3895 const filePath
= getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
3896 const actualConfig
= await engine
.calculateConfigForFile("./.eslintrc");
3897 const expectedConfig
= new CascadingConfigArrayFactory(options
)
3898 .getConfigArrayForFile(filePath
)
3899 .extractConfig(filePath
)
3900 .toCompatibleObjectAsConfigFileContent();
3902 assert
.deepStrictEqual(actualConfig
, expectedConfig
);
3905 it("should throw an error if a directory path was given.", async () => {
3906 const engine
= new ESLint();
3909 await engine
.calculateConfigForFile(".");
3911 assert
.strictEqual(error
.messageTemplate
, "print-config-with-directory-path");
3914 assert
.fail("should throw an error");
3917 it("should throw if non-string value is given to 'filePath' parameter", async () => {
3918 const eslint
= new ESLint();
3920 await assert
.rejects(() => eslint
.calculateConfigForFile(null), /'filePath' must be a non-empty string/u);
3923 // https://github.com/eslint/eslint/issues/13793
3924 it("should throw with an invalid built-in rule config", async () => {
3928 "no-alert": ["error", {
3929 thisDoesNotExist
: true
3934 const engine
= new ESLint(options
);
3935 const filePath
= getFixturePath("single-quoted.js");
3937 await assert
.rejects(
3938 () => engine
.calculateConfigForFile(filePath
),
3939 /Configuration for rule "no-alert" is invalid:/u
3944 describe("isPathIgnored", () => {
3945 it("should check if the given path is ignored", async () => {
3946 const engine
= new ESLint({
3947 ignorePath
: getFixturePath(".eslintignore2"),
3948 cwd
: getFixturePath()
3951 assert(await engine
.isPathIgnored("undef.js"));
3952 assert(!await engine
.isPathIgnored("passing.js"));
3955 it("should return false if ignoring is disabled", async () => {
3956 const engine
= new ESLint({
3958 ignorePath
: getFixturePath(".eslintignore2"),
3959 cwd
: getFixturePath()
3962 assert(!await engine
.isPathIgnored("undef.js"));
3965 // https://github.com/eslint/eslint/issues/5547
3966 it("should return true for default ignores even if ignoring is disabled", async () => {
3967 const engine
= new ESLint({
3969 cwd
: getFixturePath("cli-engine")
3972 assert(await engine
.isPathIgnored("node_modules/foo.js"));
3975 describe("about the default ignore patterns", () => {
3976 it("should always apply defaultPatterns if ignore option is true", async () => {
3977 const cwd
= getFixturePath("ignored-paths");
3978 const engine
= new ESLint({ cwd
});
3980 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
3981 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
3984 it("should still apply defaultPatterns if ignore option is is false", async () => {
3985 const cwd
= getFixturePath("ignored-paths");
3986 const engine
= new ESLint({ ignore
: false, cwd
});
3988 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
3989 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
3992 it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", async () => {
3993 const cwd
= getFixturePath("ignored-paths");
3994 const engine
= new ESLint({
3997 ignorePatterns
: "!/node_modules/package"
4001 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4004 it("should allow subfolders of defaultPatterns to be unignored by ignorePath", async () => {
4005 const cwd
= getFixturePath("ignored-paths");
4006 const engine
= new ESLint({ cwd
, ignorePath
: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
4008 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
4011 it("should ignore dotfiles", async () => {
4012 const cwd
= getFixturePath("ignored-paths");
4013 const engine
= new ESLint({ cwd
});
4015 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4016 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4019 it("should ignore directories beginning with a dot", async () => {
4020 const cwd
= getFixturePath("ignored-paths");
4021 const engine
= new ESLint({ cwd
});
4023 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4024 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4027 it("should still ignore dotfiles when ignore option disabled", async () => {
4028 const cwd
= getFixturePath("ignored-paths");
4029 const engine
= new ESLint({ ignore
: false, cwd
});
4031 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
4032 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
4035 it("should still ignore directories beginning with a dot when ignore option disabled", async () => {
4036 const cwd
= getFixturePath("ignored-paths");
4037 const engine
= new ESLint({ ignore
: false, cwd
});
4039 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
4040 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
4043 it("should not ignore absolute paths containing '..'", async () => {
4044 const cwd
= getFixturePath("ignored-paths");
4045 const engine
= new ESLint({ cwd
});
4047 assert(!await engine
.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
4050 it("should ignore /node_modules/ relative to .eslintignore when loaded", async () => {
4051 const cwd
= getFixturePath("ignored-paths");
4052 const engine
= new ESLint({ ignorePath
: getFixturePath("ignored-paths", ".eslintignore"), cwd
});
4054 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
4055 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
4058 it("should ignore /node_modules/ relative to cwd without an .eslintignore", async () => {
4059 const cwd
= getFixturePath("ignored-paths", "no-ignore-file");
4060 const engine
= new ESLint({ cwd
});
4062 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
4063 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
4067 describe("with no .eslintignore file", () => {
4068 it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", async () => {
4069 const cwd
= getFixturePath("ignored-paths", "configurations");
4070 const engine
= new ESLint({ cwd
});
4072 // a .eslintignore in parent directories includes `*.js`, but don't load it.
4073 assert(!await engine
.isPathIgnored("foo.js"));
4074 assert(await engine
.isPathIgnored("node_modules/foo.js"));
4077 it("should return false for files outside of the cwd (with no ignore file provided)", async () => {
4079 // Default ignore patterns should not inadvertently ignore files in parent directories
4080 const engine
= new ESLint({ cwd
: getFixturePath("ignored-paths", "no-ignore-file") });
4082 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4086 describe("with .eslintignore file or package.json file", () => {
4087 it("should load .eslintignore from cwd when explicitly passed", async () => {
4088 const cwd
= getFixturePath("ignored-paths");
4089 const engine
= new ESLint({ cwd
});
4091 // `${cwd}/.eslintignore` includes `sampleignorepattern`.
4092 assert(await engine
.isPathIgnored("sampleignorepattern"));
4095 it("should use package.json's eslintIgnore files if no specified .eslintignore file", async () => {
4096 const cwd
= getFixturePath("ignored-paths", "package-json-ignore");
4097 const engine
= new ESLint({ cwd
});
4099 assert(await engine
.isPathIgnored("hello.js"));
4100 assert(await engine
.isPathIgnored("world.js"));
4103 it("should use correct message template if failed to parse package.json", () => {
4104 const cwd
= getFixturePath("ignored-paths", "broken-package-json");
4106 assert
.throws(() => {
4108 // eslint-disable-next-line no-new
4109 new ESLint({ cwd
});
4111 assert
.strictEqual(error
.messageTemplate
, "failed-to-read-json");
4117 it("should not use package.json's eslintIgnore files if specified .eslintignore file", async () => {
4118 const cwd
= getFixturePath("ignored-paths");
4119 const engine
= new ESLint({ cwd
});
4122 * package.json includes `hello.js` and `world.js`.
4123 * .eslintignore includes `sampleignorepattern`.
4125 assert(!await engine
.isPathIgnored("hello.js"));
4126 assert(!await engine
.isPathIgnored("world.js"));
4127 assert(await engine
.isPathIgnored("sampleignorepattern"));
4130 it("should error if package.json's eslintIgnore is not an array of file paths", () => {
4131 const cwd
= getFixturePath("ignored-paths", "bad-package-json-ignore");
4133 assert
.throws(() => {
4134 // eslint-disable-next-line no-new
4135 new ESLint({ cwd
});
4136 }, /Package\.json eslintIgnore property requires an array of paths/u);
4140 describe("with --ignore-pattern option", () => {
4141 it("should accept a string for options.ignorePattern", async () => {
4142 const cwd
= getFixturePath("ignored-paths", "ignore-pattern");
4143 const engine
= new ESLint({
4145 ignorePatterns
: "ignore-me.txt"
4150 assert(await engine
.isPathIgnored("ignore-me.txt"));
4153 it("should accept an array for options.ignorePattern", async () => {
4154 const engine
= new ESLint({
4156 ignorePatterns
: ["a", "b"]
4161 assert(await engine
.isPathIgnored("a"));
4162 assert(await engine
.isPathIgnored("b"));
4163 assert(!await engine
.isPathIgnored("c"));
4166 it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", async () => {
4167 const cwd
= getFixturePath("ignored-paths");
4168 const engine
= new ESLint({
4170 ignorePatterns
: "not-a-file"
4175 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
4178 it("should return true for file matching an ignore pattern exactly", async () => {
4179 const cwd
= getFixturePath("ignored-paths");
4180 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "undef.js" }, cwd
});
4182 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4185 it("should return false for file matching an invalid ignore pattern with leading './'", async () => {
4186 const cwd
= getFixturePath("ignored-paths");
4187 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "./undef.js" }, cwd
});
4189 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4192 it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", async () => {
4193 const cwd
= getFixturePath("ignored-paths");
4194 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "/undef.js" }, cwd
});
4196 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
4199 it("should return true for file matching a child of an ignore pattern", async () => {
4200 const cwd
= getFixturePath("ignored-paths");
4201 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "ignore-pattern" }, cwd
});
4203 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
4206 it("should return true for file matching a grandchild of an ignore pattern", async () => {
4207 const cwd
= getFixturePath("ignored-paths");
4208 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "ignore-pattern" }, cwd
});
4210 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
4213 it("should return false for file not matching any ignore pattern", async () => {
4214 const cwd
= getFixturePath("ignored-paths");
4215 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "failing.js" }, cwd
});
4217 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
4220 it("two globstar '**' ignore pattern should ignore files in nested directories", async () => {
4221 const cwd
= getFixturePath("ignored-paths");
4222 const engine
= new ESLint({ overrideConfig
: { ignorePatterns
: "**/*.js" }, cwd
});
4224 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4225 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
4226 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
4227 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
4228 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
4229 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
4233 describe("with --ignore-path option", () => {
4234 it("initialization with ignorePath should work when cwd is a parent directory", async () => {
4235 const cwd
= getFixturePath("ignored-paths");
4236 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4237 const engine
= new ESLint({ ignorePath
, cwd
});
4239 assert(await engine
.isPathIgnored("custom-name/foo.js"));
4242 it("initialization with ignorePath should work when the file is in the cwd", async () => {
4243 const cwd
= getFixturePath("ignored-paths", "custom-name");
4244 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4245 const engine
= new ESLint({ ignorePath
, cwd
});
4247 assert(await engine
.isPathIgnored("foo.js"));
4250 it("initialization with ignorePath should work when cwd is a subdirectory", async () => {
4251 const cwd
= getFixturePath("ignored-paths", "custom-name", "subdirectory");
4252 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4253 const engine
= new ESLint({ ignorePath
, cwd
});
4255 assert(await engine
.isPathIgnored("../custom-name/foo.js"));
4258 it("initialization with invalid file should throw error", () => {
4259 const cwd
= getFixturePath("ignored-paths");
4260 const ignorePath
= getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
4262 assert
.throws(() => {
4263 // eslint-disable-next-line no-new
4264 new ESLint({ ignorePath
, cwd
});
4265 }, /Cannot read \.eslintignore file/u);
4268 it("should return false for files outside of ignorePath's directory", async () => {
4269 const cwd
= getFixturePath("ignored-paths");
4270 const ignorePath
= getFixturePath("ignored-paths", "custom-name", "ignore-file");
4271 const engine
= new ESLint({ ignorePath
, cwd
});
4273 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4276 it("should resolve relative paths from CWD", async () => {
4277 const cwd
= getFixturePath("ignored-paths", "subdir");
4278 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4279 const engine
= new ESLint({ ignorePath
, cwd
});
4281 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4282 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4285 it("should resolve relative paths from CWD when it's in a child directory", async () => {
4286 const cwd
= getFixturePath("ignored-paths");
4287 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4288 const engine
= new ESLint({ ignorePath
, cwd
});
4290 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
4291 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
4292 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
4293 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
4295 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
4298 it("should resolve relative paths from CWD when it contains negated globs", async () => {
4299 const cwd
= getFixturePath("ignored-paths");
4300 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4301 const engine
= new ESLint({ ignorePath
, cwd
});
4303 assert(await engine
.isPathIgnored("subdir/blah.txt"));
4304 assert(await engine
.isPathIgnored("blah.txt"));
4305 assert(await engine
.isPathIgnored("subdir/bar.txt"));
4306 assert(!await engine
.isPathIgnored("bar.txt"));
4307 assert(!await engine
.isPathIgnored("subdir/baz.txt"));
4308 assert(!await engine
.isPathIgnored("baz.txt"));
4311 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", async () => {
4312 const cwd
= getFixturePath("ignored-paths");
4313 const ignorePath
= getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
4314 const engine
= new ESLint({ ignorePath
, cwd
});
4316 assert(await engine
.isPathIgnored("node_modules/blah.js"));
4319 it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", async () => {
4320 const cwd
= getFixturePath("ignored-paths", "subdir");
4321 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
4322 const engine
= new ESLint({ ignorePath
, cwd
});
4324 assert(await engine
.isPathIgnored("node_modules/blah.js"));
4327 it("should handle .eslintignore which contains CRLF correctly.", async () => {
4328 const ignoreFileContent
= fs
.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
4330 assert(ignoreFileContent
.includes("\r"), "crlf/.eslintignore should contains CR.");
4331 const cwd
= getFixturePath("ignored-paths");
4332 const ignorePath
= getFixturePath("ignored-paths", "crlf/.eslintignore");
4333 const engine
= new ESLint({ ignorePath
, cwd
});
4335 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
4336 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
4337 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
4340 it("should not include comments in ignore rules", async () => {
4341 const cwd
= getFixturePath("ignored-paths");
4342 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithComments");
4343 const engine
= new ESLint({ ignorePath
, cwd
});
4345 assert(!await engine
.isPathIgnored("# should be ignored"));
4346 assert(await engine
.isPathIgnored("this_one_not"));
4349 it("should ignore a non-negated pattern", async () => {
4350 const cwd
= getFixturePath("ignored-paths");
4351 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4352 const engine
= new ESLint({ ignorePath
, cwd
});
4354 assert(await engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
4357 it("should not ignore a negated pattern", async () => {
4358 const cwd
= getFixturePath("ignored-paths");
4359 const ignorePath
= getFixturePath("ignored-paths", ".eslintignoreWithNegation");
4360 const engine
= new ESLint({ ignorePath
, cwd
});
4362 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
4366 describe("with --ignore-path option and --ignore-pattern option", () => {
4367 it("should return false for ignored file when unignored with ignore pattern", async () => {
4368 const cwd
= getFixturePath("ignored-paths");
4369 const engine
= new ESLint({
4370 ignorePath
: getFixturePath("ignored-paths", ".eslintignore"),
4372 ignorePatterns
: "!sampleignorepattern"
4377 assert(!await engine
.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
4381 it("should throw if non-string value is given to 'filePath' parameter", async () => {
4382 const eslint
= new ESLint();
4384 await assert
.rejects(() => eslint
.isPathIgnored(null), /'filePath' must be a non-empty string/u);
4388 describe("loadFormatter()", () => {
4389 it("should return a formatter object when a bundled formatter is requested", async () => {
4390 const engine
= new ESLint();
4391 const formatter
= await engine
.loadFormatter("compact");
4393 assert
.strictEqual(typeof formatter
, "object");
4394 assert
.strictEqual(typeof formatter
.format
, "function");
4397 it("should return a formatter object when no argument is passed", async () => {
4398 const engine
= new ESLint();
4399 const formatter
= await engine
.loadFormatter();
4401 assert
.strictEqual(typeof formatter
, "object");
4402 assert
.strictEqual(typeof formatter
.format
, "function");
4405 it("should return a formatter object when a custom formatter is requested", async () => {
4406 const engine
= new ESLint();
4407 const formatter
= await engine
.loadFormatter(getFixturePath("formatters", "simple.js"));
4409 assert
.strictEqual(typeof formatter
, "object");
4410 assert
.strictEqual(typeof formatter
.format
, "function");
4413 it("should return a formatter object when a custom formatter is requested, also if the path has backslashes", async () => {
4414 const engine
= new ESLint({
4415 cwd
: path
.join(fixtureDir
, "..")
4417 const formatter
= await engine
.loadFormatter(".\\fixtures\\formatters\\simple.js");
4419 assert
.strictEqual(typeof formatter
, "object");
4420 assert
.strictEqual(typeof formatter
.format
, "function");
4423 it("should return a formatter object when a formatter prefixed with eslint-formatter is requested", async () => {
4424 const engine
= new ESLint({
4425 cwd
: getFixturePath("cli-engine")
4427 const formatter
= await engine
.loadFormatter("bar");
4429 assert
.strictEqual(typeof formatter
, "object");
4430 assert
.strictEqual(typeof formatter
.format
, "function");
4433 it("should return a formatter object when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", async () => {
4434 const engine
= new ESLint({
4435 cwd
: getFixturePath("cli-engine")
4437 const formatter
= await engine
.loadFormatter("eslint-formatter-bar");
4439 assert
.strictEqual(typeof formatter
, "object");
4440 assert
.strictEqual(typeof formatter
.format
, "function");
4443 it("should return a formatter object when a formatter is requested within a scoped npm package", async () => {
4444 const engine
= new ESLint({
4445 cwd
: getFixturePath("cli-engine")
4447 const formatter
= await engine
.loadFormatter("@somenamespace/foo");
4449 assert
.strictEqual(typeof formatter
, "object");
4450 assert
.strictEqual(typeof formatter
.format
, "function");
4453 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 () => {
4454 const engine
= new ESLint({
4455 cwd
: getFixturePath("cli-engine")
4457 const formatter
= await engine
.loadFormatter("@somenamespace/eslint-formatter-foo");
4459 assert
.strictEqual(typeof formatter
, "object");
4460 assert
.strictEqual(typeof formatter
.format
, "function");
4463 it("should throw if a customer formatter doesn't exist", async () => {
4464 const engine
= new ESLint();
4465 const formatterPath
= getFixturePath("formatters", "doesntexist.js");
4466 const fullFormatterPath
= path
.resolve(formatterPath
);
4468 await assert
.rejects(async () => {
4469 await engine
.loadFormatter(formatterPath
);
4470 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
4473 it("should throw if a built-in formatter doesn't exist", async () => {
4474 const engine
= new ESLint();
4475 const fullFormatterPath
= path
.resolve(__dirname
, "../../../lib/cli-engine/formatters/special");
4477 await assert
.rejects(async () => {
4478 await engine
.loadFormatter("special");
4479 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
4482 it("should throw if the required formatter exists but has an error", async () => {
4483 const engine
= new ESLint();
4484 const formatterPath
= getFixturePath("formatters", "broken.js");
4486 await assert
.rejects(async () => {
4487 await engine
.loadFormatter(formatterPath
);
4488 }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`), "u"));
4491 it("should throw if a non-string formatter name is passed", async () => {
4492 const engine
= new ESLint();
4494 await assert
.rejects(async () => {
4495 await engine
.loadFormatter(5);
4496 }, /'name' must be a string/u);
4500 describe("getErrorResults()", () => {
4501 it("should report 5 error messages when looking for errors only", async () => {
4502 process
.chdir(originalDir
);
4503 const engine
= new ESLint();
4504 const results
= await engine
.lintText("var foo = 'bar';");
4505 const errorResults
= ESLint
.getErrorResults(results
);
4507 assert
.strictEqual(errorResults
[0].messages
.length
, 5);
4508 assert
.strictEqual(errorResults
[0].errorCount
, 5);
4509 assert
.strictEqual(errorResults
[0].fixableErrorCount
, 3);
4510 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4511 assert
.strictEqual(errorResults
[0].messages
[0].ruleId
, "strict");
4512 assert
.strictEqual(errorResults
[0].messages
[0].severity
, 2);
4513 assert
.strictEqual(errorResults
[0].messages
[1].ruleId
, "no-var");
4514 assert
.strictEqual(errorResults
[0].messages
[1].severity
, 2);
4515 assert
.strictEqual(errorResults
[0].messages
[2].ruleId
, "no-unused-vars");
4516 assert
.strictEqual(errorResults
[0].messages
[2].severity
, 2);
4517 assert
.strictEqual(errorResults
[0].messages
[3].ruleId
, "quotes");
4518 assert
.strictEqual(errorResults
[0].messages
[3].severity
, 2);
4519 assert
.strictEqual(errorResults
[0].messages
[4].ruleId
, "eol-last");
4520 assert
.strictEqual(errorResults
[0].messages
[4].severity
, 2);
4523 it("should not mutate passed report parameter", async () => {
4524 process
.chdir(originalDir
);
4525 const engine
= new ESLint({
4527 rules
: { quotes
: [1, "double"] }
4530 const results
= await engine
.lintText("var foo = 'bar';");
4531 const reportResultsLength
= results
[0].messages
.length
;
4533 ESLint
.getErrorResults(results
);
4535 assert
.strictEqual(results
[0].messages
.length
, reportResultsLength
);
4538 it("should report a warningCount of 0 when looking for errors only", async () => {
4539 process
.chdir(originalDir
);
4540 const engine
= new ESLint();
4541 const results
= await engine
.lintText("var foo = 'bar';");
4542 const errorResults
= ESLint
.getErrorResults(results
);
4544 assert
.strictEqual(errorResults
[0].warningCount
, 0);
4545 assert
.strictEqual(errorResults
[0].fixableWarningCount
, 0);
4548 it("should return 0 error or warning messages even when the file has warnings", async () => {
4549 const engine
= new ESLint({
4550 ignorePath
: path
.join(fixtureDir
, ".eslintignore"),
4551 cwd
: path
.join(fixtureDir
, "..")
4554 filePath
: "fixtures/passing.js",
4557 const results
= await engine
.lintText("var bar = foo;", options
);
4558 const errorReport
= ESLint
.getErrorResults(results
);
4560 assert
.strictEqual(errorReport
.length
, 0);
4561 assert
.strictEqual(results
.length
, 1);
4562 assert
.strictEqual(results
[0].errorCount
, 0);
4563 assert
.strictEqual(results
[0].warningCount
, 1);
4566 it("should return source code of file in the `source` property", async () => {
4567 process
.chdir(originalDir
);
4568 const engine
= new ESLint({
4571 rules
: { quotes
: [2, "double"] }
4574 const results
= await engine
.lintText("var foo = 'bar';");
4575 const errorResults
= ESLint
.getErrorResults(results
);
4577 assert
.strictEqual(errorResults
[0].messages
.length
, 1);
4578 assert
.strictEqual(errorResults
[0].source
, "var foo = 'bar';");
4581 it("should contain `output` property after fixes", async () => {
4582 process
.chdir(originalDir
);
4583 const engine
= new ESLint({
4593 const results
= await engine
.lintText("console.log('foo')");
4594 const errorResults
= ESLint
.getErrorResults(results
);
4596 assert
.strictEqual(errorResults
[0].messages
.length
, 1);
4597 assert
.strictEqual(errorResults
[0].output
, "console.log('foo');");
4601 describe("outputFixes()", () => {
4603 sinon
.verifyAndRestore();
4606 it("should call fs.writeFile() for each result with output", async () => {
4608 writeFile
: sinon
.spy(callLastArgument
)
4610 const spy
= fakeFS
.writeFile
;
4611 const { ESLint
: localESLint
} = proxyquire("../../../lib/eslint/eslint", {
4617 filePath
: path
.resolve("foo.js"),
4621 filePath
: path
.resolve("bar.js"),
4626 await localESLint
.outputFixes(results
);
4628 assert
.strictEqual(spy
.callCount
, 2);
4629 assert(spy
.firstCall
.calledWithExactly(path
.resolve("foo.js"), "bar", sinon
.match
.func
), "First call was incorrect.");
4630 assert(spy
.secondCall
.calledWithExactly(path
.resolve("bar.js"), "baz", sinon
.match
.func
), "Second call was incorrect.");
4633 it("should call fs.writeFile() for each result with output and not at all for a result without output", async () => {
4635 writeFile
: sinon
.spy(callLastArgument
)
4637 const spy
= fakeFS
.writeFile
;
4638 const { ESLint
: localESLint
} = proxyquire("../../../lib/eslint/eslint", {
4643 filePath
: path
.resolve("foo.js"),
4647 filePath
: path
.resolve("abc.js")
4650 filePath
: path
.resolve("bar.js"),
4655 await localESLint
.outputFixes(results
);
4657 assert
.strictEqual(spy
.callCount
, 2);
4658 assert(spy
.firstCall
.calledWithExactly(path
.resolve("foo.js"), "bar", sinon
.match
.func
), "First call was incorrect.");
4659 assert(spy
.secondCall
.calledWithExactly(path
.resolve("bar.js"), "baz", sinon
.match
.func
), "Second call was incorrect.");
4662 it("should throw if non object array is given to 'results' parameter", async () => {
4663 await assert
.rejects(() => ESLint
.outputFixes(null), /'results' must be an array/u);
4664 await assert
.rejects(() => ESLint
.outputFixes([null]), /'results' must include only objects/u);
4668 describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
4669 it("should report a violation for disabling rules", async () => {
4671 "alert('test'); // eslint-disable-line no-alert"
4675 allowInlineConfig
: false,
4677 env
: { browser
: true },
4681 "no-trailing-spaces": 0,
4687 const eslintCLI
= new ESLint(config
);
4688 const results
= await eslintCLI
.lintText(code
);
4689 const messages
= results
[0].messages
;
4691 assert
.strictEqual(messages
.length
, 1);
4692 assert
.strictEqual(messages
[0].ruleId
, "no-alert");
4695 it("should not report a violation by default", async () => {
4697 "alert('test'); // eslint-disable-line no-alert"
4701 allowInlineConfig
: true,
4703 env
: { browser
: true },
4707 "no-trailing-spaces": 0,
4713 const eslintCLI
= new ESLint(config
);
4714 const results
= await eslintCLI
.lintText(code
);
4715 const messages
= results
[0].messages
;
4717 assert
.strictEqual(messages
.length
, 0);
4721 describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
4722 it("should report problems for unused eslint-disable directives", async () => {
4723 const eslint
= new ESLint({ useEslintrc
: false, reportUnusedDisableDirectives
: "error" });
4725 assert
.deepStrictEqual(
4726 await eslint
.lintText("/* eslint-disable */"),
4733 message
: "Unused eslint-disable directive (no problems were reported).",
4742 fixableErrorCount
: 0,
4743 fixableWarningCount
: 0,
4744 source
: "/* eslint-disable */",
4745 usedDeprecatedRules
: []
4752 describe("when retreiving version number", () => {
4753 it("should return current version number", () => {
4754 const eslintCLI
= require("../../../lib/eslint").ESLint
;
4755 const version
= eslintCLI
.version
;
4757 assert
.strictEqual(typeof version
, "string");
4758 assert(parseInt(version
[0], 10) >= 3);
4762 describe("mutability", () => {
4763 describe("plugins", () => {
4764 it("Loading plugin in one instance doesn't mutate to another instance", async () => {
4765 const filePath
= getFixturePath("single-quoted.js");
4766 const engine1
= eslintWithPlugins({
4767 cwd
: path
.join(fixtureDir
, ".."),
4770 plugins
: ["example"],
4771 rules
: { "example/example-rule": 1 }
4774 const engine2
= new ESLint({
4775 cwd
: path
.join(fixtureDir
, ".."),
4778 const fileConfig1
= await engine1
.calculateConfigForFile(filePath
);
4779 const fileConfig2
= await engine2
.calculateConfigForFile(filePath
);
4782 assert
.deepStrictEqual(fileConfig1
.plugins
, ["example"], "Plugin is present for engine 1");
4783 assert
.deepStrictEqual(fileConfig2
.plugins
, [], "Plugin is not present for engine 2");
4787 describe("rules", () => {
4788 it("Loading rules in one instance doesn't mutate to another instance", async () => {
4789 const filePath
= getFixturePath("single-quoted.js");
4790 const engine1
= new ESLint({
4791 cwd
: path
.join(fixtureDir
, ".."),
4793 overrideConfig
: { rules
: { "example/example-rule": 1 } }
4795 const engine2
= new ESLint({
4796 cwd
: path
.join(fixtureDir
, ".."),
4799 const fileConfig1
= await engine1
.calculateConfigForFile(filePath
);
4800 const fileConfig2
= await engine2
.calculateConfigForFile(filePath
);
4803 assert
.deepStrictEqual(fileConfig1
.rules
["example/example-rule"], [1], "example is present for engine 1");
4804 assert
.strictEqual(fileConfig2
.rules
["example/example-rule"], void 0, "example is not present for engine 2");
4809 describe("with ignorePatterns config", () => {
4810 const root
= getFixturePath("cli-engine/ignore-patterns");
4812 describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
4813 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
4817 ignorePatterns
: "foo.js"
4821 "subdir/foo.js": "",
4826 beforeEach(prepare
);
4829 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
4830 const engine
= new ESLint({ cwd
: getPath() });
4832 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
4833 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
4836 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
4837 const engine
= new ESLint({ cwd
: getPath() });
4839 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
4840 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), false);
4843 it("'lintFiles()' should not verify 'foo.js'.", async () => {
4844 const engine
= new ESLint({ cwd
: getPath() });
4845 const filePaths
= (await engine
.lintFiles("**/*.js"))
4846 .map(r
=> r
.filePath
)
4849 assert
.deepStrictEqual(filePaths
, [
4850 path
.join(root
, "bar.js"),
4851 path
.join(root
, "subdir/bar.js")
4856 describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
4857 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
4861 ignorePatterns
: ["foo.js", "/bar.js"]
4866 "subdir/foo.js": "",
4867 "subdir/bar.js": "",
4872 beforeEach(prepare
);
4875 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
4876 const engine
= new ESLint({ cwd
: getPath() });
4878 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
4879 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
4882 it("'isPathIgnored()' should return 'true' for '/bar.js'.", async () => {
4883 const engine
= new ESLint({ cwd
: getPath() });
4885 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), true);
4886 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), false);
4889 it("'lintFiles()' should not verify 'foo.js' and '/bar.js'.", async () => {
4890 const engine
= new ESLint({ cwd
: getPath() });
4891 const filePaths
= (await engine
.lintFiles("**/*.js"))
4892 .map(r
=> r
.filePath
)
4895 assert
.deepStrictEqual(filePaths
, [
4896 path
.join(root
, "baz.js"),
4897 path
.join(root
, "subdir/bar.js"),
4898 path
.join(root
, "subdir/baz.js")
4903 describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
4905 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
4909 ignorePatterns
: "!/node_modules/foo"
4911 "node_modules/foo/index.js": "",
4912 "node_modules/foo/.dot.js": "",
4913 "node_modules/bar/index.js": "",
4918 beforeEach(prepare
);
4921 it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", async () => {
4922 const engine
= new ESLint({ cwd
: getPath() });
4924 assert
.strictEqual(await engine
.isPathIgnored("node_modules/foo/index.js"), false);
4927 it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", async () => {
4928 const engine
= new ESLint({ cwd
: getPath() });
4930 assert
.strictEqual(await engine
.isPathIgnored("node_modules/foo/.dot.js"), true);
4933 it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", async () => {
4934 const engine
= new ESLint({ cwd
: getPath() });
4936 assert
.strictEqual(await engine
.isPathIgnored("node_modules/bar/index.js"), true);
4939 it("'lintFiles()' should verify 'node_modules/foo/index.js'.", async () => {
4940 const engine
= new ESLint({ cwd
: getPath() });
4941 const filePaths
= (await engine
.lintFiles("**/*.js"))
4942 .map(r
=> r
.filePath
)
4945 assert
.deepStrictEqual(filePaths
, [
4946 path
.join(root
, "foo.js"),
4947 path
.join(root
, "node_modules/foo/index.js")
4952 describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
4954 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
4957 ".eslintrc.js": `module.exports = ${JSON.stringify({
4958 ignorePatterns: "!.eslintrc.js"
4964 beforeEach(prepare
);
4967 it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", async () => {
4968 const engine
= new ESLint({ cwd
: getPath() });
4970 assert
.strictEqual(await engine
.isPathIgnored(".eslintrc.js"), false);
4973 it("'lintFiles()' should verify '.eslintrc.js'.", async () => {
4974 const engine
= new ESLint({ cwd
: getPath() });
4975 const filePaths
= (await engine
.lintFiles("**/*.js"))
4976 .map(r
=> r
.filePath
)
4979 assert
.deepStrictEqual(filePaths
, [
4980 path
.join(root
, ".eslintrc.js"),
4981 path
.join(root
, "foo.js")
4986 describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
4987 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
4990 ".eslintrc.js": `module.exports = ${JSON.stringify({
4991 ignorePatterns: "!.*"
4993 ".eslintignore": ".foo*",
4999 beforeEach(prepare
);
5002 it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", async () => {
5003 const engine
= new ESLint({ cwd
: getPath() });
5005 assert
.strictEqual(await engine
.isPathIgnored(".foo.js"), true);
5008 it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", async () => {
5009 const engine
= new ESLint({ cwd
: getPath() });
5011 assert
.strictEqual(await engine
.isPathIgnored(".bar.js"), false);
5014 it("'lintFiles()' should not verify re-ignored '.foo.js'.", async () => {
5015 const engine
= new ESLint({ cwd
: getPath() });
5016 const filePaths
= (await engine
.lintFiles("**/*.js"))
5017 .map(r
=> r
.filePath
)
5020 assert
.deepStrictEqual(filePaths
, [
5021 path
.join(root
, ".bar.js"),
5022 path
.join(root
, ".eslintrc.js")
5027 describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
5028 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5031 ".eslintrc.js": `module.exports = ${JSON.stringify({
5032 ignorePatterns: "*.js"
5034 ".eslintignore": "!foo.js",
5040 beforeEach(prepare
);
5043 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
5044 const engine
= new ESLint({ cwd
: getPath() });
5046 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5049 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
5050 const engine
= new ESLint({ cwd
: getPath() });
5052 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), true);
5055 it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
5056 const engine
= new ESLint({ cwd
: getPath() });
5057 const filePaths
= (await engine
.lintFiles("**/*.js"))
5058 .map(r
=> r
.filePath
)
5061 assert
.deepStrictEqual(filePaths
, [
5062 path
.join(root
, "foo.js")
5067 describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
5068 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5071 ".eslintrc.json": JSON
.stringify({
5072 ignorePatterns
: "foo.js"
5074 "subdir/.eslintrc.json": JSON
.stringify({
5075 ignorePatterns
: "bar.js"
5079 "subdir/foo.js": "",
5080 "subdir/bar.js": "",
5081 "subdir/subsubdir/foo.js": "",
5082 "subdir/subsubdir/bar.js": ""
5087 beforeEach(prepare
);
5090 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5091 const engine
= new ESLint({ cwd
: getPath() });
5093 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5094 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5095 assert
.strictEqual(await engine
.isPathIgnored("subdir/subsubdir/foo.js"), true);
5098 it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", async () => {
5099 const engine
= new ESLint({ cwd
: getPath() });
5101 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5102 assert
.strictEqual(await engine
.isPathIgnored("subdir/subsubdir/bar.js"), true);
5105 it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", async () => {
5106 const engine
= new ESLint({ cwd
: getPath() });
5108 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5111 it("'lintFiles()' should verify 'bar.js' in the outside of 'subdir'.", async () => {
5112 const engine
= new ESLint({ cwd
: getPath() });
5113 const filePaths
= (await engine
.lintFiles("**/*.js"))
5114 .map(r
=> r
.filePath
)
5117 assert
.deepStrictEqual(filePaths
, [
5118 path
.join(root
, "bar.js")
5123 describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
5124 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5127 ".eslintrc.json": JSON
.stringify({
5128 ignorePatterns
: "foo.js"
5130 "subdir/.eslintrc.json": JSON
.stringify({
5131 ignorePatterns
: "!foo.js"
5138 beforeEach(prepare
);
5141 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
5142 const engine
= new ESLint({ cwd
: getPath() });
5144 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5147 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
5148 const engine
= new ESLint({ cwd
: getPath() });
5150 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5153 it("'lintFiles()' should verify 'foo.js' in the child directory.", async () => {
5154 const engine
= new ESLint({ cwd
: getPath() });
5155 const filePaths
= (await engine
.lintFiles("**/*.js"))
5156 .map(r
=> r
.filePath
)
5159 assert
.deepStrictEqual(filePaths
, [
5160 path
.join(root
, "subdir/foo.js")
5165 describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
5166 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5169 ".eslintrc.json": JSON
.stringify({}),
5170 "subdir/.eslintrc.json": JSON
.stringify({
5171 ignorePatterns
: "*.js"
5173 ".eslintignore": "!foo.js",
5175 "subdir/foo.js": "",
5180 beforeEach(prepare
);
5183 it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
5184 const engine
= new ESLint({ cwd
: getPath() });
5186 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5187 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5190 it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
5191 const engine
= new ESLint({ cwd
: getPath() });
5193 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5196 it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
5197 const engine
= new ESLint({ cwd
: getPath() });
5198 const filePaths
= (await engine
.lintFiles("**/*.js"))
5199 .map(r
=> r
.filePath
)
5202 assert
.deepStrictEqual(filePaths
, [
5203 path
.join(root
, "foo.js"),
5204 path
.join(root
, "subdir/foo.js")
5209 describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
5210 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5213 ".eslintrc.json": JSON
.stringify({
5214 ignorePatterns
: "foo.js"
5216 "subdir/.eslintrc.json": JSON
.stringify({
5218 ignorePatterns
: "bar.js"
5222 "subdir/foo.js": "",
5227 beforeEach(prepare
);
5230 it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
5231 const engine
= new ESLint({ cwd
: getPath() });
5233 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5236 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
5237 const engine
= new ESLint({ cwd
: getPath() });
5239 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5242 it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
5243 const engine
= new ESLint({ cwd
: getPath() });
5245 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5248 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
5249 const engine
= new ESLint({ cwd
: getPath() });
5251 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5254 it("'lintFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", async () => {
5255 const engine
= new ESLint({ cwd
: getPath() });
5256 const filePaths
= (await engine
.lintFiles("**/*.js"))
5257 .map(r
=> r
.filePath
)
5260 assert
.deepStrictEqual(filePaths
, [
5261 path
.join(root
, "bar.js"),
5262 path
.join(root
, "subdir/foo.js")
5267 describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
5268 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5271 ".eslintrc.json": JSON
.stringify({}),
5272 "subdir/.eslintrc.json": JSON
.stringify({
5274 ignorePatterns
: "bar.js"
5276 ".eslintignore": "foo.js",
5279 "subdir/foo.js": "",
5284 beforeEach(prepare
);
5287 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5288 const engine
= new ESLint({ cwd
: getPath() });
5290 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5291 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), true);
5294 it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
5295 const engine
= new ESLint({ cwd
: getPath() });
5297 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5300 it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
5301 const engine
= new ESLint({ cwd
: getPath() });
5303 assert
.strictEqual(await engine
.isPathIgnored("subdir/bar.js"), true);
5306 it("'lintFiles()' should verify 'bar.js' in the root directory.", async () => {
5307 const engine
= new ESLint({ cwd
: getPath() });
5308 const filePaths
= (await engine
.lintFiles("**/*.js"))
5309 .map(r
=> r
.filePath
)
5312 assert
.deepStrictEqual(filePaths
, [
5313 path
.join(root
, "bar.js")
5318 describe("ignorePatterns in the shareable config should be used.", () => {
5319 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5322 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5323 ignorePatterns: "foo.js"
5325 ".eslintrc.json": JSON
.stringify({
5333 beforeEach(prepare
);
5336 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5337 const engine
= new ESLint({ cwd
: getPath() });
5339 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5342 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5343 const engine
= new ESLint({ cwd
: getPath() });
5345 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5348 it("'lintFiles()' should verify 'bar.js'.", async () => {
5349 const engine
= new ESLint({ cwd
: getPath() });
5350 const filePaths
= (await engine
.lintFiles("**/*.js"))
5351 .map(r
=> r
.filePath
)
5354 assert
.deepStrictEqual(filePaths
, [
5355 path
.join(root
, "bar.js")
5360 describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
5362 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5365 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5366 ignorePatterns: "/foo.js"
5368 ".eslintrc.json": JSON
.stringify({
5376 beforeEach(prepare
);
5379 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5380 const engine
= new ESLint({ cwd
: getPath() });
5382 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5385 it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", async () => {
5386 const engine
= new ESLint({ cwd
: getPath() });
5388 assert
.strictEqual(await engine
.isPathIgnored("subdir/foo.js"), false);
5391 it("'lintFiles()' should verify 'subdir/foo.js'.", async () => {
5392 const engine
= new ESLint({ cwd
: getPath() });
5393 const filePaths
= (await engine
.lintFiles("**/*.js"))
5394 .map(r
=> r
.filePath
)
5397 assert
.deepStrictEqual(filePaths
, [
5398 path
.join(root
, "subdir/foo.js")
5403 describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
5404 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5407 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5408 ignorePatterns: "*.js"
5410 ".eslintrc.json": JSON
.stringify({
5412 ignorePatterns
: "!bar.js"
5419 beforeEach(prepare
);
5422 it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
5423 const engine
= new ESLint({ cwd
: getPath() });
5425 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), true);
5428 it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
5429 const engine
= new ESLint({ cwd
: getPath() });
5431 assert
.strictEqual(await engine
.isPathIgnored("bar.js"), false);
5434 it("'lintFiles()' should verify 'bar.js'.", async () => {
5435 const engine
= new ESLint({ cwd
: getPath() });
5436 const filePaths
= (await engine
.lintFiles("**/*.js"))
5437 .map(r
=> r
.filePath
)
5440 assert
.deepStrictEqual(filePaths
, [
5441 path
.join(root
, "bar.js")
5446 describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
5448 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5451 ".eslintrc.json": JSON
.stringify({
5452 ignorePatterns
: "*.js"
5458 beforeEach(prepare
);
5461 it("'isPathIgnored()' should return 'false' for 'foo.js'.", async () => {
5462 const engine
= new ESLint({ cwd
: getPath(), ignore
: false });
5464 assert
.strictEqual(await engine
.isPathIgnored("foo.js"), false);
5467 it("'lintFiles()' should verify 'foo.js'.", async () => {
5468 const engine
= new ESLint({ cwd
: getPath(), ignore
: false });
5469 const filePaths
= (await engine
.lintFiles("**/*.js"))
5470 .map(r
=> r
.filePath
)
5473 assert
.deepStrictEqual(filePaths
, [
5474 path
.join(root
, "foo.js")
5479 describe("ignorePatterns in overrides section is not allowed.", () => {
5481 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5484 ".eslintrc.js": `module.exports = ${JSON.stringify({
5488 ignorePatterns: "foo.js"
5496 beforeEach(prepare
);
5499 it("should throw a configuration error.", async () => {
5500 await assert
.rejects(async () => {
5501 const engine
= new ESLint({ cwd
: getPath() });
5503 await engine
.lintFiles("*.js");
5504 }, /Unexpected top-level property "overrides\[0\]\.ignorePatterns"/u);
5509 describe("'overrides[].files' adds lint targets", () => {
5510 const root
= getFixturePath("cli-engine/additional-lint-targets");
5513 describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
5514 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5517 ".eslintrc.json": JSON
.stringify({
5521 excludedFiles
: "**/ignore.txt"
5525 "foo/nested/test.txt": "",
5528 "foo/ignore.txt": "",
5531 "bar/ignore.txt": "",
5538 beforeEach(prepare
);
5541 it("'lintFiles()' with a directory path should contain 'foo/test.txt'.", async () => {
5542 const engine
= new ESLint({ cwd
: getPath() });
5543 const filePaths
= (await engine
.lintFiles("."))
5544 .map(r
=> r
.filePath
)
5547 assert
.deepStrictEqual(filePaths
, [
5548 path
.join(root
, "bar/test.js"),
5549 path
.join(root
, "foo/test.js"),
5550 path
.join(root
, "foo/test.txt"),
5551 path
.join(root
, "test.js")
5555 it("'lintFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", async () => {
5556 const engine
= new ESLint({ cwd
: getPath() });
5557 const filePaths
= (await engine
.lintFiles("**/*.js"))
5558 .map(r
=> r
.filePath
)
5561 assert
.deepStrictEqual(filePaths
, [
5562 path
.join(root
, "bar/test.js"),
5563 path
.join(root
, "foo/test.js"),
5564 path
.join(root
, "test.js")
5569 describe("if { files: 'foo/**/*.txt' } is present,", () => {
5571 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5574 ".eslintrc.json": JSON
.stringify({
5577 files
: "foo/**/*.txt"
5581 "foo/nested/test.txt": "",
5591 beforeEach(prepare
);
5594 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5595 const engine
= new ESLint({ cwd
: getPath() });
5596 const filePaths
= (await engine
.lintFiles("."))
5597 .map(r
=> r
.filePath
)
5600 assert
.deepStrictEqual(filePaths
, [
5601 path
.join(root
, "bar/test.js"),
5602 path
.join(root
, "foo/nested/test.txt"),
5603 path
.join(root
, "foo/test.js"),
5604 path
.join(root
, "foo/test.txt"),
5605 path
.join(root
, "test.js")
5610 describe("if { files: 'foo/**/*' } is present,", () => {
5612 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5615 ".eslintrc.json": JSON
.stringify({
5622 "foo/nested/test.txt": "",
5632 beforeEach(prepare
);
5635 it("'lintFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5636 const engine
= new ESLint({ cwd
: getPath() });
5637 const filePaths
= (await engine
.lintFiles("."))
5638 .map(r
=> r
.filePath
)
5641 assert
.deepStrictEqual(filePaths
, [
5642 path
.join(root
, "bar/test.js"),
5643 path
.join(root
, "foo/test.js"),
5644 path
.join(root
, "test.js")
5649 describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
5651 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5654 "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
5657 files: "foo/**/*.txt"
5661 ".eslintrc.json": JSON
.stringify({
5664 "foo/nested/test.txt": "",
5674 beforeEach(prepare
);
5677 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5678 const engine
= new ESLint({ cwd
: getPath() });
5679 const filePaths
= (await engine
.lintFiles("."))
5680 .map(r
=> r
.filePath
)
5683 assert
.deepStrictEqual(filePaths
, [
5684 path
.join(root
, "bar/test.js"),
5685 path
.join(root
, "foo/nested/test.txt"),
5686 path
.join(root
, "foo/test.js"),
5687 path
.join(root
, "foo/test.txt"),
5688 path
.join(root
, "test.js")
5693 describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
5695 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5698 "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
5702 files: "foo/**/*.txt"
5707 ".eslintrc.json": JSON
.stringify({
5708 extends: "plugin:foo/bar"
5710 "foo/nested/test.txt": "",
5720 beforeEach(prepare
);
5723 it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
5724 const engine
= new ESLint({ cwd
: getPath() });
5725 const filePaths
= (await engine
.lintFiles("."))
5726 .map(r
=> r
.filePath
)
5729 assert
.deepStrictEqual(filePaths
, [
5730 path
.join(root
, "bar/test.js"),
5731 path
.join(root
, "foo/nested/test.txt"),
5732 path
.join(root
, "foo/test.js"),
5733 path
.join(root
, "foo/test.txt"),
5734 path
.join(root
, "test.js")
5740 describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
5741 const root
= getFixturePath("cli-engine/config-and-overrides-files");
5743 describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5744 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5747 "node_modules/myconf/.eslintrc.json": {
5757 "node_modules/myconf/foo/test.js": "a == b",
5758 "foo/test.js": "a == b"
5762 beforeEach(prepare
);
5765 it("'lintFiles()' with 'foo/test.js' should use the override entry.", async () => {
5766 const engine
= new ESLint({
5767 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5772 const results
= await engine
.lintFiles("foo/test.js");
5774 // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
5775 assert
.deepStrictEqual(results
, [
5778 filePath
: path
.join(getPath(), "foo/test.js"),
5779 fixableErrorCount
: 0,
5780 fixableWarningCount
: 0,
5787 message
: "Expected '===' and instead saw '=='.",
5788 messageId
: "unexpected",
5789 nodeType
: "BinaryExpression",
5795 usedDeprecatedRules
: [],
5801 it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", async () => {
5802 const engine
= new ESLint({
5803 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5808 const results
= await engine
.lintFiles("node_modules/myconf/foo/test.js");
5810 // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
5811 assert
.deepStrictEqual(results
, [
5814 filePath
: path
.join(getPath(), "node_modules/myconf/foo/test.js"),
5815 fixableErrorCount
: 0,
5816 fixableWarningCount
: 0,
5818 usedDeprecatedRules
: [],
5825 describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5826 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5829 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5833 excludedFiles
: "foo/*.js",
5840 "node_modules/myconf/foo/test.js": "a == b",
5841 "foo/test.js": "a == b"
5845 beforeEach(prepare
);
5848 it("'lintFiles()' with 'foo/test.js' should NOT use the override entry.", async () => {
5849 const engine
= new ESLint({
5850 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5855 const results
= await engine
.lintFiles("foo/test.js");
5857 // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
5858 assert
.deepStrictEqual(results
, [
5861 filePath
: path
.join(getPath(), "foo/test.js"),
5862 fixableErrorCount
: 0,
5863 fixableWarningCount
: 0,
5865 usedDeprecatedRules
: [],
5871 it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", async () => {
5872 const engine
= new ESLint({
5873 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5878 const results
= await engine
.lintFiles("node_modules/myconf/foo/test.js");
5880 // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
5881 assert
.deepStrictEqual(results
, [
5884 filePath
: path
.join(getPath(), "node_modules/myconf/foo/test.js"),
5885 fixableErrorCount
: 0,
5886 fixableWarningCount
: 0,
5893 message
: "Expected '===' and instead saw '=='.",
5894 messageId
: "unexpected",
5895 nodeType
: "BinaryExpression",
5901 usedDeprecatedRules
: [],
5908 describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
5909 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5912 "node_modules/myconf/.eslintrc.json": JSON
.stringify({
5913 ignorePatterns
: ["!/node_modules/myconf", "foo/*.js"],
5918 "node_modules/myconf/foo/test.js": "a == b",
5919 "foo/test.js": "a == b"
5923 beforeEach(prepare
);
5926 it("'lintFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", async () => {
5927 const engine
= new ESLint({
5928 overrideConfigFile
: "node_modules/myconf/.eslintrc.json",
5932 const files
= (await engine
.lintFiles("**/*.js"))
5933 .map(r
=> r
.filePath
)
5936 assert
.deepStrictEqual(files
, [
5937 path
.join(root
, "node_modules/myconf/foo/test.js")
5943 describe("plugin conflicts", () => {
5945 const root
= getFixturePath("cli-engine/plugin-conflicts-");
5948 * Verify thrown errors.
5949 * @param {() => Promise<any>} f The function to run and throw.
5950 * @param {Record<string, any>} props The properties to verify.
5951 * @returns {Promise<void>} void
5953 async
function assertThrows(f
, props
) {
5957 for (const [key
, value
] of Object
.entries(props
)) {
5958 assert
.deepStrictEqual(error
[key
], value
, key
);
5963 assert
.fail("Function should throw an error, but not.");
5966 describe("between a config file and linear extendees.", () => {
5968 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
5969 cwd
: `${root}${++uid}`,
5971 "node_modules/eslint-plugin-foo/index.js": "",
5972 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
5973 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
5977 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
5978 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
5981 ".eslintrc.json": JSON
.stringify({
5989 beforeEach(prepare
);
5992 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
5993 const engine
= new ESLint({ cwd
: getPath() });
5995 await engine
.lintFiles("test.js");
5999 describe("between a config file and same-depth extendees.", () => {
6001 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6002 cwd
: `${root}${++uid}`,
6004 "node_modules/eslint-plugin-foo/index.js": "",
6005 "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
6006 "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
6009 "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
6010 "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
6013 ".eslintrc.json": JSON
.stringify({
6014 extends: ["one", "two"],
6021 beforeEach(prepare
);
6024 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
6025 const engine
= new ESLint({ cwd
: getPath() });
6027 await engine
.lintFiles("test.js");
6031 describe("between two config files in different directories, with single node_modules.", () => {
6033 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6034 cwd
: `${root}${++uid}`,
6036 "node_modules/eslint-plugin-foo/index.js": "",
6037 ".eslintrc.json": JSON
.stringify({
6040 "subdir/.eslintrc.json": JSON
.stringify({
6043 "subdir/test.js": ""
6047 beforeEach(prepare
);
6050 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 () => {
6051 const engine
= new ESLint({ cwd
: getPath() });
6053 await engine
.lintFiles("subdir/test.js");
6057 describe("between two config files in different directories, with multiple node_modules.", () => {
6059 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6060 cwd
: `${root}${++uid}`,
6062 "node_modules/eslint-plugin-foo/index.js": "",
6063 ".eslintrc.json": JSON
.stringify({
6066 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6067 "subdir/.eslintrc.json": JSON
.stringify({
6070 "subdir/test.js": ""
6074 beforeEach(prepare
);
6077 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 () => {
6078 const engine
= new ESLint({ cwd
: getPath() });
6081 () => engine
.lintFiles("subdir/test.js"),
6083 message
: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
6084 messageTemplate
: "plugin-conflict",
6089 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6090 importerName
: `subdir${path.sep}.eslintrc.json`
6093 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6094 importerName
: ".eslintrc.json"
6103 describe("between '--config' option and a regular config file, with single node_modules.", () => {
6105 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6106 cwd
: `${root}${++uid}`,
6108 "node_modules/eslint-plugin-foo/index.js": "",
6109 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6112 ".eslintrc.json": JSON
.stringify({
6119 beforeEach(prepare
);
6122 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 () => {
6123 const engine
= new ESLint({
6125 overrideConfigFile
: "node_modules/mine/.eslintrc.json"
6128 await engine
.lintFiles("test.js");
6132 describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
6134 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6135 cwd
: `${root}${++uid}`,
6137 "node_modules/eslint-plugin-foo/index.js": "",
6138 "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
6139 "node_modules/mine/.eslintrc.json": JSON
.stringify({
6142 ".eslintrc.json": JSON
.stringify({
6149 beforeEach(prepare
);
6152 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 () => {
6153 const engine
= new ESLint({
6155 overrideConfigFile
: "node_modules/mine/.eslintrc.json"
6159 () => engine
.lintFiles("test.js"),
6161 message
: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
6162 messageTemplate
: "plugin-conflict",
6167 filePath
: path
.join(getPath(), "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
6168 importerName
: "--config"
6171 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6172 importerName
: ".eslintrc.json"
6181 describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
6183 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6184 cwd
: `${root}${++uid}`,
6186 "node_modules/eslint-plugin-foo/index.js": "",
6187 "subdir/.eslintrc.json": JSON
.stringify({
6190 "subdir/test.js": ""
6195 beforeEach(prepare
);
6198 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 () => {
6199 const engine
= new ESLint({
6201 overrideConfig
: { plugins
: ["foo"] }
6204 await engine
.lintFiles("subdir/test.js");
6208 describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
6210 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6211 cwd
: `${root}${++uid}`,
6213 "node_modules/eslint-plugin-foo/index.js": "",
6214 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6215 "subdir/.eslintrc.json": JSON
.stringify({
6218 "subdir/test.js": ""
6222 beforeEach(prepare
);
6225 it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", async () => {
6226 const engine
= new ESLint({
6228 overrideConfig
: { plugins
: ["foo"] }
6232 () => engine
.lintFiles("subdir/test.js"),
6234 message
: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
6235 messageTemplate
: "plugin-conflict",
6240 filePath
: path
.join(getPath(), "node_modules/eslint-plugin-foo/index.js"),
6241 importerName
: "CLIOptions"
6244 filePath
: path
.join(getPath(), "subdir/node_modules/eslint-plugin-foo/index.js"),
6245 importerName
: `subdir${path.sep}.eslintrc.json`
6254 describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
6256 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6257 cwd
: `${root}${++uid}`,
6259 "node_modules/eslint-plugin-foo/index.js": "",
6260 ".eslintrc.json": JSON
.stringify({
6263 "subdir/node_modules/eslint-plugin-foo/index.js": "",
6264 "subdir/.eslintrc.json": JSON
.stringify({
6267 "subdir/test.js": ""
6271 beforeEach(prepare
);
6274 it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", async () => {
6275 const engine
= new ESLint({
6277 resolvePluginsRelativeTo
: getPath()
6280 await engine
.lintFiles("subdir/test.js");
6284 describe("between two config files with different target files.", () => {
6286 const { prepare
, cleanup
, getPath
} = createCustomTeardown({
6287 cwd
: `${root}${++uid}`,
6289 "one/node_modules/eslint-plugin-foo/index.js": "",
6290 "one/.eslintrc.json": JSON
.stringify({
6294 "two/node_modules/eslint-plugin-foo/index.js": "",
6295 "two/.eslintrc.json": JSON
.stringify({
6302 beforeEach(prepare
);
6305 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 () => {
6306 const engine
= new ESLint({ cwd
: getPath() });
6307 const results
= await engine
.lintFiles("*/test.js");
6309 assert
.strictEqual(results
.length
, 2);