Index: dart/pkg/template_binding/test/template_binding_test.dart |
=================================================================== |
--- dart/pkg/template_binding/test/template_binding_test.dart (revision 37358) |
+++ dart/pkg/template_binding/test/template_binding_test.dart (working copy) |
@@ -6,6 +6,7 @@ |
import 'dart:async'; |
import 'dart:html'; |
+import 'dart:js' show JsObject; |
import 'dart:math' as math; |
import 'package:observe/observe.dart'; |
import 'package:template_binding/template_binding.dart'; |
@@ -16,8 +17,7 @@ |
import 'binding_syntax.dart' show syntaxTests; |
import 'utils.dart'; |
-// Note: this file ported from |
-// https://github.com/Polymer/TemplateBinding/blob/fcb7a502794f19544f2d4b77c96eebb70830591d/tests/tests.js |
+// Note: this file ported from TemplateBinding's tests/tests.js |
// TODO(jmesserly): submit a small cleanup patch to original. I fixed some |
// cases where "div" and "t" were unintentionally using the JS global scope; |
@@ -38,6 +38,7 @@ |
tearDown(() { |
testDiv.remove(); |
+ clearAllTemplates(testDiv); |
testDiv = null; |
}); |
@@ -79,7 +80,13 @@ |
templateInstantiationTests() { |
// Dart note: renamed some of these tests to have unique names |
- test('Bind (simple)', () { |
+ test('accessing bindingDelegate getter without Bind', () { |
+ var div = createTestHtml('<template>'); |
+ var template = div.firstChild; |
+ expect(templateBind(template).bindingDelegate, null); |
+ }); |
+ |
+ test('Bind - simple', () { |
var div = createTestHtml('<template bind={{}}>text</template>'); |
templateBind(div.firstChild).model = {}; |
return new Future(() { |
@@ -132,8 +139,8 @@ |
var template = div.firstChild; |
var doc = document.implementation.createHtmlDocument(''); |
doc.adoptNode(div); |
- recursivelySetTemplateModel(template, {}); |
- return new Future(() => expect(div.nodes.length, 1)); |
+ templateBind(template).model = {}; |
+ return new Future(() => expect(div.nodes.length, 2)); |
}); |
test('Empty Bind', () { |
@@ -356,8 +363,9 @@ |
test('Bind If, 2', () { |
var div = createTestHtml( |
'<template bind="{{ foo }}" if="{{ bar }}">{{ bat }}</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ 'bar': null, 'foo': { 'bat': 'baz' } }); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes.length, 1); |
@@ -391,12 +399,13 @@ |
test('Empty-If', () { |
var div = createTestHtml('<template if>{{ value }}</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ 'value': 'foo' }); |
- recursivelySetTemplateModel(div, null); |
+ templateBind(template).model = null; |
return new Future(() { |
expect(div.nodes.length, 1); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
}).then(endOfMicrotask).then((_) { |
expect(div.nodes.length, 2); |
expect(div.lastChild.text, 'foo'); |
@@ -405,8 +414,9 @@ |
test('OneTime - simple text', () { |
var div = createTestHtml('<template bind>[[ value ]]</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ 'value': 'foo' }); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes.length, 2); |
expect(div.lastChild.text, 'foo'); |
@@ -422,8 +432,9 @@ |
test('OneTime - compound text', () { |
var div = createTestHtml( |
'<template bind>[[ foo ]] bar [[ baz ]]</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ 'foo': 'FOO', 'baz': 'BAZ' }); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes.length, 2); |
expect(div.lastChild.text, 'FOO bar BAZ'); |
@@ -441,8 +452,9 @@ |
test('OneTime/Dynamic Mixed - compound text', () { |
var div = createTestHtml( |
'<template bind>[[ foo ]] bar {{ baz }}</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ 'foo': 'FOO', 'baz': 'BAZ' }); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes.length, 2); |
expect(div.lastChild.text, 'FOO bar BAZ'); |
@@ -460,8 +472,9 @@ |
test('OneTime - simple attribute', () { |
var div = createTestHtml( |
'<template bind><div foo="[[ value ]]"></div></template>'); |
+ var template = div.firstChild; |
var m = toObservable({ 'value': 'foo' }); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes.length, 2); |
expect(div.lastChild.attributes['foo'], 'foo'); |
@@ -480,8 +493,9 @@ |
'<template bind>' |
'<div foo="[[ value ]]:[[ otherValue ]]"></div>' |
'</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ 'value': 'foo', 'otherValue': 'bar' }); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes.length, 2); |
expect(div.lastChild.attributes['foo'], 'foo:bar'); |
@@ -500,8 +514,9 @@ |
'<template bind>' |
'<div foo="{{ value }}:[[ otherValue ]]"></div>' |
'</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ 'value': 'foo', 'otherValue': 'bar' }); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes.length, 2); |
expect(div.lastChild.attributes['foo'], 'foo:bar'); |
@@ -692,8 +707,9 @@ |
test('TextTemplateWithNullStringBinding', () { |
var div = createTestHtml('<template bind={{}}>a{{b}}c</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'b': 'B'}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 2); |
@@ -747,8 +763,9 @@ |
test('TextTemplateWithBindingAndConditional', () { |
var div = createTestHtml( |
'<template bind="{{}}" if="{{ d }}">a{{b}}c</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'b': 'B', 'd': 1}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 2); |
@@ -778,8 +795,9 @@ |
var div = createTestHtml( |
'<template bind="{{ b }}">a{{value}}c</template>'); |
expect(div.nodes.length, 1); |
+ var template = div.firstChild; |
var model = toObservable({'b': {'value': 'B'}}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 2); |
@@ -796,8 +814,9 @@ |
'<template bind="{{}}">' |
'<div foo="a{{b}}c"></div>' |
'</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'b': 'B'}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 2); |
@@ -818,8 +837,9 @@ |
'<template bind="{{}}">' |
'<div foo?="{{b}}"></div>' |
'</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'b': 'b'}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 2); |
@@ -915,8 +935,8 @@ |
{'val': 8}, |
{'val': 1} |
]); |
- recursivelySetTemplateModel(div, model); |
var template = div.firstChild; |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 6); |
@@ -929,7 +949,7 @@ |
checkExpandos(template.nextNode); |
model = toObservable(model.reversed); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
}).then(endOfMicrotask).then((_) { |
checkExpandos(template.nextNode); |
@@ -950,9 +970,9 @@ |
var div = createTestHtml( |
'<template bind="{{ foo }}">{{ bar }}</template>'); |
+ var template = div.firstChild; |
var model = toObservable({ 'foo': { 'bar': 5 }}); |
- recursivelySetTemplateModel(div, model); |
- var template = div.firstChild; |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 2); |
@@ -961,7 +981,7 @@ |
checkExpandos(template.nextNode); |
model = toObservable({'foo': model['foo']}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
}).then(endOfMicrotask).then((_) { |
checkExpandos(template.nextNode); |
}); |
@@ -971,8 +991,9 @@ |
var div = createTestHtml( |
'<template repeat>text</template>'); |
+ var template = div.firstChild; |
var model = toObservable([0, 1, 2]); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 4); |
@@ -994,9 +1015,10 @@ |
test('Removal from iteration needs to unbind', () { |
var div = createTestHtml( |
'<template repeat="{{}}"><a>{{v}}</a></template>'); |
+ var template = div.firstChild; |
var model = toObservable([{'v': 0}, {'v': 1}, {'v': 2}, {'v': 3}, |
{'v': 4}]); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
var nodes, vs; |
return new Future(() { |
@@ -1023,11 +1045,39 @@ |
}); |
}); |
+ test('Template.clear', () { |
+ var div = createTestHtml( |
+ '<template repeat>{{}}</template>'); |
+ var template = div.firstChild; |
+ templateBind(template).model = [0, 1, 2]; |
+ |
+ return new Future(() { |
+ expect(div.nodes.length, 4); |
+ expect(div.nodes[1].text, '0'); |
+ expect(div.nodes[2].text, '1'); |
+ expect(div.nodes[3].text, '2'); |
+ |
+ // clear() synchronously removes instances and clears the model. |
+ templateBind(div.firstChild).clear(); |
+ expect(div.nodes.length, 1); |
+ expect(templateBind(template).model, null); |
+ |
+ // test that template still works if new model assigned |
+ templateBind(template).model = [3, 4]; |
+ |
+ }).then(endOfMicrotask).then((_) { |
+ expect(div.nodes.length, 3); |
+ expect(div.nodes[1].text, '3'); |
+ expect(div.nodes[2].text, '4'); |
+ }); |
+ }); |
+ |
test('DOM Stability on Iteration', () { |
var div = createTestHtml( |
'<template repeat="{{}}">{{}}</template>'); |
+ var template = div.firstChild; |
var model = toObservable([1, 2, 3, 4, 5]); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
var nodes; |
return new Future(() { |
@@ -1078,12 +1128,13 @@ |
'<template repeat="{{}}">{{value}}</template>'); |
expect(div.nodes.length, 1); |
+ var template = div.firstChild; |
var model = toObservable([ |
{'value': 0}, |
{'value': 1}, |
{'value': 2} |
]); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 4); |
@@ -1112,8 +1163,9 @@ |
'<template bind="{{}}">' |
'<input value="{{x}}">' |
'</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'x': 'hi'}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 2); |
@@ -1141,19 +1193,20 @@ |
'</template>' |
'<template bind="{{ XY }}" id="t2" ref="t1"></template>'); |
+ var t1 = document.getElementById('t1'); |
+ var t2 = document.getElementById('t2'); |
var model = toObservable({ |
'XX': {'name': 'Leela', 'title': 'Captain'}, |
'XY': {'name': 'Fry', 'title': 'Delivery boy'}, |
'XZ': {'name': 'Zoidberg', 'title': 'Doctor'} |
}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(t1).model = model; |
+ templateBind(t2).model = model; |
return new Future(() { |
- var t1 = document.getElementById('t1'); |
var instance = t1.nextElementSibling; |
expect(instance.text, 'Crew member: Leela, Job title: Captain'); |
- var t2 = document.getElementById('t2'); |
instance = t2.nextElementSibling; |
expect(instance.text, 'Crew member: Fry, Job title: Delivery boy'); |
@@ -1178,8 +1231,9 @@ |
test('Bind', () { |
var div = createTestHtml('<template bind="{{}}">Hi {{ name }}</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'name': 'Leela'}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() => expect(div.nodes[1].text, 'Hi Leela')); |
}); |
@@ -1187,8 +1241,9 @@ |
test('BindPlaceHolderHasNewLine', () { |
var div = createTestHtml( |
'<template bind="{{}}">Hi {{\nname\n}}</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'name': 'Leela'}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() => expect(div.nodes[1].text, 'Hi Leela')); |
}); |
@@ -1204,23 +1259,58 @@ |
var t1 = div.nodes.first; |
var t2 = div.nodes[1]; |
- expect(templateBind(t2).ref, t1); |
- |
var model = toObservable({'name': 'Fry'}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(t1).model = model; |
+ templateBind(t2).model = model; |
return new Future(() => expect(t2.nextNode.text, 'Hi Fry')); |
}); |
+ test('Ref at multiple', () { |
+ // Note: this test is asserting that template "ref"erences can be located |
+ // at various points. In particular: |
+ // -in the document (at large) (e.g. ref=doc) |
+ // -within template content referenced from sub-content |
+ // -both before and after the reference |
+ // The following asserts ensure that all referenced templates content is |
+ // found. |
+ var div = createTestHtml( |
+ '<template bind>' |
+ '<template bind ref=doc></template>' |
+ '<template id=elRoot>EL_ROOT</template>' |
+ '<template bind>' |
+ '<template bind ref=elRoot></template>' |
+ '<template bind>' |
+ '<template bind ref=subA></template>' |
+ '<template id=subB>SUB_B</template>' |
+ '<template bind>' |
+ '<template bind ref=subB></template>' |
+ '</template>' |
+ '</template>' |
+ '<template id=subA>SUB_A</template>' |
+ '</template>' |
+ '</template>' |
+ '<template id=doc>DOC</template>'); |
+ var t = div.firstChild; |
+ var fragment = templateBind(t).createInstance({}); |
+ expect(fragment.nodes.length, 14); |
+ expect(fragment.nodes[1].text, 'DOC'); |
+ expect(fragment.nodes[5].text, 'EL_ROOT'); |
+ expect(fragment.nodes[8].text, 'SUB_A'); |
+ expect(fragment.nodes[12].text, 'SUB_B'); |
+ div.append(fragment); |
+ }); |
test('Update Ref', () { |
+ // Updating ref by observing the attribute is dependent on MutationObserver |
var div = createTestHtml( |
'<template id=A>Hi, {{}}</template>' |
'<template id=B>Hola, {{}}</template>' |
'<template ref=A repeat></template>'); |
+ var template = div.nodes[2]; |
var model = new ObservableList.from(['Fry']); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 4); |
@@ -1229,10 +1319,35 @@ |
div.nodes[2].attributes['ref'] = 'B'; |
model.add('Leela'); |
+ }).then(nextMicrotask).then((x) { |
+ expect(div.nodes.length, 5); |
+ |
+ expect('Hola, Fry', div.nodes[3].text); |
+ expect('Hola, Leela', div.nodes[4].text); |
+ }); |
+ }); |
+ |
+ test('Bound Ref', () { |
+ var div = createTestHtml( |
+ '<template id=A>Hi, {{}}</template>' |
+ '<template id=B>Hola, {{}}</template>' |
+ '<template ref="{{ ref }}" repeat="{{ people }}"></template>'); |
+ |
+ var template = div.nodes[2]; |
+ var model = toObservable({'ref': 'A', 'people': ['Fry']}); |
+ templateBind(template).model = model; |
+ |
+ return new Future(() { |
+ expect(div.nodes.length, 4); |
+ expect('Hi, Fry', div.nodes[3].text); |
+ |
+ model['ref'] = 'B'; |
+ model['people'].add('Leela'); |
+ |
}).then(endOfMicrotask).then((x) { |
expect(div.nodes.length, 5); |
- expect('Hi, Fry', div.nodes[3].text); |
+ expect('Hola, Fry', div.nodes[3].text); |
expect('Hola, Leela', div.nodes[4].text); |
}); |
}); |
@@ -1248,7 +1363,8 @@ |
var t1 = div.firstChild; |
var t2 = div.nodes[1]; |
var model = toObservable({'name': 'Fry', 'id': id }); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(t1).model = model; |
+ templateBind(t2).model = model; |
return new Future(() => expect(t2.nextNode.text, 'Hi Fry')); |
}); |
@@ -1276,7 +1392,7 @@ |
] |
}); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(t).model = m; |
return new Future(() { |
assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); |
@@ -1320,6 +1436,7 @@ |
'<template repeat="{{ contacts }}">' |
'Hi {{ name }}' |
'</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ |
'contacts': [ |
{'name': 'Raf'}, |
@@ -1327,9 +1444,8 @@ |
{'name': 'Neal'} |
] |
}); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
- var t = div.nodes.first; |
assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); |
}); |
}); |
@@ -1344,7 +1460,7 @@ |
{'name': 'Arv'}, |
{'name': 'Neal'} |
]); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(t).model = m; |
return new Future(() { |
assertNodesAre(div, ['Hi Raf', 'Hi Arv', 'Hi Neal']); |
@@ -1383,13 +1499,13 @@ |
var t = div.nodes.first; |
var m = null; |
- recursivelySetTemplateModel(div, m); |
+ templateBind(t).model = m; |
expect(div.nodes.length, 1); |
t.attributes['iterate'] = ''; |
m = toObservable({}); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(t).model = m; |
return new Future(() => expect(div.nodes.length, 1)); |
}); |
@@ -1403,7 +1519,7 @@ |
{'name': 'Arv'}, |
{'name': 'Neal'} |
]); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(t).model = m; |
var node1, node2, node3; |
return new Future(() { |
@@ -1432,9 +1548,9 @@ |
test('TwoLevelsDeepBug', () { |
var div = createTestHtml( |
'<template bind="{{}}"><span><span>{{ foo }}</span></span></template>'); |
- |
+ var template = div.firstChild; |
var model = toObservable({'foo': 'bar'}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes[1].nodes[0].nodes[0].text, 'bar'); |
}); |
@@ -1486,6 +1602,8 @@ |
m['a']['c'] = toObservable({'d': 22}); |
}).then(endOfMicrotask).then((_) { |
expect(div.nodes[start + 2].text, '22'); |
+ |
+ //clearAllTemplates(div); |
}); |
} |
@@ -1626,6 +1744,8 @@ |
'<template ref="t" repeat="{{items}}"></template>' |
'</template>'); |
+ var template = div.firstChild; |
+ |
var m = toObservable([ |
{ |
'name': 'Item 1', |
@@ -1650,7 +1770,7 @@ |
}, |
]); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
int i = 1; |
return new Future(() { |
@@ -1686,6 +1806,7 @@ |
'</select>' |
'</template>'); |
+ var template = div.firstChild; |
var m = toObservable({ |
'selected': 1, |
'groups': [{ |
@@ -1693,7 +1814,7 @@ |
}], |
}); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
var completer = new Completer(); |
@@ -1709,9 +1830,6 @@ |
'after template expands.'); |
expect(select.nodes[0].tagName, 'TEMPLATE'); |
- expect((templateBind(templateBind(select.nodes[0]).ref) |
- .content.nodes[0] as Element).tagName, 'OPTGROUP'); |
- |
var optgroup = select.nodes[1]; |
expect(optgroup.nodes[0].tagName, 'TEMPLATE'); |
expect(optgroup.nodes[1].tagName, 'OPTION'); |
@@ -1739,13 +1857,14 @@ |
'</tr>' |
'</template>' |
'</tbody></table>'); |
+ var template = div.firstChild.firstChild.firstChild; |
var m = toObservable([ |
[{ 'val': 0 }, { 'val': 1 }], |
[{ 'val': 2 }, { 'val': 3 }] |
]); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
var tbody = div.nodes[0].nodes[0]; |
@@ -1776,13 +1895,14 @@ |
'<td template repeat="{{}}" class="{{ val }}">{{ val }}</td>' |
'</tr>' |
'</tbody></table>'); |
+ var template = div.firstChild.firstChild.firstChild; |
var m = toObservable([ |
[{ 'val': 0 }, { 'val': 1 }], |
[{ 'val': 2 }, { 'val': 3 }] |
]); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
var i = 1; |
@@ -1813,7 +1933,7 @@ |
'<template repeat="{{}}" id=t1>' |
'<li>{{name}}' |
'<ul>' |
- '<template ref=t1 repaet="{{items}}"></template>' |
+ '<template ref=t1 repeat="{{items}}"></template>' |
'</ul>' |
'</li>' |
'</template>' |
@@ -1829,9 +1949,21 @@ |
] |
} |
]); |
+ var ul = div.firstChild; |
+ var t = ul.firstChild; |
- recursivelySetTemplateModel(div, m); |
- return new Future(() => m.removeAt(0)); |
+ templateBind(t).model = m; |
+ return new Future(() { |
+ expect(ul.nodes.length, 2); |
+ var ul2 = ul.nodes[1].nodes[1]; |
+ expect(ul2.nodes.length, 2); |
+ var ul3 = ul2.nodes[1].nodes[1]; |
+ expect(ul3.nodes.length, 1); |
+ |
+ m.removeAt(0); |
+ }).then(endOfMicrotask).then((_) { |
+ expect(ul.nodes.length, 1); |
+ }); |
}); |
test('DeepNested', () { |
@@ -1843,7 +1975,7 @@ |
'</template>' |
'</p>' |
'</template>'); |
- |
+ var template = div.firstChild; |
var m = toObservable({ |
'a': { |
'b': { |
@@ -1851,7 +1983,7 @@ |
} |
} |
}); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes[1].tagName, 'P'); |
expect(div.nodes[1].nodes.first.tagName, 'TEMPLATE'); |
@@ -1861,9 +1993,10 @@ |
test('TemplateContentRemoved', () { |
var div = createTestHtml('<template bind="{{}}">{{ }}</template>'); |
+ var template = div.firstChild; |
var model = 42; |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes[1].text, '42'); |
expect(div.nodes[0].text, ''); |
@@ -1872,9 +2005,8 @@ |
test('TemplateContentRemovedEmptyArray', () { |
var div = createTestHtml('<template iterate>Remove me</template>'); |
- var model = toObservable([]); |
- |
- recursivelySetTemplateModel(div, model); |
+ var template = div.firstChild; |
+ templateBind(template).model = []; |
return new Future(() { |
expect(div.nodes.length, 1); |
expect(div.nodes[0].text, ''); |
@@ -1889,12 +2021,12 @@ |
'{{ b }}' |
'</template>' |
'</template>'); |
- |
+ var template = div.firstChild; |
var model = toObservable({ |
'a': 1, |
'b': 2 |
}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes[0].text, ''); |
expect(div.nodes[1].text, '1'); |
@@ -1906,19 +2038,20 @@ |
test('BindWithUndefinedModel', () { |
var div = createTestHtml( |
'<template bind="{{}}" if="{{}}">{{ a }}</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'a': 42}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes[1].text, '42'); |
model = null; |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
}).then(endOfMicrotask).then((_) { |
expect(div.nodes.length, 1); |
model = toObservable({'a': 42}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
}).then(endOfMicrotask).then((_) { |
expect(div.nodes[1].text, '42'); |
}); |
@@ -1935,25 +2068,28 @@ |
'Child: {{ name }}' |
'</template>' |
'</template>'); |
- |
+ var template = div.firstChild; |
var m = toObservable({ |
'name': 'Hermes', |
'wife': { |
'name': 'LaBarbara' |
} |
}); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
+ |
return new Future(() { |
expect(div.nodes.length, 5); |
expect(div.nodes[1].text, 'Name: Hermes'); |
expect(div.nodes[3].text, 'Wife: LaBarbara'); |
m['child'] = toObservable({'name': 'Dwight'}); |
+ |
}).then(endOfMicrotask).then((_) { |
expect(div.nodes.length, 6); |
expect(div.nodes[5].text, 'Child: Dwight'); |
m.remove('wife'); |
+ |
}).then(endOfMicrotask).then((_) { |
expect(div.nodes.length, 5); |
expect(div.nodes[4].text, 'Child: Dwight'); |
@@ -1966,14 +2102,14 @@ |
'Name: {{ name }}' |
'<template bind="{{friend}}" if="{{friend}}" ref="t"></template>' |
'</template>'); |
- |
+ var template = div.firstChild; |
var m = toObservable({ |
'name': 'Fry', |
'friend': { |
'name': 'Bender' |
} |
}); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
expect(div.nodes.length, 5); |
expect(div.nodes[1].text, 'Name: Fry'); |
@@ -1996,13 +2132,14 @@ |
'<template repeat>{{ foo }}' |
'<template bind></template>' |
'</template>'); |
+ var template = div.firstChild; |
var m = toObservable([{ 'foo': 'bar' }]); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
return new Future(() { |
m.add(toObservable({ 'foo': 'baz' })); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
}).then(endOfMicrotask).then((_) { |
expect(div.nodes.length, 5); |
@@ -2015,9 +2152,10 @@ |
if (!MutationObserver.supported) return null; |
var div = createTestHtml('<template repeat>{{ foo }}</template>'); |
+ var template = div.firstChild; |
var m = toObservable([{ 'foo': 'bar' }, { 'foo': 'bat'}]); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(template).model = m; |
var observer = new MutationObserver((x, y) {}); |
return new Future(() { |
observer.observe(div, childList: true); |
@@ -2038,13 +2176,35 @@ |
'</template>'); |
var m = toObservable({'foo': 'bar'}); |
- recursivelySetTemplateModel(div, m); |
+ templateBind(div.firstChild).model = m; |
return new Future(() { |
expect(div.nodes.length, 4); |
expect(div.nodes[3].text, 'bar'); |
}); |
}); |
+ test('baseURI', () { |
+ // TODO(jmesserly): Dart's setInnerHtml breaks this test -- the template |
+ // URL is created as blank despite the NullTreeSanitizer. |
+ // Use JS interop as a workaround. |
+ //var div = createTestHtml('<template bind>' |
+ // '<div style="background: url(foo.jpg)"></div></template>'); |
+ var div = new DivElement(); |
+ new JsObject.fromBrowserObject(div)['innerHTML'] = '<template bind>' |
+ '<div style="background: url(foo.jpg)"></div></template>'; |
+ testDiv.append(div); |
+ TemplateBindExtension.decorate(div.firstChild); |
+ |
+ var local = document.createElement('div'); |
+ local.attributes['style'] = 'background: url(foo.jpg)'; |
+ div.append(local); |
+ var template = div.firstChild; |
+ templateBind(template).model = {}; |
+ return new Future(() { |
+ expect(div.nodes[1].style.backgroundImage, local.style.backgroundImage); |
+ }); |
+ }); |
+ |
test('ChangeRefId', () { |
var div = createTestHtml( |
'<template id="a">a:{{ }}</template>' |
@@ -2052,8 +2212,9 @@ |
'<template repeat="{{}}">' |
'<template ref="a" bind="{{}}"></template>' |
'</template>'); |
+ var template = div.nodes[2]; |
var model = toObservable([]); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.nodes.length, 3); |
@@ -2118,7 +2279,7 @@ |
var root = createShadowTestHtml( |
'<template bind="{{}}">Hi {{ name }}</template>'); |
var model = toObservable({'name': 'Leela'}); |
- recursivelySetTemplateModel(root, model); |
+ templateBind(root.firstChild).model = model; |
return new Future(() => expect(root.nodes[1].text, 'Hi Leela')); |
}); |
@@ -2144,8 +2305,12 @@ |
if (!ShadowRoot.supported) return null; |
var root = createShadowTestHtml( |
'<template id=foo>Hi</template><template bind ref=foo></template>'); |
- recursivelySetTemplateModel(root, toObservable({})); |
- return new Future(() => expect(root.nodes.length, 3)); |
+ var template = root.nodes[1]; |
+ templateBind(template).model = toObservable({}); |
+ return new Future(() { |
+ expect(root.nodes.length, 3); |
+ clearAllTemplates(root); |
+ }); |
}); |
// https://github.com/Polymer/TemplateBinding/issues/8 |
@@ -2156,11 +2321,11 @@ |
'{{ age }}' |
'</template>' |
'</template>'); |
- |
+ var template = div.firstChild; |
var syntax = new UnbindingInNestedBindSyntax(); |
var model = toObservable({'outer': {'inner': {'age': 42}}}); |
- recursivelySetTemplateModel(div, model, syntax); |
+ templateBind(template)..model = model..bindingDelegate = syntax; |
return new Future(() { |
expect(syntax.count, 1); |
@@ -2185,7 +2350,8 @@ |
'<template bind="{{}} {{}}">' |
'<template bind="{{}}">Foo</template>' |
'</template>'); |
- recursivelySetTemplateModel(div, null); |
+ var template = div.firstChild; |
+ templateBind(template).model = null; |
return nextMicrotask; |
}); |
@@ -2199,15 +2365,10 @@ |
var outer = templateBind(div.nodes.first); |
var model = toObservable({'b': {'foo': 'bar'}}); |
- var host = new DivElement(); |
var instance = outer.createInstance(model, new TestBindingSyntax()); |
- expect(outer.content.nodes.first, |
- templateBind(instance.nodes.first).ref); |
+ expect(instance.firstChild.nextNode.text, 'bar:replaced'); |
- host.append(instance); |
- return new Future(() { |
- expect(host.firstChild.nextNode.text, 'bar:replaced'); |
- }); |
+ clearAllTemplates(instance); |
}); |
test('CreateInstance - sync error', () { |
@@ -2324,19 +2485,41 @@ |
}); |
}); |
+ test('Accessor value retrieval count', () { |
+ var div = createTestHtml( |
+ '<template bind>{{ prop }}</template>'); |
+ |
+ var model = new TestAccessorModel(); |
+ |
+ templateBind(div.firstChild).model = model; |
+ |
+ return new Future(() { |
+ expect(model.count, 1); |
+ |
+ model.value++; |
+ // Dart note: we don't handle getters in @observable, so we need to |
+ // notify regardless. |
+ model.notifyPropertyChange(#prop, 1, model.value); |
+ |
+ }).then(endOfMicrotask).then((_) { |
+ expect(model.count, 2); |
+ }); |
+ }); |
+ |
test('issue-141', () { |
var div = createTestHtml( |
'<template bind>' |
'<div foo="{{foo1}} {{foo2}}" bar="{{bar}}"></div>' |
'</template>'); |
+ var template = div.firstChild; |
var model = toObservable({ |
'foo1': 'foo1Value', |
'foo2': 'foo2Value', |
'bar': 'barValue' |
}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
expect(div.lastChild.attributes['bar'], 'barValue'); |
}); |
@@ -2350,9 +2533,10 @@ |
'<div class="foo: {{ bar }}"></div>' |
'</template>'); |
+ var template = div.firstChild; |
var model = toObservable({'bar': 2}); |
- recursivelySetTemplateModel(div, model, delegate); |
+ templateBind(template)..model = model..bindingDelegate = delegate; |
return new Future(() { |
expect(div.lastChild.attributes['class'], 'foo: 2'); |
@@ -2360,12 +2544,17 @@ |
}); |
test('issue-152', () { |
- var div = createTestHtml('<template ref=notThere></template>'); |
+ var div = createTestHtml( |
+ '<template ref=notThere bind>XXX</template>'); |
+ |
var template = div.firstChild; |
+ templateBind(template).model = {}; |
- // if a ref cannot be located, a template will continue to use itself |
- // as the source of template instances. |
- expect(template, templateBind(template).ref); |
+ return new Future(() { |
+ // if a ref cannot be located, a template will continue to use itself |
+ // as the source of template instances. |
+ expect(div.nodes[1].text, 'XXX'); |
+ }); |
}); |
} |
@@ -2379,6 +2568,7 @@ |
'<input type="number" _value="{{ number }}">' |
'</template>'); |
+ var template = div.firstChild; |
var model = toObservable({ |
'color': 'red', |
'url': 'pic.jpg', |
@@ -2386,7 +2576,7 @@ |
'number': 4 |
}); |
- recursivelySetTemplateModel(div, model); |
+ templateBind(template).model = model; |
return new Future(() { |
var subDiv = div.firstChild.nextNode; |
expect(subDiv.attributes['style'], 'color: red;'); |
@@ -2440,3 +2630,14 @@ |
return (model, _, oneTime) => new PathObserver(model, path); |
} |
} |
+ |
+class TestAccessorModel extends Observable { |
+ @observable var value = 1; |
+ var count = 0; |
+ |
+ @reflectable |
+ get prop { |
+ count++; |
+ return value; |
+ } |
+} |