diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index dd771bb2..a1e12a94 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -29,7 +29,7 @@ jobs: - name: Use Node uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 16 - name: Install dependencies uses: bahmutov/npm-install@v1 @@ -51,8 +51,8 @@ jobs: strategy: matrix: - node: [10.12, 10, '12.0', 12, 14, 16] - eslint: [7.5, 7] + node: [12.22.0, 12, 14.17.0, 14, '16.0', 16] + eslint: [7.5, 7, 8] steps: - name: Cancel Previous Runs @@ -72,7 +72,9 @@ jobs: useLockFile: false - name: Install ESLint v${{ matrix.eslint }} - run: npm install --no-save eslint@${{ matrix.eslint }} + # force installation for now until we get ESLint and all plugins updated + # in dev dependencies + run: npm install --no-save --force eslint@${{ matrix.eslint }} - name: Run tests run: npm run test:ci @@ -96,7 +98,7 @@ jobs: - name: Use Node uses: actions/setup-node@v2 with: - node-version: 14 + node-version: 16 - name: Install dependencies uses: bahmutov/npm-install@v1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 11044860..6d92df51 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,7 +44,7 @@ If you ever need to update a snapshot, you can run `npm run test:update` Based on [ESLint's Rule Naming Conventions](https://eslint.org/docs/developer-guide/working-with-rules#rule-naming-conventions), you must follow these rules: -- If your rule is disallowing something, prefix it with `no-` such as `no-debug` +- If your rule is disallowing something, prefix it with `no-` such as `no-debugging-utils` for disallowing `debug()`. - If your rule is suggesting to prefer a way of doing something, among other ways, you can **optionally** prefix it with `prefer-`. For example, `prefer-screen-queries` suggests to use `screen.getByText()` from imported `screen` rather @@ -57,11 +57,11 @@ Based on [ESLint's Rule Naming Conventions](https://eslint.org/docs/developer-gu ## Adding new rules In the [same way as ESLint](https://eslint.org/docs/developer-guide/working-with-rules), -each rule has three files named with its identifier (e.g. `no-debug`): +each rule has three files named with its identifier (e.g. `no-debugging-utils`): -- in the `lib/rules` directory: a source file (e.g. `no-debug.ts`) -- in the `tests/lib/rules` directory: a test file (e.g. `no-debug.ts`) -- in the `docs/rules` directory: a Markdown documentation file (e.g. `no-debug.md`) +- in the `lib/rules` directory: a source file (e.g. `no-debugging-utils.ts`) +- in the `tests/lib/rules` directory: a test file (e.g. `no-debugging-utils.ts`) +- in the `docs/rules` directory: a Markdown documentation file (e.g. `no-debugging-utils.md`) Additionally, you need to do a couple of extra things: diff --git a/README.md b/README.md index e7fbd779..c6cba0dc 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ $ yarn add --dev eslint-plugin-testing-library You can find detailed guides for migrating `eslint-plugin-testing-library` in the [migration guide docs](docs/migration-guides): - [Migrate guide for v4](docs/migration-guides/v4.md) +- [Migrate guide for v5](docs/migration-guides/v5.md) ## Usage @@ -68,7 +69,7 @@ Then configure the rules you want to use within `rules` property of your `.eslin "rules": { "testing-library/await-async-query": "error", "testing-library/no-await-sync-query": "error", - "testing-library/no-debug": "warn", + "testing-library/no-debugging-utils": "warn", "testing-library/no-dom-import": "off" } } @@ -195,21 +196,21 @@ To enable this configuration use the `extends` property in your | [`testing-library/no-await-sync-events`](./docs/rules/no-await-sync-events.md) | Disallow unnecessary `await` for sync events | | | | [`testing-library/no-await-sync-query`](./docs/rules/no-await-sync-query.md) | Disallow unnecessary `await` for sync queries | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | | [`testing-library/no-container`](./docs/rules/no-container.md) | Disallow the use of `container` methods | | ![angular-badge][] ![react-badge][] ![vue-badge][] | -| [`testing-library/no-debug`](./docs/rules/no-debug.md) | Disallow the use of debugging utilities like `debug` | | ![angular-badge][] ![react-badge][] ![vue-badge][] | +| [`testing-library/no-debugging-utils`](./docs/rules/no-debugging-utils.md) | Disallow the use of debugging utilities like `debug` | | ![angular-badge][] ![react-badge][] ![vue-badge][] | | [`testing-library/no-dom-import`](./docs/rules/no-dom-import.md) | Disallow importing from DOM Testing Library | 🔧 | ![angular-badge][] ![react-badge][] ![vue-badge][] | | [`testing-library/no-manual-cleanup`](./docs/rules/no-manual-cleanup.md) | Disallow the use of `cleanup` | | | | [`testing-library/no-node-access`](./docs/rules/no-node-access.md) | Disallow direct Node access | | ![angular-badge][] ![react-badge][] ![vue-badge][] | | [`testing-library/no-promise-in-fire-event`](./docs/rules/no-promise-in-fire-event.md) | Disallow the use of promises passed to a `fireEvent` method | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | -| [`testing-library/no-render-in-setup`](./docs/rules/no-render-in-setup.md) | Disallow the use of `render` in testing frameworks setup functions | | | -| [`testing-library/no-unnecessary-act`](./docs/rules/no-unnecessary-act.md) | Disallow wrapping Testing Library utils or empty callbacks in `act` | | | +| [`testing-library/no-render-in-setup`](./docs/rules/no-render-in-setup.md) | Disallow the use of `render` in testing frameworks setup functions | | ![angular-badge][] ![react-badge][] ![vue-badge][] | +| [`testing-library/no-unnecessary-act`](./docs/rules/no-unnecessary-act.md) | Disallow wrapping Testing Library utils or empty callbacks in `act` | | ![react-badge][] | | [`testing-library/no-wait-for-empty-callback`](./docs/rules/no-wait-for-empty-callback.md) | Disallow empty callbacks for `waitFor` and `waitForElementToBeRemoved` | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | -| [`testing-library/no-wait-for-multiple-assertions`](./docs/rules/no-wait-for-multiple-assertions.md) | Disallow the use of multiple `expect` calls inside `waitFor` | | | -| [`testing-library/no-wait-for-side-effects`](./docs/rules/no-wait-for-side-effects.md) | Disallow the use of side effects in `waitFor` | | | -| [`testing-library/no-wait-for-snapshot`](./docs/rules/no-wait-for-snapshot.md) | Ensures no snapshot is generated inside of a `waitFor` call | | | +| [`testing-library/no-wait-for-multiple-assertions`](./docs/rules/no-wait-for-multiple-assertions.md) | Disallow the use of multiple `expect` calls inside `waitFor` | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | +| [`testing-library/no-wait-for-side-effects`](./docs/rules/no-wait-for-side-effects.md) | Disallow the use of side effects in `waitFor` | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | +| [`testing-library/no-wait-for-snapshot`](./docs/rules/no-wait-for-snapshot.md) | Ensures no snapshot is generated inside of a `waitFor` call | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | | [`testing-library/prefer-explicit-assert`](./docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than standalone queries | | | | [`testing-library/prefer-find-by`](./docs/rules/prefer-find-by.md) | Suggest using `find(All)By*` query instead of `waitFor` + `get(All)By*` to wait for elements | 🔧 | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | -| [`testing-library/prefer-presence-queries`](./docs/rules/prefer-presence-queries.md) | Ensure appropriate `get*`/`query*` queries are used with their respective matchers | | | -| [`testing-library/prefer-query-by-disappearance`](./docs/rules/prefer-query-by-disappearance.md) | Suggest using `queryBy*` queries when waiting for disappearance | | | +| [`testing-library/prefer-presence-queries`](./docs/rules/prefer-presence-queries.md) | Ensure appropriate `get*`/`query*` queries are used with their respective matchers | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | +| [`testing-library/prefer-query-by-disappearance`](./docs/rules/prefer-query-by-disappearance.md) | Suggest using `queryBy*` queries when waiting for disappearance | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | | [`testing-library/prefer-screen-queries`](./docs/rules/prefer-screen-queries.md) | Suggest using `screen` while querying | | ![dom-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | | [`testing-library/prefer-user-event`](./docs/rules/prefer-user-event.md) | Suggest using `userEvent` over `fireEvent` for simulating user interactions | | | | [`testing-library/prefer-wait-for`](./docs/rules/prefer-wait-for.md) | Use `waitFor` instead of deprecated wait methods | 🔧 | | diff --git a/docs/migration-guides/v5.md b/docs/migration-guides/v5.md new file mode 100644 index 00000000..0ca34954 --- /dev/null +++ b/docs/migration-guides/v5.md @@ -0,0 +1,25 @@ +# Guide: migrating to v5 + +Assuming you are already in v4, migrating to v5 will be easy. If you are not in v4 yet, we recommend you to follow [the proper guide to migrate to it](docs/migration-guides/v4.md). + +## Overview + +- Support for ESLint v8 +- Drop support for Node v10. Required node version is now `^12.22.0 || ^14.17.0 || >=16.0.0`. Node v10 was EOL'd in April 2021, and ESLint v8 dropped support for it too. +- Update dependencies +- `no-debug` is now called `no-debugging-utils` +- `no-render-in-setup` is now enabled by default in the Angular, React & Vue configs +- `no-unnecessary-act`'s `isStrict` option is now `true` by default +- `no-unnecessary-act` is now enabled by default in the React config +- `no-wait-for-multiple-assertions` is now enabled by default in all configs +- `no-wait-for-side-effects` is now enabled by default in all configs +- `no-wait-for-snapshot` is now enabled by default in all configs +- `prefer-presence-queries` is now enabled by default in all configs +- `prefer-query-by-disappearance` is now enabled by default in all configs + +## Steps to upgrade + +- `eslint-plugin-testing-library` supports both ESLint v7 and v8, so you are fine with either version +- Making sure you are using a compatible Node version (`^12.22.0 || ^14.17.0 || >=16.0.0`), and update it if it's not the case +- Renaming `testing-library/no-debug` to `testing-library/no-debugging-utils` if you were referencing it manually somewhere +- Being aware of new rules enabled in Shared Configs which can lead to new reported errors diff --git a/docs/rules/no-debug.md b/docs/rules/no-debugging-utils.md similarity index 91% rename from docs/rules/no-debug.md rename to docs/rules/no-debugging-utils.md index 9ae030dd..7737eb9f 100644 --- a/docs/rules/no-debug.md +++ b/docs/rules/no-debugging-utils.md @@ -1,4 +1,4 @@ -# Disallow the use of debugging utilities like `debug` (`testing-library/no-debug`) +# Disallow the use of debugging utilities (`testing-library/no-debugging-utils`) Just like `console.log` statements pollutes the browser's output, debug statements also pollutes the tests if one of your teammates forgot to remove it. `debug` statements should be used when you actually want to debug your tests but should not be pushed to the codebase. @@ -41,7 +41,7 @@ You can control which debugging utils are checked for with the `utilsToCheckFor` ```json { - "testing-library/no-debug": [ + "testing-library/no-debugging-utils": [ "error", { "utilsToCheckFor": { diff --git a/lib/configs/angular.ts b/lib/configs/angular.ts index 671b496b..af9b277c 100644 --- a/lib/configs/angular.ts +++ b/lib/configs/angular.ts @@ -9,12 +9,18 @@ export = { 'testing-library/await-async-utils': 'error', 'testing-library/no-await-sync-query': 'error', 'testing-library/no-container': 'error', - 'testing-library/no-debug': 'error', + 'testing-library/no-debugging-utils': 'error', 'testing-library/no-dom-import': ['error', 'angular'], 'testing-library/no-node-access': 'error', 'testing-library/no-promise-in-fire-event': 'error', + 'testing-library/no-render-in-setup': 'error', 'testing-library/no-wait-for-empty-callback': 'error', + 'testing-library/no-wait-for-multiple-assertions': 'error', + 'testing-library/no-wait-for-side-effects': 'error', + 'testing-library/no-wait-for-snapshot': 'error', 'testing-library/prefer-find-by': 'error', + 'testing-library/prefer-presence-queries': 'error', + 'testing-library/prefer-query-by-disappearance': 'error', 'testing-library/prefer-screen-queries': 'error', 'testing-library/render-result-naming-convention': 'error', }, diff --git a/lib/configs/dom.ts b/lib/configs/dom.ts index 261cde83..ce153733 100644 --- a/lib/configs/dom.ts +++ b/lib/configs/dom.ts @@ -10,7 +10,12 @@ export = { 'testing-library/no-await-sync-query': 'error', 'testing-library/no-promise-in-fire-event': 'error', 'testing-library/no-wait-for-empty-callback': 'error', + 'testing-library/no-wait-for-multiple-assertions': 'error', + 'testing-library/no-wait-for-side-effects': 'error', + 'testing-library/no-wait-for-snapshot': 'error', 'testing-library/prefer-find-by': 'error', + 'testing-library/prefer-presence-queries': 'error', + 'testing-library/prefer-query-by-disappearance': 'error', 'testing-library/prefer-screen-queries': 'error', }, }; diff --git a/lib/configs/react.ts b/lib/configs/react.ts index b2161875..5e2bc966 100644 --- a/lib/configs/react.ts +++ b/lib/configs/react.ts @@ -9,12 +9,19 @@ export = { 'testing-library/await-async-utils': 'error', 'testing-library/no-await-sync-query': 'error', 'testing-library/no-container': 'error', - 'testing-library/no-debug': 'error', + 'testing-library/no-debugging-utils': 'error', 'testing-library/no-dom-import': ['error', 'react'], 'testing-library/no-node-access': 'error', 'testing-library/no-promise-in-fire-event': 'error', + 'testing-library/no-render-in-setup': 'error', + 'testing-library/no-unnecessary-act': 'error', 'testing-library/no-wait-for-empty-callback': 'error', + 'testing-library/no-wait-for-multiple-assertions': 'error', + 'testing-library/no-wait-for-side-effects': 'error', + 'testing-library/no-wait-for-snapshot': 'error', 'testing-library/prefer-find-by': 'error', + 'testing-library/prefer-presence-queries': 'error', + 'testing-library/prefer-query-by-disappearance': 'error', 'testing-library/prefer-screen-queries': 'error', 'testing-library/render-result-naming-convention': 'error', }, diff --git a/lib/configs/vue.ts b/lib/configs/vue.ts index 046bb774..cf9e42bb 100644 --- a/lib/configs/vue.ts +++ b/lib/configs/vue.ts @@ -10,12 +10,18 @@ export = { 'testing-library/await-fire-event': 'error', 'testing-library/no-await-sync-query': 'error', 'testing-library/no-container': 'error', - 'testing-library/no-debug': 'error', + 'testing-library/no-debugging-utils': 'error', 'testing-library/no-dom-import': ['error', 'vue'], 'testing-library/no-node-access': 'error', 'testing-library/no-promise-in-fire-event': 'error', + 'testing-library/no-render-in-setup': 'error', 'testing-library/no-wait-for-empty-callback': 'error', + 'testing-library/no-wait-for-multiple-assertions': 'error', + 'testing-library/no-wait-for-side-effects': 'error', + 'testing-library/no-wait-for-snapshot': 'error', 'testing-library/prefer-find-by': 'error', + 'testing-library/prefer-presence-queries': 'error', + 'testing-library/prefer-query-by-disappearance': 'error', 'testing-library/prefer-screen-queries': 'error', 'testing-library/render-result-naming-convention': 'error', }, diff --git a/lib/rules/await-async-query.ts b/lib/rules/await-async-query.ts index c3860452..90be4e9f 100644 --- a/lib/rules/await-async-query.ts +++ b/lib/rules/await-async-query.ts @@ -20,7 +20,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Enforce promises from async queries to be handled', - category: 'Best Practices', recommendedConfig: { dom: 'error', angular: 'error', diff --git a/lib/rules/await-async-utils.ts b/lib/rules/await-async-utils.ts index 6206fe1e..1f23e9fa 100644 --- a/lib/rules/await-async-utils.ts +++ b/lib/rules/await-async-utils.ts @@ -19,7 +19,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Enforce promises from async utils to be awaited properly', - category: 'Best Practices', recommendedConfig: { dom: 'error', angular: 'error', diff --git a/lib/rules/await-fire-event.ts b/lib/rules/await-fire-event.ts index 912086f2..e6a70568 100644 --- a/lib/rules/await-fire-event.ts +++ b/lib/rules/await-fire-event.ts @@ -19,7 +19,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Enforce promises from `fireEvent` methods to be handled', - category: 'Best Practices', recommendedConfig: { dom: false, angular: false, diff --git a/lib/rules/consistent-data-testid.ts b/lib/rules/consistent-data-testid.ts index e799acd0..ed462367 100644 --- a/lib/rules/consistent-data-testid.ts +++ b/lib/rules/consistent-data-testid.ts @@ -18,7 +18,6 @@ export default createTestingLibraryRule({ type: 'suggestion', docs: { description: 'Ensures consistent usage of `data-testid`', - category: 'Best Practices', recommendedConfig: { dom: false, angular: false, diff --git a/lib/rules/no-await-sync-events.ts b/lib/rules/no-await-sync-events.ts index bdb407ab..87753dc6 100644 --- a/lib/rules/no-await-sync-events.ts +++ b/lib/rules/no-await-sync-events.ts @@ -21,7 +21,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Disallow unnecessary `await` for sync events', - category: 'Best Practices', recommendedConfig: { dom: false, angular: false, diff --git a/lib/rules/no-await-sync-query.ts b/lib/rules/no-await-sync-query.ts index 5e71c9fc..1797aa9d 100644 --- a/lib/rules/no-await-sync-query.ts +++ b/lib/rules/no-await-sync-query.ts @@ -13,7 +13,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Disallow unnecessary `await` for sync queries', - category: 'Best Practices', recommendedConfig: { dom: 'error', angular: 'error', diff --git a/lib/rules/no-container.ts b/lib/rules/no-container.ts index 3da280b3..e64af6ca 100644 --- a/lib/rules/no-container.ts +++ b/lib/rules/no-container.ts @@ -20,7 +20,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Disallow the use of `container` methods', - category: 'Best Practices', recommendedConfig: { dom: false, angular: 'error', diff --git a/lib/rules/no-debug.ts b/lib/rules/no-debugging-utils.ts similarity index 98% rename from lib/rules/no-debug.ts rename to lib/rules/no-debugging-utils.ts index a0808154..a6357cd5 100644 --- a/lib/rules/no-debug.ts +++ b/lib/rules/no-debugging-utils.ts @@ -21,7 +21,7 @@ type DebugUtilsToCheckFor = Partial< Record >; -export const RULE_NAME = 'no-debug'; +export const RULE_NAME = 'no-debugging-utils'; export type MessageIds = 'noDebug'; type Options = [{ utilsToCheckFor?: DebugUtilsToCheckFor }]; @@ -31,7 +31,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Disallow the use of debugging utilities like `debug`', - category: 'Best Practices', recommendedConfig: { dom: false, angular: 'error', diff --git a/lib/rules/no-dom-import.ts b/lib/rules/no-dom-import.ts index 5298eea2..9ae585ee 100644 --- a/lib/rules/no-dom-import.ts +++ b/lib/rules/no-dom-import.ts @@ -18,7 +18,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Disallow importing from DOM Testing Library', - category: 'Best Practices', recommendedConfig: { dom: false, angular: ['error', 'angular'], diff --git a/lib/rules/no-manual-cleanup.ts b/lib/rules/no-manual-cleanup.ts index 506dc9c8..45d4a1c2 100644 --- a/lib/rules/no-manual-cleanup.ts +++ b/lib/rules/no-manual-cleanup.ts @@ -29,7 +29,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Disallow the use of `cleanup`', - category: 'Best Practices', recommendedConfig: { dom: false, angular: false, diff --git a/lib/rules/no-node-access.ts b/lib/rules/no-node-access.ts index a9e4ce4e..36d232be 100644 --- a/lib/rules/no-node-access.ts +++ b/lib/rules/no-node-access.ts @@ -13,7 +13,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Disallow direct Node access', - category: 'Best Practices', recommendedConfig: { dom: false, angular: 'error', diff --git a/lib/rules/no-promise-in-fire-event.ts b/lib/rules/no-promise-in-fire-event.ts index ea1c6f8b..01027201 100644 --- a/lib/rules/no-promise-in-fire-event.ts +++ b/lib/rules/no-promise-in-fire-event.ts @@ -20,7 +20,6 @@ export default createTestingLibraryRule({ docs: { description: 'Disallow the use of promises passed to a `fireEvent` method', - category: 'Best Practices', recommendedConfig: { dom: 'error', angular: 'error', diff --git a/lib/rules/no-render-in-setup.ts b/lib/rules/no-render-in-setup.ts index e5c7f437..29f9a442 100644 --- a/lib/rules/no-render-in-setup.ts +++ b/lib/rules/no-render-in-setup.ts @@ -50,12 +50,11 @@ export default createTestingLibraryRule({ docs: { description: 'Disallow the use of `render` in testing frameworks setup functions', - category: 'Best Practices', recommendedConfig: { dom: false, - angular: false, - react: false, - vue: false, + angular: 'error', + react: 'error', + vue: 'error', }, }, messages: { diff --git a/lib/rules/no-unnecessary-act.ts b/lib/rules/no-unnecessary-act.ts index 4f4f68d4..5cd9f4b1 100644 --- a/lib/rules/no-unnecessary-act.ts +++ b/lib/rules/no-unnecessary-act.ts @@ -23,11 +23,10 @@ export default createTestingLibraryRule({ docs: { description: 'Disallow wrapping Testing Library utils or empty callbacks in `act`', - category: 'Possible Errors', recommendedConfig: { dom: false, angular: false, - react: false, + react: 'error', vue: false, }, }, @@ -40,18 +39,20 @@ export default createTestingLibraryRule({ { type: 'object', properties: { - isStrict: { type: 'boolean' }, + isStrict: { + type: 'boolean', + }, }, }, ], }, defaultOptions: [ { - isStrict: false, + isStrict: true, }, ], - create(context, [options], helpers) { + create(context, [{ isStrict = true }], helpers) { function getStatementIdentifier(statement: TSESTree.Statement) { const callExpression = getStatementCallExpression(statement); @@ -113,7 +114,6 @@ export default createTestingLibraryRule({ function checkNoUnnecessaryActFromBlockStatement( blockStatementNode: TSESTree.BlockStatement ) { - const { isStrict } = options; const functionNode = blockStatementNode.parent as | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression diff --git a/lib/rules/no-wait-for-empty-callback.ts b/lib/rules/no-wait-for-empty-callback.ts index d731ecd7..7bbfef99 100644 --- a/lib/rules/no-wait-for-empty-callback.ts +++ b/lib/rules/no-wait-for-empty-callback.ts @@ -18,7 +18,6 @@ export default createTestingLibraryRule({ docs: { description: 'Disallow empty callbacks for `waitFor` and `waitForElementToBeRemoved`', - category: 'Best Practices', recommendedConfig: { dom: 'error', angular: 'error', diff --git a/lib/rules/no-wait-for-multiple-assertions.ts b/lib/rules/no-wait-for-multiple-assertions.ts index 86499e89..f3f23ebd 100644 --- a/lib/rules/no-wait-for-multiple-assertions.ts +++ b/lib/rules/no-wait-for-multiple-assertions.ts @@ -17,12 +17,11 @@ export default createTestingLibraryRule({ docs: { description: 'Disallow the use of multiple `expect` calls inside `waitFor`', - category: 'Best Practices', recommendedConfig: { - dom: false, - angular: false, - react: false, - vue: false, + dom: 'error', + angular: 'error', + react: 'error', + vue: 'error', }, }, messages: { diff --git a/lib/rules/no-wait-for-side-effects.ts b/lib/rules/no-wait-for-side-effects.ts index 06bc34d9..4c919245 100644 --- a/lib/rules/no-wait-for-side-effects.ts +++ b/lib/rules/no-wait-for-side-effects.ts @@ -20,12 +20,11 @@ export default createTestingLibraryRule({ type: 'suggestion', docs: { description: 'Disallow the use of side effects in `waitFor`', - category: 'Best Practices', recommendedConfig: { - dom: false, - angular: false, - react: false, - vue: false, + dom: 'error', + angular: 'error', + react: 'error', + vue: 'error', }, }, messages: { diff --git a/lib/rules/no-wait-for-snapshot.ts b/lib/rules/no-wait-for-snapshot.ts index 0c78f30d..96450678 100644 --- a/lib/rules/no-wait-for-snapshot.ts +++ b/lib/rules/no-wait-for-snapshot.ts @@ -19,12 +19,11 @@ export default createTestingLibraryRule({ docs: { description: 'Ensures no snapshot is generated inside of a `waitFor` call', - category: 'Best Practices', recommendedConfig: { - dom: false, - angular: false, - react: false, - vue: false, + dom: 'error', + angular: 'error', + react: 'error', + vue: 'error', }, }, messages: { diff --git a/lib/rules/prefer-explicit-assert.ts b/lib/rules/prefer-explicit-assert.ts index 86e1f4ed..a8d376f0 100644 --- a/lib/rules/prefer-explicit-assert.ts +++ b/lib/rules/prefer-explicit-assert.ts @@ -69,7 +69,6 @@ export default createTestingLibraryRule({ docs: { description: 'Suggest using explicit assertions rather than standalone queries', - category: 'Best Practices', recommendedConfig: { dom: false, angular: false, diff --git a/lib/rules/prefer-find-by.ts b/lib/rules/prefer-find-by.ts index 40bb865a..460eab38 100644 --- a/lib/rules/prefer-find-by.ts +++ b/lib/rules/prefer-find-by.ts @@ -56,7 +56,6 @@ export default createTestingLibraryRule({ docs: { description: 'Suggest using `find(All)By*` query instead of `waitFor` + `get(All)By*` to wait for elements', - category: 'Best Practices', recommendedConfig: { dom: 'error', angular: 'error', diff --git a/lib/rules/prefer-presence-queries.ts b/lib/rules/prefer-presence-queries.ts index 1b8839c4..611cf5ed 100644 --- a/lib/rules/prefer-presence-queries.ts +++ b/lib/rules/prefer-presence-queries.ts @@ -11,14 +11,13 @@ export default createTestingLibraryRule({ name: RULE_NAME, meta: { docs: { - category: 'Best Practices', description: 'Ensure appropriate `get*`/`query*` queries are used with their respective matchers', recommendedConfig: { - dom: false, - angular: false, - react: false, - vue: false, + dom: 'error', + angular: 'error', + react: 'error', + vue: 'error', }, }, messages: { diff --git a/lib/rules/prefer-query-by-disappearance.ts b/lib/rules/prefer-query-by-disappearance.ts index e65f9db7..bbb2a9e6 100644 --- a/lib/rules/prefer-query-by-disappearance.ts +++ b/lib/rules/prefer-query-by-disappearance.ts @@ -23,12 +23,11 @@ export default createTestingLibraryRule({ docs: { description: 'Suggest using `queryBy*` queries when waiting for disappearance', - category: 'Possible Errors', recommendedConfig: { - dom: false, - angular: false, - react: false, - vue: false, + dom: 'error', + angular: 'error', + react: 'error', + vue: 'error', }, }, messages: { diff --git a/lib/rules/prefer-screen-queries.ts b/lib/rules/prefer-screen-queries.ts index bca47eef..acca7c5a 100644 --- a/lib/rules/prefer-screen-queries.ts +++ b/lib/rules/prefer-screen-queries.ts @@ -40,7 +40,6 @@ export default createTestingLibraryRule({ type: 'suggestion', docs: { description: 'Suggest using `screen` while querying', - category: 'Best Practices', recommendedConfig: { dom: 'error', angular: 'error', diff --git a/lib/rules/prefer-user-event.ts b/lib/rules/prefer-user-event.ts index 76f37f93..2e0a8958 100644 --- a/lib/rules/prefer-user-event.ts +++ b/lib/rules/prefer-user-event.ts @@ -71,7 +71,6 @@ export default createTestingLibraryRule({ docs: { description: 'Suggest using `userEvent` over `fireEvent` for simulating user interactions', - category: 'Best Practices', recommendedConfig: { dom: false, angular: false, diff --git a/lib/rules/prefer-wait-for.ts b/lib/rules/prefer-wait-for.ts index fc8f654b..a302ee1c 100644 --- a/lib/rules/prefer-wait-for.ts +++ b/lib/rules/prefer-wait-for.ts @@ -26,7 +26,6 @@ export default createTestingLibraryRule({ type: 'suggestion', docs: { description: 'Use `waitFor` instead of deprecated wait methods', - category: 'Best Practices', recommendedConfig: { dom: false, angular: false, diff --git a/lib/rules/render-result-naming-convention.ts b/lib/rules/render-result-naming-convention.ts index 8e9d9e4f..046ce4ed 100644 --- a/lib/rules/render-result-naming-convention.ts +++ b/lib/rules/render-result-naming-convention.ts @@ -24,7 +24,6 @@ export default createTestingLibraryRule({ type: 'suggestion', docs: { description: 'Enforce a valid naming for return value from `render`', - category: 'Best Practices', recommendedConfig: { dom: false, angular: 'error', diff --git a/package.json b/package.json index 979b9b4e..8d055a2b 100644 --- a/package.json +++ b/package.json @@ -42,41 +42,41 @@ "prepare": "is-ci || husky install" }, "dependencies": { - "@typescript-eslint/experimental-utils": "^4.30.0" + "@typescript-eslint/experimental-utils": "^5.0.0" }, "devDependencies": { "@babel/eslint-plugin": "^7.14.5", - "@commitlint/cli": "^12.1.4", - "@commitlint/config-conventional": "^12.1.4", - "@types/jest": "^27.0.1", - "@types/node": "^10.17.60", - "@typescript-eslint/eslint-plugin": "^4.30.0", - "@typescript-eslint/parser": "^4.30.0", + "@commitlint/cli": "^13.2.1", + "@commitlint/config-conventional": "^13.2.0", + "@types/jest": "^27.0.2", + "@types/node": "^16.10.6", + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", "cpy-cli": "^3.1.1", "eslint": "^7.32.0", - "eslint-config-kentcdodds": "^19.1.1", + "eslint-config-kentcdodds": "^19.2.0", "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.24.2", - "eslint-plugin-jest": "^24.4.0", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-jest": "^25.2.2", "eslint-plugin-jest-formatting": "^3.0.0", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^3.4.1", + "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-promise": "^5.1.0", "husky": "^7.0.2", "is-ci": "^3.0.0", - "jest": "^27.1.0", - "lint-staged": "^11.1.2", - "prettier": "2.3.2", - "semantic-release": "^17.4.7", - "ts-jest": "27.0.5", - "ts-node": "^10.2.1", - "typescript": "^4.4.2" + "jest": "^27.3.0", + "lint-staged": "^11.2.3", + "prettier": "2.4.1", + "semantic-release": "^18.0.0", + "ts-jest": "27.0.7", + "ts-node": "^10.3.0", + "typescript": "^4.4.4" }, "peerDependencies": { - "eslint": "^7.5.0" + "eslint": "^7.5.0 || ^8.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0", + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", "npm": ">=6" }, "license": "MIT" diff --git a/tests/__snapshots__/index.test.ts.snap b/tests/__snapshots__/index.test.ts.snap index d154465d..d800dee4 100644 --- a/tests/__snapshots__/index.test.ts.snap +++ b/tests/__snapshots__/index.test.ts.snap @@ -11,15 +11,21 @@ Object { "testing-library/await-async-utils": "error", "testing-library/no-await-sync-query": "error", "testing-library/no-container": "error", - "testing-library/no-debug": "error", + "testing-library/no-debugging-utils": "error", "testing-library/no-dom-import": Array [ "error", "angular", ], "testing-library/no-node-access": "error", "testing-library/no-promise-in-fire-event": "error", + "testing-library/no-render-in-setup": "error", "testing-library/no-wait-for-empty-callback": "error", + "testing-library/no-wait-for-multiple-assertions": "error", + "testing-library/no-wait-for-side-effects": "error", + "testing-library/no-wait-for-snapshot": "error", "testing-library/prefer-find-by": "error", + "testing-library/prefer-presence-queries": "error", + "testing-library/prefer-query-by-disappearance": "error", "testing-library/prefer-screen-queries": "error", "testing-library/render-result-naming-convention": "error", }, @@ -34,7 +40,12 @@ Object { "testing-library/no-await-sync-query": "error", "testing-library/no-promise-in-fire-event": "error", "testing-library/no-wait-for-empty-callback": "error", + "testing-library/no-wait-for-multiple-assertions": "error", + "testing-library/no-wait-for-side-effects": "error", + "testing-library/no-wait-for-snapshot": "error", "testing-library/prefer-find-by": "error", + "testing-library/prefer-presence-queries": "error", + "testing-library/prefer-query-by-disappearance": "error", "testing-library/prefer-screen-queries": "error", }, }, @@ -47,15 +58,22 @@ Object { "testing-library/await-async-utils": "error", "testing-library/no-await-sync-query": "error", "testing-library/no-container": "error", - "testing-library/no-debug": "error", + "testing-library/no-debugging-utils": "error", "testing-library/no-dom-import": Array [ "error", "react", ], "testing-library/no-node-access": "error", "testing-library/no-promise-in-fire-event": "error", + "testing-library/no-render-in-setup": "error", + "testing-library/no-unnecessary-act": "error", "testing-library/no-wait-for-empty-callback": "error", + "testing-library/no-wait-for-multiple-assertions": "error", + "testing-library/no-wait-for-side-effects": "error", + "testing-library/no-wait-for-snapshot": "error", "testing-library/prefer-find-by": "error", + "testing-library/prefer-presence-queries": "error", + "testing-library/prefer-query-by-disappearance": "error", "testing-library/prefer-screen-queries": "error", "testing-library/render-result-naming-convention": "error", }, @@ -70,15 +88,21 @@ Object { "testing-library/await-fire-event": "error", "testing-library/no-await-sync-query": "error", "testing-library/no-container": "error", - "testing-library/no-debug": "error", + "testing-library/no-debugging-utils": "error", "testing-library/no-dom-import": Array [ "error", "vue", ], "testing-library/no-node-access": "error", "testing-library/no-promise-in-fire-event": "error", + "testing-library/no-render-in-setup": "error", "testing-library/no-wait-for-empty-callback": "error", + "testing-library/no-wait-for-multiple-assertions": "error", + "testing-library/no-wait-for-side-effects": "error", + "testing-library/no-wait-for-snapshot": "error", "testing-library/prefer-find-by": "error", + "testing-library/prefer-presence-queries": "error", + "testing-library/prefer-query-by-disappearance": "error", "testing-library/prefer-screen-queries": "error", "testing-library/render-result-naming-convention": "error", }, diff --git a/tests/fake-rule.ts b/tests/fake-rule.ts index 70a8d5da..9f57493e 100644 --- a/tests/fake-rule.ts +++ b/tests/fake-rule.ts @@ -26,7 +26,6 @@ export default createTestingLibraryRule({ type: 'problem', docs: { description: 'Fake rule to test rule maker and detection helpers', - category: 'Possible Errors', recommendedConfig: { dom: false, angular: false, diff --git a/tests/lib/rules/no-debug.test.ts b/tests/lib/rules/no-debugging-utils.test.ts similarity index 99% rename from tests/lib/rules/no-debug.test.ts rename to tests/lib/rules/no-debugging-utils.test.ts index aabbfb61..56814597 100644 --- a/tests/lib/rules/no-debug.test.ts +++ b/tests/lib/rules/no-debugging-utils.test.ts @@ -1,4 +1,4 @@ -import rule, { RULE_NAME } from '../../../lib/rules/no-debug'; +import rule, { RULE_NAME } from '../../../lib/rules/no-debugging-utils'; import { createRuleTester } from '../test-utils'; const ruleTester = createRuleTester(); diff --git a/tests/lib/rules/no-unnecessary-act.test.ts b/tests/lib/rules/no-unnecessary-act.test.ts index 0a372f3f..62407e30 100644 --- a/tests/lib/rules/no-unnecessary-act.test.ts +++ b/tests/lib/rules/no-unnecessary-act.test.ts @@ -13,15 +13,18 @@ type ValidTestCase = TSESLint.ValidTestCase; type InvalidTestCase = TSESLint.InvalidTestCase; type TestCase = InvalidTestCase | ValidTestCase; -const enableStrict = (array: T[]): T[] => +const addOptions = ( + array: T[], + options?: Options[number] +): T[] => array.map((testCase) => ({ ...testCase, - options: [ - { - isStrict: true, - }, - ], + options: [options], })); +const disableStrict = (array: T[]): T[] => + addOptions(array, { isStrict: false }); +const enableStrict = (array: T[]): T[] => + addOptions(array, { isStrict: true }); /** * - AGR stands for Aggressive Reporting @@ -208,11 +211,6 @@ const validTestCases: ValidTestCase[] = [ const invalidStrictTestCases: InvalidTestCase[] = [ { - options: [ - { - isStrict: true, - }, - ], code: `// case: RTL act wrapping both RTL and non-RTL calls with strict option import { act, render } from '@testing-library/react' @@ -886,12 +884,12 @@ const invalidTestCases: InvalidTestCase[] = [ ruleTester.run(RULE_NAME, rule, { valid: [ ...validTestCases, - ...validNonStrictTestCases, - ...enableStrict(validTestCases), + ...disableStrict(validNonStrictTestCases), + ...disableStrict(validTestCases), ], invalid: [ ...invalidTestCases, - ...invalidStrictTestCases, - ...enableStrict(invalidTestCases), + ...enableStrict(invalidStrictTestCases), + ...disableStrict(invalidTestCases), ], });