From 25805639edf59b5d8825cd4245e1fa66aff56382 Mon Sep 17 00:00:00 2001 From: Bryan Mishkin <698306+bmish@users.noreply.github.com> Date: Sat, 10 Sep 2022 07:52:41 -0400 Subject: [PATCH] fix: consistent rule doc notices and sections (#1226) Co-authored-by: Gareth Jones --- README.md | 2 + docs/rules/consistent-test-it.md | 14 +- docs/rules/expect-expect.md | 6 + docs/rules/max-expects.md | 8 +- docs/rules/max-nested-describe.md | 8 +- docs/rules/no-alias-methods.md | 10 ++ docs/rules/no-commented-out-tests.md | 8 +- docs/rules/no-conditional-expect.md | 8 +- docs/rules/no-conditional-in-test.md | 8 +- docs/rules/no-deprecated-functions.md | 10 ++ docs/rules/no-disabled-tests.md | 8 +- docs/rules/no-done-callback.md | 10 ++ docs/rules/no-duplicate-hooks.md | 8 +- docs/rules/no-export.md | 8 +- docs/rules/no-focused-tests.md | 13 +- docs/rules/no-hooks.md | 8 +- docs/rules/no-identical-title.md | 8 +- docs/rules/no-if.md | 8 +- docs/rules/no-interpolation-in-snapshots.md | 8 +- docs/rules/no-jasmine-globals.md | 12 +- docs/rules/no-large-snapshots.md | 8 +- docs/rules/no-mocks-import.md | 8 +- docs/rules/no-restricted-matchers.md | 12 +- docs/rules/no-standalone-expect.md | 8 +- docs/rules/no-test-prefixes.md | 10 ++ docs/rules/no-test-return-statement.md | 6 + docs/rules/prefer-called-with.md | 6 + docs/rules/prefer-comparison-matcher.md | 10 ++ docs/rules/prefer-each.md | 6 + docs/rules/prefer-equality-matcher.md | 10 ++ docs/rules/prefer-expect-assertions.md | 10 ++ docs/rules/prefer-expect-resolves.md | 10 ++ docs/rules/prefer-hooks-in-order.md | 8 +- docs/rules/prefer-hooks-on-top.md | 8 +- docs/rules/prefer-lowercase-title.md | 10 ++ docs/rules/prefer-mock-promise-shorthand.md | 12 +- docs/rules/prefer-snapshot-hint.md | 6 + docs/rules/prefer-spy-on.md | 10 ++ docs/rules/prefer-strict-equal.md | 10 ++ docs/rules/prefer-to-be.md | 10 ++ docs/rules/prefer-to-contain.md | 10 ++ docs/rules/prefer-to-have-length.md | 10 ++ docs/rules/prefer-todo.md | 10 ++ docs/rules/require-hook.md | 6 + docs/rules/require-to-throw-message.md | 6 + docs/rules/require-top-level-describe.md | 10 +- docs/rules/unbound-method.md | 11 +- docs/rules/valid-describe-callback.md | 8 +- docs/rules/valid-expect-in-promise.md | 6 + docs/rules/valid-expect.md | 6 + docs/rules/valid-title.md | 12 +- tools/regenerate-docs.ts | 138 ++++++++++++++++++-- tools/rule-notices.ts | 116 ++++++++++++++++ 53 files changed, 659 insertions(+), 41 deletions(-) create mode 100644 tools/rule-notices.ts diff --git a/README.md b/README.md index 5e34686f6..80790dceb 100644 --- a/README.md +++ b/README.md @@ -215,6 +215,7 @@ installations requiring long-term consistency. | [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | ![recommended][] | ![suggest][] | | [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | | | [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | ![recommended][] | | +| [no-if](docs/rules/no-if.md) | Disallow conditional logic | ![deprecated][] | | | [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside snapshots | ![recommended][] | | | [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals | ![recommended][] | ![fixable][] | | [no-large-snapshots](docs/rules/no-large-snapshots.md) | disallow large snapshots | | | @@ -308,4 +309,5 @@ https://github.com/istanbuljs/eslint-plugin-istanbul [suggest]: https://img.shields.io/badge/-suggest-yellow.svg [fixable]: https://img.shields.io/badge/-fixable-green.svg [style]: https://img.shields.io/badge/-style-blue.svg +[deprecated]: https://img.shields.io/badge/-deprecated-red.svg [`no-deprecated-functions`]: docs/rules/no-deprecated-functions.md diff --git a/docs/rules/consistent-test-it.md b/docs/rules/consistent-test-it.md index 94e74e61b..71d303181 100644 --- a/docs/rules/consistent-test-it.md +++ b/docs/rules/consistent-test-it.md @@ -1,14 +1,26 @@ # Have control over `test` and `it` usages (`consistent-test-it`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + Jest allows you to choose how you want to define your tests, using the `it` or the `test` keywords, with multiple permutations for each: - **it:** `it`, `xit`, `fit`, `it.only`, `it.skip`. - **test:** `test`, `xtest`, `test.only`, `test.skip`. +## Rule details + This rule gives you control over the usage of these keywords in your codebase. -## Rule Details +## Options This rule can be configured as follows diff --git a/docs/rules/expect-expect.md b/docs/rules/expect-expect.md index 636216067..f832faeb7 100644 --- a/docs/rules/expect-expect.md +++ b/docs/rules/expect-expect.md @@ -1,5 +1,11 @@ # Enforce assertion to be made in a test body (`expect-expect`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + Ensure that there is at least one `expect` call made in a test. ## Rule details diff --git a/docs/rules/max-expects.md b/docs/rules/max-expects.md index 1efa59ae7..5034f4d4a 100644 --- a/docs/rules/max-expects.md +++ b/docs/rules/max-expects.md @@ -1,10 +1,16 @@ # Enforces a maximum number assertion calls in a test body (`max-expects`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + As more assertions are made, there is a possible tendency for the test to be more likely to mix multiple objectives. To avoid this, this rule reports when the maximum number of assertions is exceeded. -## Rule Details +## Rule details This rule enforces a maximum number of `expect()` calls. diff --git a/docs/rules/max-nested-describe.md b/docs/rules/max-nested-describe.md index 9f10f9828..6293ae1a4 100644 --- a/docs/rules/max-nested-describe.md +++ b/docs/rules/max-nested-describe.md @@ -1,10 +1,16 @@ # Enforces a maximum depth to nested describe calls (`max-nested-describe`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + While it's useful to be able to group your tests together within the same file using `describe()`, having too many levels of nesting throughout your tests make them difficult to read. -## Rule Details +## Rule details This rule enforces a maximum depth to nested `describe()` calls to improve code clarity in your tests. diff --git a/docs/rules/no-alias-methods.md b/docs/rules/no-alias-methods.md index d439104de..fc61154c3 100644 --- a/docs/rules/no-alias-methods.md +++ b/docs/rules/no-alias-methods.md @@ -1,5 +1,15 @@ # Disallow alias methods (`no-alias-methods`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + > These aliases are going to be removed in the next major version of Jest - see > https://github.com/facebook/jest/issues/13164 for more diff --git a/docs/rules/no-commented-out-tests.md b/docs/rules/no-commented-out-tests.md index b12755c47..413008d76 100644 --- a/docs/rules/no-commented-out-tests.md +++ b/docs/rules/no-commented-out-tests.md @@ -1,9 +1,15 @@ # Disallow commented out tests (`no-commented-out-tests`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + This rule raises a warning about commented out tests. It's similar to no-disabled-tests rule. -## Rule Details +## Rule details The rule uses fuzzy matching to do its best to determine what constitutes a commented out test, checking for a presence of `it(`, `describe(`, `it.skip(`, diff --git a/docs/rules/no-conditional-expect.md b/docs/rules/no-conditional-expect.md index fc46d3ff7..b15dd68ab 100644 --- a/docs/rules/no-conditional-expect.md +++ b/docs/rules/no-conditional-expect.md @@ -1,12 +1,18 @@ # Prevent calling `expect` conditionally (`no-conditional-expect`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + This rule prevents the use of `expect` in conditional blocks, such as `if`s & `catch`s. This includes using `expect` in callbacks to functions named `catch`, which are assumed to be promises. -## Rule Details +## Rule details Jest only considers a test to have failed if it throws an error, meaning if calls to assertion functions like `expect` occur in conditional code such as a diff --git a/docs/rules/no-conditional-in-test.md b/docs/rules/no-conditional-in-test.md index 6850cc47f..7fe5e9c8f 100644 --- a/docs/rules/no-conditional-in-test.md +++ b/docs/rules/no-conditional-in-test.md @@ -1,11 +1,17 @@ # Disallow conditional logic in tests (`no-conditional-in-test`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + Conditional logic in tests is usually an indication that a test is attempting to cover too much, and not testing the logic it intends to. Each branch of code executing within a conditional statement will usually be better served by a test devoted to it. -## Rule Details +## Rule details This rule reports on any use of a conditional statement such as `if`, `switch`, and ternary expressions. diff --git a/docs/rules/no-deprecated-functions.md b/docs/rules/no-deprecated-functions.md index 63fa808f4..4b3a23909 100644 --- a/docs/rules/no-deprecated-functions.md +++ b/docs/rules/no-deprecated-functions.md @@ -1,5 +1,15 @@ # Disallow use of deprecated functions (`no-deprecated-functions`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + Over the years Jest has accrued some debt in the form of functions that have either been renamed for clarity, or replaced with more powerful APIs. diff --git a/docs/rules/no-disabled-tests.md b/docs/rules/no-disabled-tests.md index c6726686a..56595ed55 100644 --- a/docs/rules/no-disabled-tests.md +++ b/docs/rules/no-disabled-tests.md @@ -1,5 +1,11 @@ # Disallow disabled tests (`no-disabled-tests`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + Jest has a feature that allows you to temporarily mark tests as disabled. This feature is often helpful while debugging or to create placeholders for future tests. Before committing changes we may want to check that all tests are @@ -7,7 +13,7 @@ running. This rule raises a warning about disabled tests. -## Rule Details +## Rule details There are a number of ways to disable tests in Jest: diff --git a/docs/rules/no-done-callback.md b/docs/rules/no-done-callback.md index abae2b017..551fb9e0d 100644 --- a/docs/rules/no-done-callback.md +++ b/docs/rules/no-done-callback.md @@ -1,5 +1,15 @@ # Avoid using a callback in asynchronous tests and hooks (`no-done-callback`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + +πŸ’‘ This rule provides +[suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) +that can be applied manually. + + + When calling asynchronous code in hooks and tests, `jest` needs to know when the asynchronous work is complete to progress the current run. diff --git a/docs/rules/no-duplicate-hooks.md b/docs/rules/no-duplicate-hooks.md index 58b69d5dd..72bca8b31 100644 --- a/docs/rules/no-duplicate-hooks.md +++ b/docs/rules/no-duplicate-hooks.md @@ -1,8 +1,14 @@ # Disallow duplicate setup and teardown hooks (`no-duplicate-hooks`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + A `describe` block should not contain duplicate hooks. -## Rule Details +## Rule details Examples of **incorrect** code for this rule diff --git a/docs/rules/no-export.md b/docs/rules/no-export.md index f8379b72e..df9136be5 100644 --- a/docs/rules/no-export.md +++ b/docs/rules/no-export.md @@ -1,8 +1,14 @@ # Disallow using `exports` in files containing tests (`no-export`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + Prevents using `exports` if a file has one or more tests in it. -## Rule Details +## Rule details This rule aims to eliminate duplicate runs of tests by exporting things from test files. If you import from a test file, then all the tests in that file will diff --git a/docs/rules/no-focused-tests.md b/docs/rules/no-focused-tests.md index 22f00bd99..02975a0b3 100644 --- a/docs/rules/no-focused-tests.md +++ b/docs/rules/no-focused-tests.md @@ -1,5 +1,16 @@ # Disallow focused tests (`no-focused-tests`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + +πŸ’‘ This rule provides +[suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) +that can be applied manually. + + + + Jest has a feature that allows you to focus tests by appending `.only` or prepending `f` to a test-suite or a test-case. This feature is really helpful to debug a failing test, so you don’t have to execute all of your tests. After you @@ -9,7 +20,7 @@ have fixed your test and before committing the changes you have to remove This rule reminds you to remove `.only` from your tests by raising a warning whenever you are using the exclusivity feature. -## Rule Details +## Rule details This rule looks for every `describe.only`, `it.only`, `test.only`, `fdescribe`, and `fit` occurrences within the source code. Of course there are some diff --git a/docs/rules/no-hooks.md b/docs/rules/no-hooks.md index 708d3550d..75438f4cb 100644 --- a/docs/rules/no-hooks.md +++ b/docs/rules/no-hooks.md @@ -1,10 +1,16 @@ # Disallow setup and teardown hooks (`no-hooks`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + Jest provides global functions for setup and teardown tasks, which are called before/after each test case and each test suite. The use of these hooks promotes shared state between tests. -## Rule Details +## Rule details This rule reports for the following function calls: diff --git a/docs/rules/no-identical-title.md b/docs/rules/no-identical-title.md index d56e41e90..495b0faeb 100644 --- a/docs/rules/no-identical-title.md +++ b/docs/rules/no-identical-title.md @@ -1,11 +1,17 @@ # Disallow identical titles (`no-identical-title`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + Having identical titles for two different tests or test suites may create confusion. For example, when a test with the same title as another test in the same test suite fails, it is harder to know which one failed and thus harder to fix. -## Rule Details +## Rule details This rule looks at the title of every test and test suite. It will report when two test suites or two test cases at the same level of a test suite have the diff --git a/docs/rules/no-if.md b/docs/rules/no-if.md index e44015e0b..033a9c3a2 100644 --- a/docs/rules/no-if.md +++ b/docs/rules/no-if.md @@ -1,9 +1,9 @@ # Disallow conditional logic (`no-if`) -## Deprecated +❌ This rule is deprecated. It was replaced by +[no-conditional-in-test](no-conditional-in-test.md). -This rule has been deprecated in favor of -[`no-conditional-in-test`](no-conditional-in-test.md). + Conditional logic in tests is usually an indication that a test is attempting to cover too much, and not testing the logic it intends to. Each branch of code @@ -13,7 +13,7 @@ to it. Conditionals are often used to satisfy the typescript type checker. In these cases, using the non-null assertion operator (!) would be best. -## Rule Details +## Rule details This rule prevents the use of if/ else statements and conditional (ternary) operations in tests. diff --git a/docs/rules/no-interpolation-in-snapshots.md b/docs/rules/no-interpolation-in-snapshots.md index 0ac13540e..a4a394614 100644 --- a/docs/rules/no-interpolation-in-snapshots.md +++ b/docs/rules/no-interpolation-in-snapshots.md @@ -1,8 +1,14 @@ # Disallow string interpolation inside snapshots (`no-interpolation-in-snapshots`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + Prevents the use of string interpolations in snapshots. -## Rule Details +## Rule details Interpolation prevents snapshots from being updated. Instead, properties should be overloaded with a matcher by using diff --git a/docs/rules/no-jasmine-globals.md b/docs/rules/no-jasmine-globals.md index 8fbb47356..fb48142bb 100644 --- a/docs/rules/no-jasmine-globals.md +++ b/docs/rules/no-jasmine-globals.md @@ -1,5 +1,15 @@ # Disallow Jasmine globals (`no-jasmine-globals`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + `jest` uses `jasmine` as a test runner. A side effect of this is that both a `jasmine` object, and some jasmine-specific globals, are exposed to the test environment. Most functionality offered by Jasmine has been ported to Jest, and @@ -7,7 +17,7 @@ the Jasmine globals will stop working in the future. Developers should therefore migrate to Jest's documented API instead of relying on the undocumented Jasmine API. -### Rule details +## Rule details This rule reports on any usage of Jasmine globals, which is not ported to Jest, and suggests alternatives from Jest's own API. diff --git a/docs/rules/no-large-snapshots.md b/docs/rules/no-large-snapshots.md index 8572fda98..8a4d6e27e 100644 --- a/docs/rules/no-large-snapshots.md +++ b/docs/rules/no-large-snapshots.md @@ -1,5 +1,11 @@ # disallow large snapshots (`no-large-snapshots`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + When using Jest's snapshot capability one should be mindful of the size of created snapshots. As a general best practice snapshots should be limited in size in order to be more manageable and reviewable. A stored snapshot is only as @@ -22,7 +28,7 @@ module.exports = { }; ``` -## Rule Details +## Rule details This rule looks at all Jest inline and external snapshots (files with `.snap` extension) and validates that each stored snapshot within those files does not diff --git a/docs/rules/no-mocks-import.md b/docs/rules/no-mocks-import.md index 429ed3241..4c03ce549 100644 --- a/docs/rules/no-mocks-import.md +++ b/docs/rules/no-mocks-import.md @@ -1,5 +1,11 @@ # Disallow manually importing from `__mocks__` (`no-mocks-import`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + When using `jest.mock`, your tests (just like the code being tested) should import from `./x`, not `./__mocks__/x`. Not following this rule can lead to confusion, because you will have multiple instances of the mocked module: @@ -14,7 +20,7 @@ test('x', () => { }); ``` -### Rule details +## Rule details This rule reports imports from a path containing a `__mocks__` component. diff --git a/docs/rules/no-restricted-matchers.md b/docs/rules/no-restricted-matchers.md index 77138b558..c5efff6ad 100644 --- a/docs/rules/no-restricted-matchers.md +++ b/docs/rules/no-restricted-matchers.md @@ -1,9 +1,19 @@ # Disallow specific matchers & modifiers (`no-restricted-matchers`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + +You may want to ban specific matchers & modifiers from being used. + +## Rule details + This rule bans specific matchers & modifiers from being used, and can suggest alternatives. -## Rule Details +## Options Bans are expressed in the form of a map, with the value being either a string message to be shown, or `null` if the default rule message should be used. diff --git a/docs/rules/no-standalone-expect.md b/docs/rules/no-standalone-expect.md index efdd4f9cf..9152161b0 100644 --- a/docs/rules/no-standalone-expect.md +++ b/docs/rules/no-standalone-expect.md @@ -1,10 +1,16 @@ # Disallow using `expect` outside of `it` or `test` blocks (`no-standalone-expect`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + Prevents `expect` statements outside of a `test` or `it` block. An `expect` within a helper function (but outside of a `test` or `it` block) will not trigger this rule. -## Rule Details +## Rule details This rule aims to eliminate `expect` statements that will not be executed. An `expect` inside of a `describe` block but outside of a `test` or `it` block or diff --git a/docs/rules/no-test-prefixes.md b/docs/rules/no-test-prefixes.md index 21b0ba059..5a9eaee97 100644 --- a/docs/rules/no-test-prefixes.md +++ b/docs/rules/no-test-prefixes.md @@ -1,5 +1,15 @@ # Use `.only` and `.skip` over `f` and `x` (`no-test-prefixes`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + Jest allows you to choose how you want to define focused and skipped tests, with multiple permutations for each: diff --git a/docs/rules/no-test-return-statement.md b/docs/rules/no-test-return-statement.md index 6577062cc..f5d6a1e53 100644 --- a/docs/rules/no-test-return-statement.md +++ b/docs/rules/no-test-return-statement.md @@ -1,5 +1,11 @@ # Disallow explicitly returning from tests (`no-test-return-statement`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + Tests in Jest should be void and not return values. If you are returning Promises then you should update the test to use diff --git a/docs/rules/prefer-called-with.md b/docs/rules/prefer-called-with.md index 09bf7360c..b9acf363b 100644 --- a/docs/rules/prefer-called-with.md +++ b/docs/rules/prefer-called-with.md @@ -1,5 +1,11 @@ # Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` (`prefer-called-with`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + The `toBeCalled()` matcher is used to assert that a mock function has been called one or more times, without checking the arguments passed. The assertion is stronger when arguments are also validated using the `toBeCalledWith()` diff --git a/docs/rules/prefer-comparison-matcher.md b/docs/rules/prefer-comparison-matcher.md index 33c740535..5f27ffce4 100644 --- a/docs/rules/prefer-comparison-matcher.md +++ b/docs/rules/prefer-comparison-matcher.md @@ -1,5 +1,15 @@ # Suggest using the built-in comparison matchers (`prefer-comparison-matcher`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + Jest has a number of built-in matchers for comparing numbers, which allow for more readable tests and error messages if an expectation fails. diff --git a/docs/rules/prefer-each.md b/docs/rules/prefer-each.md index cb995ba00..381a063c4 100644 --- a/docs/rules/prefer-each.md +++ b/docs/rules/prefer-each.md @@ -1,5 +1,11 @@ # Prefer using `.each` rather than manual loops (`prefer-each`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + Reports where you might be able to use `.each` instead of native loops. ## Rule details diff --git a/docs/rules/prefer-equality-matcher.md b/docs/rules/prefer-equality-matcher.md index d27eb433a..afcec0356 100644 --- a/docs/rules/prefer-equality-matcher.md +++ b/docs/rules/prefer-equality-matcher.md @@ -1,5 +1,15 @@ # Suggest using the built-in equality matchers (`prefer-equality-matcher`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ’‘ This rule provides +[suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) +that can be applied manually. + + + Jest has built-in matchers for expecting equality, which allow for more readable tests and error messages if an expectation fails. diff --git a/docs/rules/prefer-expect-assertions.md b/docs/rules/prefer-expect-assertions.md index 512797217..dd55676eb 100644 --- a/docs/rules/prefer-expect-assertions.md +++ b/docs/rules/prefer-expect-assertions.md @@ -1,5 +1,15 @@ # Suggest using `expect.assertions()` OR `expect.hasAssertions()` (`prefer-expect-assertions`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ’‘ This rule provides +[suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) +that can be applied manually. + + + Ensure every test to have either `expect.assertions()` OR `expect.hasAssertions()` as its first expression. diff --git a/docs/rules/prefer-expect-resolves.md b/docs/rules/prefer-expect-resolves.md index baba945b7..bdb2baacd 100644 --- a/docs/rules/prefer-expect-resolves.md +++ b/docs/rules/prefer-expect-resolves.md @@ -1,5 +1,15 @@ # Prefer `await expect(...).resolves` over `expect(await ...)` syntax (`prefer-expect-resolves`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + When working with promises, there are two primary ways you can test the resolved value: diff --git a/docs/rules/prefer-hooks-in-order.md b/docs/rules/prefer-hooks-in-order.md index f83ff9238..d24e21957 100644 --- a/docs/rules/prefer-hooks-in-order.md +++ b/docs/rules/prefer-hooks-in-order.md @@ -1,5 +1,11 @@ # Prefer having hooks in a consistent order (`prefer-hooks-in-order`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + While hooks can be setup in any order, they're always called by `jest` in this specific order: @@ -11,7 +17,7 @@ specific order: This rule aims to make that more obvious by enforcing grouped hooks be setup in that order within tests. -## Rule Details +## Rule details Examples of **incorrect** code for this rule diff --git a/docs/rules/prefer-hooks-on-top.md b/docs/rules/prefer-hooks-on-top.md index 75e4413c7..74a36ed0d 100644 --- a/docs/rules/prefer-hooks-on-top.md +++ b/docs/rules/prefer-hooks-on-top.md @@ -1,12 +1,18 @@ # Suggest having hooks before any test cases (`prefer-hooks-on-top`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + While hooks can be setup anywhere in a test file, they are always called in a specific order, which means it can be confusing if they're intermixed with test cases. This rule helps to ensure that hooks are always defined before test cases. -## Rule Details +## Rule details Examples of **incorrect** code for this rule diff --git a/docs/rules/prefer-lowercase-title.md b/docs/rules/prefer-lowercase-title.md index 5099fcdfe..742481a55 100644 --- a/docs/rules/prefer-lowercase-title.md +++ b/docs/rules/prefer-lowercase-title.md @@ -1,5 +1,15 @@ # Enforce lowercase test names (`prefer-lowercase-title`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + ## Rule details Enforce `it`, `test` and `describe` to have descriptions that begin with a diff --git a/docs/rules/prefer-mock-promise-shorthand.md b/docs/rules/prefer-mock-promise-shorthand.md index f7dda79a3..90d3ef62d 100644 --- a/docs/rules/prefer-mock-promise-shorthand.md +++ b/docs/rules/prefer-mock-promise-shorthand.md @@ -1,11 +1,21 @@ # Prefer mock resolved/rejected shorthands for promises (`prefer-mock-promise-shorthand`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + When working with mocks of functions that return promises, Jest provides some API sugar functions to reduce the amount of boilerplate you have to write. These methods should be preferred when possible. -## Rule Details +## Rule details The following patterns are warnings: diff --git a/docs/rules/prefer-snapshot-hint.md b/docs/rules/prefer-snapshot-hint.md index 4c4dbc515..d6f91666d 100644 --- a/docs/rules/prefer-snapshot-hint.md +++ b/docs/rules/prefer-snapshot-hint.md @@ -1,5 +1,11 @@ # Prefer including a hint with external snapshots (`prefer-snapshot-hint`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + When working with external snapshot matchers it's considered best practice to provide a hint (as the last argument to the matcher) describing the expected snapshot content that will be included in the snapshots name by Jest. diff --git a/docs/rules/prefer-spy-on.md b/docs/rules/prefer-spy-on.md index 25877d629..7a3d071e3 100644 --- a/docs/rules/prefer-spy-on.md +++ b/docs/rules/prefer-spy-on.md @@ -1,5 +1,15 @@ # Suggest using `jest.spyOn()` (`prefer-spy-on`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + When mocking a function by overwriting a property you have to manually restore the original implementation when cleaning up. When using `jest.spyOn()` Jest keeps track of changes, and they can be restored with `jest.restoreAllMocks()`, diff --git a/docs/rules/prefer-strict-equal.md b/docs/rules/prefer-strict-equal.md index 81a2b5f92..1e4689027 100644 --- a/docs/rules/prefer-strict-equal.md +++ b/docs/rules/prefer-strict-equal.md @@ -1,5 +1,15 @@ # Suggest using `toStrictEqual()` (`prefer-strict-equal`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ’‘ This rule provides +[suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) +that can be applied manually. + + + `toStrictEqual` not only checks that two objects contain the same data but also that they have the same structure. It is common to expect objects to not only have identical values but also to have identical keys. A stricter equality will diff --git a/docs/rules/prefer-to-be.md b/docs/rules/prefer-to-be.md index 8611b42cf..60d0e8e40 100644 --- a/docs/rules/prefer-to-be.md +++ b/docs/rules/prefer-to-be.md @@ -1,5 +1,15 @@ # Suggest using `toBe()` for primitive literals (`prefer-to-be`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `style`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + When asserting against primitive literals such as numbers and strings, the equality matchers all operate the same, but read slightly differently in code. diff --git a/docs/rules/prefer-to-contain.md b/docs/rules/prefer-to-contain.md index b1144bc26..d6b4600a4 100644 --- a/docs/rules/prefer-to-contain.md +++ b/docs/rules/prefer-to-contain.md @@ -1,5 +1,15 @@ # Suggest using `toContain()` (`prefer-to-contain`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `style`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + In order to have a better failure message, `toContain()` should be used upon asserting expectations on an array containing an object. diff --git a/docs/rules/prefer-to-have-length.md b/docs/rules/prefer-to-have-length.md index d44e9e079..38d965838 100644 --- a/docs/rules/prefer-to-have-length.md +++ b/docs/rules/prefer-to-have-length.md @@ -1,5 +1,15 @@ # Suggest using `toHaveLength()` (`prefer-to-have-length`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `style`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + In order to have a better failure message, `toHaveLength()` should be used upon asserting expectations on objects length property. diff --git a/docs/rules/prefer-todo.md b/docs/rules/prefer-todo.md index c294cbdbf..104ca69fc 100644 --- a/docs/rules/prefer-todo.md +++ b/docs/rules/prefer-todo.md @@ -1,5 +1,15 @@ # Suggest using `test.todo` (`prefer-todo`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + When test cases are empty then it is better to mark them as `test.todo` as it will be highlighted in the summary output. diff --git a/docs/rules/require-hook.md b/docs/rules/require-hook.md index 41b83bc7f..a8e6fc6d4 100644 --- a/docs/rules/require-hook.md +++ b/docs/rules/require-hook.md @@ -1,5 +1,11 @@ # Require setup and teardown code to be within a hook (`require-hook`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + Often while writing tests you have some setup work that needs to happen before tests run, and you have some finishing work that needs to happen after tests run. Jest provides helper functions to handle this. diff --git a/docs/rules/require-to-throw-message.md b/docs/rules/require-to-throw-message.md index 4eea732f2..afb529cc0 100644 --- a/docs/rules/require-to-throw-message.md +++ b/docs/rules/require-to-throw-message.md @@ -1,5 +1,11 @@ # Require a message for `toThrow()` (`require-to-throw-message`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + `toThrow()` (and its alias `toThrowError()`) is used to check if an error is thrown by a function call, such as in `expect(() => a()).toThrow()`. However, if no message is defined, then the test will pass for any thrown error. Requiring a diff --git a/docs/rules/require-top-level-describe.md b/docs/rules/require-top-level-describe.md index 389b8dbdb..8e99f5337 100644 --- a/docs/rules/require-top-level-describe.md +++ b/docs/rules/require-top-level-describe.md @@ -1,11 +1,17 @@ # Require test cases and hooks to be inside a `describe` block (`require-top-level-describe`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + Jest allows you to organise your test files the way you want it. However, the more your codebase grows, the more it becomes hard to navigate in your test files. This rule makes sure you provide at least a top-level `describe` block in your test file. -## Rule Details +## Rule details This rule triggers a warning if a test case (`test` and `it`) or a hook (`beforeAll`, `beforeEach`, `afterEach`, `afterAll`) is not located in a @@ -47,6 +53,8 @@ describe('test suite', () => { }); ``` +## Options + You can also enforce a limit on the number of describes allowed at the top-level using the `maxNumberOfTopLevelDescribes` option: diff --git a/docs/rules/unbound-method.md b/docs/rules/unbound-method.md index d4bef0920..95998e8cc 100644 --- a/docs/rules/unbound-method.md +++ b/docs/rules/unbound-method.md @@ -1,6 +1,12 @@ # Enforce unbound methods are called with their expected scope (`unbound-method`) -## Rule Details +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`. + + + +## Rule details This rule extends the base [`@typescript-eslint/unbound-method`][original-rule] rule, meaning you must depend on `@typescript-eslint/eslint-plugin` for it to @@ -46,7 +52,8 @@ which should be applied to the rest of your codebase. ## Options -See [`@typescript-eslint/unbound-method`][original-rule] options. +See [`@typescript-eslint/unbound-method`][original-rule] options (e.g. +`ignoreStatic`). Taken with ❀️ [from `@typescript-eslint` core][original-rule] diff --git a/docs/rules/valid-describe-callback.md b/docs/rules/valid-describe-callback.md index 32ef3a18e..920e46c0c 100644 --- a/docs/rules/valid-describe-callback.md +++ b/docs/rules/valid-describe-callback.md @@ -1,9 +1,15 @@ # Enforce valid `describe()` callback (`valid-describe-callback`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + Using an improper `describe()` callback function can lead to unexpected test errors. -## Rule Details +## Rule details This rule validates that the second parameter of a `describe()` function is a callback function. This callback function: diff --git a/docs/rules/valid-expect-in-promise.md b/docs/rules/valid-expect-in-promise.md index 03c3fb6d0..d8a1cbaab 100644 --- a/docs/rules/valid-expect-in-promise.md +++ b/docs/rules/valid-expect-in-promise.md @@ -1,5 +1,11 @@ # Ensure promises that have expectations in their chain are valid (`valid-expect-in-promise`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + Ensure promises that include expectations are returned or awaited. ## Rule details diff --git a/docs/rules/valid-expect.md b/docs/rules/valid-expect.md index 39f0518b4..09d41318f 100644 --- a/docs/rules/valid-expect.md +++ b/docs/rules/valid-expect.md @@ -1,5 +1,11 @@ # Enforce valid `expect()` usage (`valid-expect`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + + + Ensure `expect()` is called with a single argument and there is an actual expectation made. diff --git a/docs/rules/valid-title.md b/docs/rules/valid-title.md index ab1ae76ad..87c1993f0 100644 --- a/docs/rules/valid-title.md +++ b/docs/rules/valid-title.md @@ -1,5 +1,15 @@ # Enforce valid titles (`valid-title`) +πŸ’Ό This rule is enabled in the following +[configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations): +`all`, `recommended`. + +πŸ”§ This rule is automatically fixable using the `--fix` +[option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) +on the command line. + + + Checks that the title of Jest blocks are valid by ensuring that titles are: - not empty, @@ -7,7 +17,7 @@ Checks that the title of Jest blocks are valid by ensuring that titles are: - not prefixed with their block name, - have no leading or trailing spaces -## Rule Details +## Rule details **emptyTitle** diff --git a/tools/regenerate-docs.ts b/tools/regenerate-docs.ts index 975554c22..af0f4bd72 100644 --- a/tools/regenerate-docs.ts +++ b/tools/regenerate-docs.ts @@ -2,10 +2,14 @@ import * as fs from 'fs'; import * as path from 'path'; -import type { TSESLint } from '@typescript-eslint/utils'; +import type { JSONSchema, TSESLint } from '@typescript-eslint/utils'; import prettier, { Options } from 'prettier'; import { prettier as prettierRC } from '../package.json'; -import config from '../src/index'; +import plugin from '../src/index'; +import { getRuleNoticeLines } from './rule-notices'; + +// Marker so that rule doc header (title/notices) can be automatically updated. +export const END_RULE_HEADER_MARKER = ''; const pathTo = { readme: path.resolve(__dirname, '../README.md'), @@ -23,6 +27,8 @@ interface RuleDetails { description: string; fixable: FixType | false; requiresTypeChecking: boolean; + deprecated: boolean; + schema: JSONSchema.JSONSchema4; } type RuleModule = TSESLint.RuleModule & { @@ -35,14 +41,18 @@ const staticElements = { }; const getConfigurationColumnValueForRule = (rule: RuleDetails): string => { - if (`jest/${rule.name}` in config.configs.recommended.rules) { + if (`jest/${rule.name}` in plugin.configs.recommended.rules) { return '![recommended][]'; } - if (`jest/${rule.name}` in config.configs.style.rules) { + if (`jest/${rule.name}` in plugin.configs.style.rules) { return '![style][]'; } + if (rule.deprecated) { + return '![deprecated][]'; + } + return ''; }; @@ -89,6 +99,97 @@ const updateRulesList = ( ].join('\n'); }; +/** + * Generate a rule doc header for a particular rule. + * @param description - rule description + * @param name - rule name + * @returns {string[]} - lines for new header including marker + */ +const generateRuleHeaderLines = ( + description: string, + name: string, +): string[] => [ + `# ${description} (\`${name}\`)`, + ...getRuleNoticeLines(name), + END_RULE_HEADER_MARKER, +]; + +/** + * Replace the header of a doc up to and including the specified marker. + * Insert at beginning if header doesn't exist. + * @param lines - lines of doc + * @param newHeaderLines - lines of new header including marker + * @param marker - marker to indicate end of header + */ +const replaceOrCreateHeader = ( + lines: string[], + newHeaderLines: string[], + marker: string, +) => { + const markerLineIndex = lines.findIndex(line => line === marker); + + // Replace header section (or create at top if missing). + lines.splice(0, markerLineIndex + 1, ...newHeaderLines); +}; + +/** + * Ensure a rule doc contains (or doesn't contain) some particular content. + * Upon failure, output the failure and set a failure exit code. + * @param ruleName - which rule we are checking + * @param contents - the rule doc's contents + * @param content - the content we are checking for + * @param expected - whether the content should be present or not present + */ +const expectContent = ( + ruleName: string, + contents: string, + content: string, + expected: boolean, +) => { + if (contents.includes(content) !== expected) { + console.error( + `\`${ruleName}\` rule doc should ${ + expected ? '' : 'not ' + }have included: ${content}`, + ); + process.exitCode = 1; + } +}; + +/** + * Gather a list of named options from a rule schema. + * @param jsonSchema - the JSON schema to check + * @returns - list of named options we could detect from the schema + */ +const getAllNamedOptions = (jsonSchema: JSONSchema.JSONSchema4): string[] => { + if (!jsonSchema) { + return []; + } + + if (Array.isArray(jsonSchema)) { + return jsonSchema.flatMap(getAllNamedOptions); + } + + if (jsonSchema.items) { + return getAllNamedOptions(jsonSchema.items); + } + + if (jsonSchema.properties) { + return Object.keys(jsonSchema.properties); + } + + return []; +}; + +/** + * Check if a rule schema is non-blank/empty and thus has actual options. + * @param jsonSchema - the JSON schema to check + * @returns - whether the schema has options + */ +const hasOptions = (jsonSchema: JSONSchema.JSONSchema4): boolean => + (Array.isArray(jsonSchema) && jsonSchema.length > 0) || + (typeof jsonSchema === 'object' && Object.keys(jsonSchema).length > 0); + // copied from https://github.com/babel/babel/blob/d8da63c929f2d28c401571e2a43166678c555bc4/packages/babel-helpers/src/helpers.js#L602-L606 /* istanbul ignore next */ const interopRequireDefault = (obj: any): { default: any } => @@ -101,12 +202,11 @@ const importDefault = (moduleName: string) => const requireJestRule = (name: string): RuleModule => importDefault(path.join(pathTo.rules, name)) as RuleModule; -const details: RuleDetails[] = Object.keys(config.configs.all.rules) - .map(name => name.split('/')[1]) +const details: RuleDetails[] = Object.keys(plugin.rules) .map(name => [name, requireJestRule(name)] as const) .filter( (nameAndRule): nameAndRule is [string, Required] => - !!nameAndRule[1].meta && !nameAndRule[1].meta.deprecated, + !!nameAndRule[1].meta, ) .map( ([name, rule]): RuleDetails => ({ @@ -118,17 +218,33 @@ const details: RuleDetails[] = Object.keys(config.configs.all.rules) ? 'suggest' : false, requiresTypeChecking: rule.meta.docs.requiresTypeChecking ?? false, + deprecated: rule.meta.deprecated ?? false, + schema: rule.meta.schema, }), ); -details.forEach(({ name, description }) => { +details.forEach(({ name, description, schema }) => { const pathToDoc = path.join(pathTo.docs, 'rules', `${name}.md`); + const contents = fs.readFileSync(pathToDoc).toString(); + const lines = contents.split('\n'); + + // Regenerate the header (title/notices) of each rule doc. + const newHeaderLines = generateRuleHeaderLines(description, name); - const contents = fs.readFileSync(pathToDoc).toString().split('\n'); + replaceOrCreateHeader(lines, newHeaderLines, END_RULE_HEADER_MARKER); - contents[0] = `# ${description} (\`${name}\`)`; + fs.writeFileSync(pathToDoc, format(lines.join('\n'))); - fs.writeFileSync(pathToDoc, format(contents.join('\n'))); + // Check for potential issues with the rule doc. + + // "Rule details" section. + expectContent(name, contents, '## Rule details', true); + + // "Options" section. + expectContent(name, contents, '## Options', hasOptions(schema)); + for (const namedOption of getAllNamedOptions(schema)) { + expectContent(name, contents, namedOption, true); // Each rule option is mentioned. + } }); const [baseRules, typeRules] = details.reduce<[RuleDetails[], RuleDetails[]]>( diff --git a/tools/rule-notices.ts b/tools/rule-notices.ts new file mode 100644 index 000000000..d73a09605 --- /dev/null +++ b/tools/rule-notices.ts @@ -0,0 +1,116 @@ +import plugin from '../src'; + +enum MESSAGE_TYPE { + CONFIGS = 'configs', + DEPRECATED = 'deprecated', + FIXABLE = 'fixable', + HAS_SUGGESTIONS = 'hasSuggestions', +} + +export const MESSAGES = { + [MESSAGE_TYPE.CONFIGS]: + 'πŸ’Ό This rule is enabled in the following [configs](https://github.com/jest-community/eslint-plugin-jest/blob/main/README.md#shareable-configurations):', + [MESSAGE_TYPE.DEPRECATED]: '❌ This rule is deprecated.', + [MESSAGE_TYPE.FIXABLE]: + 'πŸ”§ This rule is automatically fixable using the `--fix` [option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) on the command line.', + [MESSAGE_TYPE.HAS_SUGGESTIONS]: + 'πŸ’‘ This rule provides [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) that can be applied manually.', +}; + +type Rule = typeof plugin.rules[string]; + +/** + * Get config names that a given rule belongs to. + */ +function getConfigsForRule(ruleName: string) { + const { configs } = plugin; + const configNames: Array = []; + let configName: keyof typeof configs; + + for (configName in configs) { + const config = configs[configName]; + const value = config.rules[`jest/${ruleName}`]; + const isEnabled = [2, 'error'].includes(value); + + if (isEnabled) { + configNames.push(configName); + } + } + + return configNames.sort(); +} + +/** + * Convert list of configs to string list of formatted names. + */ +function configNamesToList(configNames: readonly string[]) { + return `\`${configNames.join('`, `')}\``; +} + +/** + * Convert list of rule names to string list of links. + */ +function rulesNamesToList(ruleNames: readonly string[]) { + return ruleNames.map(ruleName => `[${ruleName}](${ruleName}.md)`).join(', '); +} + +/** + * Determine which notices should and should not be included at the top of a rule doc. + */ +export function getNoticesForRule(rule: Rule) { + const notices: { + [key in MESSAGE_TYPE]: boolean; + } = { + [MESSAGE_TYPE.CONFIGS]: !rule.meta.deprecated, + [MESSAGE_TYPE.DEPRECATED]: rule.meta.deprecated || false, + [MESSAGE_TYPE.FIXABLE]: Boolean(rule.meta.fixable), + [MESSAGE_TYPE.HAS_SUGGESTIONS]: rule.meta.hasSuggestions || false, + }; + + return notices; +} + +/** + * Get the lines for the notice section at the top of a rule doc. + */ +export function getRuleNoticeLines(ruleName: string) { + const lines: string[] = []; + + const rule = plugin.rules[ruleName]; + const notices = getNoticesForRule(rule); + let messageType: keyof typeof notices; + + for (messageType in notices) { + const expected = notices[messageType]; + + if (!expected) { + // This notice should not be included. + continue; + } + + lines.push(''); // Blank line first. + + if (messageType === MESSAGE_TYPE.CONFIGS) { + // This notice should have a list of the rule's configs. + const configsEnabled = getConfigsForRule(ruleName); + const message = `${MESSAGES[MESSAGE_TYPE.CONFIGS]} ${configNamesToList( + configsEnabled, + )}.`; + + lines.push(message); + } else if (messageType === MESSAGE_TYPE.DEPRECATED) { + // This notice should include links to the replacement rule(s) if available. + const message = rule.meta.replacedBy + ? `${MESSAGES[messageType]} It was replaced by ${rulesNamesToList( + rule.meta.replacedBy, + )}.` + : MESSAGES[messageType]; + + lines.push(message); + } else { + lines.push(MESSAGES[messageType]); + } + } + + return lines; +}