Skip to content

Commit eb4f402

Browse files
committed
feat(prefer-screen-queries): add prefer-screen-queries
Closes #95
1 parent 833277c commit eb4f402

File tree

6 files changed

+136
-13
lines changed

6 files changed

+136
-13
lines changed

README.md

+15-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
[![Tweet][tweet-badge]][tweet-url]
2424

2525
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
26+
2627
[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors-)
28+
2729
<!-- ALL-CONTRIBUTORS-BADGE:END -->
2830

2931
## Installation
@@ -132,18 +134,19 @@ To enable this configuration use the `extends` property in your
132134

133135
## Supported Rules
134136

135-
| Rule | Description | Configurations | Fixable |
136-
| --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------ |
137-
| [await-async-query](docs/rules/await-async-query.md) | Enforce async queries to have proper `await` | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
138-
| [await-async-utils](docs/rules/await-async-utils.md) | Enforce async utils to be awaited properly | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
139-
| [await-fire-event](docs/rules/await-fire-event.md) | Enforce async fire event methods to be awaited | ![vue-badge][] | |
140-
| [consistent-data-testid](docs/rules/consistent-data-testid.md) | Ensure `data-testid` values match a provided regex. | | |
141-
| [no-await-sync-query](docs/rules/no-await-sync-query.md) | Disallow unnecessary `await` for sync queries | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
142-
| [no-debug](docs/rules/no-debug.md) | Disallow the use of `debug` | ![angular-badge][] ![react-badge][] ![vue-badge][] | |
143-
| [no-dom-import](docs/rules/no-dom-import.md) | Disallow importing from DOM Testing Library | ![angular-badge][] ![react-badge][] ![vue-badge][] | ![fixable-badge][] |
137+
| Rule | Description | Configurations | Fixable |
138+
| ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------ |
139+
| [await-async-query](docs/rules/await-async-query.md) | Enforce async queries to have proper `await` | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
140+
| [await-async-utils](docs/rules/await-async-utils.md) | Enforce async utils to be awaited properly | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
141+
| [await-fire-event](docs/rules/await-fire-event.md) | Enforce async fire event methods to be awaited | ![vue-badge][] | |
142+
| [consistent-data-testid](docs/rules/consistent-data-testid.md) | Ensure `data-testid` values match a provided regex. | | |
143+
| [no-await-sync-query](docs/rules/no-await-sync-query.md) | Disallow unnecessary `await` for sync queries | ![recommended-badge][] ![angular-badge][] ![react-badge][] ![vue-badge][] | |
144+
| [no-debug](docs/rules/no-debug.md) | Disallow the use of `debug` | ![angular-badge][] ![react-badge][] ![vue-badge][] | |
145+
| [no-dom-import](docs/rules/no-dom-import.md) | Disallow importing from DOM Testing Library | ![angular-badge][] ![react-badge][] ![vue-badge][] | ![fixable-badge][] |
144146
| [no-get-by-for-checking-element-not-present](docs/rules/no-get-by-for-checking-element-not-present.md) | Disallow the use of `getBy*` queries when checking elements are not present | | |
145-
| [no-manual-cleanup](docs/rules/no-manual-cleanup.md) | Disallow the use of `cleanup` | | |
146-
| [prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than just `getBy*` queries | | |
147+
| [no-manual-cleanup](docs/rules/no-manual-cleanup.md) | Disallow the use of `cleanup` | | |
148+
| [prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than just `getBy*` queries | | |
149+
| [prefer-screen-queries](docs/rules/prefer-screen-queries.md) | Suggest using screen while using queries | | |
147150

148151
[build-badge]: https://img.shields.io/travis/testing-library/eslint-plugin-testing-library?style=flat-square
149152
[build-url]: https://travis-ci.org/testing-library/eslint-plugin-testing-library
@@ -194,6 +197,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
194197

195198
<!-- markdownlint-enable -->
196199
<!-- prettier-ignore-end -->
200+
197201
<!-- ALL-CONTRIBUTORS-LIST:END -->
198202

199203
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

docs/rules/prefer-screen-queries.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Suggest using screen while using queries (prefer-screen-queries)
2+
3+
## Rule Details
4+
5+
This works better with autocomplete and makes each test a little simpler.
6+
7+
Examples of **incorrect** code for this rule:
8+
9+
```js
10+
// calling a query from the `render` method
11+
const { getByText } = render(<Component />);
12+
getByText('foo');
13+
14+
const utils = render(<Component />);
15+
utils.getByText('foo');
16+
```
17+
18+
Examples of **correct** code for this rule:
19+
20+
```js
21+
import { screen } from '@testing-library/any-framework';
22+
23+
screen.getByText('foo');
24+
```
25+
26+
## Further Reading
27+
28+
- [`screen` documentation](https://testing-library.com/docs/dom-testing-library/api-queries#screen)

lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const rules = {
1111
'no-get-by-for-checking-element-not-present': require('./rules/no-get-by-for-checking-element-not-present'),
1212
'no-manual-cleanup': require('./rules/no-manual-cleanup'),
1313
'prefer-explicit-assert': require('./rules/prefer-explicit-assert'),
14+
'prefer-screen-queries': require('./rules/prefer-screen-queries'),
1415
};
1516

1617
const recommendedRules = {

lib/rules/prefer-screen-queries.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict';
2+
3+
const { getDocsUrl, ALL_QUERIES_COMBINATIONS } = require('../utils');
4+
5+
const ALL_QUERIES_COMBINATIONS_REGEXP = ALL_QUERIES_COMBINATIONS.join('|');
6+
7+
module.exports = {
8+
meta: {
9+
type: 'suggestion',
10+
docs: {
11+
description: 'Suggest using screen while using queries',
12+
category: 'Best Practices',
13+
recommended: false,
14+
url: getDocsUrl('prefer-screen-queries'),
15+
},
16+
messages: {
17+
preferScreenQueries:
18+
'Use screen to query DOM elements, `screen.{{ name }}`',
19+
},
20+
fixable: null,
21+
schema: [],
22+
},
23+
24+
create: function(context) {
25+
function reportInvalidUsage(node) {
26+
context.report({
27+
node,
28+
messageId: 'preferScreenQueries',
29+
data: {
30+
name: node.name,
31+
},
32+
});
33+
}
34+
35+
return {
36+
[`CallExpression > Identifier[name=/^${ALL_QUERIES_COMBINATIONS_REGEXP}$/]`]: reportInvalidUsage,
37+
[`MemberExpression[object.name!="screen"] > Identifier[name=/^${ALL_QUERIES_COMBINATIONS_REGEXP}$/]`]: reportInvalidUsage,
38+
};
39+
},
40+
};

lib/utils.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ const ASYNC_QUERIES_COMBINATIONS = combineQueries(
4444
);
4545

4646
const ALL_QUERIES_COMBINATIONS = [
47-
SYNC_QUERIES_COMBINATIONS,
48-
ASYNC_QUERIES_COMBINATIONS,
47+
...SYNC_QUERIES_COMBINATIONS,
48+
...ASYNC_QUERIES_COMBINATIONS,
4949
];
5050

5151
const ASYNC_UTILS = [
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'use strict';
2+
3+
const rule = require('../../../lib/rules/prefer-screen-queries');
4+
const { ALL_QUERIES_COMBINATIONS } = require('../../../lib/utils');
5+
const RuleTester = require('eslint').RuleTester;
6+
7+
// ------------------------------------------------------------------------------
8+
// Tests
9+
// ------------------------------------------------------------------------------
10+
11+
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2018 } });
12+
ruleTester.run('prefer-screen-queries', rule, {
13+
valid: [
14+
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
15+
code: `screen.${queryMethod}()`,
16+
})),
17+
{
18+
code: `otherFunctionShouldNotThrow()`,
19+
},
20+
{
21+
code: `component.otherFunctionShouldNotThrow()`,
22+
},
23+
],
24+
25+
invalid: [
26+
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
27+
code: `${queryMethod}()`,
28+
errors: [
29+
{
30+
messageId: 'preferScreenQueries',
31+
data: {
32+
name: queryMethod,
33+
},
34+
},
35+
],
36+
})),
37+
38+
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
39+
code: `component.${queryMethod}()`,
40+
errors: [
41+
{
42+
messageId: 'preferScreenQueries',
43+
data: {
44+
name: queryMethod,
45+
},
46+
},
47+
],
48+
})),
49+
],
50+
});

0 commit comments

Comments
 (0)