Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep the order of scoped and scopeless nodes in polyfilled browsers. #44

Merged
merged 1 commit into from
Jan 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion imported-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@
// find only root templates
let templates = this.import instanceof Document ?
this.import.querySelectorAll("head>template,body>template,imported-template-scope>template") :
this.import.children.filter(e => e.tagName === 'TEMPLATE').concat(this.import.querySelectorAll("imported-template-scope>template"));
Array.prototype.filter.call(
this.import.querySelectorAll("template"),
(e => e.parentNode === this.import || e.parentNode.tagName === 'IMPORTED-TEMPLATE-SCOPE')
);
var fragment, template;
var singleTemplate, singleFragment, nodes;

Expand Down
3 changes: 3 additions & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
'content-legacy/no-content.html',
'content-legacy/skipping.html',
// specific imported=tempaltefeatures
// scoping
'scopes/stamp-in-order.html',
// html-imports
'html-imports_behavior/per-template_scripts.html',
'html-imports_behavior/per-import_script.html',
'use-cases/previousElementSibling/previousElementSibling.html',
Expand Down
128 changes: 128 additions & 0 deletions test/scopes/stamp-in-order.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<!doctype html>
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">

<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../../web-component-tester/browser.js"></script>

<!-- Step 1: import the element to test -->
<link rel="import" href="../../imported-template.html">
</head>

<body>

<!-- You can use the document as a place to set up your fixtures. -->
<test-fixture id="imported-template-fixture">
<template>
<!-- nest to workaround test-fixture bug -->
<div><imported-template></imported-template></div>
</template>
</test-fixture>

<script>
describe('<imported-template>', function() {
const STAMPED_FRAGMENT = `Scopeless <span>1</span>Scoped <span>1</span>Scopeless <span>2</span>Scoped <span>2</span>Scopeless <span>3</span>`;
let juicyElement, container;
context('when loads merged document with scopeless and scoped templates', function() {
beforeEach(function() {
container = fixture('imported-template-fixture');
juicyElement = container.querySelector('imported-template');
});
afterEach(function(done){
setTimeout(done, 500);
})
it('should fire `stamping` event', function(done){
let stampingEventCallback = sinon.spy();
juicyElement.addEventListener('stamping', stampingEventCallback);
juicyElement.href = './stamp-in-order.import.html';
setTimeout(function waitForLoad(){
expect(stampingEventCallback).to.be.called;
expect(stampingEventCallback).to.be.calledOnce;
done();
}, 500);
});
it('should fire `stamping` event with document fragment perserving the order in `event.detail`', function(done){
juicyElement.addEventListener('stamping', stampingEventCallback);
juicyElement.href = './stamp-in-order.import.html';
function stampingEventCallback(event){
juicyElement.removeEventListener('stamping', stampingEventCallback);

expect(event).to.have.property('detail');
expect(event.detail).to.be.instanceof(DocumentFragment);

const parsedFragment = document.createElement('div');
parsedFragment.appendChild(event.detail.cloneNode(true));
expect(parsedFragment.innerHTML).to.equal(STAMPED_FRAGMENT);
done();
}
});
context('once `stamping` event is fired', function(){
beforeEach(function(done) {
juicyElement = fixture('imported-template-fixture').querySelector('imported-template');
juicyElement.addEventListener('stamping', function(){
done();
});
juicyElement.href = './stamp-in-order.import.html';
});
it('`element.stampedNodes` as an array of all stamped nodes in perserved order', function(){
expect(juicyElement.stampedNodes).to.be.an('array');
expect(juicyElement.stampedNodes).to.have.lengthOf(10);
expect(juicyElement.stampedNodes[0].textContent).to.equal('Scopeless ');
expect(juicyElement.stampedNodes[1].textContent).to.equal('1');
expect(juicyElement.stampedNodes[2].textContent).to.equal('Scoped ');
expect(juicyElement.stampedNodes[3].textContent).to.equal('1');
expect(juicyElement.stampedNodes[4].textContent).to.equal('Scopeless ');
expect(juicyElement.stampedNodes[5].textContent).to.equal('2');
expect(juicyElement.stampedNodes[6].textContent).to.equal('Scoped ');
expect(juicyElement.stampedNodes[7].textContent).to.equal('2');
expect(juicyElement.stampedNodes[8].textContent).to.equal('Scopeless ');
expect(juicyElement.stampedNodes[9].textContent).to.equal('3');
});
it('should fire `stamping` event with set `element.scopedNodes` as an array of stamped, scoped nodes in perserved order', function(){
expect(juicyElement.scopedNodes).to.be.an('array').that.have.lengthOf(2);

expect(juicyElement.scopedNodes[0]).to.be.an('array')
.that.have.lengthOf(2)
.have.property('scope', 'Vendor1')
expect(juicyElement.scopedNodes[0][0].textContent).to.equal('Scoped ');
expect(juicyElement.scopedNodes[0][1].textContent).to.equal('1');

expect(juicyElement.scopedNodes[1]).to.be.an('array')
.that.have.lengthOf(2)
.have.property('scope', 'Vendor2')
expect(juicyElement.scopedNodes[1][0].textContent).to.equal('Scoped ');
expect(juicyElement.scopedNodes[1][1].textContent).to.equal('2');

});
it('should fire `stamping` event with set `element.scopelessNodes` as an array of stamped, scopeless nodes in perserved order', function(){
expect(juicyElement.scopelessNodes).to.be.an('array');
expect(juicyElement.scopelessNodes).to.have.lengthOf(6);
expect(juicyElement.scopelessNodes[0].textContent).to.equal('Scopeless ');
expect(juicyElement.scopelessNodes[1].textContent).to.equal('1');
expect(juicyElement.scopelessNodes[2].textContent).to.equal('Scopeless ');
expect(juicyElement.scopelessNodes[3].textContent).to.equal('2');
expect(juicyElement.scopelessNodes[4].textContent).to.equal('Scopeless ');
expect(juicyElement.scopelessNodes[5].textContent).to.equal('3');

});
});
it('should stamp them in order eventually', function(done){
juicyElement.href = './stamp-in-order.import.html';
setTimeout(()=>{
// protect aginst variable order of attributes
expect(container.innerHTML.replace(/<imported-template[^>]*>/,'')).to.equal(
'</imported-template>' +
STAMPED_FRAGMENT)
done();
}, 500);
});
});
});
</script>

</body>

</html>
9 changes: 9 additions & 0 deletions test/scopes/stamp-in-order.import.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>Scopeless <span>1</span></template>
<imported-template-scope scope="Vendor1">
<template>Scoped <span>1</span></template>
</imported-template-scope>
<template>Scopeless <span>2</span></template>
<imported-template-scope scope="Vendor2">
<template>Scoped <span>2</span></template>
</imported-template-scope>
<template>Scopeless <span>3</span></template>