Skip to content

Commit 02680e5

Browse files
committed
test: port ember-template-lint test cases to ESLint rules
1 parent dfd8fa2 commit 02680e5

18 files changed

Lines changed: 277 additions & 56 deletions

tests/lib/rules/template-no-attrs-in-components.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ ruleTester.run('template-no-attrs-in-components', rule, {
1616
<template>{{this.args.name}}</template>
1717
}`,
1818
'<template>{{attrs}}</template>',
19+
20+
// Test cases ported from ember-template-lint - basic smoke tests
21+
'<template><div></div></template>',
22+
'<template>{{foo}}</template>',
23+
'<template><div>{{foo.bar}}</div></template>',
1924
],
2025
invalid: [
2126
{

tests/lib/rules/template-no-bare-strings.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,5 +181,17 @@ ruleTester.run('template-no-bare-strings', rule, {
181181
output: null,
182182
errors: [{ messageId: 'bareString' }, { messageId: 'bareString' }],
183183
},
184+
{
185+
code: '<template><input placeholder="This is a placeholder" /></template>',
186+
filename: 'template.gjs',
187+
output: null,
188+
errors: [{ messageId: 'bareString' }],
189+
},
190+
{
191+
code: '<template><img alt="This is alt text" /></template>',
192+
filename: 'template.gts',
193+
output: null,
194+
errors: [{ messageId: 'bareString' }],
195+
},
184196
],
185197
});

tests/lib/rules/template-no-curly-component-invocation.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,35 @@ ruleTester.run('template-no-curly-component-invocation', rule, {
6464
},
6565
],
6666
},
67+
{
68+
code: '<template>{{#foo-bar}}{{/foo-bar}}</template>',
69+
output: null,
70+
errors: [
71+
{
72+
message:
73+
"You are using the component {{#foo-bar}} with curly component syntax. You should use <FooBar> instead. If it is actually a helper you must manually add it to the 'no-curly-component-invocation' rule configuration, e.g. `'no-curly-component-invocation': { allow: ['foo-bar'] }`.",
74+
},
75+
],
76+
},
77+
{
78+
code: '<template>{{#foo-bar/baz/boo-foo}}block{{/foo-bar/baz/boo-foo}}</template>',
79+
output: null,
80+
errors: [
81+
{
82+
message:
83+
"You are using the component {{#foo-bar/baz/boo-foo}} with curly component syntax. You should use <FooBar::Baz::BooFoo> instead. If it is actually a helper you must manually add it to the 'no-curly-component-invocation' rule configuration, e.g. `'no-curly-component-invocation': { allow: ['foo-bar/baz/boo-foo'] }`.",
84+
},
85+
],
86+
},
87+
{
88+
code: '<template>{{foo}}</template>',
89+
options: [{ disallow: ['foo'] }],
90+
output: null,
91+
errors: [
92+
{
93+
message: generateError('foo'),
94+
},
95+
],
96+
},
6797
],
6898
});

tests/lib/rules/template-no-duplicate-attributes.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ ruleTester.run('template-no-duplicate-attributes', rule, {
3737
'<template><a class="btn">{{btnLabel}}</a></template>',
3838
'<template>{{employee-profile employee=(hash firstName=firstName lastName=lastName age=age)}}</template>',
3939
'<template>{{employee-profile employee=(hash fullName=(hash firstName=firstName lastName=lastName) age=age)}}</template>',
40+
41+
// Block form with params (no duplicates)
42+
'<template>{{#my-component firstName=firstName lastName=lastName as |fullName|}}{{fullName}}{{/my-component}}</template>',
4043
],
4144

4245
invalid: [

tests/lib/rules/template-no-duplicate-landmark-elements.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@ ruleTester.run('template-no-duplicate-landmark-elements', rule, {
1111
'<template><header aria-label="Main">Header</header></template>',
1212
'<template><nav aria-label="Primary">Nav 1</nav><nav aria-label="Secondary">Nav 2</nav></template>',
1313
'<template><main>Content</main></template>',
14+
15+
// Test cases ported from ember-template-lint
16+
// Nav + div with role="navigation" (different unique labels)
17+
'<template><nav aria-label="primary site navigation"></nav><div role="navigation" aria-label="secondary site navigation within home page"></div></template>',
18+
19+
// Form with aria-labelledby + another form with aria-label (unique labels)
20+
'<template><form aria-labelledby="form-title"><div id="form-title">Shipping Address</div></form><form aria-label="meaningful title of second form"></form></template>',
21+
22+
// Standard page layout (unique landmarks by type)
23+
'<template><header></header><main></main><footer></footer></template>',
24+
25+
// role="none" — not a landmark, should be ignored
26+
'<template><img role="none"><img role="none"></template>',
1427
],
1528

1629
invalid: [

tests/lib/rules/template-no-forbidden-elements.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,11 @@ ruleTester.run('template-no-forbidden-elements', rule, {
4343
output: null,
4444
errors: [{ messageId: 'forbidden' }],
4545
},
46+
{
47+
code: '<template><Foo /></template>',
48+
output: null,
49+
options: [['Foo']],
50+
errors: [{ messageId: 'forbidden' }],
51+
},
4652
],
4753
});

tests/lib/rules/template-no-invalid-link-text.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,11 @@ ruleTester.run('template-no-invalid-link-text', rule, {
111111
output: null,
112112
errors: [{ messageId: 'invalidText' }],
113113
},
114+
{
115+
code: '<template><MyLink>click here</MyLink></template>',
116+
output: null,
117+
options: [{ linkComponents: ['MyLink'] }],
118+
errors: [{ messageId: 'invalidText' }],
119+
},
114120
],
115121
});

tests/lib/rules/template-no-invalid-meta.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,26 @@ ruleTester.run('template-no-invalid-meta', rule, {
1212
'<template><meta charset="UTF-8" /></template>',
1313
'<template><meta charset="utf8" /></template>',
1414
'<template><meta name="viewport" content="width=device-width" /></template>',
15+
16+
// Test cases ported from ember-template-lint
17+
// Bare meta (no attrs)
18+
'<template><meta></template>',
19+
20+
// Valid http-equiv refresh (delay=0 for redirect, >72000)
21+
'<template><meta http-equiv="refresh" content="0; url=http://www.example.com"></template>',
22+
'<template><meta http-equiv="refresh" content="72001"></template>',
23+
24+
// Dynamic attributes (can't validate at lint time)
25+
'<template><meta http-equiv={{httpEquiv}} content={{content}}></template>',
26+
'<template><meta name={{name}} content={{content}}></template>',
27+
28+
// Viewport with user-scalable=yes (valid)
29+
'<template><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"></template>',
30+
'<template><meta name="viewport" content="width=device-width, initial-scale=1"></template>',
31+
32+
// property and itemprop with content (valid)
33+
'<template><meta property="og:type" content="website"></template>',
34+
'<template><meta itemprop="type" content="website"></template>',
1535
],
1636

1737
invalid: [

tests/lib/rules/template-no-negated-condition.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,51 @@ ruleTester.run('template-no-negated-condition', rule, {
1515
'<template>{{#if isValid}}Yes{{/if}}</template>',
1616
'<template>{{#unless isInvalid}}Yes{{/unless}}</template>',
1717
'<template>{{#if (eq value 1)}}Yes{{/if}}</template>',
18+
19+
// Test cases ported from ember-template-lint: not with multiple args / non-not helpers
20+
'<template>{{#if condition}}<img>{{/if}}</template>',
21+
'<template>{{#if (or c1 c2)}}{{/if}}</template>',
22+
'<template>{{#if (not (or c1 c2))}}{{/if}}</template>',
23+
'<template>{{#if (not c1 c2)}}{{/if}}</template>',
24+
'<template>{{#if (not (not c1) c2)}}<img>{{/if}}</template>',
25+
'<template>{{#if (not c1 (not c2))}}<img>{{/if}}</template>',
26+
27+
// simplifyHelpers: false config
28+
{
29+
code: '<template>{{#if (not (not c2))}}<img>{{/if}}</template>',
30+
options: [{ simplifyHelpers: false }],
31+
},
32+
{
33+
code: '<template>{{#if (not (eq c2))}}<img>{{/if}}</template>',
34+
options: [{ simplifyHelpers: false }],
35+
},
36+
37+
// if...else / if...else if patterns
38+
'<template>{{#if condition}}<img>{{else}}<img>{{/if}}</template>',
39+
'<template>{{#if (or c1 c2)}}<img>{{else}}<img>{{/if}}</template>',
40+
'<template>{{#if condition}}<img>{{else if condition}}<img>{{/if}}</template>',
41+
'<template>{{#if condition}}<img>{{else if (not condition2)}}<img>{{/if}}</template>',
42+
'<template>{{#if (not condition)}}<img>{{else if (not condition2)}}<img>{{/if}}</template>',
43+
'<template>{{#if condition}}<img>{{else if condition}}<img>{{else}}<img>{{/if}}</template>',
44+
'<template>{{#if (not condition)}}<img>{{else if (not condition2)}}<img>{{else}}<img>{{/if}}</template>',
45+
46+
// unless variants
47+
'<template>{{#unless (or c1 c2)}}<img>{{/unless}}</template>',
48+
'<template>{{#unless condition}}<img>{{else}}<img>{{/unless}}</template>',
49+
'<template>{{#unless condition}}<img>{{else if condition}}<img>{{/unless}}</template>',
50+
'<template>{{#unless condition}}<img>{{else if condition}}<img>{{else}}<img>{{/unless}}</template>',
51+
52+
// MustacheStatement context (inline)
53+
'<template><img class={{if condition "some-class"}}></template>',
54+
'<template><img class={{if condition "some-class" "other-class"}}></template>',
55+
'<template><img class={{unless condition "some-class"}}></template>',
56+
'<template><img class={{if (not (or c1 c2)) "some-class"}}></template>',
57+
58+
// SubExpression context
59+
'<template>{{input class=(if condition "some-class")}}</template>',
60+
'<template>{{input class=(if condition "some-class" "other-class")}}</template>',
61+
'<template>{{input class=(unless condition "some-class")}}</template>',
62+
'<template>{{input class=(if (not (or c1 c2)) "some-class")}}</template>',
1863
],
1964
invalid: [
2065
{

tests/lib/rules/template-no-nested-splattributes.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,29 @@ ruleTester.run('template-no-nested-splattributes', rule, {
5656

5757
// Test cases ported from ember-template-lint
5858
{
59-
code: `<template><div ...attributes><div ...attributes>
60-
</div></div></template>`,
59+
code: `<template><div ...attributes>
60+
<div ...attributes>
61+
...
62+
</div>
63+
</div>
64+
</template>`,
65+
output: null,
66+
errors: [
67+
{
68+
message:
69+
'Do not use ...attributes on nested elements. Only use it on the top-level element of a component.',
70+
},
71+
],
72+
},
73+
{
74+
code: `<template><div ...attributes>
75+
<div>
76+
<div ...attributes>
77+
...
78+
</div>
79+
</div>
80+
</div>
81+
</template>`,
6182
output: null,
6283
errors: [
6384
{

0 commit comments

Comments
 (0)