Skip to content

Commit 65d9c34

Browse files
authored
feat: add support for multiple test id attributes (#211)
1 parent 591edb3 commit 65d9c34

File tree

3 files changed

+99
-9
lines changed

3 files changed

+99
-9
lines changed

docs/rules/consistent-data-testid.md

+15-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ const baz = props => <div>...</div>;
2424

2525
## Options
2626

27-
| Option | Required | Default | Details | Example |
28-
| ----------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
29-
| `testIdPattern` | Yes | None | A regex used to validate the format of the `data-testid` value. `{fileName}` can optionally be used as a placeholder and will be substituted with the name of the file OR the name of the files parent directory in the case when the file name is `index.js` | `^{fileName}(\_\_([A-Z]+[a-z]_?)+)_\$` |
30-
| `testIdAttribute` | No | `data-testid` | A string used to specify the attribute used for querying by ID. This is only required if data-testid has been explicitly overridden in the [RTL configuration](https://testing-library.com/docs/dom-testing-library/api-queries#overriding-data-testid) | `data-my-test-attribute` |
27+
| Option | Required | Default | Details | Example |
28+
| ----------------- | -------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
29+
| `testIdPattern` | Yes | None | A regex used to validate the format of the `data-testid` value. `{fileName}` can optionally be used as a placeholder and will be substituted with the name of the file OR the name of the files parent directory in the case when the file name is `index.js` | `^{fileName}(\_\_([A-Z]+[a-z]_?)+)_\$` |
30+
| `testIdAttribute` | No | `data-testid` | A string (or array of strings) used to specify the attribute used for querying by ID. This is only required if data-testid has been explicitly overridden in the [RTL configuration](https://testing-library.com/docs/dom-testing-library/api-queries#overriding-data-testid) | `data-my-test-attribute`, `["data-testid", "testId"]` |
3131

3232
## Example
3333

@@ -41,3 +41,14 @@ const baz = props => <div>...</div>;
4141
]
4242
}
4343
```
44+
45+
```json
46+
{
47+
"testing-library/consistent-data-testid": [
48+
2,
49+
{
50+
"testIdAttribute": ["data-testid", "testId"]
51+
}
52+
]
53+
}
54+
```

lib/rules/consistent-data-testid.ts

+27-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export type MessageIds = 'invalidTestId';
77
type Options = [
88
{
99
testIdPattern: string;
10-
testIdAttribute: string;
10+
testIdAttribute?: string | string[];
1111
}
1212
];
1313

@@ -37,8 +37,18 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
3737
type: 'string',
3838
},
3939
testIdAttribute: {
40-
type: 'string',
4140
default: 'data-testid',
41+
oneOf: [
42+
{
43+
type: 'string',
44+
},
45+
{
46+
type: 'array',
47+
items: {
48+
type: 'string',
49+
},
50+
},
51+
],
4252
},
4353
},
4454
},
@@ -70,9 +80,21 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
7080
return new RegExp(testIdPattern.replace(FILENAME_PLACEHOLDER, fileName));
7181
}
7282

83+
function isTestIdAttribute(name: string) {
84+
if (typeof attr === 'string') {
85+
return attr === name;
86+
} else {
87+
return attr.includes(name);
88+
}
89+
}
90+
7391
return {
74-
[`JSXIdentifier[name=${attr}]`]: (node: TSESTree.JSXIdentifier) => {
75-
if (!isJSXAttribute(node.parent) || !isLiteral(node.parent.value)) {
92+
[`JSXIdentifier`]: (node: TSESTree.JSXIdentifier) => {
93+
if (
94+
!isJSXAttribute(node.parent) ||
95+
!isLiteral(node.parent.value) ||
96+
!isTestIdAttribute(node.name)
97+
) {
7698
return;
7799
}
78100

@@ -85,7 +107,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
85107
node,
86108
messageId: 'invalidTestId',
87109
data: {
88-
attr,
110+
attr: node.name,
89111
value,
90112
regex,
91113
},

tests/lib/rules/consistent-data-testid.test.ts

+57
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,25 @@ ruleTester.run(RULE_NAME, rule, {
136136
code: `
137137
import React from 'react';
138138
139+
const TestComponent = props => {
140+
return (
141+
<div another-custom-attr="right-1" custom-attr="right-2">
142+
Hello
143+
</div>
144+
)
145+
};
146+
`,
147+
options: [
148+
{
149+
testIdPattern: '^right(.*)$',
150+
testIdAttribute: ['custom-attr', 'another-custom-attr'],
151+
},
152+
],
153+
},
154+
{
155+
code: `
156+
import React from 'react';
157+
139158
const TestComponent = props => {
140159
return (
141160
<div data-test-id="Parent">
@@ -256,6 +275,44 @@ ruleTester.run(RULE_NAME, rule, {
256275
code: `
257276
import React from 'react';
258277
278+
const TestComponent = props => {
279+
return (
280+
<div custom-attr="wrong" another-custom-attr="wrong">
281+
Hello
282+
</div>
283+
)
284+
};
285+
`,
286+
options: [
287+
{
288+
testIdPattern: '^right$',
289+
testIdAttribute: ['custom-attr', 'another-custom-attr'],
290+
},
291+
],
292+
filename: '/my/cool/__tests__/Parent/index.js',
293+
errors: [
294+
{
295+
messageId: 'invalidTestId',
296+
data: {
297+
attr: 'custom-attr',
298+
value: 'wrong',
299+
regex: '/^right$/',
300+
},
301+
},
302+
{
303+
messageId: 'invalidTestId',
304+
data: {
305+
attr: 'another-custom-attr',
306+
value: 'wrong',
307+
regex: '/^right$/',
308+
},
309+
},
310+
],
311+
},
312+
{
313+
code: `
314+
import React from 'react';
315+
259316
const TestComponent = props => {
260317
return (
261318
<div data-testid="WrongComponent__cool">

0 commit comments

Comments
 (0)