Skip to content

Commit

Permalink
Perform dom-bind work in attached/detached. Add tests.
Browse files Browse the repository at this point in the history
Fixes #1515.
  • Loading branch information
kevinpschaaf committed May 22, 2015
1 parent a640b7e commit e28307d
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 7 deletions.
36 changes: 30 additions & 6 deletions src/lib/template/dom-bind.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,41 @@
},

_finishDistribute: function() {
this._children = Array.prototype.slice.call(this.root.childNodes);
this._insertChildren();
},

_insertChildren: function() {
var parentDom = Polymer.dom(Polymer.dom(this).parentNode);
parentDom.insertBefore(this.root, this);
},

_removeChildren: function() {
for (var i=0; i<this._children.length; i++) {
this.root.appendChild(this._children[i]);
}
},

_initFeatures: function() {
this._template = this;
this._prepAnnotations();
this._prepEffects();
this._prepBehaviors();
this._prepBindings();
Polymer.Base._initFeatures.call(this);
// Ensure attached runs
this._readied = true;
},

attached: function() {
if (!this._children) {
this._template = this;
this._prepAnnotations();
this._prepEffects();
this._prepBehaviors();
this._prepBindings();
Polymer.Base._initFeatures.call(this);
} else {
this._insertChildren();
}
},

detached: function() {
this._removeChildren();
}

});
Expand Down
3 changes: 2 additions & 1 deletion test/runner.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
'unit/custom-style.html',
'unit/dynamic-import.html',
'unit/dom-repeat.html',
'unit/dom-if.html'
'unit/dom-if.html',
'unit/dom-bind.html'
]);
</script>
</body>
Expand Down
241 changes: 241 additions & 0 deletions test/unit/dom-bind.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
<!doctype html>
<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<meta charset="utf-8">
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../../web-component-tester/browser.js"></script>
<link rel="import" href="../../polymer.html">
</head>
<body>

<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-basic',
properties: {
notifyingvalue: {
notify: true
}
}
});
});
</script>

<template is="dom-bind" id="decDomBind">
<x-basic id="decEl1" value="{{value}}" notifyingvalue="{{nvalue}}" on-custom="handleEvent" computed="{{compute(dep)}}"></x-basic>
<x-basic id="decEl2" value="{{value}}" notifyingvalue="{{nvalue}}"></x-basic>
</template>

<div id="container">
</div>

<script>

suite('declarative dom-bind', function() {

var domBind;
var el1;
var el2;

setup(function() {
domBind = decDomBind;
el1 = decEl1;
el2 = decEl2;
});

test('value binds top-down', function() {
domBind.value = 'foo';
assert.equal(el1.value, 'foo');
assert.equal(el2.value, 'foo');
});

test('notifyingvalue binds from child to child', function() {
el1.notifyingvalue = 'bar';
assert.equal(domBind.nvalue, 'bar');
assert.equal(el2.notifyingvalue, 'bar');
});

test('event listener fires', function() {
var count = 0;
domBind.handleEvent = function() {
count++;
};
el1.fire('custom');
assert.equal(count, 1);
});

test('inline function runs', function() {
domBind.compute = function(val) {
return val * 10;
};
domBind.dep = 5;
assert.equal(el1.computed, 50);
});

});

suite('imperative dom-bind', function() {

var domBind;
var el1;
var el2;

setup(function() {
domBind = document.createElement('template', 'dom-bind');
var doc = domBind.content.ownerDocument;
el1 = doc.createElement('x-basic');
el1.setAttribute('id', 'impEl1');
el1.setAttribute('value', '{{value}}');
el1.setAttribute('notifyingvalue', '{{nvalue}}');
el1.setAttribute('on-custom', 'handleEvent');
el1.setAttribute('computed', '{{compute(dep)}}');
el2 = doc.createElement('x-basic');
el2.setAttribute('id', 'impEl2');
el2.setAttribute('value', '{{value}}');
el2.setAttribute('notifyingvalue', '{{nvalue}}');
domBind.content.appendChild(el1);
domBind.content.appendChild(el2);
document.body.appendChild(domBind);
CustomElements.takeRecords();
el1 = domBind.$.impEl1;
el2 = domBind.$.impEl2;
});

teardown(function() {
if (domBind.parentElement) {
domBind.parentElement.removeChild(domBind);
}
});

test('value binds top-down', function() {
domBind.value = 'foo';
assert.equal(el1.value, 'foo');
assert.equal(el2.value, 'foo');
});

test('notifyingvalue binds from child to child', function() {
el1.notifyingvalue = 'bar';
assert.equal(domBind.nvalue, 'bar');
assert.equal(el2.notifyingvalue, 'bar');
});

test('event listener fires', function() {
var count = 0;
domBind.handleEvent = function() {
count++;
};
el1.fire('custom');
assert.equal(count, 1);
});

test('inline function runs', function() {
domBind.compute = function(val) {
return val * 10;
};
domBind.dep = 5;
assert.equal(el1.computed, 50);
});

test('move dom-bind', function() {
domBind.parentElement.removeChild(domBind);
// TODO(kschaaf): detached/attached not called if takeRecords isn't
// called between remove & insert on polyfill... seems bad?
CustomElements.takeRecords();
container.appendChild(domBind);
CustomElements.takeRecords();
assert.equal(container.firstElementChild, el1);
assert.equal(container.firstElementChild.nextElementSibling, el2);
});

test('remove dom-bind', function() {
domBind.parentElement.removeChild(domBind);
CustomElements.takeRecords();
assert(!document.contains(el1));
assert(!document.contains(el2));
});

});

suite('innerHTML dom-bind', function() {

var domBind;
var el1;
var el2;

setup(function() {
domBind = document.createElement('template', 'dom-bind');
domBind.innerHTML =
'<x-basic id="impEl1" value="{{value}}" notifyingvalue="{{nvalue}}" on-custom="handleEvent" computed="{{compute(dep)}}"></x-basic>' +
'<x-basic id="impEl2" value="{{value}}" notifyingvalue="{{nvalue}}"></x-basic>';
document.body.appendChild(domBind);
CustomElements.takeRecords();
el1 = domBind.$.impEl1;
el2 = domBind.$.impEl2;
});

teardown(function() {
if (domBind.parentElement) {
domBind.parentElement.removeChild(domBind);
}
});

test('value binds top-down', function() {
domBind.value = 'foo';
assert.equal(el1.value, 'foo');
assert.equal(el2.value, 'foo');
});

test('notifyingvalue binds from child to child', function() {
el1.notifyingvalue = 'bar';
assert.equal(domBind.nvalue, 'bar');
assert.equal(el2.notifyingvalue, 'bar');
});

test('event listener fires', function() {
var count = 0;
domBind.handleEvent = function() {
count++;
};
el1.fire('custom');
assert.equal(count, 1);
});

test('inline function runs', function() {
domBind.compute = function(val) {
return val * 10;
};
domBind.dep = 5;
assert.equal(el1.computed, 50);
});

test('move dom-bind', function() {
domBind.parentElement.removeChild(domBind);
CustomElements.takeRecords();
container.appendChild(domBind);
CustomElements.takeRecords();
assert.equal(container.firstElementChild, el1);
assert.equal(container.firstElementChild.nextElementSibling, el2);
});

test('remove dom-bind', function() {
domBind.parentElement.removeChild(domBind);
CustomElements.takeRecords();
assert(!document.contains(el1));
assert(!document.contains(el2));
});

});

</script>

</body>
</html>

0 comments on commit e28307d

Please sign in to comment.