From b609c2b5088c321a947a25a69e36fa21aefabfa1 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Mon, 1 Dec 2025 18:46:03 +0800 Subject: [PATCH 1/8] test: remove unnecessary `semver` calls (#2985) --- .../component-name-in-template-casing.js | 256 +++++++++--------- tests/lib/rules/no-boolean-default.js | 88 +++--- tests/lib/rules/no-export-in-script-setup.js | 9 +- tests/lib/rules/no-implicit-coercion.js | 69 +++-- tests/lib/rules/no-loss-of-precision.js | 141 ++++------ tests/lib/rules/no-reserved-keys.js | 76 +++--- tests/lib/rules/no-restricted-props.js | 218 +++++++-------- tests/lib/rules/no-undef-components.js | 96 +++---- tests/lib/rules/prop-name-casing.js | 62 ++--- tests/lib/rules/require-default-prop.js | 56 ++-- tests/lib/rules/space-in-parens.js | 70 ++--- tests/lib/rules/space-infix-ops.js | 7 +- 12 files changed, 521 insertions(+), 627 deletions(-) diff --git a/tests/lib/rules/component-name-in-template-casing.js b/tests/lib/rules/component-name-in-template-casing.js index 34e3574fc..9ad24fad3 100644 --- a/tests/lib/rules/component-name-in-template-casing.js +++ b/tests/lib/rules/component-name-in-template-casing.js @@ -4,7 +4,6 @@ 'use strict' const rule = require('../../../lib/rules/component-name-in-template-casing') -const semver = require('semver') const RuleTester = require('../../eslint-compat').RuleTester const tester = new RuleTester({ @@ -218,42 +217,36 @@ tester.run('component-name-in-template-casing', rule, { }, // type-only imports - ...(semver.gte( - require('@typescript-eslint/parser/package.json').version, - '5.0.0' - ) - ? [ - { - code: ` - - - `, - options: ['PascalCase', { registeredComponentsOnly: true }], - languageOptions: { - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - } - } - ] - : []) + { + code: ` + + + + `, + options: ['PascalCase', { registeredComponentsOnly: true }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + } ], invalid: [ { @@ -1305,106 +1298,99 @@ tester.run('component-name-in-template-casing', rule, { ] }, // type-only imports - ...(semver.gte( - require('@typescript-eslint/parser/package.json').version, - '5.0.0' - ) - ? [ - { - code: ` - + { + code: ` + - - `, - options: ['PascalCase', { registeredComponentsOnly: false }], - languageOptions: { - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - output: ` - + + `, + output: ` + - - `, - errors: [ - { - message: 'Component name "foo" is not PascalCase.', - line: 13, - column: 17, - endLine: 13, - endColumn: 21 - }, - { - message: 'Component name "hello-world1" is not PascalCase.', - line: 14, - column: 17, - endLine: 14, - endColumn: 30 - }, - { - message: 'Component name "hello-world2" is not PascalCase.', - line: 15, - column: 17, - endLine: 15, - endColumn: 30 - }, - { - message: 'Component name "hello-world3" is not PascalCase.', - line: 16, - column: 17, - endLine: 16, - endColumn: 30 - }, - { - message: 'Component name "hello-world4" is not PascalCase.', - line: 17, - column: 17, - endLine: 17, - endColumn: 30 - }, - { - message: 'Component name "hello-world5" is not PascalCase.', - line: 18, - column: 17, - endLine: 18, - endColumn: 30 - } - ] - } - ] - : []) + + `, + options: ['PascalCase', { registeredComponentsOnly: false }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Component name "foo" is not PascalCase.', + line: 13, + column: 11, + endLine: 13, + endColumn: 15 + }, + { + message: 'Component name "hello-world1" is not PascalCase.', + line: 14, + column: 11, + endLine: 14, + endColumn: 24 + }, + { + message: 'Component name "hello-world2" is not PascalCase.', + line: 15, + column: 11, + endLine: 15, + endColumn: 24 + }, + { + message: 'Component name "hello-world3" is not PascalCase.', + line: 16, + column: 11, + endLine: 16, + endColumn: 24 + }, + { + message: 'Component name "hello-world4" is not PascalCase.', + line: 17, + column: 11, + endLine: 17, + endColumn: 24 + }, + { + message: 'Component name "hello-world5" is not PascalCase.', + line: 18, + column: 11, + endLine: 18, + endColumn: 24 + } + ] + } ] }) diff --git a/tests/lib/rules/no-boolean-default.js b/tests/lib/rules/no-boolean-default.js index c3132a5fd..56e9cd1cc 100644 --- a/tests/lib/rules/no-boolean-default.js +++ b/tests/lib/rules/no-boolean-default.js @@ -4,7 +4,6 @@ */ 'use strict' -const semver = require('semver') const rule = require('../../../lib/rules/no-boolean-default') const RuleTester = require('../../eslint-compat').RuleTester @@ -484,15 +483,9 @@ ruleTester.run('no-boolean-default', rule, { } ] }, - ...(semver.lt( - require('@typescript-eslint/parser/package.json').version, - '4.0.0' - ) - ? [] - : [ - { - filename: 'test.vue', - code: ` + { + filename: 'test.vue', + code: ` `, - languageOptions: { - parser: require('vue-eslint-parser'), - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - errors: [ - { - message: - 'Boolean prop should not set a default (Vue defaults it to false).', - line: 7, - column: 14, - endLine: 7, - endColumn: 19 - } - ] - }, - { - filename: 'test.vue', - code: ` + languageOptions: { + parser: require('vue-eslint-parser'), + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: + 'Boolean prop should not set a default (Vue defaults it to false).', + line: 7, + column: 14, + endLine: 7, + endColumn: 19 + } + ] + }, + { + filename: 'test.vue', + code: ` `, - languageOptions: { - parser: require('vue-eslint-parser'), - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - options: ['default-false'], - errors: [ - { - message: 'Boolean prop should only be defaulted to false.', - line: 7, - column: 14, - endLine: 7, - endColumn: 18 - } - ] - } - ]), + options: ['default-false'], + languageOptions: { + parser: require('vue-eslint-parser'), + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Boolean prop should only be defaulted to false.', + line: 7, + column: 14, + endLine: 7, + endColumn: 18 + } + ] + }, { filename: 'test.vue', code: ` diff --git a/tests/lib/rules/no-export-in-script-setup.js b/tests/lib/rules/no-export-in-script-setup.js index bf24b8682..e678d5f99 100644 --- a/tests/lib/rules/no-export-in-script-setup.js +++ b/tests/lib/rules/no-export-in-script-setup.js @@ -42,11 +42,10 @@ ruleTester.run('no-export-in-script-setup', rule, { ` }, - ...(semver.gte( - require('@typescript-eslint/parser/package.json').version, - '5.4.0' - ) && - semver.satisfies(require('typescript/package.json').version, '>=4.5.0-0') + ...(semver.satisfies( + require('typescript/package.json').version, + '>=4.5.0-0' + ) ? [ { filename: 'test.vue', diff --git a/tests/lib/rules/no-implicit-coercion.js b/tests/lib/rules/no-implicit-coercion.js index 7a2f89359..78e8ac91e 100644 --- a/tests/lib/rules/no-implicit-coercion.js +++ b/tests/lib/rules/no-implicit-coercion.js @@ -49,9 +49,7 @@ tester.run('no-implicit-coercion', rule, { ] }, ``, - ...(semver.gte(ESLint.version, '8.28.0') - ? [``] - : []), + ``, { filename: 'test.vue', code: ``, @@ -238,40 +236,35 @@ tester.run('no-implicit-coercion', rule, { } ] }, - ...(semver.gte(ESLint.version, '7.24.0') - ? [ - { - filename: 'test.vue', - code: ``, - output: semver.gte(ESLint.version, '9.0.0') - ? null - : ``, - options: [ - { - disallowTemplateShorthand: true - } - ], - errors: [ - { - message: getExpectedErrorMessage('String(foo)'), - line: 1, - column: 27, - endLine: 1, - endColumn: 35, - suggestions: semver.gte(ESLint.version, '9.0.0') - ? [ - { - messageId: 'useRecommendation', - data: { recommendation: 'String(foo)' }, - output: - '' - } - ] - : [] - } - ] - } - ] - : []) + { + filename: 'test.vue', + code: ``, + output: semver.gte(ESLint.version, '9.0.0') + ? null + : ``, + options: [ + { + disallowTemplateShorthand: true + } + ], + errors: [ + { + message: getExpectedErrorMessage('String(foo)'), + line: 1, + column: 27, + endLine: 1, + endColumn: 35, + suggestions: semver.gte(ESLint.version, '9.0.0') + ? [ + { + messageId: 'useRecommendation', + data: { recommendation: 'String(foo)' }, + output: '' + } + ] + : [] + } + ] + } ] }) diff --git a/tests/lib/rules/no-loss-of-precision.js b/tests/lib/rules/no-loss-of-precision.js index a9d632862..1b60a33ca 100644 --- a/tests/lib/rules/no-loss-of-precision.js +++ b/tests/lib/rules/no-loss-of-precision.js @@ -4,8 +4,7 @@ */ 'use strict' -const { RuleTester, ESLint } = require('../../eslint-compat') -const semver = require('semver') +const { RuleTester } = require('../../eslint-compat') const rule = require('../../../lib/rules/no-loss-of-precision') const tester = new RuleTester({ @@ -17,86 +16,66 @@ const tester = new RuleTester({ }) tester.run('no-loss-of-precision', rule, { valid: [ - ...(semver.gte(ESLint.version, '7.1.0') - ? [ - { - filename: 'test.vue', - code: ` - - ` - }, - { - filename: 'test.vue', - code: ` - - ` - } - ] - : []) + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + } ], invalid: [ - ...(semver.gte(ESLint.version, '7.1.0') - ? [ - { - filename: 'test.vue', - code: ` - - `, - errors: [ - { - message: 'This number literal will lose precision at runtime.', - line: 3, - column: 17, - endLine: 3, - endColumn: 37 - }, - { - message: 'This number literal will lose precision at runtime.', - line: 4, - column: 17, - endLine: 4, - endColumn: 39 - } - ] - }, - { - filename: 'test.vue', - code: ` - - `, - errors: [ - { - message: 'This number literal will lose precision at runtime.', - line: 3, - column: 34, - endLine: 3, - endColumn: 54 - } - ] - } - ] - : [ - { - filename: 'test.vue', - code: ` - - `, - errors: [ - 'Failed to extend ESLint core rule "no-loss-of-precision". You may be able to use this rule by upgrading the version of ESLint. If you cannot upgrade it, turn off this rule.' - ] - } - ]) + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: 'This number literal will lose precision at runtime.', + line: 3, + column: 13, + endLine: 3, + endColumn: 33 + }, + { + message: 'This number literal will lose precision at runtime.', + line: 4, + column: 13, + endLine: 4, + endColumn: 35 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: 'This number literal will lose precision at runtime.', + line: 3, + column: 30, + endLine: 3, + endColumn: 50 + } + ] + } ] }) diff --git a/tests/lib/rules/no-reserved-keys.js b/tests/lib/rules/no-reserved-keys.js index 277c12c92..7ece338f1 100644 --- a/tests/lib/rules/no-reserved-keys.js +++ b/tests/lib/rules/no-reserved-keys.js @@ -4,7 +4,6 @@ */ 'use strict' -const semver = require('semver') const rule = require('../../../lib/rules/no-reserved-keys') const RuleTester = require('../../eslint-compat').RuleTester @@ -293,15 +292,9 @@ ruleTester.run('no-reserved-keys', rule, { } ] }, - ...(semver.lt( - require('@typescript-eslint/parser/package.json').version, - '4.0.0' - ) - ? [] - : [ - { - filename: 'test.vue', - code: ` + { + filename: 'test.vue', + code: ` `, - languageOptions: { - parser: require('vue-eslint-parser'), - ecmaVersion: 6, - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - errors: [ - { - message: "Key '$el' is reserved.", - line: 4 - } - ] - }, - { - filename: 'test.vue', - code: ` + languageOptions: { + parser: require('vue-eslint-parser'), + ecmaVersion: 6, + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: "Key '$el' is reserved.", + line: 4 + } + ] + }, + { + filename: 'test.vue', + code: ` `, - languageOptions: { - parser: require('vue-eslint-parser'), - ecmaVersion: 6, - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - errors: [ - { - message: "Key '$el' is reserved.", - line: 4 - } - ] - } - ]) + languageOptions: { + parser: require('vue-eslint-parser'), + ecmaVersion: 6, + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: "Key '$el' is reserved.", + line: 4 + } + ] + } ] }) diff --git a/tests/lib/rules/no-restricted-props.js b/tests/lib/rules/no-restricted-props.js index a91615e15..e1d55d090 100644 --- a/tests/lib/rules/no-restricted-props.js +++ b/tests/lib/rules/no-restricted-props.js @@ -3,7 +3,6 @@ */ 'use strict' -const semver = require('semver') const RuleTester = require('../../eslint-compat').RuleTester const rule = require('../../../lib/rules/no-restricted-props') const { @@ -414,15 +413,9 @@ tester.run('no-restricted-props', rule, { } ] }, - ...(semver.lt( - require('@typescript-eslint/parser/package.json').version, - '4.0.0' - ) - ? [] - : [ - { - filename: 'test.vue', - code: ` + { + filename: 'test.vue', + code: ` `, - languageOptions: { - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - options: [{ name: 'foo', suggest: 'Foo' }], - errors: [ - { - message: 'Using `foo` props is not allowed.', - line: 4, - suggestions: [ - { - desc: 'Instead, change to `Foo`.', - output: ` + options: [{ name: 'foo', suggest: 'Foo' }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Using `foo` props is not allowed.', + line: 4, + suggestions: [ + { + desc: 'Instead, change to `Foo`.', + output: ` ` - } - ] - } - ] - }, - { - filename: 'test.vue', - code: ` + } + ] + } + ] + }, + { + filename: 'test.vue', + code: ` `, - languageOptions: { - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - options: [{ name: 'foo', suggest: 'Foo' }], - errors: [ - { - message: 'Using `foo` props is not allowed.', - line: 4, - suggestions: [ - { - desc: 'Instead, change to `Foo`.', - output: ` + options: [{ name: 'foo', suggest: 'Foo' }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Using `foo` props is not allowed.', + line: 4, + suggestions: [ + { + desc: 'Instead, change to `Foo`.', + output: ` ` - } - ] - } - ] - }, - { - filename: 'test.vue', - code: ` + } + ] + } + ] + }, + { + filename: 'test.vue', + code: ` @@ -517,20 +510,20 @@ tester.run('no-restricted-props', rule, { ) `, - languageOptions: { - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - options: [{ name: 'foo', suggest: 'Foo' }], - errors: [ - { - message: 'Using `foo` props is not allowed.', - line: 7, - suggestions: [ - { - desc: 'Instead, change to `Foo`.', - output: ` + options: [{ name: 'foo', suggest: 'Foo' }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Using `foo` props is not allowed.', + line: 7, + suggestions: [ + { + desc: 'Instead, change to `Foo`.', + output: ` @@ -545,14 +538,14 @@ tester.run('no-restricted-props', rule, { ) ` - } - ] - } - ] - }, - { - filename: 'test.vue', - code: ` + } + ] + } + ] + }, + { + filename: 'test.vue', + code: ` `, - languageOptions: { - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - options: [{ name: 'foo', suggest: 'Foo' }], - errors: [ - { - message: 'Using `foo` props is not allowed.', - line: 9, - suggestions: [ - { - desc: 'Instead, change to `Foo`.', - output: ` + options: [{ name: 'foo', suggest: 'Foo' }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Using `foo` props is not allowed.', + line: 9, + suggestions: [ + { + desc: 'Instead, change to `Foo`.', + output: ` ` - } - ] - } - ] - }, - { - code: ` - - `, - ...getTypeScriptFixtureTestOptions(), - options: [{ name: 'foo', suggest: 'Foo' }], - errors: [ - { - message: 'Using `foo` props is not allowed.', - line: 4, - suggestions: null - } - ] - } - ]), + } + ] + } + ] + }, + { + code: ` + + `, + options: [{ name: 'foo', suggest: 'Foo' }], + errors: [ + { + message: 'Using `foo` props is not allowed.', + line: 4, + suggestions: null + } + ], + ...getTypeScriptFixtureTestOptions() + }, { filename: 'test.vue', code: ` diff --git a/tests/lib/rules/no-undef-components.js b/tests/lib/rules/no-undef-components.js index 37a3bec68..f87f9dcd5 100644 --- a/tests/lib/rules/no-undef-components.js +++ b/tests/lib/rules/no-undef-components.js @@ -6,7 +6,6 @@ const RuleTester = require('../../eslint-compat').RuleTester const rule = require('../../../lib/rules/no-undef-components') -const semver = require('semver') const tester = new RuleTester({ languageOptions: { @@ -746,14 +745,9 @@ tester.run('no-undef-components', rule, { } ] }, - ...(semver.gte( - require('@typescript-eslint/parser/package.json').version, - '5.0.0' - ) - ? [ - { - filename: 'test.vue', - code: ` + { + filename: 'test.vue', + code: ` - `, - languageOptions: { - parser: require('vue-eslint-parser'), - ...languageOptions, - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - errors: [ - { - message: 'Prop "greeting_text" is not in camelCase.', - line: 4, - column: 15, - endLine: 4, - endColumn: 36 - } - ] - } - ]), + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { + parser: require('vue-eslint-parser'), + ...languageOptions, + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Prop "greeting_text" is not in camelCase.', + line: 4, + column: 9, + endLine: 4, + endColumn: 30 + } + ] + }, { filename: 'test.vue', code: ` diff --git a/tests/lib/rules/require-default-prop.js b/tests/lib/rules/require-default-prop.js index 43160dfda..cbca0ee19 100644 --- a/tests/lib/rules/require-default-prop.js +++ b/tests/lib/rules/require-default-prop.js @@ -4,7 +4,6 @@ */ 'use strict' -const semver = require('semver') const rule = require('../../../lib/rules/require-default-prop') const RuleTester = require('../../eslint-compat').RuleTester const languageOptions = { @@ -655,37 +654,30 @@ ruleTester.run('require-default-prop', rule, { } ] }, - ...(semver.lt( - require('@typescript-eslint/parser/package.json').version, - '4.0.0' - ) - ? [] - : [ - { - filename: 'test.vue', - code: ` - - `, - languageOptions: { - parser: require('vue-eslint-parser'), - ...languageOptions, - parserOptions: { - parser: require.resolve('@typescript-eslint/parser') - } - }, - errors: [ - { - message: "Prop 'foo' requires default value to be set.", - line: 4 - } - ] - } - ]), + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { + parser: require('vue-eslint-parser'), + ...languageOptions, + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: "Prop 'foo' requires default value to be set.", + line: 4 + } + ] + }, { filename: 'test.vue', code: ` diff --git a/tests/lib/rules/space-in-parens.js b/tests/lib/rules/space-in-parens.js index d6218216d..9b1509f07 100644 --- a/tests/lib/rules/space-in-parens.js +++ b/tests/lib/rules/space-in-parens.js @@ -3,21 +3,9 @@ */ 'use strict' -const { RuleTester, ESLint } = require('../../eslint-compat') -const semver = require('semver') +const { RuleTester } = require('../../eslint-compat') const rule = require('../../../lib/rules/space-in-parens') -const errorMessage = semver.lt(ESLint.version, '6.4.0') - ? (obj) => { - const messageId = obj.messageId - delete obj.messageId - obj.message = messageId.startsWith('missing') - ? 'There must be a space inside this paren.' - : 'There should be no spaces inside this paren.' - return obj - } - : (obj) => obj - const tester = new RuleTester({ languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2015 } }) @@ -76,14 +64,14 @@ tester.run('space-in-parens', rule, { /> `, errors: [ - errorMessage({ + { messageId: 'rejectedOpeningSpace', line: 4 - }), - errorMessage({ + }, + { messageId: 'rejectedClosingSpace', line: 4 - }) + } ] }, { @@ -101,14 +89,14 @@ tester.run('space-in-parens', rule, { `, options: ['always'], errors: [ - errorMessage({ + { messageId: 'missingOpeningSpace', line: 4 - }), - errorMessage({ + }, + { messageId: 'missingClosingSpace', line: 4 - }) + } ] }, { @@ -125,14 +113,14 @@ tester.run('space-in-parens', rule, { > `, errors: [ - errorMessage({ + { messageId: 'rejectedOpeningSpace', line: 4 - }), - errorMessage({ + }, + { messageId: 'rejectedClosingSpace', line: 4 - }) + } ] }, { @@ -150,14 +138,14 @@ tester.run('space-in-parens', rule, { `, options: ['always'], errors: [ - errorMessage({ + { messageId: 'missingOpeningSpace', line: 4 - }), - errorMessage({ + }, + { messageId: 'missingClosingSpace', line: 4 - }) + } ] }, { @@ -174,14 +162,14 @@ tester.run('space-in-parens', rule, { > `, errors: [ - errorMessage({ + { messageId: 'rejectedOpeningSpace', line: 4 - }), - errorMessage({ + }, + { messageId: 'rejectedClosingSpace', line: 4 - }) + } ] }, { @@ -199,14 +187,14 @@ tester.run('space-in-parens', rule, { `, options: ['always'], errors: [ - errorMessage({ + { messageId: 'missingOpeningSpace', line: 4 - }), - errorMessage({ + }, + { messageId: 'missingClosingSpace', line: 4 - }) + } ] }, @@ -225,14 +213,14 @@ tester.run('space-in-parens', rule, { } `, errors: [ - errorMessage({ + { messageId: 'rejectedOpeningSpace', line: 4 - }), - errorMessage({ + }, + { messageId: 'rejectedClosingSpace', line: 4 - }) + } ] } ] diff --git a/tests/lib/rules/space-infix-ops.js b/tests/lib/rules/space-infix-ops.js index 0325884a7..d05e25170 100644 --- a/tests/lib/rules/space-infix-ops.js +++ b/tests/lib/rules/space-infix-ops.js @@ -3,17 +3,14 @@ */ 'use strict' -const { RuleTester, ESLint } = require('../../eslint-compat') -const semver = require('semver') +const { RuleTester } = require('../../eslint-compat') const rule = require('../../../lib/rules/space-infix-ops') const tester = new RuleTester({ languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2015 } }) -const message = semver.lt(ESLint.version, '5.10.0') - ? () => 'Infix operators must be spaced.' - : (operator) => `Operator '${operator}' must be spaced.` +const message = (operator) => `Operator '${operator}' must be spaced.` tester.run('space-infix-ops', rule, { valid: [ From 16d17a4b4aa20215e487bab0f601f5a5ce12b9b4 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Fri, 5 Dec 2025 10:30:29 +0800 Subject: [PATCH 2/8] test: rewrite some files in `.ts` (#2968) --- eslint.config.mjs | 1 + .../lib/configs/{eslintrc.js => eslintrc.ts} | 6 +- tests/lib/configs/{flat.js => flat.ts} | 103 +++++++++--------- .../rules/{block-order.js => block-order.ts} | 40 ++----- ...ment-directive.js => comment-directive.ts} | 25 +++-- tsconfig.json | 4 + 6 files changed, 83 insertions(+), 96 deletions(-) rename tests/lib/configs/{eslintrc.js => eslintrc.ts} (83%) rename tests/lib/configs/{flat.js => flat.ts} (65%) rename tests/lib/rules/{block-order.js => block-order.ts} (94%) rename tests/lib/rules/{comment-directive.js => comment-directive.ts} (97%) diff --git a/eslint.config.mjs b/eslint.config.mjs index f5c8aee09..4857aaeb7 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -275,6 +275,7 @@ export default typegen([ '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-empty-object-type': 'off', '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/triple-slash-reference': 'off', '@typescript-eslint/unified-signatures': 'off', '@typescript-eslint/ban-ts-comment': [ diff --git a/tests/lib/configs/eslintrc.js b/tests/lib/configs/eslintrc.ts similarity index 83% rename from tests/lib/configs/eslintrc.js rename to tests/lib/configs/eslintrc.ts index a9febaeeb..85d25022c 100644 --- a/tests/lib/configs/eslintrc.js +++ b/tests/lib/configs/eslintrc.ts @@ -1,7 +1,5 @@ -'use strict' - -const { ESLint } = require('../../eslint-compat') -const plugin = require('../../../lib/index') +import { ESLint } from '../../eslint-compat' +import plugin from '../../../lib' describe('eslintrc configs', () => { for (const name of Object.keys(plugin.configs)) { diff --git a/tests/lib/configs/flat.js b/tests/lib/configs/flat.ts similarity index 65% rename from tests/lib/configs/flat.js rename to tests/lib/configs/flat.ts index 51449953a..ed9e282b1 100644 --- a/tests/lib/configs/flat.js +++ b/tests/lib/configs/flat.ts @@ -3,14 +3,13 @@ * @author 唯然 */ -'use strict' +import { Linter } from 'eslint' +import plugin from '../../../lib' +import { strict as assert } from 'assert' +import { FlatESLint } from '../../eslint-compat' -const plugin = require('../../../lib/index') -const { strict: assert } = require('assert') // node v14 does not support 'assert/strict' -const { FlatESLint } = require('../../eslint-compat') - -function mergeConfig(configs) { - let config = { rules: {}, plugins: {} } +function mergeConfig(configs: Linter.FlatConfig[]): Linter.FlatConfig { + let config: Linter.FlatConfig = { rules: {}, plugins: {} } for (const item of configs) { config = { ...config, @@ -37,16 +36,16 @@ describe('flat configs', () => { const forVue = mergeConfig( base.filter((config) => config.files?.includes('*.vue') || !config.files) ) - assert.strictEqual(forVue.plugins.vue, plugin) + assert.strictEqual(forVue.plugins!.vue, plugin) assert.strictEqual(forVue.processor, 'vue/vue') - assert.strictEqual(forVue.rules['vue/comment-directive'], 'error') + assert.strictEqual(forVue.rules!['vue/comment-directive'], 'error') const forOtherThanVue = mergeConfig( base.filter((config) => !config.files?.includes('*.vue')) ) - assert.strictEqual(forOtherThanVue.plugins.vue, plugin) + assert.strictEqual(forOtherThanVue.plugins!.vue, plugin) assert.strictEqual( - forOtherThanVue.rules['vue/comment-directive'], + forOtherThanVue.rules!['vue/comment-directive'], undefined ) }) @@ -61,20 +60,20 @@ describe('flat configs', () => { (config) => config.files?.includes('*.vue') || !config.files ) ) - assert.strictEqual(forVue.plugins.vue, plugin) - assert.strictEqual(forVue.rules['vue/comment-directive'], 'error') - assert.strictEqual(forVue.rules['vue/multi-word-component-names'], 'error') + assert.strictEqual(forVue.plugins!.vue, plugin) + assert.strictEqual(forVue.rules!['vue/comment-directive'], 'error') + assert.strictEqual(forVue.rules!['vue/multi-word-component-names'], 'error') const forOtherThanVue = mergeConfig( essential.filter((config) => !config.files?.includes('*.vue')) ) - assert.strictEqual(forOtherThanVue.plugins.vue, plugin) + assert.strictEqual(forOtherThanVue.plugins!.vue, plugin) assert.strictEqual( - forOtherThanVue.rules['vue/comment-directive'], + forOtherThanVue.rules!['vue/comment-directive'], undefined ) assert.strictEqual( - forOtherThanVue.rules['vue/multi-word-component-names'], + forOtherThanVue.rules!['vue/multi-word-component-names'], 'error' ) }) @@ -89,20 +88,20 @@ describe('flat configs', () => { (config) => config.files?.includes('*.vue') || !config.files ) ) - assert.strictEqual(forVue.plugins.vue, plugin) - assert.strictEqual(forVue.rules['vue/comment-directive'], 'error') - assert.strictEqual(forVue.rules['vue/multi-word-component-names'], 'error') + assert.strictEqual(forVue.plugins!.vue, plugin) + assert.strictEqual(forVue.rules!['vue/comment-directive'], 'error') + assert.strictEqual(forVue.rules!['vue/multi-word-component-names'], 'error') const forOtherThanVue = mergeConfig( stronglyRecommended.filter((config) => !config.files?.includes('*.vue')) ) - assert.strictEqual(forOtherThanVue.plugins.vue, plugin) + assert.strictEqual(forOtherThanVue.plugins!.vue, plugin) assert.strictEqual( - forOtherThanVue.rules['vue/comment-directive'], + forOtherThanVue.rules!['vue/comment-directive'], undefined ) assert.strictEqual( - forOtherThanVue.rules['vue/multi-word-component-names'], + forOtherThanVue.rules!['vue/multi-word-component-names'], 'error' ) }) @@ -117,24 +116,24 @@ describe('flat configs', () => { (config) => config.files?.includes('*.vue') || !config.files ) ) - assert.strictEqual(forVue.plugins.vue, plugin) - assert.strictEqual(forVue.rules['vue/comment-directive'], 'error') - assert.strictEqual(forVue.rules['vue/multi-word-component-names'], 'error') - assert.strictEqual(forVue.rules['vue/attributes-order'], 'warn') + assert.strictEqual(forVue.plugins!.vue, plugin) + assert.strictEqual(forVue.rules!['vue/comment-directive'], 'error') + assert.strictEqual(forVue.rules!['vue/multi-word-component-names'], 'error') + assert.strictEqual(forVue.rules!['vue/attributes-order'], 'warn') const forOtherThanVue = mergeConfig( recommended.filter((config) => !config.files?.includes('*.vue')) ) - assert.strictEqual(forOtherThanVue.plugins.vue, plugin) + assert.strictEqual(forOtherThanVue.plugins!.vue, plugin) assert.strictEqual( - forOtherThanVue.rules['vue/comment-directive'], + forOtherThanVue.rules!['vue/comment-directive'], undefined ) assert.strictEqual( - forOtherThanVue.rules['vue/multi-word-component-names'], + forOtherThanVue.rules!['vue/multi-word-component-names'], 'error' ) - assert.strictEqual(forOtherThanVue.rules['vue/attributes-order'], 'warn') + assert.strictEqual(forOtherThanVue.rules!['vue/attributes-order'], 'warn') }) it('should export vue2-essential config', () => { @@ -147,20 +146,20 @@ describe('flat configs', () => { (config) => config.files?.includes('*.vue') || !config.files ) ) - assert.strictEqual(forVue.plugins.vue, plugin) - assert.strictEqual(forVue.rules['vue/comment-directive'], 'error') - assert.strictEqual(forVue.rules['vue/multi-word-component-names'], 'error') + assert.strictEqual(forVue.plugins!.vue, plugin) + assert.strictEqual(forVue.rules!['vue/comment-directive'], 'error') + assert.strictEqual(forVue.rules!['vue/multi-word-component-names'], 'error') const forOtherThanVue = mergeConfig( essential.filter((config) => !config.files?.includes('*.vue')) ) - assert.strictEqual(forOtherThanVue.plugins.vue, plugin) + assert.strictEqual(forOtherThanVue.plugins!.vue, plugin) assert.strictEqual( - forOtherThanVue.rules['vue/comment-directive'], + forOtherThanVue.rules!['vue/comment-directive'], undefined ) assert.strictEqual( - forOtherThanVue.rules['vue/multi-word-component-names'], + forOtherThanVue.rules!['vue/multi-word-component-names'], 'error' ) }) @@ -175,20 +174,20 @@ describe('flat configs', () => { (config) => config.files?.includes('*.vue') || !config.files ) ) - assert.strictEqual(forVue.plugins.vue, plugin) - assert.strictEqual(forVue.rules['vue/comment-directive'], 'error') - assert.strictEqual(forVue.rules['vue/multi-word-component-names'], 'error') + assert.strictEqual(forVue.plugins!.vue, plugin) + assert.strictEqual(forVue.rules!['vue/comment-directive'], 'error') + assert.strictEqual(forVue.rules!['vue/multi-word-component-names'], 'error') const forOtherThanVue = mergeConfig( stronglyRecommended.filter((config) => !config.files?.includes('*.vue')) ) - assert.strictEqual(forOtherThanVue.plugins.vue, plugin) + assert.strictEqual(forOtherThanVue.plugins!.vue, plugin) assert.strictEqual( - forOtherThanVue.rules['vue/comment-directive'], + forOtherThanVue.rules!['vue/comment-directive'], undefined ) assert.strictEqual( - forOtherThanVue.rules['vue/multi-word-component-names'], + forOtherThanVue.rules!['vue/multi-word-component-names'], 'error' ) }) @@ -203,24 +202,24 @@ describe('flat configs', () => { (config) => config.files?.includes('*.vue') || !config.files ) ) - assert.strictEqual(forVue.plugins.vue, plugin) - assert.strictEqual(forVue.rules['vue/comment-directive'], 'error') - assert.strictEqual(forVue.rules['vue/multi-word-component-names'], 'error') - assert.strictEqual(forVue.rules['vue/attributes-order'], 'warn') + assert.strictEqual(forVue.plugins!.vue, plugin) + assert.strictEqual(forVue.rules!['vue/comment-directive'], 'error') + assert.strictEqual(forVue.rules!['vue/multi-word-component-names'], 'error') + assert.strictEqual(forVue.rules!['vue/attributes-order'], 'warn') const forOtherThanVue = mergeConfig( recommended.filter((config) => !config.files?.includes('*.vue')) ) - assert.strictEqual(forOtherThanVue.plugins.vue, plugin) + assert.strictEqual(forOtherThanVue.plugins!.vue, plugin) assert.strictEqual( - forOtherThanVue.rules['vue/comment-directive'], + forOtherThanVue.rules!['vue/comment-directive'], undefined ) assert.strictEqual( - forOtherThanVue.rules['vue/multi-word-component-names'], + forOtherThanVue.rules!['vue/multi-word-component-names'], 'error' ) - assert.strictEqual(forOtherThanVue.rules['vue/attributes-order'], 'warn') + assert.strictEqual(forOtherThanVue.rules!['vue/attributes-order'], 'warn') }) it('should work the suppress comments with base config', async () => { @@ -281,7 +280,7 @@ describe('flat configs', () => { const result = await eslint.lintText(code, { filePath: 'MyComponent.vue' }) assert.deepStrictEqual( - result[0].messages.map((message) => message.ruleId), + result[0].messages.map((message: Linter.LintMessage) => message.ruleId), [ 'vue/no-parsing-error', 'vue/max-attributes-per-line', diff --git a/tests/lib/rules/block-order.js b/tests/lib/rules/block-order.ts similarity index 94% rename from tests/lib/rules/block-order.js rename to tests/lib/rules/block-order.ts index 4eb25e2bd..659522cb6 100644 --- a/tests/lib/rules/block-order.js +++ b/tests/lib/rules/block-order.ts @@ -1,12 +1,13 @@ /** * @author Yosuke Ota */ -'use strict' - -const rule = require('../../../lib/rules/block-order') -const RuleTester = require('../../eslint-compat').RuleTester -const assert = require('assert') -const { ESLint } = require('../../eslint-compat') +import { Rule } from '../../../node_modules/@types/eslint' +import assert from 'assert' +import parserVue from 'vue-eslint-parser' +import rule from '../../../lib/rules/block-order' +import { ESLint, RuleTester } from '../../eslint-compat' +import pluginVue from '../../../lib' +import processor from '../../../lib/processor' // Initialize linter. const eslint = new ESLint({ @@ -14,26 +15,26 @@ const eslint = new ESLint({ overrideConfig: { files: ['**/*.vue'], languageOptions: { - parser: require('vue-eslint-parser'), + parser: parserVue, ecmaVersion: 2015 }, - plugins: { vue: require('../../../lib/index') }, + plugins: { vue: pluginVue }, rules: { 'vue/comment-directive': 'error', 'vue/block-order': 'error' }, - processor: require('../../../lib/processor') + processor }, fix: true }) const tester = new RuleTester({ languageOptions: { - parser: require('vue-eslint-parser') + parser: parserVue } }) -tester.run('block-order', rule, { +tester.run('block-order', rule as unknown as Rule.RuleModule, { valid: [ // default '', @@ -71,44 +72,36 @@ tester.run('block-order', rule, { // order { code: '', - output: null, options: [{ order: ['script', 'template', 'style'] }] }, { code: '', - output: null, options: [{ order: ['template', 'script', 'style'] }] }, { code: '', - output: null, options: [{ order: ['style', 'template', 'script'] }] }, { code: '', - output: null, options: [{ order: ['template', 'docs', 'script', 'style'] }] }, { code: '', - output: null, options: [{ order: ['template', 'script', 'style'] }] }, { code: '
text

', - output: null, options: [{ order: ['docs', 'script', 'template', 'style'] }] }, { code: '', - output: null, options: [ { order: ['script[setup]', 'script:not([setup])', 'template', 'style'] } ] }, { code: '', - output: null, options: [ { order: [['script[setup]', 'script:not([setup])', 'template'], 'style'] @@ -117,24 +110,20 @@ tester.run('block-order', rule, { }, { code: '', - output: null, options: [{ order: ['script', 'template', 'style'] }] }, { code: '', - output: null, options: [{ order: [['script', 'template'], 'style'] }] }, { code: '', - output: null, options: [ { order: ['script:not([setup])', 'script[setup]', 'template', 'style'] } ] }, { code: '', - output: null, options: [ { order: [['script:not([setup])', 'script[setup]', 'template'], 'style'] @@ -143,7 +132,6 @@ tester.run('block-order', rule, { }, { code: '', - output: null, options: [ { order: [ @@ -158,7 +146,6 @@ tester.run('block-order', rule, { }, { code: '', - output: null, options: [ { order: [ @@ -175,17 +162,14 @@ tester.run('block-order', rule, { }, { code: '', - output: null, options: [{ order: [['docs', 'script', 'template'], 'style'] }] }, { code: '', - output: null, options: [{ order: ['i18n[locale=en]', 'i18n[locale=ja]'] }] }, { code: '', - output: null, options: [{ order: ['style:not([scoped])', 'style[scoped]'] }] }, diff --git a/tests/lib/rules/comment-directive.js b/tests/lib/rules/comment-directive.ts similarity index 97% rename from tests/lib/rules/comment-directive.js rename to tests/lib/rules/comment-directive.ts index b9acb1092..2a7efdab6 100644 --- a/tests/lib/rules/comment-directive.js +++ b/tests/lib/rules/comment-directive.ts @@ -3,10 +3,11 @@ * @author Toru Nagashima */ -'use strict' - -const assert = require('assert') -const { ESLint } = require('../../eslint-compat') +import assert from 'assert' +import parserVue from 'vue-eslint-parser' +import { ESLint } from '../../eslint-compat' +import pluginVue from '../../../lib' +import processor from '../../../lib/processor' // Initialize linter. const eslint = new ESLint({ @@ -14,21 +15,21 @@ const eslint = new ESLint({ overrideConfig: { files: ['*.*'], languageOptions: { - parser: require('vue-eslint-parser'), + parser: parserVue, ecmaVersion: 2015 }, - plugins: { vue: require('../../../lib/index') }, + plugins: { vue: pluginVue }, rules: { 'no-unused-vars': 'error', 'vue/comment-directive': 'error', 'vue/no-parsing-error': 'error', 'vue/no-duplicate-attributes': 'error' }, - processor: require('../../../lib/processor') + processor } }) -async function lintMessages(code) { +async function lintMessages(code: string) { const result = await eslint.lintText(code, { filePath: 'test.vue' }) return result[0].messages } @@ -357,10 +358,10 @@ describe('comment-directive', () => { overrideConfig: { files: ['**/*.vue'], languageOptions: { - parser: require('vue-eslint-parser'), + parser: parserVue, ecmaVersion: 2015 }, - plugins: { vue: require('../../../lib/index') }, + plugins: { vue: pluginVue }, rules: { 'no-unused-vars': 'error', 'vue/comment-directive': [ @@ -370,11 +371,11 @@ describe('comment-directive', () => { 'vue/no-parsing-error': 'error', 'vue/no-duplicate-attributes': 'error' }, - processor: require('../../../lib/processor') + processor } }) - async function lintMessages(code) { + async function lintMessages(code: string) { const result = await eslint.lintText(code, { filePath: 'test.vue' }) return result[0].messages } diff --git a/tsconfig.json b/tsconfig.json index b488a6b93..2008bef78 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,9 @@ "module": "node16", "moduleResolution": "Node16", "lib": ["es2020"], + "types": [ + "vitest/globals" + ], "allowJs": true, "checkJs": true, "noEmit": true, @@ -25,6 +28,7 @@ }, "include": [ "lib/**/*", + "tests/**/*.ts", "typings/eslint-plugin-vue/global.d.ts", "docs/.vitepress/**/*.ts", "docs/.vitepress/**/*.mts" From d617fbbd61383df5ac271deb1dfa4e589181582c Mon Sep 17 00:00:00 2001 From: rzzf Date: Fri, 5 Dec 2025 10:44:25 +0800 Subject: [PATCH 3/8] feat(vue/no-negated-v-if-condition): upgrade rule suggestion to autofix (#2984) Co-authored-by: Flo Edelmann --- .changeset/rich-zebras-type.md | 5 + docs/rules/index.md | 2 +- docs/rules/no-negated-v-if-condition.md | 4 +- lib/rules/no-negated-v-if-condition.js | 16 +- tests/lib/rules/no-negated-v-if-condition.js | 198 ++++++------------- 5 files changed, 73 insertions(+), 152 deletions(-) create mode 100644 .changeset/rich-zebras-type.md diff --git a/.changeset/rich-zebras-type.md b/.changeset/rich-zebras-type.md new file mode 100644 index 000000000..62c2438ae --- /dev/null +++ b/.changeset/rich-zebras-type.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-vue": minor +--- + +Changed `vue/no-negated-v-if-condition` suggestion to autofix diff --git a/docs/rules/index.md b/docs/rules/index.md index 3209c157d..5d8deaf00 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -238,7 +238,7 @@ For example: | [vue/no-empty-component-block] | disallow the `