Skip to content

Commit 9329ed6

Browse files
authored
Feature/rule no dom import (#11)
* feat: add no-dom-import rule * test: add no-dom-import tests * docs: add no-dom-import docs * docs: update no-dom-import docs
1 parent 3f817aa commit 9329ed6

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ To enable this configuration use the `extends` property in your
120120
| [await-async-query](docs/rules/await-async-query.md) | Enforce async queries to have proper `await` | ![recommended][] | |
121121
| [no-await-sync-query](docs/rules/no-await-sync-query.md) | Disallow unnecessary `await` for sync queries | ![recommended][] | |
122122
| [no-debug](docs/rules/no-debug.md) | Disallow the use of `debug` | | ![angular][] ![react][] ![vue][] |
123+
| [no-dom-import](docs/rules/no-dom-import.md) | Disallow importing from DOM Testing Library | | ![angular][] ![react][] ![vue][] |
123124

124125
[recommended]: https://img.shields.io/badge/recommended-lightgrey?style=flat-square
125126
[angular]: https://img.shields.io/badge/-Angular-black?style=flat-square&logo=angular&logoColor=white&labelColor=DD0031&color=black

docs/rules/no-dom-import.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Disallow importing from DOM Testing Library
2+
3+
Ensure that there are no direct imports from `@testing-library/dom` or
4+
`@testing-library/dom` when using some testing library framework
5+
wrapper.
6+
7+
## Rule Details
8+
9+
Testing Library framework wrappers as React Testing Library already
10+
re-exports everything from DOM Testing Library so you always have to
11+
import DOM Testing Library utils from corresponding framework wrapper
12+
module to:
13+
14+
- use proper extended version of some of those methods containing
15+
additional functionality related to specific framework (e.g.
16+
`fireEvent` util)
17+
- avoid importing from extraneous dependencies (similar to
18+
eslint-plugin-import)
19+
20+
This rule aims to prevent users from import anything directly from
21+
`@testing-library/dom` (or `dom-testing-library`) and it's useful for
22+
new starters or when IDEs autoimport from wrong module.
23+
24+
Examples of **incorrect** code for this rule:
25+
26+
```js
27+
import { fireEvent } from 'dom-testing-library';
28+
```
29+
30+
```js
31+
import { fireEvent } from '@testing-library/dom';
32+
```
33+
34+
```js
35+
const { fireEvent } = require('dom-testing-library');
36+
```
37+
38+
```js
39+
const { fireEvent } = require('@testing-library/dom');
40+
```
41+
42+
Examples of **correct** code for this rule:
43+
44+
```js
45+
import { fireEvent } from 'react-testing-library';
46+
```
47+
48+
```js
49+
import { fireEvent } from '@testing-library/react';
50+
```
51+
52+
```js
53+
const { fireEvent } = require('react-testing-library');
54+
```
55+
56+
```js
57+
const { fireEvent } = require('@testing-library/react');
58+
```
59+
60+
## Further Reading
61+
62+
- [Angular Testing Library API](https://testing-library.com/docs/angular-testing-library/api)
63+
- [React Testing Library API](https://testing-library.com/docs/react-testing-library/api)
64+
- [Vue Testing Library API](https://testing-library.com/docs/vue-testing-library/api)

lib/rules/no-dom-import.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
'use strict';
2+
3+
const { getDocsUrl } = require('../utils');
4+
5+
const DOM_TESTING_LIBRARY_MODULES = [
6+
'dom-testing-library',
7+
'@testing-library/dom',
8+
];
9+
10+
module.exports = {
11+
meta: {
12+
type: 'problem',
13+
docs: {
14+
description: 'Disallow importing from DOM Testing Library',
15+
category: 'Best Practices',
16+
recommended: false,
17+
url: getDocsUrl('no-dom-import'),
18+
},
19+
messages: {
20+
noDomImport:
21+
'import from DOM Testing Library is restricted, import from corresponding Testing library framework instead',
22+
},
23+
fixable: null,
24+
schema: [],
25+
},
26+
27+
create: function(context) {
28+
return {
29+
ImportDeclaration(node) {
30+
if (DOM_TESTING_LIBRARY_MODULES.includes(node.source.value)) {
31+
context.report({
32+
node,
33+
messageId: 'noDomImport',
34+
});
35+
}
36+
},
37+
38+
[`CallExpression > Identifier[name="require"]`](node) {
39+
const { arguments: args } = node.parent;
40+
41+
if (
42+
args.some(args => DOM_TESTING_LIBRARY_MODULES.includes(args.value))
43+
) {
44+
context.report({
45+
node,
46+
messageId: 'noDomImport',
47+
});
48+
}
49+
},
50+
};
51+
},
52+
};

tests/lib/rules/no-dom-import.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
'use strict';
2+
3+
const rule = require('../../../lib/rules/no-dom-import');
4+
const RuleTester = require('eslint').RuleTester;
5+
6+
const ruleTester = new RuleTester({
7+
parserOptions: { ecmaVersion: 2015, sourceType: 'module' },
8+
});
9+
10+
ruleTester.run('no-dom-import', rule, {
11+
valid: [
12+
{ code: 'import { foo } from "foo"' },
13+
{ code: 'import "foo"' },
14+
{ code: 'import { fireEvent } from "react-testing-library"' },
15+
{ code: 'import * as testing from "react-testing-library"' },
16+
{ code: 'import { fireEvent } from "@testing-library/react"' },
17+
{ code: 'import * as testing from "@testing-library/react"' },
18+
{ code: 'import "react-testing-library"' },
19+
{ code: 'import "@testing-library/react"' },
20+
{ code: 'const { foo } = require("foo")' },
21+
{ code: 'require("foo")' },
22+
{ code: 'require("")' },
23+
{ code: 'require()' },
24+
{ code: 'const { fireEvent } = require("react-testing-library")' },
25+
{ code: 'const { fireEvent } = require("@testing-library/react")' },
26+
{ code: 'require("react-testing-library")' },
27+
{ code: 'require("@testing-library/react")' },
28+
],
29+
invalid: [
30+
{
31+
code: 'import { fireEvent } from "dom-testing-library"',
32+
errors: [
33+
{
34+
messageId: 'noDomImport',
35+
},
36+
],
37+
},
38+
{
39+
code: 'import * as testing from "dom-testing-library"',
40+
errors: [
41+
{
42+
messageId: 'noDomImport',
43+
},
44+
],
45+
},
46+
{
47+
code: 'import { fireEvent } from "@testing-library/dom"',
48+
errors: [
49+
{
50+
messageId: 'noDomImport',
51+
},
52+
],
53+
},
54+
{
55+
code: 'import * as testing from "@testing-library/dom"',
56+
errors: [
57+
{
58+
messageId: 'noDomImport',
59+
},
60+
],
61+
},
62+
{
63+
code: 'import "dom-testing-library"',
64+
errors: [
65+
{
66+
messageId: 'noDomImport',
67+
},
68+
],
69+
},
70+
{
71+
code: 'import "@testing-library/dom"',
72+
errors: [
73+
{
74+
messageId: 'noDomImport',
75+
},
76+
],
77+
},
78+
{
79+
code: 'const { fireEvent } = require("dom-testing-library")',
80+
errors: [
81+
{
82+
messageId: 'noDomImport',
83+
},
84+
],
85+
},
86+
{
87+
code: 'const { fireEvent } = require("@testing-library/dom")',
88+
errors: [
89+
{
90+
messageId: 'noDomImport',
91+
},
92+
],
93+
},
94+
{
95+
code: 'require("dom-testing-library")',
96+
errors: [
97+
{
98+
messageId: 'noDomImport',
99+
},
100+
],
101+
},
102+
{
103+
code: 'require("@testing-library/dom")',
104+
errors: [
105+
{
106+
messageId: 'noDomImport',
107+
},
108+
],
109+
},
110+
],
111+
});

0 commit comments

Comments
 (0)