Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: dart/pkg/template_binding/test/custom_element_bindings_test.dart

Issue 336013003: Version 1.5.0-dev.4.14 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library template_binding.test.custom_element_bindings_test; 5 library template_binding.test.custom_element_bindings_test;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:html'; 8 import 'dart:html';
9 import 'dart:collection' show MapView; 9 import 'dart:collection' show MapView;
10 import 'package:template_binding/template_binding.dart'; 10 import 'package:template_binding/template_binding.dart';
11 import 'package:observe/observe.dart'; 11 import 'package:observe/observe.dart';
12 import 'package:unittest/html_config.dart'; 12 import 'package:unittest/html_config.dart';
13 import 'package:unittest/unittest.dart'; 13 import 'package:unittest/unittest.dart';
14 import 'package:web_components/polyfill.dart'; 14 import 'package:web_components/polyfill.dart';
15 import 'utils.dart'; 15 import 'utils.dart';
16 16
17 Future _registered; 17 Future _registered;
18 18
19 main() => dirtyCheckZone().run(() { 19 main() => dirtyCheckZone().run(() {
20 useHtmlConfiguration(); 20 useHtmlConfiguration();
21 21
22 _registered = customElementsReady.then((_) { 22 _registered = customElementsReady.then((_) {
23 document.register('my-custom-element', MyCustomElement); 23 document.registerElement('my-custom-element', MyCustomElement);
24 document.register('with-attrs-custom-element', WithAttrsCustomElement); 24 document.registerElement('with-attrs-custom-element',
25 WithAttrsCustomElement);
25 }); 26 });
26 27
27 group('Custom Element Bindings', customElementBindingsTest); 28 group('Custom Element Bindings', customElementBindingsTest);
28 }); 29 });
29 30
30 customElementBindingsTest() { 31 customElementBindingsTest() {
31 setUp(() { 32 setUp(() {
32 document.body.append(testDiv = new DivElement()); 33 document.body.append(testDiv = new DivElement());
33 return _registered; 34 return _registered;
34 }); 35 });
35 36
36 tearDown(() { 37 tearDown(() {
37 testDiv.remove(); 38 testDiv.remove();
38 testDiv = null; 39 testDiv = null;
39 }); 40 });
40 41
41 test('override bind/unbind/unbindAll', () { 42 test('override bind/bindFinished', () {
42 var element = new MyCustomElement(); 43 var element = new MyCustomElement();
43 var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)}); 44 var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});
44 45
45 nodeBind(element) 46 var pointBinding = nodeBind(element)
46 ..bind('my-point', new PathObserver(model, 'a')) 47 .bind('my-point', new PathObserver(model, 'a'));
47 ..bind('scary-monster', new PathObserver(model, 'b')); 48
49 var scaryBinding = nodeBind(element)
50 .bind('scary-monster', new PathObserver(model, 'b'));
48 51
49 expect(element.attributes, isNot(contains('my-point'))); 52 expect(element.attributes, isNot(contains('my-point')));
50 expect(element.attributes, isNot(contains('scary-monster'))); 53 expect(element.attributes, isNot(contains('scary-monster')));
51 54
52 expect(element.myPoint, model['a']); 55 expect(element.myPoint, model['a']);
53 expect(element.scaryMonster, model['b']); 56 expect(element.scaryMonster, model['b']);
54 57
55 model['a'] = null; 58 model['a'] = null;
56 return new Future(() { 59 return new Future(() {
57 expect(element.myPoint, null); 60 expect(element.myPoint, null);
58 nodeBind(element).unbind('my-point'); 61 expect(element.bindFinishedCalled, 0);
62 pointBinding.close();
59 63
60 model['a'] = new Point(1, 2); 64 model['a'] = new Point(1, 2);
61 model['b'] = new Monster(200); 65 model['b'] = new Monster(200);
62 }).then(endOfMicrotask).then((_) { 66 }).then(endOfMicrotask).then((_) {
63 expect(element.scaryMonster, model['b']); 67 expect(element.scaryMonster, model['b']);
64 expect(element.myPoint, null, reason: 'a was unbound'); 68 expect(element.myPoint, null, reason: 'a was unbound');
65 69
66 nodeBind(element).unbindAll(); 70 scaryBinding.close();
67 model['b'] = null; 71 model['b'] = null;
68 }).then(endOfMicrotask).then((_) { 72 }).then(endOfMicrotask).then((_) {
69 expect(element.scaryMonster.health, 200); 73 expect(element.scaryMonster.health, 200);
74 expect(element.bindFinishedCalled, 0);
70 }); 75 });
71 }); 76 });
72 77
73 test('override attribute setter', () { 78 test('override attribute setter', () {
74 var element = new WithAttrsCustomElement(); 79 var element = new WithAttrsCustomElement();
75 var model = toObservable({'a': 1, 'b': 2}); 80 var model = toObservable({'a': 1, 'b': 2});
76 nodeBind(element).bind('hidden?', new PathObserver(model, 'a')); 81 nodeBind(element).bind('hidden?', new PathObserver(model, 'a'));
77 nodeBind(element).bind('id', new PathObserver(model, 'b')); 82 nodeBind(element).bind('id', new PathObserver(model, 'b'));
78 83
79 expect(element.attributes, contains('hidden')); 84 expect(element.attributes, contains('hidden'));
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 122
118 var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)}); 123 var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});
119 var div = createTestHtml('<template bind>' 124 var div = createTestHtml('<template bind>'
120 '<my-custom-element my-point="{{a}}" scary-monster="{{b}}">' 125 '<my-custom-element my-point="{{a}}" scary-monster="{{b}}">'
121 '</my-custom-element>' 126 '</my-custom-element>'
122 '</template>'); 127 '</template>');
123 128
124 templateBind(div.query('template')).model = model; 129 templateBind(div.query('template')).model = model;
125 var element; 130 var element;
126 return new Future(() { 131 return new Future(() {
127 print('!!! running future');
128 element = div.nodes[1]; 132 element = div.nodes[1];
129 133
130 expect(element is MyCustomElement, true, 134 expect(element is MyCustomElement, true,
131 reason: '$element should be a MyCustomElement'); 135 reason: '$element should be a MyCustomElement');
132 136
133 expect(element.myPoint, model['a']); 137 expect(element.myPoint, model['a']);
134 expect(element.scaryMonster, model['b']); 138 expect(element.scaryMonster, model['b']);
135 139
136 expect(element.attributes, isNot(contains('my-point'))); 140 expect(element.attributes, isNot(contains('my-point')));
137 expect(element.attributes, isNot(contains('scary-monster'))); 141 expect(element.attributes, isNot(contains('scary-monster')));
138 142
143 expect(element.bindFinishedCalled, 1);
144
139 model['a'] = null; 145 model['a'] = null;
140 }).then(endOfMicrotask).then((_) { 146 }).then(endOfMicrotask).then((_) {
141 expect(element.myPoint, null); 147 expect(element.myPoint, null);
148 expect(element.bindFinishedCalled, 1);
149
142 150
143 templateBind(div.query('template')).model = null; 151 templateBind(div.query('template')).model = null;
144 }).then(endOfMicrotask).then((_) { 152 }).then(endOfMicrotask).then((_) {
145 153 // Note: the detached element
146 expect(element.parentNode, null, reason: 'element was detached'); 154 expect(element.parentNode is DocumentFragment, true,
155 reason: 'removed element is added back to its document fragment');
156 expect(element.parentNode.parentNode, null,
157 reason: 'document fragment is detached');
158 expect(element.bindFinishedCalled, 1);
147 159
148 model['a'] = new Point(1, 2); 160 model['a'] = new Point(1, 2);
149 model['b'] = new Monster(200); 161 model['b'] = new Monster(200);
150 }).then(endOfMicrotask).then((_) { 162 }).then(endOfMicrotask).then((_) {
151
152 expect(element.myPoint, null, reason: 'model was unbound'); 163 expect(element.myPoint, null, reason: 'model was unbound');
153 expect(element.scaryMonster.health, 100, reason: 'model was unbound'); 164 expect(element.scaryMonster.health, 100, reason: 'model was unbound');
165 expect(element.bindFinishedCalled, 1);
154 }); 166 });
155 }); 167 });
156 168
157 } 169 }
158 170
159 class Monster { 171 class Monster {
160 int health; 172 int health;
161 Monster(this.health); 173 Monster(this.health);
162 } 174 }
163 175
164 /** Demonstrates a custom element overriding bind/unbind/unbindAll. */ 176 /** Demonstrates a custom element overriding bind/bindFinished. */
165 class MyCustomElement extends HtmlElement implements NodeBindExtension { 177 class MyCustomElement extends HtmlElement implements NodeBindExtension {
166 Point myPoint; 178 Point myPoint;
167 Monster scaryMonster; 179 Monster scaryMonster;
180 int bindFinishedCalled = 0;
168 181
169 factory MyCustomElement() => new Element.tag('my-custom-element'); 182 factory MyCustomElement() => new Element.tag('my-custom-element');
170 183
171 MyCustomElement.created() : super.created(); 184 MyCustomElement.created() : super.created();
172 185
173 Bindable bind(String name, value, {oneTime: false}) { 186 Bindable bind(String name, value, {oneTime: false}) {
174 switch (name) { 187 switch (name) {
175 case 'my-point': 188 case 'my-point':
176 case 'scary-monster': 189 case 'scary-monster':
177 attributes.remove(name); 190 attributes.remove(name);
178 if (oneTime) { 191 if (oneTime) {
179 _setProperty(name, value); 192 _setProperty(name, value);
180 return null; 193 return null;
181 } 194 }
182 unbind(name);
183 _setProperty(name, value.open((x) => _setProperty(name, x))); 195 _setProperty(name, value.open((x) => _setProperty(name, x)));
196
197 if (!enableBindingsReflection) return value;
198 if (bindings == null) bindings = {};
199 var old = bindings[name];
200 if (old != null) old.close();
184 return bindings[name] = value; 201 return bindings[name] = value;
185 } 202 }
186 return nodeBindFallback(this).bind(name, value, oneTime: oneTime); 203 return nodeBindFallback(this).bind(name, value, oneTime: oneTime);
187 } 204 }
188 205
189 unbind(name) => nodeBindFallback(this).unbind(name); 206 void bindFinished() {
190 unbindAll() => nodeBindFallback(this).unbindAll(); 207 bindFinishedCalled++;
208 }
209
191 get bindings => nodeBindFallback(this).bindings; 210 get bindings => nodeBindFallback(this).bindings;
211 set bindings(x) => nodeBindFallback(this).bindings = x;
192 get templateInstance => nodeBindFallback(this).templateInstance; 212 get templateInstance => nodeBindFallback(this).templateInstance;
193 213
194 void _setProperty(String property, newValue) { 214 void _setProperty(String property, newValue) {
195 if (property == 'my-point') myPoint = newValue; 215 if (property == 'my-point') myPoint = newValue;
196 if (property == 'scary-monster') scaryMonster = newValue; 216 if (property == 'scary-monster') scaryMonster = newValue;
197 } 217 }
198 } 218 }
199 219
200 220
201 /** 221 /**
(...skipping 19 matching lines...) Expand all
221 241
222 AttributeMapWrapper(Map map) : super(map); 242 AttributeMapWrapper(Map map) : super(map);
223 243
224 void operator []=(K key, V value) { 244 void operator []=(K key, V value) {
225 log.add(['[]=', key, value]); 245 log.add(['[]=', key, value]);
226 super[key] = value; 246 super[key] = value;
227 } 247 }
228 248
229 V remove(Object key) { 249 V remove(Object key) {
230 log.add(['remove', key]); 250 log.add(['remove', key]);
231 super.remove(key); 251 return super.remove(key);
232 } 252 }
233 } 253 }
OLDNEW
« no previous file with comments | « dart/pkg/template_binding/test/binding_syntax.dart ('k') | dart/pkg/template_binding/test/node_bind_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698