-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19977 from Windvis/unique-id
Add a feature flag for the unique-id helper
- Loading branch information
Showing
3 changed files
with
120 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
223 changes: 113 additions & 110 deletions
223
packages/@ember/-internals/glimmer/tests/integration/helpers/unique-id-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,144 +1,147 @@ | ||
import { RenderingTestCase, strip, moduleFor, runTask } from 'internal-test-helpers'; | ||
import { setProperties } from '@ember/-internals/metal'; | ||
|
||
moduleFor( | ||
'Helpers test: {{unique-id}}', | ||
class extends RenderingTestCase { | ||
['@test it generates a unique id (string) each time']() { | ||
let { first, second } = this.render(`<p>{{unique-id}}</p><p>{{unique-id}}</p>`, () => { | ||
let first = this.asElement(this.firstChild); | ||
let second = this.asElement(this.nthChild(1)); | ||
|
||
return { | ||
first: this.asTextContent(first.firstChild), | ||
second: this.asTextContent(second.firstChild), | ||
}; | ||
}); | ||
|
||
this.assert.notStrictEqual( | ||
first, | ||
second, | ||
`different invocations of {{unique-id}} should produce different values` | ||
); | ||
} | ||
|
||
[`@test when unique-id is used with #let, it remains stable when it's used`]() { | ||
let { first, second } = this.render( | ||
strip` | ||
{{#let (unique-id) as |id|}} | ||
<p>{{id}}</p><p>{{id}}</p> | ||
{{/let}} | ||
`, | ||
() => { | ||
import { EMBER_UNIQUE_ID_HELPER } from '@ember/canary-features'; | ||
|
||
if (EMBER_UNIQUE_ID_HELPER) { | ||
moduleFor( | ||
'Helpers test: {{unique-id}}', | ||
class extends RenderingTestCase { | ||
['@test it generates a unique id (string) each time']() { | ||
let { first, second } = this.render(`<p>{{unique-id}}</p><p>{{unique-id}}</p>`, () => { | ||
let first = this.asElement(this.firstChild); | ||
let second = this.asElement(this.nthChild(1)); | ||
|
||
return { | ||
first: this.asTextContent(first.firstChild), | ||
second: this.asTextContent(second.firstChild), | ||
}; | ||
} | ||
); | ||
}); | ||
|
||
this.assert.strictEqual( | ||
first, | ||
second, | ||
`when unique-id is used as a variable, it remains the same` | ||
); | ||
} | ||
this.assert.notStrictEqual( | ||
first, | ||
second, | ||
`different invocations of {{unique-id}} should produce different values` | ||
); | ||
} | ||
|
||
[`@test unique-id doesn't change if it's concatenated with a value that does change`]() { | ||
class Elements { | ||
constructor(label, input, assert) { | ||
this.label = label; | ||
this.input = input; | ||
this.assert = assert; | ||
} | ||
[`@test when unique-id is used with #let, it remains stable when it's used`]() { | ||
let { first, second } = this.render( | ||
strip` | ||
{{#let (unique-id) as |id|}} | ||
<p>{{id}}</p><p>{{id}}</p> | ||
{{/let}} | ||
`, | ||
() => { | ||
let first = this.asElement(this.firstChild); | ||
let second = this.asElement(this.nthChild(1)); | ||
|
||
return { | ||
first: this.asTextContent(first.firstChild), | ||
second: this.asTextContent(second.firstChild), | ||
}; | ||
} | ||
); | ||
|
||
id(regex) { | ||
let forAttr = this.label.getAttribute('for'); | ||
this.assert.strictEqual( | ||
first, | ||
second, | ||
`when unique-id is used as a variable, it remains the same` | ||
); | ||
} | ||
|
||
this.assert.strictEqual( | ||
forAttr, | ||
this.input.getAttribute('id'), | ||
`the label's 'for' attribute should be the same as the input's 'id' attribute` | ||
); | ||
[`@test unique-id doesn't change if it's concatenated with a value that does change`]() { | ||
class Elements { | ||
constructor(label, input, assert) { | ||
this.label = label; | ||
this.input = input; | ||
this.assert = assert; | ||
} | ||
|
||
let match = forAttr.match(regex); | ||
id(regex) { | ||
let forAttr = this.label.getAttribute('for'); | ||
|
||
this.assert.ok(match, 'the id starts with the prefix'); | ||
this.assert.strictEqual( | ||
forAttr, | ||
this.input.getAttribute('id'), | ||
`the label's 'for' attribute should be the same as the input's 'id' attribute` | ||
); | ||
|
||
return match[1]; | ||
let match = forAttr.match(regex); | ||
|
||
this.assert.ok(match, 'the id starts with the prefix'); | ||
|
||
return match[1]; | ||
} | ||
} | ||
} | ||
|
||
let { elements, id } = this.render( | ||
strip` | ||
let { elements, id } = this.render( | ||
strip` | ||
{{#let (unique-id) as |id|}} | ||
<label for="{{this.prefix}}-{{id}}">Enable Feature</label> | ||
<input id="{{this.prefix}}-{{id}}" type="checkbox"> | ||
{{/let}}`, | ||
{ prefix: 'app' }, | ||
() => { | ||
let label = this.asElement(this.firstChild, 'label'); | ||
let input = this.asElement(this.nthChild(1), 'input'); | ||
|
||
let elements = new Elements(label, input, this.assert); | ||
|
||
return { elements, id: elements.id(/^app-(.*)$/) }; | ||
} | ||
); | ||
{ prefix: 'app' }, | ||
() => { | ||
let label = this.asElement(this.firstChild, 'label'); | ||
let input = this.asElement(this.nthChild(1), 'input'); | ||
|
||
this.update({ prefix: 'melanie' }, () => { | ||
let newId = elements.id(/^melanie-(.*)$/); | ||
let elements = new Elements(label, input, this.assert); | ||
|
||
this.assert.strictEqual( | ||
id, | ||
newId, | ||
`the unique-id part of a concatenated attribute shouldn't change just because a dynamic part of it changed` | ||
return { elements, id: elements.id(/^app-(.*)$/) }; | ||
} | ||
); | ||
}); | ||
} | ||
|
||
render(template, ...rest) { | ||
// If there are three parameters to `render`, the second parameter is the | ||
// template's arguments. | ||
let args = rest.length === 2 ? rest[0] : {}; | ||
// If there are two parameters to `render`, the second parameter is the | ||
// postcondition. Otherwise, the third parameter is the postcondition. | ||
let postcondition = rest.length === 2 ? rest[1] : rest[0]; | ||
|
||
super.render(template, args); | ||
let result = postcondition(); | ||
this.assertStableRerender(); | ||
return result; | ||
} | ||
this.update({ prefix: 'melanie' }, () => { | ||
let newId = elements.id(/^melanie-(.*)$/); | ||
|
||
update(args, postcondition) { | ||
runTask(() => setProperties(this.context, args)); | ||
postcondition(); | ||
this.assertStableRerender(); | ||
} | ||
this.assert.strictEqual( | ||
id, | ||
newId, | ||
`the unique-id part of a concatenated attribute shouldn't change just because a dynamic part of it changed` | ||
); | ||
}); | ||
} | ||
|
||
asElement(node, tag) { | ||
this.assert.ok(node !== null && node.nodeType === 1); | ||
render(template, ...rest) { | ||
// If there are three parameters to `render`, the second parameter is the | ||
// template's arguments. | ||
let args = rest.length === 2 ? rest[0] : {}; | ||
// If there are two parameters to `render`, the second parameter is the | ||
// postcondition. Otherwise, the third parameter is the postcondition. | ||
let postcondition = rest.length === 2 ? rest[1] : rest[0]; | ||
|
||
super.render(template, args); | ||
let result = postcondition(); | ||
this.assertStableRerender(); | ||
return result; | ||
} | ||
|
||
if (tag) { | ||
this.assert.strictEqual(node.tagName.toLowerCase(), tag, `Element is <${tag}>`); | ||
update(args, postcondition) { | ||
runTask(() => setProperties(this.context, args)); | ||
postcondition(); | ||
this.assertStableRerender(); | ||
} | ||
|
||
return node; | ||
} | ||
asElement(node, tag) { | ||
this.assert.ok(node !== null && node.nodeType === 1); | ||
|
||
asTextNode(node) { | ||
this.assert.ok(node !== null && node.nodeType === 3); | ||
return node; | ||
} | ||
if (tag) { | ||
this.assert.strictEqual(node.tagName.toLowerCase(), tag, `Element is <${tag}>`); | ||
} | ||
|
||
asTextContent(node) { | ||
let data = this.asTextNode(node).data; | ||
this.assert.ok(data.trim().length > 0, `The text node has content`); | ||
return data; | ||
return node; | ||
} | ||
|
||
asTextNode(node) { | ||
this.assert.ok(node !== null && node.nodeType === 3); | ||
return node; | ||
} | ||
|
||
asTextContent(node) { | ||
let data = this.asTextNode(node).data; | ||
this.assert.ok(data.trim().length > 0, `The text node has content`); | ||
return data; | ||
} | ||
} | ||
} | ||
); | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters