Skip to content

Commit 79b380f

Browse files
patriscusPatrick Ahmetovic
and
Patrick Ahmetovic
authored
feat(consistent-data-testid): add support for custom error message (#719)
Closes #718 * feat(consistent-data-testid): add support for custom message in the rule configuration * feat(consistent-data-testid): update docs * feat(consistent-data-testid): use undefined as default value for customMessage * feat(consistent-data-testid): add comment to test case Co-authored-by: Patrick Ahmetovic <[email protected]>
1 parent 137dc26 commit 79b380f

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

docs/rules/consistent-data-testid.md

+12
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const baz = (props) => <div>...</div>;
3434
| ----------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
3535
| `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` OR empty string in the case of dynamically changing routes (that contain square brackets) with `Gatsby.js` or `Next.js` | `^{fileName}(\_\_([A-Z]+[a-z]_?)+)_\$` |
3636
| `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"]` |
37+
| `customMessage` | No | `undefined` | A string used to display a custom message whenever warnings/errors are reported. | `A custom message` |
3738

3839
## Example
3940

@@ -59,6 +60,17 @@ const baz = (props) => <div>...</div>;
5960
}
6061
```
6162

63+
```json
64+
{
65+
"testing-library/consistent-data-testid": [
66+
2,
67+
{
68+
"customMessage": "A custom message"
69+
}
70+
]
71+
}
72+
```
73+
6274
## Notes
6375

6476
- If you are using Gatsby.js's [client-only routes](https://www.gatsbyjs.com/docs/reference/routing/file-system-route-api/#syntax-client-only-routes) or Next.js's [dynamic routes](https://nextjs.org/docs/routing/dynamic-routes) and therefore have square brackets (`[]`) in the filename (e.g. `../path/to/[component].js`), the `{fileName}` placeholder will be replaced with an empty string. This is because a linter cannot know what the dynamic content will be at run time.

lib/rules/consistent-data-testid.ts

+21-3
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ import { createTestingLibraryRule } from '../create-testing-library-rule';
22
import { isJSXAttribute, isLiteral } from '../node-utils';
33

44
export const RULE_NAME = 'consistent-data-testid';
5-
export type MessageIds = 'consistentDataTestId';
5+
export type MessageIds =
6+
| 'consistentDataTestId'
7+
| 'consistentDataTestIdCustomMessage';
68
export type Options = [
79
{
810
testIdAttribute?: string[] | string;
911
testIdPattern: string;
12+
customMessage?: string;
1013
}
1114
];
1215

@@ -28,6 +31,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
2831
},
2932
messages: {
3033
consistentDataTestId: '`{{attr}}` "{{value}}" should match `{{regex}}`',
34+
consistentDataTestIdCustomMessage: '`{{message}}`',
3135
},
3236
schema: [
3337
{
@@ -53,6 +57,10 @@ export default createTestingLibraryRule<Options, MessageIds>({
5357
},
5458
],
5559
},
60+
customMessage: {
61+
default: undefined,
62+
type: 'string',
63+
},
5664
},
5765
},
5866
],
@@ -61,6 +69,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
6169
{
6270
testIdPattern: '',
6371
testIdAttribute: 'data-testid',
72+
customMessage: undefined,
6473
},
6574
],
6675
detectionOptions: {
@@ -69,7 +78,7 @@ export default createTestingLibraryRule<Options, MessageIds>({
6978

7079
create: (context, [options]) => {
7180
const { getFilename } = context;
72-
const { testIdPattern, testIdAttribute: attr } = options;
81+
const { testIdPattern, testIdAttribute: attr, customMessage } = options;
7382

7483
function getFileNameData() {
7584
const splitPath = getFilename().split('/');
@@ -100,6 +109,14 @@ export default createTestingLibraryRule<Options, MessageIds>({
100109
}
101110
}
102111

112+
function getErrorMessageId(): MessageIds {
113+
if (customMessage === undefined) {
114+
return 'consistentDataTestId';
115+
}
116+
117+
return 'consistentDataTestIdCustomMessage';
118+
}
119+
103120
return {
104121
JSXIdentifier: (node) => {
105122
if (
@@ -118,11 +135,12 @@ export default createTestingLibraryRule<Options, MessageIds>({
118135
if (value && typeof value === 'string' && !regex.test(value)) {
119136
context.report({
120137
node,
121-
messageId: 'consistentDataTestId',
138+
messageId: getErrorMessageId(),
122139
data: {
123140
attr: node.name,
124141
value,
125142
regex,
143+
message: customMessage,
126144
},
127145
});
128146
}

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

+36
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ const invalidTestCases: InvalidTestCase[] = [
283283
attr: 'data-testid',
284284
value: 'Awesome__CoolStuff',
285285
regex: '/error/',
286+
message: '',
286287
},
287288
},
288289
],
@@ -312,6 +313,7 @@ const invalidTestCases: InvalidTestCase[] = [
312313
attr: 'data-testid',
313314
value: 'Nope',
314315
regex: '/matchMe/',
316+
message: '',
315317
},
316318
},
317319
],
@@ -342,6 +344,7 @@ const invalidTestCases: InvalidTestCase[] = [
342344
attr: 'my-custom-attr',
343345
value: 'WrongComponent__cool',
344346
regex: '/^Parent(__([A-Z]+[a-z]*?)+)*$/',
347+
message: '',
345348
},
346349
},
347350
],
@@ -380,6 +383,7 @@ const invalidTestCases: InvalidTestCase[] = [
380383
attr: 'another-custom-attr',
381384
value: 'wrong',
382385
regex: '/^right$/',
386+
message: '',
383387
},
384388
},
385389
],
@@ -409,6 +413,38 @@ const invalidTestCases: InvalidTestCase[] = [
409413
attr: 'data-testid',
410414
value: 'WrongComponent__cool',
411415
regex: '/^Parent(__([A-Z]+[a-z]*?)+)*$/',
416+
message: '',
417+
},
418+
},
419+
],
420+
},
421+
{
422+
code: ` // test for custom message
423+
import React from 'react';
424+
425+
const TestComponent = props => {
426+
return (
427+
<div data-testid="snake_case_value">
428+
Hello
429+
</div>
430+
)
431+
};
432+
`,
433+
options: [
434+
{
435+
testIdPattern: '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', //kebab-case
436+
customMessage: 'Please use kebab-cased data-testid values.',
437+
},
438+
],
439+
filename: '/my/cool/__tests__/Parent/index.js',
440+
errors: [
441+
{
442+
messageId: 'consistentDataTestIdCustomMessage',
443+
data: {
444+
attr: 'data-testid',
445+
value: 'snake_case_value',
446+
regex: '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',
447+
message: 'Please use kebab-cased data-testid values.',
412448
},
413449
},
414450
],

0 commit comments

Comments
 (0)