From 537b052b01f66f476c647fd7b20125539eb353bf Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 23 Nov 2025 00:27:17 +0800 Subject: [PATCH 1/4] test: rewrite some files in `.ts` --- .../lib/configs/{eslintrc.js => eslintrc.ts} | 6 +- tests/lib/configs/{flat.js => flat.ts} | 103 +++++++++--------- .../rules/{block-order.js => block-order.ts} | 21 ++-- ...ment-directive.js => comment-directive.ts} | 25 +++-- tsconfig.json | 4 + 5 files changed, 81 insertions(+), 78 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} (97%) rename tests/lib/rules/{comment-directive.js => comment-directive.ts} (97%) 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 97% rename from tests/lib/rules/block-order.js rename to tests/lib/rules/block-order.ts index 4eb25e2bd..e421055a7 100644 --- a/tests/lib/rules/block-order.js +++ b/tests/lib/rules/block-order.ts @@ -1,12 +1,12 @@ /** * @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 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,25 +14,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 } }) +// @ts-expect-error tester.run('block-order', rule, { valid: [ // default 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 3507f1ea2e20998b2411a844cb44ded82cb5cd14 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 23 Nov 2025 00:38:46 +0800 Subject: [PATCH 2/4] chore: fix lint --- eslint.config.mjs | 1 + tests/lib/rules/block-order.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 044005f23..350050bdb 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -284,6 +284,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/rules/block-order.ts b/tests/lib/rules/block-order.ts index e421055a7..c96eda126 100644 --- a/tests/lib/rules/block-order.ts +++ b/tests/lib/rules/block-order.ts @@ -33,7 +33,7 @@ const tester = new RuleTester({ } }) -// @ts-expect-error +// @ts-expect-error rule ts(#2345) tester.run('block-order', rule, { valid: [ // default From abd07e8bd694e4eef31b5a44a6d571337358b03c Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Thu, 27 Nov 2025 20:36:18 +0800 Subject: [PATCH 3/4] test: update --- tests/lib/rules/block-order.ts | 21 ++------------------- typings/eslint/index.d.ts | 2 +- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/tests/lib/rules/block-order.ts b/tests/lib/rules/block-order.ts index c96eda126..659522cb6 100644 --- a/tests/lib/rules/block-order.ts +++ b/tests/lib/rules/block-order.ts @@ -1,6 +1,7 @@ /** * @author Yosuke Ota */ +import { Rule } from '../../../node_modules/@types/eslint' import assert from 'assert' import parserVue from 'vue-eslint-parser' import rule from '../../../lib/rules/block-order' @@ -33,8 +34,7 @@ const tester = new RuleTester({ } }) -// @ts-expect-error rule ts(#2345) -tester.run('block-order', rule, { +tester.run('block-order', rule as unknown as Rule.RuleModule, { valid: [ // default '', @@ -72,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'] @@ -118,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'] @@ -144,7 +132,6 @@ tester.run('block-order', rule, { }, { code: '', - output: null, options: [ { order: [ @@ -159,7 +146,6 @@ tester.run('block-order', rule, { }, { code: '', - output: null, options: [ { order: [ @@ -176,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/typings/eslint/index.d.ts b/typings/eslint/index.d.ts index f45f216d8..72d512e59 100644 --- a/typings/eslint/index.d.ts +++ b/typings/eslint/index.d.ts @@ -271,7 +271,7 @@ export namespace SourceCode { } export namespace Rule { - interface RuleModule /*extends ESLintRule.RuleModule*/ { + interface RuleModule extends ESLintRule.RuleModule { meta: RuleMetaData create(context: RuleContext): Rule.RuleListener } From 35bfd7ccf98290dda80a978b9a372003a1749df3 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Thu, 27 Nov 2025 20:39:05 +0800 Subject: [PATCH 4/4] revert `eslint/index.d.ts` --- typings/eslint/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/eslint/index.d.ts b/typings/eslint/index.d.ts index 72d512e59..f45f216d8 100644 --- a/typings/eslint/index.d.ts +++ b/typings/eslint/index.d.ts @@ -271,7 +271,7 @@ export namespace SourceCode { } export namespace Rule { - interface RuleModule extends ESLintRule.RuleModule { + interface RuleModule /*extends ESLintRule.RuleModule*/ { meta: RuleMetaData create(context: RuleContext): Rule.RuleListener }