diff --git a/crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs b/crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs index 2d4909c54b30e..badf51bb613bc 100644 --- a/crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs +++ b/crates/oxc_linter/src/rules/jest/no_duplicate_hooks.rs @@ -31,6 +31,9 @@ declare_oxc_lint!( /// ### Why is this bad? /// /// Having duplicate hooks in a describe block can lead to confusion and unexpected behavior. + /// When multiple hooks of the same type exist, they all execute in order, which can make it + /// difficult to understand the test setup flow and may result in redundant or conflicting + /// operations. This makes tests harder to maintain and debug. /// /// ### Examples /// diff --git a/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs b/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs index c2cd38a3395d9..0b1b93059c843 100644 --- a/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs +++ b/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs @@ -21,7 +21,14 @@ pub struct NoJasmineGlobals; declare_oxc_lint!( /// ### What it does /// - /// This rule reports on any usage of Jasmine globals, which is not ported to Jest, and suggests alternatives from Jest's own API. + /// This rule reports on any usage of Jasmine globals, which is not ported to + /// Jest, and suggests alternatives from Jest's own API. + /// + /// ### Why is this bad? + /// + /// When migrating from Jasmine to Jest, relying on Jasmine-specific globals + /// creates compatibility issues and prevents taking advantage of Jest's + /// improved testing features and better error reporting. /// /// ### Examples /// @@ -29,10 +36,24 @@ declare_oxc_lint!( /// ```javascript /// jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; /// test('my test', () => { - /// pending(); + /// pending(); + /// }); + /// test('my test', () => { + /// jasmine.createSpy(); + /// }); + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```javascript + /// jest.setTimeout(5000); + /// test('my test', () => { + /// // Use test.skip() instead of pending() + /// }); + /// test.skip('my test', () => { + /// // Skipped test /// }); /// test('my test', () => { - /// jasmine.createSpy(); + /// jest.fn(); // Use jest.fn() instead of jasmine.createSpy() /// }); /// ``` NoJasmineGlobals, diff --git a/crates/oxc_linter/src/rules/jest/no_mocks_import.rs b/crates/oxc_linter/src/rules/jest/no_mocks_import.rs index c61c14a53c036..7a388aedd4ade 100644 --- a/crates/oxc_linter/src/rules/jest/no_mocks_import.rs +++ b/crates/oxc_linter/src/rules/jest/no_mocks_import.rs @@ -24,7 +24,11 @@ declare_oxc_lint!( /// /// ### Why is this bad? /// - /// Manually importing mocks from a `__mocks__` directory can lead to unexpected behavior. + /// Manually importing mocks from a `__mocks__` directory can lead to unexpected behavior + /// and breaks Jest's automatic mocking system. Jest is designed to automatically resolve + /// and use mocks from `__mocks__` directories when `jest.mock()` is called. Directly + /// importing from these directories bypasses Jest's module resolution system and can cause + /// inconsistencies between test and production environments. /// /// ### Examples /// diff --git a/crates/oxc_linter/src/rules/jest/no_restricted_matchers.rs b/crates/oxc_linter/src/rules/jest/no_restricted_matchers.rs index 315458a9c7fc7..fa2233f0124e5 100644 --- a/crates/oxc_linter/src/rules/jest/no_restricted_matchers.rs +++ b/crates/oxc_linter/src/rules/jest/no_restricted_matchers.rs @@ -46,6 +46,14 @@ declare_oxc_lint!( /// /// Ban specific matchers & modifiers from being used, and can suggest alternatives. /// + /// ### Why is this bad? + /// + /// Some matchers or modifiers might be discouraged in your codebase for various reasons: + /// they might be deprecated, cause confusion, have performance implications, or there + /// might be better alternatives available. This rule allows you to enforce consistent + /// testing patterns by restricting certain Jest matchers and providing guidance on + /// preferred alternatives. + /// /// ### Examples /// /// Bans are expressed in the form of a map, with the value being either a string message to be shown, diff --git a/crates/oxc_linter/src/rules/jest/no_standalone_expect/mod.rs b/crates/oxc_linter/src/rules/jest/no_standalone_expect/mod.rs index a61de4a70c126..f6b3b93d5a98e 100644 --- a/crates/oxc_linter/src/rules/jest/no_standalone_expect/mod.rs +++ b/crates/oxc_linter/src/rules/jest/no_standalone_expect/mod.rs @@ -49,6 +49,13 @@ declare_oxc_lint!( /// Statements like `expect.hasAssertions()` will NOT trigger this rule since these /// calls will execute if they are not in a test block. /// + /// ### Why is this bad? + /// + /// `expect` statements outside of test blocks will not be executed by the Jest + /// test runner, which means they won't actually test anything. This can lead to + /// false confidence in test coverage and may hide bugs that would otherwise be + /// caught by proper testing. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/prefer_called_with.rs b/crates/oxc_linter/src/rules/jest/prefer_called_with.rs index 4a4a27eb82cfd..f9968bc6d81df 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_called_with.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_called_with.rs @@ -29,6 +29,14 @@ declare_oxc_lint!( /// /// Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` /// + /// ### Why is this bad? + /// + /// When testing function calls, it's often more valuable to assert both + /// that a function was called AND what arguments it was called with. + /// Using `toBeCalled()` or `toHaveBeenCalled()` only verifies the function + /// was invoked, but doesn't validate the arguments, potentially missing + /// bugs where functions are called with incorrect parameters. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/prefer_comparison_matcher.rs b/crates/oxc_linter/src/rules/jest/prefer_comparison_matcher.rs index dd7c2372c24f2..0954520548475 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_comparison_matcher.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_comparison_matcher.rs @@ -36,6 +36,13 @@ declare_oxc_lint!( /// - `toBeLessThan` /// - `toBeLessThanOrEqual` /// + /// ### Why is this bad? + /// + /// Using generic matchers like `toBe(true)` with comparison expressions + /// makes tests less readable and provides less helpful error messages when + /// they fail. Jest's specific comparison matchers offer clearer intent and + /// better error output that shows the actual values being compared. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/prefer_equality_matcher.rs b/crates/oxc_linter/src/rules/jest/prefer_equality_matcher.rs index d38e0dabdf016..105c3077d3284 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_equality_matcher.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_equality_matcher.rs @@ -28,6 +28,14 @@ declare_oxc_lint!( /// Jest has built-in matchers for expecting equality, which allow for more readable /// tests and error messages if an expectation fails. /// + /// ### Why is this bad? + /// + /// Testing equality expressions with generic matchers like `toBe(true)` + /// makes tests harder to read and understand. When tests fail, the error + /// messages are less helpful because they don't show what the actual values + /// were. Using specific equality matchers provides clearer test intent and + /// better debugging information. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/prefer_hooks_on_top.rs b/crates/oxc_linter/src/rules/jest/prefer_hooks_on_top.rs index 2ae27e19d89e1..48ac1b91062b6 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_hooks_on_top.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_hooks_on_top.rs @@ -30,6 +30,14 @@ declare_oxc_lint!( /// specific order, which means it can be confusing if they're intermixed with test /// cases. /// + /// ### Why is this bad? + /// + /// When hooks are mixed with test cases, it becomes harder to understand + /// the test setup and execution order. This can lead to confusion about + /// which hooks apply to which tests and when they run. Grouping hooks at + /// the top of each `describe` block makes the test structure clearer and + /// more maintainable. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/prefer_jest_mocked.rs b/crates/oxc_linter/src/rules/jest/prefer_jest_mocked.rs index 3b8c1698a6bcb..53f8d51cfc019 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_jest_mocked.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_jest_mocked.rs @@ -30,6 +30,14 @@ declare_oxc_lint!( /// - `jest.MockedClass` /// - `jest.MockedObject` /// + /// ### Why is this bad? + /// + /// Using type assertions like `fn as jest.Mock` is a less safe approach + /// than using `jest.mocked()`. The `jest.mocked()` helper provides better + /// type safety by preserving the original function signature while adding + /// mock capabilities. It also makes the code more readable and explicit + /// about mocking intentions. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/prefer_mock_promise_shorthand.rs b/crates/oxc_linter/src/rules/jest/prefer_mock_promise_shorthand.rs index d2ad97dbc581a..2c8b895ab8ed0 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_mock_promise_shorthand.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_mock_promise_shorthand.rs @@ -24,6 +24,14 @@ declare_oxc_lint!( /// API sugar functions to reduce the amount of boilerplate you have to write. /// These methods should be preferred when possible. /// + /// ### Why is this bad? + /// + /// Using generic mock functions like `mockImplementation(() => Promise.resolve())` + /// or `mockReturnValue(Promise.reject())` is more verbose and less readable than + /// Jest's specialized promise shorthands. The shorthand methods like + /// `mockResolvedValue()` and `mockRejectedValue()` are more expressive and + /// make the test intent clearer. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/prefer_spy_on.rs b/crates/oxc_linter/src/rules/jest/prefer_spy_on.rs index 60f204a601bec..3431452e4f753 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_spy_on.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_spy_on.rs @@ -40,6 +40,14 @@ declare_oxc_lint!( /// `mockFn.mockImplementation()` or by some of the /// [other mock functions](https://jestjs.io/docs/en/mock-function-api). /// + /// ### Why is this bad? + /// + /// Directly overwriting properties with mock functions can lead to cleanup issues + /// and test isolation problems. When you manually assign a mock to a property, + /// you're responsible for restoring the original implementation, which is easy to + /// forget and can cause tests to interfere with each other. Using `jest.spyOn()` + /// provides automatic cleanup capabilities and makes your tests more reliable. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/prefer_strict_equal.rs b/crates/oxc_linter/src/rules/jest/prefer_strict_equal.rs index de5adfafbea8c..5ea69665688c1 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_strict_equal.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_strict_equal.rs @@ -22,6 +22,13 @@ declare_oxc_lint!( /// /// This rule triggers a warning if `toEqual()` is used to assert equality. /// + /// ### Why is this bad? + /// + /// The `toEqual()` matcher performs a deep equality check but ignores + /// `undefined` values in objects and arrays. This can lead to false + /// positives where tests pass when they should fail. `toStrictEqual()` + /// provides more accurate comparison by checking for `undefined` values. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/require_hook.rs b/crates/oxc_linter/src/rules/jest/require_hook.rs index 04e902ae7e6e1..254cb4addc139 100644 --- a/crates/oxc_linter/src/rules/jest/require_hook.rs +++ b/crates/oxc_linter/src/rules/jest/require_hook.rs @@ -52,6 +52,15 @@ declare_oxc_lint!( /// - Types /// - Calls to the standard Jest globals /// + /// ### Why is this bad? + /// + /// Having setup and teardown code outside of hooks can lead to unpredictable test + /// behavior. Code that runs at the top level executes when the test file is loaded, + /// not when tests run, which can cause issues with test isolation and make tests + /// dependent on execution order. Using proper hooks like `beforeEach`, `beforeAll`, + /// `afterEach`, and `afterAll` ensures that setup and teardown code runs at the + /// correct time and maintains test isolation. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jest/require_to_throw_message.rs b/crates/oxc_linter/src/rules/jest/require_to_throw_message.rs index b5ea6b52729e0..31335c53c8f4e 100644 --- a/crates/oxc_linter/src/rules/jest/require_to_throw_message.rs +++ b/crates/oxc_linter/src/rules/jest/require_to_throw_message.rs @@ -23,6 +23,14 @@ declare_oxc_lint!( /// /// This rule triggers a warning if `toThrow()` or `toThrowError()` is used without an error message. /// + /// ### Why is this bad? + /// + /// Using `toThrow()` or `toThrowError()` without specifying an expected error message + /// makes tests less specific and harder to debug. When a test only checks that an + /// error was thrown but not what kind of error, it can pass even when the wrong + /// error is thrown, potentially hiding bugs. Providing an expected error message + /// or error type makes tests more precise and helps catch regressions more effectively. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/jsdoc/check_access.rs b/crates/oxc_linter/src/rules/jsdoc/check_access.rs index eccc2875c620b..ba24611c27c05 100644 --- a/crates/oxc_linter/src/rules/jsdoc/check_access.rs +++ b/crates/oxc_linter/src/rules/jsdoc/check_access.rs @@ -34,7 +34,11 @@ declare_oxc_lint!( /// /// ### Why is this bad? /// - /// It is important to have a consistent way of specifying access levels. + /// It is important to have a consistent way of specifying access levels in JSDoc + /// comments. Using invalid or multiple access level tags creates confusion about + /// the intended visibility of documented elements and can lead to inconsistencies + /// in API documentation generation. Mixing different access tags or using invalid + /// values makes the documentation unclear and potentially misleading. /// /// ### Examples /// diff --git a/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs b/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs index 60b4186cd384e..25c0596389d7e 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/aria_activedescendant_has_tabindex.rs @@ -28,6 +28,13 @@ declare_oxc_lint!( /// /// Enforce elements with aria-activedescendant are tabbable. /// + /// ### Why is this bad? + /// + /// Elements with `aria-activedescendant` must be tabbable for users to + /// navigate to them using keyboard input. Without proper tabindex, screen + /// reader users cannot access the element through keyboard navigation, + /// making the functionality inaccessible. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/nextjs/no_styled_jsx_in_document.rs b/crates/oxc_linter/src/rules/nextjs/no_styled_jsx_in_document.rs index 81fcec88873c5..baf78ee5a83a5 100644 --- a/crates/oxc_linter/src/rules/nextjs/no_styled_jsx_in_document.rs +++ b/crates/oxc_linter/src/rules/nextjs/no_styled_jsx_in_document.rs @@ -30,10 +30,47 @@ declare_oxc_lint!( /// /// Examples of **incorrect** code for this rule: /// ```javascript + /// // pages/_document.js + /// import Document, { Html, Head, Main, NextScript } from 'next/document' + /// + /// class MyDocument extends Document { + /// render() { + /// return ( + /// + /// + /// + ///
+ /// + /// + /// + /// + /// ) + /// } + /// } /// ``` /// /// Examples of **correct** code for this rule: /// ```javascript + /// // pages/_document.js + /// import Document, { Html, Head, Main, NextScript } from 'next/document' + /// + /// class MyDocument extends Document { + /// render() { + /// return ( + /// + /// + /// + ///
+ /// + /// + /// + /// ) + /// } + /// } /// ``` NoStyledJsxInDocument, nextjs, diff --git a/crates/oxc_linter/src/rules/oxc/no_async_await.rs b/crates/oxc_linter/src/rules/oxc/no_async_await.rs index bf35a2275bc33..7d975d066731a 100644 --- a/crates/oxc_linter/src/rules/oxc/no_async_await.rs +++ b/crates/oxc_linter/src/rules/oxc/no_async_await.rs @@ -19,6 +19,13 @@ declare_oxc_lint!( /// /// Disallows the use of async/await. /// + /// ### Why is this bad? + /// + /// This rule is useful for environments that don't support async/await syntax + /// or when you want to enforce the use of promises or other asynchronous + /// patterns instead. It can also be used to maintain consistency in codebases + /// that use alternative async patterns. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/oxc/no_barrel_file.rs b/crates/oxc_linter/src/rules/oxc/no_barrel_file.rs index 4b7b79ebcff07..37e3a6e6aa652 100644 --- a/crates/oxc_linter/src/rules/oxc/no_barrel_file.rs +++ b/crates/oxc_linter/src/rules/oxc/no_barrel_file.rs @@ -35,6 +35,14 @@ declare_oxc_lint!( /// /// The default threshold is 100; /// + /// ### Why is this bad? + /// + /// Barrel files that re-export many modules can significantly slow down + /// applications and bundlers. When a barrel file exports a large number of + /// modules, importing from it forces the runtime or bundler to process all + /// the exported modules, even if only a few are actually used. This leads + /// to slower startup times and larger bundle sizes. + /// /// References: /// /// * diff --git a/crates/oxc_linter/src/rules/oxc/no_optional_chaining.rs b/crates/oxc_linter/src/rules/oxc/no_optional_chaining.rs index f7ff1f1d00c88..798379165803b 100644 --- a/crates/oxc_linter/src/rules/oxc/no_optional_chaining.rs +++ b/crates/oxc_linter/src/rules/oxc/no_optional_chaining.rs @@ -36,6 +36,15 @@ declare_oxc_lint!( /// /// Disallow [optional chaining](https://github.com/tc39/proposal-optional-chaining). /// + /// ### Why is this bad? + /// + /// Optional chaining is a relatively new JavaScript feature that may not be + /// supported in older environments. In some cases, transpiling optional + /// chaining can result in verbose helper code that impacts bundle size or + /// performance. This rule is useful when you need to maintain compatibility + /// with older JavaScript targets or want to avoid the overhead of transpiled + /// optional chaining. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: diff --git a/crates/oxc_linter/src/rules/oxc/no_rest_spread_properties.rs b/crates/oxc_linter/src/rules/oxc/no_rest_spread_properties.rs index ed30bbce5ebab..5fb349b2c604e 100644 --- a/crates/oxc_linter/src/rules/oxc/no_rest_spread_properties.rs +++ b/crates/oxc_linter/src/rules/oxc/no_rest_spread_properties.rs @@ -35,6 +35,14 @@ declare_oxc_lint!( /// /// Disallow [Object Rest/Spread Properties](https://github.com/tc39/proposal-object-rest-spread#readme). /// + /// ### Why is this bad? + /// + /// Object rest/spread properties are a relatively new JavaScript feature that may + /// not be supported in all target environments. If you need to support older + /// browsers or JavaScript engines that don't support these features, using them + /// can cause runtime errors. This rule helps maintain compatibility with older + /// environments by preventing the use of these modern syntax features. + /// /// ### Examples /// /// Examples of **incorrect** code for this rule: