Skip to content

Commit 38d58ab

Browse files
committed
Create a rule avoid duplicate data-lgid and data-testid attributes
1 parent 8a53158 commit 38d58ab

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
/**
22
* DO NOT MODIFY THIS FILE
33
* ANY CHANGES WILL BE REMOVED ON THE NEXT BUILD
4+
* USE THE "create-rule" SCRIPT TO ADD NEW RULES INSTEAD
45
*/
6+
import { noDuplicateIdsRule } from './no-duplicate-ids';
57
import { noIndirectImportsRule } from './no-indirect-imports';
68
import { noRenderHookFromRtlRule } from './no-render-hook-from-rtl';
79

810
export const rules = {
11+
'no-duplicate-ids': noDuplicateIdsRule,
912
'no-indirect-imports': noIndirectImportsRule,
1013
'no-render-hook-from-rtl': noRenderHookFromRtlRule,
1114
};
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { TSESTree } from '@typescript-eslint/types';
2+
3+
import { createRule } from '../utils/createRule';
4+
5+
export const noDuplicateIdsRule = createRule({
6+
name: 'no-duplicate-ids',
7+
meta: {
8+
type: 'suggestion',
9+
messages: {
10+
'issue:noDuplicateIds':
11+
'Do not reference the same lgid or testid in multiple places within a component',
12+
},
13+
schema: [],
14+
docs: {
15+
description:
16+
'Prevents duplicate lgid or testid usage within a component file',
17+
},
18+
},
19+
defaultOptions: [],
20+
create: context => {
21+
const seen: Record<
22+
'data-lgid' | 'data-testid',
23+
Record<string, TSESTree.JSXAttribute | undefined>
24+
> = {
25+
'data-lgid': {},
26+
'data-testid': {},
27+
};
28+
29+
return {
30+
JSXAttribute(node) {
31+
if (node.name.type !== 'JSXIdentifier') {
32+
return;
33+
}
34+
35+
const { name: attributeName } = node.name;
36+
37+
if (attributeName !== 'data-lgid' && attributeName !== 'data-testid') {
38+
return;
39+
}
40+
41+
if (
42+
node.value?.type !== 'JSXExpressionContainer' ||
43+
node.value.expression.type !== 'MemberExpression' ||
44+
node.value.expression.object.type !== 'Identifier' ||
45+
node.value.expression.object.name !== 'lgIds'
46+
) {
47+
return;
48+
}
49+
50+
const { property } = node.value.expression;
51+
52+
const name =
53+
property.type === 'Identifier'
54+
? property.name
55+
: property.type === 'Literal'
56+
? property.value
57+
: undefined;
58+
59+
if (typeof name === 'string') {
60+
const other = seen[attributeName][name];
61+
62+
if (other) {
63+
context.report({
64+
node,
65+
messageId: 'issue:noDuplicateIds',
66+
});
67+
} else {
68+
seen[attributeName][name] = node;
69+
}
70+
}
71+
},
72+
};
73+
},
74+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { noDuplicateIdsRule } from '../rules/no-duplicate-ids';
2+
3+
import { ruleTester } from './utils/ruleTester.testutils';
4+
5+
ruleTester.run('no-duplicate-ids', noDuplicateIdsRule, {
6+
valid: [
7+
{
8+
code: `<div data-lgid={lgIds.root}><div data-lgid={lgIds.nested} /></div>`,
9+
languageOptions: {
10+
parserOptions: {
11+
ecmaFeatures: {
12+
jsx: true,
13+
},
14+
},
15+
},
16+
},
17+
],
18+
invalid: [
19+
{
20+
code: `<div data-lgid={lgIds.root}><div data-lgid={lgIds.root} /></div>`,
21+
languageOptions: {
22+
parserOptions: {
23+
ecmaFeatures: {
24+
jsx: true,
25+
},
26+
},
27+
},
28+
errors: [
29+
{
30+
messageId: 'issue:noDuplicateIds',
31+
},
32+
],
33+
},
34+
],
35+
});

0 commit comments

Comments
 (0)