Skip to content

Commit 46d8a9d

Browse files
committed
Sync with ember-template-lint
1 parent 85ac3df commit 46d8a9d

4 files changed

Lines changed: 82 additions & 133 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ rules in templates can be disabled with eslint directives with mustache or html
258258
| [template-no-obsolete-elements](docs/rules/template-no-obsolete-elements.md) | disallow obsolete HTML elements | | | |
259259
| [template-no-outlet-outside-routes](docs/rules/template-no-outlet-outside-routes.md) | disallow {{outlet}} outside of route templates | | | |
260260
| [template-no-page-title-component](docs/rules/template-no-page-title-component.md) | disallow usage of ember-page-title component | | | |
261-
| [template-no-positional-data-test-selectors](docs/rules/template-no-positional-data-test-selectors.md) | disallow positional data-test selectors | | | |
261+
| [template-no-positional-data-test-selectors](docs/rules/template-no-positional-data-test-selectors.md) | disallow positional data-test-* params in curly invocations | | | |
262262
| [template-no-potential-path-strings](docs/rules/template-no-potential-path-strings.md) | disallow potential path strings in attribute values | | | |
263263
| [template-no-splattributes-with-class](docs/rules/template-no-splattributes-with-class.md) | disallow splattributes with class attribute | | | |
264264
| [template-no-trailing-spaces](docs/rules/template-no-trailing-spaces.md) | disallow trailing whitespace at the end of lines in templates | | 🔧 | |

docs/rules/template-no-positional-data-test-selectors.md

Lines changed: 9 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22

33
<!-- end auto-generated rule header -->
44

5-
Disallows positional data-test selectors.
6-
7-
## Rule Details
8-
9-
Data-test selectors should use descriptive names rather than positional indices for better maintainability and clarity.
10-
115
## Motivation
126

137
[ember-test-selectors](https://github.com/simplabs/ember-test-selectors) is a very popular library that enables better element selectors for testing.
@@ -26,51 +20,20 @@ Additionally, the nature of these "fake" local properties significantly confuses
2620

2721
## Examples
2822

29-
This rule checks two things:
30-
31-
1. **Curly component invocations** with positional `data-test-*` params (e.g. `{{badge data-test-profile-card}}`), which should use named arguments instead (e.g. `data-test-profile-card=true`).
32-
2. **HTML attribute values** that are purely numeric (e.g. `data-test-item="0"`), which should use descriptive names instead.
23+
This rule forbids the following:
3324

34-
Examples of **incorrect** code for this rule:
35-
36-
```gjs
37-
<template>
38-
{{badge data-test-profile-card}}
39-
</template>
40-
```
41-
42-
```gjs
43-
<template>
44-
<div data-test-item="0"></div>
45-
</template>
46-
```
47-
48-
```gjs
49-
<template>
50-
<div data-test-card="1"></div>
51-
</template>
52-
```
53-
54-
Examples of **correct** code for this rule:
55-
56-
```gjs
57-
<template>
58-
{{badge data-test-profile-card=true}}
59-
</template>
25+
```hbs
26+
{{foo-bar data-test-blah}}
27+
{{#foo-bar data-test-blah}}{{/foo-bar}}
6028
```
6129

62-
```gjs
63-
<template>
64-
<div data-test-user-card></div>
65-
</template>
66-
```
30+
And suggests using the following instead:
6731

68-
```gjs
69-
<template>
70-
<div data-test-item="my-item"></div>
71-
</template>
32+
```hbs
33+
{{foo-bar data-test-blah=true}}
34+
{{#foo-bar data-test-blah=true}}{{/foo-bar}}
7235
```
7336

7437
## References
7538

76-
- [eslint-plugin-ember template-no-positional-data-test-selectors](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/template-no-positional-data-test-selectors.md)
39+
- [ember-test-selectors#d47f73d](https://github.com/simplabs/ember-test-selectors/commit/d47f73d76b3ccbc9f0be5df3b897afd08b1636a6)

lib/rules/template-no-positional-data-test-selectors.js

Lines changed: 64 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,67 @@
1+
const BUILT_INS = new Set([
2+
'action',
3+
'array',
4+
'component',
5+
'concat',
6+
'debugger',
7+
'each',
8+
'each-in',
9+
'fn',
10+
'get',
11+
'hasBlock',
12+
'has-block',
13+
'has-block-params',
14+
'hash',
15+
'if',
16+
'input',
17+
'let',
18+
'link-to',
19+
'loc',
20+
'log',
21+
'mount',
22+
'mut',
23+
'on',
24+
'outlet',
25+
'partial',
26+
'query-params',
27+
'textarea',
28+
'unbound',
29+
'unless',
30+
'with',
31+
'-in-element',
32+
'in-element',
33+
]);
34+
35+
function checkNode(node, context) {
36+
if (!node.path || BUILT_INS.has(node.path.original)) {
37+
return;
38+
}
39+
40+
if (!node.params) {
41+
return;
42+
}
43+
44+
for (const param of node.params) {
45+
if (
46+
param.type === 'GlimmerPathExpression' &&
47+
param.original &&
48+
param.original.startsWith('data-test-')
49+
) {
50+
context.report({
51+
node,
52+
messageId: 'noPositionalDataTest',
53+
});
54+
return;
55+
}
56+
}
57+
}
58+
159
/** @type {import('eslint').Rule.RuleModule} */
260
module.exports = {
361
meta: {
462
type: 'suggestion',
563
docs: {
6-
description: 'disallow positional data-test selectors',
64+
description: 'disallow positional data-test-* params in curly invocations',
765
category: 'Best Practices',
866
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-positional-data-test-selectors.md',
967
templateMode: 'both',
@@ -12,7 +70,7 @@ module.exports = {
1270
schema: [],
1371
messages: {
1472
noPositionalDataTest:
15-
'Use named data-test attributes instead of positional data-test-* attributes.',
73+
'Passing a `data-test-*` positional param to a curly invocation should be avoided.',
1674
},
1775
originallyFrom: {
1876
name: 'ember-template-lint',
@@ -24,43 +82,12 @@ module.exports = {
2482

2583
create(context) {
2684
return {
27-
GlimmerElementNode(node) {
28-
if (!node.attributes) {
29-
return;
30-
}
31-
32-
for (const attr of node.attributes) {
33-
if (attr.type === 'GlimmerAttrNode' && attr.name && attr.name.startsWith('data-test-')) {
34-
// Check if it's a positional selector (has a value that looks like an index)
35-
if (attr.value && attr.value.type === 'GlimmerTextNode') {
36-
const value = attr.value.chars;
37-
if (/^\d+$/.test(value)) {
38-
context.report({
39-
node: attr,
40-
messageId: 'noPositionalDataTest',
41-
});
42-
}
43-
}
44-
}
45-
}
85+
GlimmerMustacheStatement(node) {
86+
checkNode(node, context);
4687
},
4788

48-
GlimmerMustacheStatement(node) {
49-
if (!node.params) {
50-
return;
51-
}
52-
for (const param of node.params) {
53-
if (
54-
param.type === 'GlimmerPathExpression' &&
55-
param.original &&
56-
param.original.startsWith('data-test-')
57-
) {
58-
context.report({
59-
node: param,
60-
messageId: 'noPositionalDataTest',
61-
});
62-
}
63-
}
89+
GlimmerBlockStatement(node) {
90+
checkNode(node, context);
6491
},
6592
};
6693
},

tests/lib/rules/template-no-positional-data-test-selectors.js

Lines changed: 8 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,6 @@ const ruleTester = new RuleTester({
1616

1717
ruleTester.run('template-no-positional-data-test-selectors', rule, {
1818
valid: [
19-
`<template>
20-
<div data-test-user-card></div>
21-
</template>`,
22-
`<template>
23-
<div data-test-item="my-item"></div>
24-
</template>`,
25-
`<template>
26-
<button data-test-button></button>
27-
</template>`,
28-
2919
`<template>
3020
{{#if data-test-foo}}
3121
{{/if}}
@@ -80,43 +70,6 @@ ruleTester.run('template-no-positional-data-test-selectors', rule, {
8070
],
8171

8272
invalid: [
83-
{
84-
code: `<template>
85-
<div data-test-item="0"></div>
86-
</template>`,
87-
output: null,
88-
errors: [
89-
{
90-
message: 'Use named data-test attributes instead of positional data-test-* attributes.',
91-
type: 'GlimmerAttrNode',
92-
},
93-
],
94-
},
95-
{
96-
code: `<template>
97-
<div data-test-card="1"></div>
98-
</template>`,
99-
output: null,
100-
errors: [
101-
{
102-
message: 'Use named data-test attributes instead of positional data-test-* attributes.',
103-
type: 'GlimmerAttrNode',
104-
},
105-
],
106-
},
107-
{
108-
code: `<template>
109-
<button data-test-button="123"></button>
110-
</template>`,
111-
output: null,
112-
errors: [
113-
{
114-
message: 'Use named data-test attributes instead of positional data-test-* attributes.',
115-
type: 'GlimmerAttrNode',
116-
},
117-
],
118-
},
119-
12073
{
12174
code: `<template>
12275
{{badge
@@ -127,7 +80,10 @@ ruleTester.run('template-no-positional-data-test-selectors', rule, {
12780
</template>`,
12881
output: null,
12982
errors: [
130-
{ message: 'Use named data-test attributes instead of positional data-test-* attributes.' },
83+
{
84+
message:
85+
'Passing a `data-test-*` positional param to a curly invocation should be avoided.',
86+
},
13187
],
13288
},
13389
],
@@ -206,7 +162,10 @@ hbsRuleTester.run('template-no-positional-data-test-selectors', rule, {
206162
`,
207163
output: null,
208164
errors: [
209-
{ message: 'Use named data-test attributes instead of positional data-test-* attributes.' },
165+
{
166+
message:
167+
'Passing a `data-test-*` positional param to a curly invocation should be avoided.',
168+
},
210169
],
211170
},
212171
],

0 commit comments

Comments
 (0)