diff --git a/docs/rules/no-focused-tests.md b/docs/rules/no-focused-tests.md index 94aa901..31a29b1 100644 --- a/docs/rules/no-focused-tests.md +++ b/docs/rules/no-focused-tests.md @@ -31,3 +31,35 @@ test('it', () => { /* ... */ }) ``` + +### Options + +This rule have a `fixable` option that is enabled by default; It tell this plugin to fix tests for you. If you don't want this rule to auto fix your tests, you can disable it in your `eslint.config.js` file using the following configuration. + +```ts +import vitest from 'eslint-plugin-vitest' + +export default [ + { + files: ['**/*.ts', '**/*.js'], // or any other pattern + plugins: { + vitest, + }, + rules: { + ...vitest.configs.recommended.all, + 'vitest/no-focused-tests': ['error', { 'fixable': false }] + }, + settings: { + vitest: { + typecheck: true + } + }, + languageOptions: { + parser: parser, + globals: { + ...vitest.environments.env.globals + } + } + } +] +``` diff --git a/src/rules/no-focused-tests.ts b/src/rules/no-focused-tests.ts index 87dcaf4..eeffb4c 100644 --- a/src/rules/no-focused-tests.ts +++ b/src/rules/no-focused-tests.ts @@ -3,7 +3,11 @@ import { createEslintRule } from '../utils' export type MessageIds = 'noFocusedTests' export const RULE_NAME = 'no-focused-tests' -export type Options = [] +export type Options = [ + Partial<{ + fixable: boolean + }> +] const isTestOrDescribe = (node: TSESTree.Expression) => { return node.type === 'Identifier' && ['it', 'test', 'describe'].includes(node.name) @@ -22,13 +26,29 @@ export default createEslintRule({ recommended: 'strict' }, fixable: 'code', - schema: [], + schema: [ + { + type: 'object', + properties: { + fixable: { + type: 'boolean', + default: true + } + }, + additionalProperties: false + } + ], messages: { noFocusedTests: 'Focused tests are not allowed.' } }, - defaultOptions: [], + defaultOptions: [{ fixable: true }], create: (context) => { + const config = context.options[0] ?? { + fixable: true + } + const fixable = config.fixable + return { ExpressionStatement(node) { if (node.expression.type === 'CallExpression') { @@ -40,7 +60,8 @@ export default createEslintRule({ ) { context.report({ node: callee.property, - messageId: 'noFocusedTests' + messageId: 'noFocusedTests', + fix: fixer => fixable ? fixer.removeRange([callee.property.range[0] - 1, callee.property.range[1]]) : null }) } @@ -55,7 +76,8 @@ export default createEslintRule({ ) { context.report({ node: tagCall.property, - messageId: 'noFocusedTests' + messageId: 'noFocusedTests', + fix: fixer => fixable ? fixer.removeRange([tagCall.property.range[0] - 1, tagCall.property.range[1]]) : null }) } } @@ -73,9 +95,17 @@ export default createEslintRule({ && callee.property.type === 'Identifier' && callee.property.name === 'each' ) { + const onlyCallee = callee.object.property + context.report({ node: callee.object.property, - messageId: 'noFocusedTests' + messageId: 'noFocusedTests', + fix: fixer => fixable + ? fixer.removeRange([ + onlyCallee.range[0] - 1, + onlyCallee.range[1] + ]) + : null }) } } diff --git a/tests/no-focused-tests.test.ts b/tests/no-focused-tests.test.ts index 808fc71..ff8e65e 100644 --- a/tests/no-focused-tests.test.ts +++ b/tests/no-focused-tests.test.ts @@ -6,6 +6,9 @@ ruleTester.run(RULE_NAME, rule, { invalid: [ { + options: [{ + fixable: false + }], code: 'it.only("test", () => {});', errors: [ { @@ -19,6 +22,9 @@ ruleTester.run(RULE_NAME, rule, { output: 'it.only("test", () => {});' }, { + options: [{ + fixable: false + }], code: 'describe.only("test", () => {});', errors: [ { @@ -32,6 +38,9 @@ ruleTester.run(RULE_NAME, rule, { output: 'describe.only("test", () => {});' }, { + options: [{ + fixable: false + }], code: 'test.only("test", () => {});', errors: [ { @@ -45,6 +54,9 @@ ruleTester.run(RULE_NAME, rule, { output: 'test.only("test", () => {});' }, { + options: [{ + fixable: false + }], code: 'it.only.each([])("test", () => {});', errors: [ { @@ -58,6 +70,9 @@ ruleTester.run(RULE_NAME, rule, { output: 'it.only.each([])("test", () => {});' }, { + options: [{ + fixable: false + }], code: 'test.only.each``("test", () => {});', errors: [ { @@ -71,6 +86,9 @@ ruleTester.run(RULE_NAME, rule, { output: 'test.only.each``("test", () => {});' }, { + options: [{ + fixable: false + }], code: 'it.only.each``("test", () => {});', errors: [ { @@ -85,3 +103,106 @@ ruleTester.run(RULE_NAME, rule, { } ] }) + +ruleTester.run(RULE_NAME, rule, { + valid: ['it("test", () => {});', 'describe("test group", () => {});'], + + invalid: [ + { + options: [{ + fixable: true + }], + code: 'it.only("test", () => {});', + errors: [ + { + column: 4, + endColumn: 8, + endLine: 1, + line: 1, + messageId: 'noFocusedTests' + } + ], + output: 'it("test", () => {});' + }, + { + options: [{ + fixable: true + }], + code: 'describe.only("test", () => {});', + errors: [ + { + column: 10, + endColumn: 14, + endLine: 1, + line: 1, + messageId: 'noFocusedTests' + } + ], + output: 'describe("test", () => {});' + }, + { + options: [{ + fixable: true + }], + code: 'test.only("test", () => {});', + errors: [ + { + column: 6, + endColumn: 10, + endLine: 1, + line: 1, + messageId: 'noFocusedTests' + } + ], + output: 'test("test", () => {});' + }, + { + options: [{ + fixable: true + }], + code: 'it.only.each([])("test", () => {});', + errors: [ + { + column: 4, + endColumn: 8, + endLine: 1, + line: 1, + messageId: 'noFocusedTests' + } + ], + output: 'it.each([])("test", () => {});' + }, + { + options: [{ + fixable: true + }], + code: 'test.only.each``("test", () => {});', + errors: [ + { + column: 6, + endColumn: 10, + endLine: 1, + line: 1, + messageId: 'noFocusedTests' + } + ], + output: 'test.each``("test", () => {});' + }, + { + options: [{ + fixable: true + }], + code: 'it.only.each``("test", () => {});', + errors: [ + { + column: 4, + endColumn: 8, + endLine: 1, + line: 1, + messageId: 'noFocusedTests' + } + ], + output: 'it.each``("test", () => {});' + } + ] +})