Skip to content

Commit 3716b8f

Browse files
NullVoxPopuliclaude
andcommitted
Remove element from BUILTIN_HELPERS and convert all tests to strict mode
Per review feedback: don't register element in loose mode (users with ember-element-helper may have different behavior), and use strict mode templates exclusively in tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 179124a commit 3716b8f

2 files changed

Lines changed: 64 additions & 85 deletions

File tree

packages/@ember/-internals/glimmer/lib/resolver.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import { default as eachIn } from './helpers/each-in';
3838
import { default as mut } from './helpers/mut';
3939
import { default as readonly } from './helpers/readonly';
4040
import { default as unbound } from './helpers/unbound';
41-
import { default as element } from './helpers/element';
4241
import { default as uniqueId } from './helpers/unique-id';
4342

4443
import { mountHelper } from './syntax/mount';
@@ -109,7 +108,6 @@ const BUILTIN_HELPERS: Record<string, object> = {
109108
fn,
110109
get,
111110
hash,
112-
element,
113111
'unique-id': uniqueId,
114112
};
115113

packages/@ember/-internals/glimmer/tests/integration/helpers/element-test.js

Lines changed: 64 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1-
import { set } from '@ember/object';
21
import { DEBUG } from '@glimmer/env';
3-
import { RenderingTestCase, moduleFor, runTask } from 'internal-test-helpers';
4-
import { element as elementHelper } from '@ember/helper';
2+
import { tracked } from '@glimmer/tracking';
3+
import { RenderingTestCase, defineSimpleHelper, moduleFor, runTask } from 'internal-test-helpers';
4+
import { element as elementHelper, hash } from '@ember/helper';
5+
import { on } from '@ember/modifier';
56
import { template } from '@ember/template-compiler/runtime';
67

78
moduleFor(
89
'Helpers test: {{element}}',
910
class extends RenderingTestCase {
1011
'@test it renders a tag with the given tag name'() {
11-
this.render(`{{#let (element "h1") as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}`);
12-
this.assertHTML('<h1 id="content">hello world!</h1>');
13-
}
14-
15-
'@test it renders a tag in strict mode'() {
1612
let AComponent = template(
1713
`{{#let (element "h1") as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}`,
1814
{ scope: () => ({ element: elementHelper }) }
@@ -21,8 +17,11 @@ moduleFor(
2117
}
2218

2319
'@test it does not render any tags when passed an empty string'() {
24-
this.render(`{{#let (element "") as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}`);
25-
this.assertText('hello world!');
20+
let AComponent = template(
21+
`{{#let (element "") as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}`,
22+
{ scope: () => ({ element: elementHelper }) }
23+
);
24+
this.renderComponent(AComponent, { expect: 'hello world!' });
2625
}
2726

2827
['@test it throws when passed null']() {
@@ -31,10 +30,12 @@ moduleFor(
3130
return;
3231
}
3332

33+
let nil = null;
3434
this.assert.throws(() => {
35-
this.render(
36-
`<div>{{#let (element null) as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}</div>`
37-
);
35+
let AComponent = template(`{{#let (element nil) as |Tag|}}<Tag>hello</Tag>{{/let}}`, {
36+
scope: () => ({ element: elementHelper, nil }),
37+
});
38+
this.renderComponent(AComponent, { expect: '' });
3839
}, /The argument passed to the `element` helper must be a string/);
3940
}
4041

@@ -44,49 +45,63 @@ moduleFor(
4445
return;
4546
}
4647

48+
let undef = undefined;
4749
this.assert.throws(() => {
48-
this.render(
49-
`<div>{{#let (element undefined) as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}</div>`
50-
);
50+
let AComponent = template(`{{#let (element undef) as |Tag|}}<Tag>hello</Tag>{{/let}}`, {
51+
scope: () => ({ element: elementHelper, undef }),
52+
});
53+
this.renderComponent(AComponent, { expect: '' });
5154
}, /The argument passed to the `element` helper must be a string/);
5255
}
5356

5457
'@test it works with element modifiers'() {
55-
this.render(
56-
`{{#let (element "button") as |Tag|}}<Tag type="button" id="action" {{on "click" this.didClick}}>hello world!</Tag>{{/let}}`,
57-
{ didClick: () => {} }
58+
let didClick = () => {};
59+
let AComponent = template(
60+
`{{#let (element "button") as |Tag|}}<Tag type="button" id="action" {{on "click" didClick}}>hello world!</Tag>{{/let}}`,
61+
{ scope: () => ({ element: elementHelper, on, didClick }) }
5862
);
59-
60-
this.assertHTML('<button type="button" id="action">hello world!</button>');
63+
this.renderComponent(AComponent, {
64+
expect: '<button type="button" id="action">hello world!</button>',
65+
});
6166
}
6267

6368
'@test it can be rendered multiple times'() {
64-
this.render(
65-
`{{#let (element "h1") as |Tag|}}<Tag id="content-1">hello</Tag><Tag id="content-2">world</Tag><Tag id="content-3">!!!!!</Tag>{{/let}}`
66-
);
67-
this.assertHTML(
68-
'<h1 id="content-1">hello</h1><h1 id="content-2">world</h1><h1 id="content-3">!!!!!</h1>'
69+
let AComponent = template(
70+
`{{#let (element "h1") as |Tag|}}<Tag id="content-1">hello</Tag><Tag id="content-2">world</Tag><Tag id="content-3">!!!!!</Tag>{{/let}}`,
71+
{ scope: () => ({ element: elementHelper }) }
6972
);
73+
this.renderComponent(AComponent, {
74+
expect:
75+
'<h1 id="content-1">hello</h1><h1 id="content-2">world</h1><h1 id="content-3">!!!!!</h1>',
76+
});
7077
}
7178

7279
'@test it renders when the tag name changes'() {
73-
// Note: use htmlTag instead of tagName, because RenderingTestCase
74-
// overrides tagName on the root component context
75-
this.render(`{{#let (element this.htmlTag) as |Tag|}}<Tag id="content">hello</Tag>{{/let}}`, {
76-
htmlTag: 'h1',
80+
class State {
81+
@tracked htmlTag = 'h1';
82+
}
83+
84+
let state = new State();
85+
let getTag = defineSimpleHelper(() => state.htmlTag);
86+
87+
let AComponent = template(
88+
`{{#let (element (getTag)) as |Tag|}}<Tag id="content">hello</Tag>{{/let}}`,
89+
{ scope: () => ({ element: elementHelper, getTag }) }
90+
);
91+
this.renderComponent(AComponent, {
92+
expect: '<h1 id="content">hello</h1>',
7793
});
78-
this.assertHTML('<h1 id="content">hello</h1>');
7994

80-
runTask(() => set(this.context, 'htmlTag', 'h2'));
95+
runTask(() => (state.htmlTag = 'h2'));
8196
this.assertHTML('<h2 id="content">hello</h2>');
8297

83-
runTask(() => set(this.context, 'htmlTag', 'h3'));
98+
runTask(() => (state.htmlTag = 'h3'));
8499
this.assertHTML('<h3 id="content">hello</h3>');
85100

86-
runTask(() => set(this.context, 'htmlTag', ''));
101+
runTask(() => (state.htmlTag = ''));
87102
this.assertText('hello');
88103

89-
runTask(() => set(this.context, 'htmlTag', 'h1'));
104+
runTask(() => (state.htmlTag = 'h1'));
90105
this.assertHTML('<h1 id="content">hello</h1>');
91106
}
92107

@@ -103,55 +118,18 @@ moduleFor(
103118
this.renderComponent(Outer, { expect: '<p id="content" class="extra">Test</p>' });
104119
}
105120

106-
['@test it requires at least one argument']() {
107-
if (!DEBUG) {
108-
this.assert.expect(0);
109-
return;
110-
}
111-
112-
this.assert.throws(() => {
113-
this.render(
114-
`<div>{{#let (element) as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}</div>`
115-
);
116-
}, /The `element` helper takes a single positional argument/);
117-
}
118-
119-
['@test it requires no more than one argument']() {
120-
if (!DEBUG) {
121-
this.assert.expect(0);
122-
return;
123-
}
124-
125-
this.assert.throws(() => {
126-
this.render(
127-
`<div>{{#let (element "h1" "h2") as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}</div>`
128-
);
129-
}, /The `element` helper takes a single positional argument/);
130-
}
131-
132-
['@test it does not take any named arguments']() {
133-
if (!DEBUG) {
134-
this.assert.expect(0);
135-
return;
136-
}
137-
138-
this.assert.throws(() => {
139-
this.render(
140-
`<div>{{#let (element "h1" id="content") as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}</div>`
141-
);
142-
}, /The `element` helper does not take any named arguments/);
143-
}
144-
145121
['@test it throws when passed a number']() {
146122
if (!DEBUG) {
147123
this.assert.expect(0);
148124
return;
149125
}
150126

127+
let num = 123;
151128
this.assert.throws(() => {
152-
this.render(
153-
`<div>{{#let (element 123) as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}</div>`
154-
);
129+
let AComponent = template(`{{#let (element num) as |Tag|}}<Tag>hello</Tag>{{/let}}`, {
130+
scope: () => ({ element: elementHelper, num }),
131+
});
132+
this.renderComponent(AComponent, { expect: '' });
155133
}, /The argument passed to the `element` helper must be a string \(you passed `123`\)/);
156134
}
157135

@@ -161,10 +139,12 @@ moduleFor(
161139
return;
162140
}
163141

142+
let bool = false;
164143
this.assert.throws(() => {
165-
this.render(
166-
`<div>{{#let (element false) as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}</div>`
167-
);
144+
let AComponent = template(`{{#let (element bool) as |Tag|}}<Tag>hello</Tag>{{/let}}`, {
145+
scope: () => ({ element: elementHelper, bool }),
146+
});
147+
this.renderComponent(AComponent, { expect: '' });
168148
}, /The argument passed to the `element` helper must be a string \(you passed `false`\)/);
169149
}
170150

@@ -175,9 +155,10 @@ moduleFor(
175155
}
176156

177157
this.assert.throws(() => {
178-
this.render(
179-
`<div>{{#let (element (hash)) as |Tag|}}<Tag id="content">hello world!</Tag>{{/let}}</div>`
180-
);
158+
let AComponent = template(`{{#let (element (hash)) as |Tag|}}<Tag>hello</Tag>{{/let}}`, {
159+
scope: () => ({ element: elementHelper, hash }),
160+
});
161+
this.renderComponent(AComponent, { expect: '' });
181162
}, /The argument passed to the `element` helper must be a string/);
182163
}
183164
}

0 commit comments

Comments
 (0)