From 6a0196c51310630a0ff96a1e8d7f257c2c7adda9 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Wed, 7 Jun 2023 09:25:04 +0200 Subject: [PATCH] chore: use eslint-plugin-eslint-plugin flat configs (#17204) * chore: use eslint-plugin-eslint-plugin flat configs * fix bin tests * fix cli tests * fix flat-eslint tests * fix eslint tests * fix cli-engine tests --- .eslintrc.js | 4 - eslint.config.js | 41 ++-- lib/rules/logical-assignment-operators.js | 1 - lib/rules/newline-after-var.js | 2 - package.json | 2 +- tests/bin/eslint.js | 8 +- .../simple-valid-project/.eslintrc.js | 5 + .../simple-valid-project/eslint.config.js | 5 + tests/fixtures/simple-valid-project/foo.js | 1 + .../simple-valid-project/src/foobar.js | 1 + tests/lib/cli-engine/cli-engine.js | 202 +++++++++++++----- tests/lib/cli.js | 55 ++++- tests/lib/eslint/eslint.js | 165 ++++++++++---- tests/lib/eslint/flat-eslint.js | 21 +- 14 files changed, 361 insertions(+), 152 deletions(-) create mode 100644 tests/fixtures/simple-valid-project/.eslintrc.js create mode 100644 tests/fixtures/simple-valid-project/eslint.config.js create mode 100644 tests/fixtures/simple-valid-project/foo.js create mode 100644 tests/fixtures/simple-valid-project/src/foobar.js diff --git a/.eslintrc.js b/.eslintrc.js index 4ceed4d3693..ae258dc6441 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -96,9 +96,6 @@ module.exports = { "plugin:eslint-plugin/rules-recommended" ], rules: { - "eslint-plugin/no-missing-message-ids": "error", - "eslint-plugin/no-unused-message-ids": "error", - "eslint-plugin/prefer-message-ids": "error", "eslint-plugin/prefer-placeholders": "error", "eslint-plugin/prefer-replace-text": "error", "eslint-plugin/report-message-format": ["error", "[^a-z].*\\.$"], @@ -119,7 +116,6 @@ module.exports = { "plugin:eslint-plugin/tests-recommended" ], rules: { - "eslint-plugin/prefer-output-null": "error", "eslint-plugin/test-case-property-ordering": "error", "eslint-plugin/test-case-shorthand-strings": "error" } diff --git a/eslint.config.js b/eslint.config.js index 5c488a57a15..492e6793ffa 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -27,10 +27,12 @@ const path = require("path"); const internalPlugin = require("eslint-plugin-internal-rules"); -const eslintPlugin = require("eslint-plugin-eslint-plugin"); +const eslintPluginRulesRecommendedConfig = require("eslint-plugin-eslint-plugin/configs/rules-recommended"); +const eslintPluginTestsRecommendedConfig = require("eslint-plugin-eslint-plugin/configs/tests-recommended"); const { FlatCompat } = require("@eslint/eslintrc"); const js = require("./packages/js"); const globals = require("globals"); +const merge = require("lodash.merge"); //----------------------------------------------------------------------------- // Helpers @@ -99,8 +101,7 @@ module.exports = [ }, { plugins: { - "internal-rules": internalPlugin, - "eslint-plugin": eslintPlugin + "internal-rules": internalPlugin }, languageOptions: { ecmaVersion: "latest" @@ -129,33 +130,31 @@ module.exports = [ { files: ["lib/rules/*", "tools/internal-rules/*"], ignores: ["**/index.js"], - rules: { - ...eslintPlugin.configs["rules-recommended"].rules, - "eslint-plugin/no-missing-message-ids": "error", - "eslint-plugin/no-unused-message-ids": "error", - "eslint-plugin/prefer-message-ids": "error", - "eslint-plugin/prefer-placeholders": "error", - "eslint-plugin/prefer-replace-text": "error", - "eslint-plugin/report-message-format": ["error", "[^a-z].*\\.$"], - "eslint-plugin/require-meta-docs-description": ["error", { pattern: "^(Enforce|Require|Disallow) .+[^. ]$" }], - "internal-rules/no-invalid-meta": "error" - } + ...merge({}, eslintPluginRulesRecommendedConfig, { + rules: { + "eslint-plugin/prefer-placeholders": "error", + "eslint-plugin/prefer-replace-text": "error", + "eslint-plugin/report-message-format": ["error", "[^a-z].*\\.$"], + "eslint-plugin/require-meta-docs-description": ["error", { pattern: "^(Enforce|Require|Disallow) .+[^. ]$" }], + "internal-rules/no-invalid-meta": "error" + } + }) }, { files: ["lib/rules/*"], - ignores: ["index.js"], + ignores: ["**/index.js"], rules: { "eslint-plugin/require-meta-docs-url": ["error", { pattern: "https://eslint.org/docs/latest/rules/{{name}}" }] } }, { files: ["tests/lib/rules/*", "tests/tools/internal-rules/*"], - rules: { - ...eslintPlugin.configs["tests-recommended"].rules, - "eslint-plugin/prefer-output-null": "error", - "eslint-plugin/test-case-property-ordering": "error", - "eslint-plugin/test-case-shorthand-strings": "error" - } + ...merge({}, eslintPluginTestsRecommendedConfig, { + rules: { + "eslint-plugin/test-case-property-ordering": "error", + "eslint-plugin/test-case-shorthand-strings": "error" + } + }) }, { files: ["tests/**/*.js"], diff --git a/lib/rules/logical-assignment-operators.js b/lib/rules/logical-assignment-operators.js index d373bec6d09..cb1cbe5a16b 100644 --- a/lib/rules/logical-assignment-operators.js +++ b/lib/rules/logical-assignment-operators.js @@ -188,7 +188,6 @@ module.exports = { }] }, fixable: "code", - // eslint-disable-next-line eslint-plugin/require-meta-has-suggestions -- Does not detect conditional suggestions hasSuggestions: true, messages: { assignment: "Assignment (=) can be replaced with operator assignment ({{operator}}).", diff --git a/lib/rules/newline-after-var.js b/lib/rules/newline-after-var.js index 5c9b5fbd10f..dc8b24d4738 100644 --- a/lib/rules/newline-after-var.js +++ b/lib/rules/newline-after-var.js @@ -212,7 +212,6 @@ module.exports = { context.report({ node, messageId: "unexpected", - data: { identifier: node.name }, fix(fixer) { const linesBetween = sourceCode.getText().slice(lastToken.range[1], nextToken.range[0]).split(astUtils.LINEBREAK_MATCHER); @@ -231,7 +230,6 @@ module.exports = { context.report({ node, messageId: "expected", - data: { identifier: node.name }, fix(fixer) { if ((noNextLineToken ? getLastCommentLineOfBlock(nextLineNum) : lastToken.loc.end.line) === nextToken.loc.start.line) { return fixer.insertTextBefore(nextToken, "\n\n"); diff --git a/package.json b/package.json index 7a34beb8fa7..9798881120e 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "eslint": "file:.", "eslint-config-eslint": "file:packages/eslint-config-eslint", "eslint-plugin-eslint-comments": "^3.2.0", - "eslint-plugin-eslint-plugin": "^4.4.0", + "eslint-plugin-eslint-plugin": "^5.1.0", "eslint-plugin-internal-rules": "file:tools/internal-rules", "eslint-plugin-jsdoc": "^38.1.6", "eslint-plugin-n": "^15.2.4", diff --git a/tests/bin/eslint.js b/tests/bin/eslint.js index 848dba14671..b09496202b0 100644 --- a/tests/bin/eslint.js +++ b/tests/bin/eslint.js @@ -204,10 +204,10 @@ describe("bin/eslint.js", () => { }); describe("running on files", () => { - it("has exit code 0 if no linting errors occur", () => assertExitCode(runESLint(["bin/eslint.js"]), 0)); + it("has exit code 0 if no linting errors occur", () => assertExitCode(runESLint(["bin/eslint.js", "--no-config-lookup"]), 0)); it("has exit code 0 if a linting warning is reported", () => assertExitCode(runESLint(["bin/eslint.js", "--no-config-lookup", "--rule", "semi: [1, never]"]), 0)); it("has exit code 1 if a linting error is reported", () => assertExitCode(runESLint(["bin/eslint.js", "--no-config-lookup", "--rule", "semi: [2, never]"]), 1)); - it("has exit code 1 if a syntax error is thrown", () => assertExitCode(runESLint(["tests/fixtures/exit-on-fatal-error/fatal-error.js", "--no-ignore"]), 1)); + it("has exit code 1 if a syntax error is thrown", () => assertExitCode(runESLint(["tests/fixtures/exit-on-fatal-error/fatal-error.js", "--no-config-lookup"]), 1)); }); describe("automatically fixing files", () => { @@ -359,7 +359,7 @@ describe("bin/eslint.js", () => { describe("handling crashes", () => { it("prints the error message to stderr in the event of a crash", () => { - const child = runESLint(["--rule=no-restricted-syntax:[error, 'Invalid Selector [[[']", "Makefile.js"]); + const child = runESLint(["--rule=no-restricted-syntax:[error, 'Invalid Selector [[[']", "--no-config-lookup", "Makefile.js"]); const exitCodeAssertion = assertExitCode(child, 2); const outputAssertion = getOutput(child).then(output => { const expectedSubstring = "Syntax error in selector"; @@ -372,7 +372,7 @@ describe("bin/eslint.js", () => { }); it("prints the error message exactly once to stderr in the event of a crash", () => { - const child = runESLint(["--rule=no-restricted-syntax:[error, 'Invalid Selector [[[']", "Makefile.js"]); + const child = runESLint(["--rule=no-restricted-syntax:[error, 'Invalid Selector [[[']", "--no-config-lookup", "Makefile.js"]); const exitCodeAssertion = assertExitCode(child, 2); const outputAssertion = getOutput(child).then(output => { const expectedSubstring = "Syntax error in selector"; diff --git a/tests/fixtures/simple-valid-project/.eslintrc.js b/tests/fixtures/simple-valid-project/.eslintrc.js new file mode 100644 index 00000000000..cf2cd6e50a4 --- /dev/null +++ b/tests/fixtures/simple-valid-project/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + rules: { + quotes: ["error", "single"] + } +}; diff --git a/tests/fixtures/simple-valid-project/eslint.config.js b/tests/fixtures/simple-valid-project/eslint.config.js new file mode 100644 index 00000000000..6817217d965 --- /dev/null +++ b/tests/fixtures/simple-valid-project/eslint.config.js @@ -0,0 +1,5 @@ +module.exports = [{ + rules: { + quotes: ["error", "single"] + } +}]; diff --git a/tests/fixtures/simple-valid-project/foo.js b/tests/fixtures/simple-valid-project/foo.js new file mode 100644 index 00000000000..9e9f472d7ee --- /dev/null +++ b/tests/fixtures/simple-valid-project/foo.js @@ -0,0 +1 @@ +var a = 'b'; diff --git a/tests/fixtures/simple-valid-project/src/foobar.js b/tests/fixtures/simple-valid-project/src/foobar.js new file mode 100644 index 00000000000..9e9f472d7ee --- /dev/null +++ b/tests/fixtures/simple-valid-project/src/foobar.js @@ -0,0 +1 @@ +var a = 'b'; diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js index 2528a398ea1..971d6e60964 100644 --- a/tests/lib/cli-engine/cli-engine.js +++ b/tests/lib/cli-engine/cli-engine.js @@ -138,57 +138,83 @@ describe("CLIEngine", () => { let engine; - it("should report the total and per file errors when using local cwd .eslintrc", () => { + describe("when using local cwd .eslintrc", () => { - engine = new CLIEngine(); + const { prepare, cleanup, getPath } = createCustomTeardown({ + cwd: path.join(os.tmpdir(), "eslint/multiple-rules-config"), + files: { + ".eslintrc.json": { + root: true, + rules: { + quotes: 2, + "no-var": 2, + "eol-last": 2, + strict: [2, "global"], + "no-unused-vars": 2 + }, + env: { + node: true + } + } + } + }); - const report = engine.executeOnText("var foo = 'bar';"); + beforeEach(prepare); + afterEach(cleanup); - assert.strictEqual(report.results.length, 1); - assert.strictEqual(report.errorCount, 5); - assert.strictEqual(report.warningCount, 0); - assert.strictEqual(report.fatalErrorCount, 0); - assert.strictEqual(report.fixableErrorCount, 3); - assert.strictEqual(report.fixableWarningCount, 0); - assert.strictEqual(report.results[0].messages.length, 5); - assert.strictEqual(report.results[0].messages[0].ruleId, "strict"); - assert.strictEqual(report.results[0].messages[1].ruleId, "no-var"); - assert.strictEqual(report.results[0].messages[2].ruleId, "no-unused-vars"); - assert.strictEqual(report.results[0].messages[3].ruleId, "quotes"); - assert.strictEqual(report.results[0].messages[4].ruleId, "eol-last"); - assert.strictEqual(report.results[0].fixableErrorCount, 3); - assert.strictEqual(report.results[0].fixableWarningCount, 0); - assert.strictEqual(report.results[0].suppressedMessages.length, 0); - }); + it("should report the total and per file errors", () => { - it("should report the total and per file warnings when using local cwd .eslintrc", () => { + engine = new CLIEngine({ cwd: getPath() }); - engine = new CLIEngine({ - rules: { - quotes: 1, - "no-var": 1, - "eol-last": 1, - strict: 1, - "no-unused-vars": 1 - } + const report = engine.executeOnText("var foo = 'bar';"); + + assert.strictEqual(report.results.length, 1); + assert.strictEqual(report.errorCount, 5); + assert.strictEqual(report.warningCount, 0); + assert.strictEqual(report.fatalErrorCount, 0); + assert.strictEqual(report.fixableErrorCount, 3); + assert.strictEqual(report.fixableWarningCount, 0); + assert.strictEqual(report.results[0].messages.length, 5); + assert.strictEqual(report.results[0].messages[0].ruleId, "strict"); + assert.strictEqual(report.results[0].messages[1].ruleId, "no-var"); + assert.strictEqual(report.results[0].messages[2].ruleId, "no-unused-vars"); + assert.strictEqual(report.results[0].messages[3].ruleId, "quotes"); + assert.strictEqual(report.results[0].messages[4].ruleId, "eol-last"); + assert.strictEqual(report.results[0].fixableErrorCount, 3); + assert.strictEqual(report.results[0].fixableWarningCount, 0); + assert.strictEqual(report.results[0].suppressedMessages.length, 0); }); - const report = engine.executeOnText("var foo = 'bar';"); + it("should report the total and per file warnings", () => { - assert.strictEqual(report.results.length, 1); - assert.strictEqual(report.errorCount, 0); - assert.strictEqual(report.warningCount, 5); - assert.strictEqual(report.fixableErrorCount, 0); - assert.strictEqual(report.fixableWarningCount, 3); - assert.strictEqual(report.results[0].messages.length, 5); - assert.strictEqual(report.results[0].messages[0].ruleId, "strict"); - assert.strictEqual(report.results[0].messages[1].ruleId, "no-var"); - assert.strictEqual(report.results[0].messages[2].ruleId, "no-unused-vars"); - assert.strictEqual(report.results[0].messages[3].ruleId, "quotes"); - assert.strictEqual(report.results[0].messages[4].ruleId, "eol-last"); - assert.strictEqual(report.results[0].fixableErrorCount, 0); - assert.strictEqual(report.results[0].fixableWarningCount, 3); - assert.strictEqual(report.results[0].suppressedMessages.length, 0); + engine = new CLIEngine({ + cwd: getPath(), + rules: { + quotes: 1, + "no-var": 1, + "eol-last": 1, + strict: 1, + "no-unused-vars": 1 + } + }); + + const report = engine.executeOnText("var foo = 'bar';"); + + assert.strictEqual(report.results.length, 1); + assert.strictEqual(report.errorCount, 0); + assert.strictEqual(report.warningCount, 5); + assert.strictEqual(report.fixableErrorCount, 0); + assert.strictEqual(report.fixableWarningCount, 3); + assert.strictEqual(report.results[0].messages.length, 5); + assert.strictEqual(report.results[0].messages[0].ruleId, "strict"); + assert.strictEqual(report.results[0].messages[1].ruleId, "no-var"); + assert.strictEqual(report.results[0].messages[2].ruleId, "no-unused-vars"); + assert.strictEqual(report.results[0].messages[3].ruleId, "quotes"); + assert.strictEqual(report.results[0].messages[4].ruleId, "eol-last"); + assert.strictEqual(report.results[0].fixableErrorCount, 0); + assert.strictEqual(report.results[0].fixableWarningCount, 3); + assert.strictEqual(report.results[0].suppressedMessages.length, 0); + }); }); it("should report one message when using specific config file", () => { @@ -836,10 +862,12 @@ describe("CLIEngine", () => { engine = new CLIEngine({ cwd: originalDir, - configFile: ".eslintrc.js" + useEslintrc: false, + ignore: false, + overrideConfigFile: "tests/fixtures/simple-valid-project/.eslintrc.js" }); - const report = engine.executeOnFiles(["lib/**/cli*.js"]); + const report = engine.executeOnFiles(["tests/fixtures/simple-valid-project/**/foo*.js"]); assert.strictEqual(report.results.length, 2); assert.strictEqual(report.results[0].messages.length, 0); @@ -851,10 +879,16 @@ describe("CLIEngine", () => { engine = new CLIEngine({ cwd: originalDir, - configFile: ".eslintrc.js" + useEslintrc: false, + ignore: false, + overrideConfigFile: "tests/fixtures/simple-valid-project/.eslintrc.js" }); - const report = engine.executeOnFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]); + const report = engine.executeOnFiles([ + "tests/fixtures/simple-valid-project/**/foo*.js", + "tests/fixtures/simple-valid-project/foo.?s", + "tests/fixtures/simple-valid-project/{foo,src/foobar}.js" + ]); assert.strictEqual(report.results.length, 2); assert.strictEqual(report.results[0].messages.length, 0); @@ -1394,6 +1428,7 @@ describe("CLIEngine", () => { it("should throw an error when all given files are ignored", () => { engine = new CLIEngine({ + useEslintrc: false, ignorePath: getFixturePath(".eslintignore") }); @@ -1404,6 +1439,7 @@ describe("CLIEngine", () => { it("should throw an error when all given files are ignored even with a `./` prefix", () => { engine = new CLIEngine({ + useEslintrc: false, ignorePath: getFixturePath(".eslintignore") }); @@ -1450,6 +1486,7 @@ describe("CLIEngine", () => { it("should throw an error when all given files are ignored via ignore-pattern", () => { engine = new CLIEngine({ + useEslintrc: false, ignorePattern: "tests/fixtures/single-quoted.js" }); @@ -1712,7 +1749,7 @@ describe("CLIEngine", () => { it("should warn when deprecated rules are configured", () => { engine = new CLIEngine({ cwd: originalDir, - configFile: ".eslintrc.js", + useEslintrc: false, rules: { "indent-legacy": 1, "require-jsdoc": 1, @@ -1736,7 +1773,7 @@ describe("CLIEngine", () => { it("should not warn when deprecated rules are not configured", () => { engine = new CLIEngine({ cwd: originalDir, - configFile: ".eslintrc.js", + useEslintrc: false, rules: { indent: 1, "valid-jsdoc": 0, "require-jsdoc": 0 } }); @@ -4881,7 +4918,21 @@ describe("CLIEngine", () => { it("should report 5 error messages when looking for errors only", () => { process.chdir(originalDir); - const engine = new CLIEngine(); + const engine = new CLIEngine({ + useEslintrc: false, + baseConfig: { + rules: { + quotes: 2, + "no-var": 2, + "eol-last": 2, + strict: [2, "global"], + "no-unused-vars": 2 + }, + env: { + node: true + } + } + }); const report = engine.executeOnText("var foo = 'bar';"); const errorResults = CLIEngine.getErrorResults(report.results); @@ -4905,7 +4956,21 @@ describe("CLIEngine", () => { it("should report no error messages when looking for errors only", () => { process.chdir(originalDir); - const engine = new CLIEngine(); + const engine = new CLIEngine({ + useEslintrc: false, + baseConfig: { + rules: { + quotes: 2, + "no-var": 2, + "eol-last": 2, + strict: [2, "global"], + "no-unused-vars": 2 + }, + env: { + node: true + } + } + }); const report = engine.executeOnText("var foo = 'bar'; // eslint-disable-line strict, no-var, no-unused-vars, quotes, eol-last -- justification"); const errorResults = CLIEngine.getErrorResults(report.results); @@ -4916,12 +4981,18 @@ describe("CLIEngine", () => { it("should not mutate passed report.results parameter", () => { process.chdir(originalDir); const engine = new CLIEngine({ - rules: { quotes: [1, "double"] } + useEslintrc: false, + rules: { + quotes: [1, "double"], + "no-var": 2 + } }); const report = engine.executeOnText("var foo = 'bar';"); const reportResultsLength = report.results[0].messages.length; + assert.strictEqual(report.results[0].messages.length, 2); + CLIEngine.getErrorResults(report.results); assert.lengthOf(report.results[0].messages, reportResultsLength); @@ -4930,9 +5001,16 @@ describe("CLIEngine", () => { it("should report no suppressed error messages when looking for errors only", () => { process.chdir(originalDir); const engine = new CLIEngine({ + useEslintrc: false, rules: { - quotes: [1, "double"], - "no-var": 2 + quotes: 1, + "no-var": 2, + "eol-last": 2, + strict: [2, "global"], + "no-unused-vars": 2 + }, + env: { + node: true } }); @@ -4948,7 +5026,21 @@ describe("CLIEngine", () => { it("should report a warningCount of 0 when looking for errors only", () => { process.chdir(originalDir); - const engine = new CLIEngine(); + const engine = new CLIEngine({ + useEslintrc: false, + baseConfig: { + rules: { + quotes: 2, + "no-var": 2, + "eol-last": 2, + strict: [2, "global"], + "no-unused-vars": 2 + }, + env: { + node: true + } + } + }); const report = engine.executeOnText("var foo = 'bar';"); const errorResults = CLIEngine.getErrorResults(report.results); diff --git a/tests/lib/cli.js b/tests/lib/cli.js index a487c9553de..15556e5cfd1 100644 --- a/tests/lib/cli.js +++ b/tests/lib/cli.js @@ -114,15 +114,16 @@ describe("cli", () => { describe("execute()", () => { it(`should return error when text with incorrect quotes is passed as argument with configType:${configType}`, async () => { + const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc"; const configFile = getFixturePath("configurations", "quotes-error.js"); - const result = await cli.execute(`-c ${configFile} --stdin --stdin-filename foo.js`, "var foo = 'bar';", useFlatConfig); + const result = await cli.execute(`${flag} -c ${configFile} --stdin --stdin-filename foo.js`, "var foo = 'bar';", useFlatConfig); assert.strictEqual(result, 1); }); it(`should not print debug info when passed the empty string as text with configType:${configType}`, async () => { const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc"; - const result = await cli.execute(["--stdin", flag, "--stdin-filename", "foo.js"], "", useFlatConfig); + const result = await cli.execute(["argv0", "argv1", "--stdin", flag, "--stdin-filename", "foo.js"], "", useFlatConfig); assert.strictEqual(result, 0); assert.isTrue(log.info.notCalled); @@ -206,20 +207,30 @@ describe("cli", () => { describe("when there is a local config file", () => { + const originalCwd = process.cwd; + + beforeEach(() => { + process.cwd = () => getFixturePath(); + }); + + afterEach(() => { + process.cwd = originalCwd; + }); + it(`should load the local config file with configType:${configType}`, async () => { - await cli.execute("lib/cli.js", null, useFlatConfig); + await cli.execute("cli/passing.js --no-ignore", null, useFlatConfig); }); if (useFlatConfig) { it(`should load the local config file with glob pattern and configType:${configType}`, async () => { - await cli.execute("lib/cli*.js", null, useFlatConfig); + await cli.execute("cli/pass*.js --no-ignore", null, useFlatConfig); }); } // only works on Windows if (os.platform() === "win32") { it(`should load the local config file with Windows slashes glob pattern and configType:${configType}`, async () => { - await cli.execute("lib\\cli*.js", null, useFlatConfig); + await cli.execute("cli\\pass*.js --no-ignore", null, useFlatConfig); }); } }); @@ -336,10 +347,21 @@ describe("cli", () => { }); describe("when given an invalid formatter path", () => { + + const originalCwd = process.cwd; + + beforeEach(() => { + process.cwd = () => getFixturePath(); + }); + + afterEach(() => { + process.cwd = originalCwd; + }); + it(`should execute with error with configType:${configType}`, async () => { const formatterPath = getFixturePath("formatters", "file-does-not-exist.js"); const filePath = getFixturePath("passing.js"); - const exit = await cli.execute(`-f ${formatterPath} ${filePath}`, null, useFlatConfig); + const exit = await cli.execute(`--no-ignore -f ${formatterPath} ${filePath}`, null, useFlatConfig); assert.strictEqual(exit, 2); }); @@ -869,13 +891,15 @@ describe("cli", () => { }); describe("when supplied with report output file path", () => { + const flag = useFlatConfig ? "--no-config-lookup" : "--no-eslintrc"; + afterEach(() => { sh.rm("-rf", "tests/output"); }); it(`should write the file and create dirs if they don't exist with configType:${configType}`, async () => { const filePath = getFixturePath("single-quoted.js"); - const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`; + const code = `${flag} --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`; await cli.execute(code, null, useFlatConfig); @@ -885,7 +909,7 @@ describe("cli", () => { it(`should return an error if the path is a directory with configType:${configType}`, async () => { const filePath = getFixturePath("single-quoted.js"); - const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output ${filePath}`; + const code = `${flag} --rule 'quotes: [1, double]' --o tests/output ${filePath}`; fs.mkdirSync("tests/output"); @@ -898,7 +922,7 @@ describe("cli", () => { it(`should return an error if the path could not be written to with configType:${configType}`, async () => { const filePath = getFixturePath("single-quoted.js"); - const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`; + const code = `${flag} --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`; fs.writeFileSync("tests/output", "foo"); @@ -1277,8 +1301,19 @@ describe("cli", () => { }); describe("when passing --print-config", () => { + + const originalCwd = process.cwd; + + beforeEach(() => { + process.cwd = () => getFixturePath(); + }); + + afterEach(() => { + process.cwd = originalCwd; + }); + it(`should print out the configuration with configType:${configType}`, async () => { - const filePath = getFixturePath("xxxx"); + const filePath = getFixturePath("xxx.js"); const exitCode = await cli.execute(`--print-config ${filePath}`, null, useFlatConfig); diff --git a/tests/lib/eslint/eslint.js b/tests/lib/eslint/eslint.js index c05a869641d..a422f4b867f 100644 --- a/tests/lib/eslint/eslint.js +++ b/tests/lib/eslint/eslint.js @@ -117,7 +117,7 @@ describe("ESLint", () => { it("the default value of 'options.cwd' should be the current working directory.", async () => { process.chdir(__dirname); try { - const engine = new ESLint(); + const engine = new ESLint({ useEslintrc: false }); const results = await engine.lintFiles("eslint.js"); assert.strictEqual(path.dirname(results[0].filePath), __dirname); @@ -239,46 +239,71 @@ describe("ESLint", () => { describe("lintText()", () => { let eslint; - it("should report the total and per file errors when using local cwd .eslintrc", async () => { - eslint = new ESLint(); - const results = await eslint.lintText("var foo = 'bar';"); - - assert.strictEqual(results.length, 1); - assert.strictEqual(results[0].messages.length, 5); - assert.strictEqual(results[0].messages[0].ruleId, "strict"); - assert.strictEqual(results[0].messages[1].ruleId, "no-var"); - assert.strictEqual(results[0].messages[2].ruleId, "no-unused-vars"); - assert.strictEqual(results[0].messages[3].ruleId, "quotes"); - assert.strictEqual(results[0].messages[4].ruleId, "eol-last"); - assert.strictEqual(results[0].fixableErrorCount, 3); - assert.strictEqual(results[0].fixableWarningCount, 0); - assert.strictEqual(results[0].usedDeprecatedRules.length, 0); - }); - - it("should report the total and per file warnings when using local cwd .eslintrc", async () => { - eslint = new ESLint({ - overrideConfig: { - rules: { - quotes: 1, - "no-var": 1, - "eol-last": 1, - strict: 1, - "no-unused-vars": 1 + describe("when using local cwd .eslintrc", () => { + const { prepare, cleanup, getPath } = createCustomTeardown({ + cwd: path.join(os.tmpdir(), "eslint/multiple-rules-config"), + files: { + ".eslintrc.json": { + root: true, + rules: { + quotes: 2, + "no-var": 2, + "eol-last": 2, + strict: [2, "global"], + "no-unused-vars": 2 + }, + env: { + node: true + } } } }); - const results = await eslint.lintText("var foo = 'bar';"); - assert.strictEqual(results.length, 1); - assert.strictEqual(results[0].messages.length, 5); - assert.strictEqual(results[0].messages[0].ruleId, "strict"); - assert.strictEqual(results[0].messages[1].ruleId, "no-var"); - assert.strictEqual(results[0].messages[2].ruleId, "no-unused-vars"); - assert.strictEqual(results[0].messages[3].ruleId, "quotes"); - assert.strictEqual(results[0].messages[4].ruleId, "eol-last"); - assert.strictEqual(results[0].fixableErrorCount, 0); - assert.strictEqual(results[0].fixableWarningCount, 3); - assert.strictEqual(results[0].usedDeprecatedRules.length, 0); + beforeEach(prepare); + afterEach(cleanup); + + it("should report the total and per file errors", async () => { + eslint = new ESLint({ cwd: getPath() }); + const results = await eslint.lintText("var foo = 'bar';"); + + assert.strictEqual(results.length, 1); + assert.strictEqual(results[0].messages.length, 5); + assert.strictEqual(results[0].messages[0].ruleId, "strict"); + assert.strictEqual(results[0].messages[1].ruleId, "no-var"); + assert.strictEqual(results[0].messages[2].ruleId, "no-unused-vars"); + assert.strictEqual(results[0].messages[3].ruleId, "quotes"); + assert.strictEqual(results[0].messages[4].ruleId, "eol-last"); + assert.strictEqual(results[0].fixableErrorCount, 3); + assert.strictEqual(results[0].fixableWarningCount, 0); + assert.strictEqual(results[0].usedDeprecatedRules.length, 0); + }); + + it("should report the total and per file warnings", async () => { + eslint = new ESLint({ + cwd: getPath(), + overrideConfig: { + rules: { + quotes: 1, + "no-var": 1, + "eol-last": 1, + strict: 1, + "no-unused-vars": 1 + } + } + }); + const results = await eslint.lintText("var foo = 'bar';"); + + assert.strictEqual(results.length, 1); + assert.strictEqual(results[0].messages.length, 5); + assert.strictEqual(results[0].messages[0].ruleId, "strict"); + assert.strictEqual(results[0].messages[1].ruleId, "no-var"); + assert.strictEqual(results[0].messages[2].ruleId, "no-unused-vars"); + assert.strictEqual(results[0].messages[3].ruleId, "quotes"); + assert.strictEqual(results[0].messages[4].ruleId, "eol-last"); + assert.strictEqual(results[0].fixableErrorCount, 0); + assert.strictEqual(results[0].fixableWarningCount, 3); + assert.strictEqual(results[0].usedDeprecatedRules.length, 0); + }); }); it("should report one message when using specific config file", async () => { @@ -950,9 +975,11 @@ describe("ESLint", () => { it("should report zero messages when given a config file and a valid file", async () => { eslint = new ESLint({ cwd: originalDir, - overrideConfigFile: ".eslintrc.js" + useEslintrc: false, + ignore: false, + overrideConfigFile: "tests/fixtures/simple-valid-project/.eslintrc.js" }); - const results = await eslint.lintFiles(["lib/**/cli*.js"]); + const results = await eslint.lintFiles(["tests/fixtures/simple-valid-project/**/foo*.js"]); assert.strictEqual(results.length, 2); assert.strictEqual(results[0].messages.length, 0); @@ -962,9 +989,15 @@ describe("ESLint", () => { it("should handle multiple patterns with overlapping files", async () => { eslint = new ESLint({ cwd: originalDir, - overrideConfigFile: ".eslintrc.js" + useEslintrc: false, + ignore: false, + overrideConfigFile: "tests/fixtures/simple-valid-project/.eslintrc.js" }); - const results = await eslint.lintFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]); + const results = await eslint.lintFiles([ + "tests/fixtures/simple-valid-project/**/foo*.js", + "tests/fixtures/simple-valid-project/foo.?s", + "tests/fixtures/simple-valid-project/{foo,src/foobar}.js" + ]); assert.strictEqual(results.length, 2); assert.strictEqual(results[0].messages.length, 0); @@ -1396,6 +1429,10 @@ describe("ESLint", () => { }); it("should throw an error when all given files are ignored", async () => { + eslint = new ESLint({ + useEslintrc: false, + ignorePath: getFixturePath(".eslintignore") + }); await assert.rejects(async () => { await eslint.lintFiles(["tests/fixtures/cli-engine/"]); }, /All files matched by 'tests\/fixtures\/cli-engine\/' are ignored\./u); @@ -1403,6 +1440,7 @@ describe("ESLint", () => { it("should throw an error when all given files are ignored even with a `./` prefix", async () => { eslint = new ESLint({ + useEslintrc: false, ignorePath: getFixturePath(".eslintignore") }); @@ -1466,6 +1504,7 @@ describe("ESLint", () => { it("should throw an error when all given files are ignored via ignore-pattern", async () => { eslint = new ESLint({ + useEslintrc: false, overrideConfig: { ignorePatterns: "tests/fixtures/single-quoted.js" } @@ -1675,7 +1714,7 @@ describe("ESLint", () => { it("should warn when deprecated rules are configured", async () => { eslint = new ESLint({ cwd: originalDir, - overrideConfigFile: ".eslintrc.js", + useEslintrc: false, overrideConfig: { rules: { "indent-legacy": 1, @@ -1699,7 +1738,7 @@ describe("ESLint", () => { it("should not warn when deprecated rules are not configured", async () => { eslint = new ESLint({ cwd: originalDir, - overrideConfigFile: ".eslintrc.js", + useEslintrc: false, overrideConfig: { rules: { indent: 1, "valid-jsdoc": 0, "require-jsdoc": 0 } } @@ -4865,7 +4904,21 @@ describe("ESLint", () => { describe("getErrorResults()", () => { it("should report 5 error messages when looking for errors only", async () => { process.chdir(originalDir); - const engine = new ESLint(); + const engine = new ESLint({ + useEslintrc: false, + overrideConfig: { + rules: { + quotes: 2, + "no-var": 2, + "eol-last": 2, + strict: [2, "global"], + "no-unused-vars": 2 + }, + env: { + node: true + } + } + }); const results = await engine.lintText("var foo = 'bar';"); const errorResults = ESLint.getErrorResults(results); @@ -4888,13 +4941,19 @@ describe("ESLint", () => { it("should not mutate passed report parameter", async () => { process.chdir(originalDir); const engine = new ESLint({ + useEslintrc: false, overrideConfig: { - rules: { quotes: [1, "double"] } + rules: { + quotes: [1, "double"], + "no-var": 2 + } } }); const results = await engine.lintText("var foo = 'bar';"); const reportResultsLength = results[0].messages.length; + assert.strictEqual(results[0].messages.length, 2); + ESLint.getErrorResults(results); assert.strictEqual(results[0].messages.length, reportResultsLength); @@ -4902,7 +4961,21 @@ describe("ESLint", () => { it("should report a warningCount of 0 when looking for errors only", async () => { process.chdir(originalDir); - const engine = new ESLint(); + const engine = new ESLint({ + useEslintrc: false, + overrideConfig: { + rules: { + quotes: 2, + "no-var": 2, + "eol-last": 2, + strict: [2, "global"], + "no-unused-vars": 2 + }, + env: { + node: true + } + } + }); const results = await engine.lintText("var foo = 'bar';"); const errorResults = ESLint.getErrorResults(results); diff --git a/tests/lib/eslint/flat-eslint.js b/tests/lib/eslint/flat-eslint.js index b68dabc2837..ffad0a793ea 100644 --- a/tests/lib/eslint/flat-eslint.js +++ b/tests/lib/eslint/flat-eslint.js @@ -769,9 +769,9 @@ describe("FlatESLint", () => { it("should report zero messages when given a config file and a valid file", async () => { eslint = new FlatESLint({ cwd: originalDir, - overrideConfigFile: "eslint.config.js" + overrideConfigFile: "tests/fixtures/simple-valid-project/eslint.config.js" }); - const results = await eslint.lintFiles(["lib/**/cli*.js"]); + const results = await eslint.lintFiles(["tests/fixtures/simple-valid-project/**/foo*.js"]); assert.strictEqual(results.length, 2); assert.strictEqual(results[0].messages.length, 0); @@ -782,9 +782,13 @@ describe("FlatESLint", () => { it("should handle multiple patterns with overlapping files", async () => { eslint = new FlatESLint({ cwd: originalDir, - overrideConfigFile: "eslint.config.js" + overrideConfigFile: "tests/fixtures/simple-valid-project/eslint.config.js" }); - const results = await eslint.lintFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]); + const results = await eslint.lintFiles([ + "tests/fixtures/simple-valid-project/**/foo*.js", + "tests/fixtures/simple-valid-project/foo.?s", + "tests/fixtures/simple-valid-project/{foo,src/foobar}.js" + ]); assert.strictEqual(results.length, 2); assert.strictEqual(results[0].messages.length, 0); @@ -1408,11 +1412,10 @@ describe("FlatESLint", () => { }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u); }); - it("should throw an error when all given files are ignored via ignore-pattern", async () => { + it("should throw an error when all given files are ignored via ignorePatterns", async () => { eslint = new FlatESLint({ - overrideConfig: { - ignorePatterns: "tests/fixtures/single-quoted.js" - } + overrideConfigFile: true, + ignorePatterns: ["tests/fixtures/single-quoted.js"] }); await assert.rejects(async () => { @@ -1817,6 +1820,7 @@ describe("FlatESLint", () => { it("should warn when deprecated rules are configured", async () => { eslint = new FlatESLint({ cwd: originalDir, + overrideConfigFile: true, overrideConfig: { rules: { "indent-legacy": 1, @@ -1840,6 +1844,7 @@ describe("FlatESLint", () => { it("should not warn when deprecated rules are not configured", async () => { eslint = new FlatESLint({ cwd: originalDir, + overrideConfigFile: true, overrideConfig: { rules: { indent: 1, "valid-jsdoc": 0, "require-jsdoc": 0 } }