Skip to content

feat(prefer-screen-queries): add prefer-screen-queries #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ To enable this configuration use the `extends` property in your
| [no-manual-cleanup](docs/rules/no-manual-cleanup.md) | Disallow the use of `cleanup` | | |
| [no-wait-for-empty-callback](docs/rules/no-wait-for-empty-callback.md) | Disallow empty callbacks for `waitFor` and `waitForElementToBeRemoved` | | |
| [prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than just `getBy*` queries | | |
| [prefer-screen-queries](docs/rules/prefer-screen-queries.md) | Suggest using screen while using queries | | |
| [prefer-wait-for](docs/rules/prefer-wait-for.md) | Use `waitFor` instead of deprecated wait methods | | ![fixable-badge][] |

[build-badge]: https://img.shields.io/travis/testing-library/eslint-plugin-testing-library?style=flat-square
Expand Down
30 changes: 30 additions & 0 deletions docs/rules/prefer-screen-queries.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Suggest using screen while using queries (prefer-screen-queries)

## Rule Details

DOM Testing Library (and other Testing Library frameworks built on top of it) exports a `screen` object which has every query (and a `debug` method). This works better with autocomplete and makes each test a little simpler to write and maintain.
This rule aims to force writing tests using queries directly from `screen` object rather than destructuring them from `render` result.

Examples of **incorrect** code for this rule:

```js
// calling a query from the `render` method
const { getByText } = render(<Component />);
getByText('foo');

const utils = render(<Component />);
utils.getByText('foo');
```

Examples of **correct** code for this rule:

```js
import { screen } from '@testing-library/any-framework';

Copy link
Member

@Belco90 Belco90 Mar 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add here the render line to have a full example?

Suggested change
render(<Component />);

render(<Component />);
screen.getByText('foo');
```

## Further Reading

- [`screen` documentation](https://testing-library.com/docs/dom-testing-library/api-queries#screen)
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const rules = {
'no-manual-cleanup': require('./rules/no-manual-cleanup'),
'no-wait-for-empty-callback': require('./rules/no-wait-for-empty-callback'),
'prefer-explicit-assert': require('./rules/prefer-explicit-assert'),
'prefer-screen-queries': require('./rules/prefer-screen-queries'),
'prefer-wait-for': require('./rules/prefer-wait-for'),
};

Expand Down
40 changes: 40 additions & 0 deletions lib/rules/prefer-screen-queries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict';

const { getDocsUrl, ALL_QUERIES_COMBINATIONS } = require('../utils');

const ALL_QUERIES_COMBINATIONS_REGEXP = ALL_QUERIES_COMBINATIONS.join('|');

module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'Suggest using screen while using queries',
category: 'Best Practices',
recommended: false,
url: getDocsUrl('prefer-screen-queries'),
},
messages: {
preferScreenQueries:
'Use screen to query DOM elements, `screen.{{ name }}`',
},
fixable: null,
schema: [],
},

create: function(context) {
function reportInvalidUsage(node) {
context.report({
node,
messageId: 'preferScreenQueries',
data: {
name: node.name,
},
});
}

return {
[`CallExpression > Identifier[name=/^${ALL_QUERIES_COMBINATIONS_REGEXP}$/]`]: reportInvalidUsage,
[`MemberExpression[object.name!="screen"] > Identifier[name=/^${ALL_QUERIES_COMBINATIONS_REGEXP}$/]`]: reportInvalidUsage,
};
},
};
4 changes: 2 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ const ASYNC_QUERIES_COMBINATIONS = combineQueries(
);

const ALL_QUERIES_COMBINATIONS = [
SYNC_QUERIES_COMBINATIONS,
ASYNC_QUERIES_COMBINATIONS,
...SYNC_QUERIES_COMBINATIONS,
...ASYNC_QUERIES_COMBINATIONS,
];

const ASYNC_UTILS = [
Expand Down
50 changes: 50 additions & 0 deletions tests/lib/rules/prefer-screen-queries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

const rule = require('../../../lib/rules/prefer-screen-queries');
const { ALL_QUERIES_COMBINATIONS } = require('../../../lib/utils');
const RuleTester = require('eslint').RuleTester;

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2018 } });
ruleTester.run('prefer-screen-queries', rule, {
valid: [
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `screen.${queryMethod}()`,
})),
{
code: `otherFunctionShouldNotThrow()`,
},
{
code: `component.otherFunctionShouldNotThrow()`,
},
],

invalid: [
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `${queryMethod}()`,
errors: [
{
messageId: 'preferScreenQueries',
data: {
name: queryMethod,
},
},
],
})),

...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `component.${queryMethod}()`,
errors: [
{
messageId: 'preferScreenQueries',
data: {
name: queryMethod,
},
},
],
})),
],
});