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

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

Issue 132403010: big update to observe, template_binding, polymer (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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.node_bind_test; 5 library template_binding.test.node_bind_test;
6 6
7 import 'dart:async';
7 import 'dart:html'; 8 import 'dart:html';
8 9
9 import 'package:observe/observe.dart' show toObservable, PathObserver; 10 import 'package:observe/observe.dart'
11 show toObservable, PathObserver, PropertyPath;
10 import 'package:template_binding/template_binding.dart' show nodeBind; 12 import 'package:template_binding/template_binding.dart' show nodeBind;
11 import 'package:template_binding/src/node_binding.dart' show getObserverForTest;
12 13
13 import 'package:unittest/html_config.dart'; 14 import 'package:unittest/html_config.dart';
14 import 'package:unittest/unittest.dart'; 15 import 'package:unittest/unittest.dart';
15 import 'utils.dart'; 16 import 'utils.dart';
16 17
17 // Note: this file ported from 18 // Note: this file ported from
18 // https://github.com/toolkitchen/mdv/blob/master/tests/node_bindings.js 19 // https://github.com/toolkitchen/mdv/blob/master/tests/node_bindings.js
19 20
20 main() { 21 main() => dirtyCheckZone().run(() {
21 useHtmlConfiguration(); 22 useHtmlConfiguration();
22 23
23 setUp(() { 24 setUp(() {
24 document.body.append(testDiv = new DivElement()); 25 document.body.append(testDiv = new DivElement());
25 }); 26 });
26 27
27 tearDown(() { 28 tearDown(() {
28 testDiv.remove(); 29 testDiv.remove();
29 testDiv = null; 30 testDiv = null;
30 }); 31 });
31 32
32
33 group('Text bindings', testBindings); 33 group('Text bindings', testBindings);
34 group('Element attribute bindings', elementBindings); 34 group('Element attribute bindings', elementBindings);
35 group('Form Element bindings', formBindings); 35 group('Form Element bindings', formBindings);
36 } 36 });
37 37
38 testBindings() { 38 testBindings() {
39 observeTest('Basic', () { 39 test('Basic', () {
40 var text = new Text('hi'); 40 var text = new Text('hi');
41 var model = toObservable({'a': 1}); 41 var model = toObservable({'a': 1});
42 nodeBind(text).bind('text', model, 'a'); 42 nodeBind(text).bind('text', new PathObserver(model, 'a'));
43 expect(text.text, '1'); 43 expect(text.text, '1');
44 44
45 model['a'] = 2; 45 model['a'] = 2;
46 performMicrotaskCheckpoint(); 46 return new Future(() {
47 expect(text.text, '2'); 47 expect(text.text, '2');
48 48
49 nodeBind(text).unbind('text'); 49 nodeBind(text).unbind('text');
50 model['a'] = 3; 50 model['a'] = 3;
51 performMicrotaskCheckpoint(); 51 }).then(endOfMicrotask).then((_) {
52 expect(text.text, '2'); 52 // TODO(rafaelw): Throw on binding to unavailable property?
53 53 expect(text.text, '2');
54 // TODO(rafaelw): Throw on binding to unavailable property? 54 });
55 }); 55 });
56 56
57 observeTest('No Path', () { 57 test('oneTime', () {
58 var text = new Text('hi'); 58 var text = new Text('hi');
59 var model = 1; 59 nodeBind(text).bind('text', 1, oneTime: true);
60 nodeBind(text).bind('text', model);
61 expect(text.text, '1'); 60 expect(text.text, '1');
62 }); 61 });
63 62
64 observeTest('Path unreachable', () { 63 test('No Path', () {
64 var text = new Text('hi');
65 var model = 1;
66 nodeBind(text).bind('text', new PathObserver(model));
67 expect(text.text, '1');
68 });
69
70 test('Path unreachable', () {
65 var text = testDiv.append(new Text('hi')); 71 var text = testDiv.append(new Text('hi'));
66 var model = 1; 72 var model = 1;
67 nodeBind(text).bind('text', model, 'a'); 73 nodeBind(text).bind('text', new PathObserver(model, 'a'));
68 expect(text.text, ''); 74 expect(text.text, '');
69 }); 75 });
70 76
71 observeTest('Observer is Model', () { 77 test('Observer is Model', () {
72 var text = new Text(''); 78 var text = new Text('');
73 var model = toObservable({'a': {'b': {'c': 1}}}); 79 var model = toObservable({'a': {'b': {'c': 1}}});
74 var observer = new PathObserver(model, 'a.b.c'); 80 var observer = new PathObserver(model, 'a.b.c');
75 nodeBind(text).bind('text', observer, 'value'); 81 nodeBind(text).bind('text', observer);
76 expect(text.text, '1'); 82 expect(text.text, '1');
77 83
78 var binding = nodeBind(text).bindings['text']; 84 var binding = nodeBind(text).bindings['text'];
79 expect(binding, isNotNull); 85 expect(binding, observer, reason: 'should reuse observer');
80 expect(getObserverForTest(binding), observer,
81 reason: 'should reuse observer');
82 86
83 model['a']['b']['c'] = 2; 87 model['a']['b']['c'] = 2;
84 performMicrotaskCheckpoint(); 88 return new Future(() {
85 expect(text.text, '2'); 89 expect(text.text, '2');
86 nodeBind(text).unbind('text'); 90 nodeBind(text).unbind('text');
91 });
87 }); 92 });
88 } 93 }
89 94
90 elementBindings() { 95 elementBindings() {
91 observeTest('Basic', () { 96 test('Basic', () {
92 var el = new DivElement(); 97 var el = new DivElement();
93 var model = toObservable({'a': '1'}); 98 var model = toObservable({'a': '1'});
94 nodeBind(el).bind('foo', model, 'a'); 99 nodeBind(el).bind('foo', new PathObserver(model, 'a'));
95 performMicrotaskCheckpoint();
96 expect(el.attributes['foo'], '1');
97 100
98 model['a'] = '2'; 101 return new Future(() {
99 performMicrotaskCheckpoint(); 102 expect(el.attributes['foo'], '1');
100 expect(el.attributes['foo'], '2'); 103 model['a'] = '2';
101 104 }).then(endOfMicrotask).then((_) {
102 model['a'] = 232.2; 105 expect(el.attributes['foo'], '2');
103 performMicrotaskCheckpoint(); 106 model['a'] = 232.2;
104 expect(el.attributes['foo'], '232.2'); 107 }).then(endOfMicrotask).then((_) {
105 108 expect(el.attributes['foo'], '232.2');
106 model['a'] = 232; 109 model['a'] = 232;
107 performMicrotaskCheckpoint(); 110 }).then(endOfMicrotask).then((_) {
108 expect(el.attributes['foo'], '232'); 111 expect(el.attributes['foo'], '232');
109 112 model['a'] = null;
110 model['a'] = null; 113 }).then(endOfMicrotask).then((_) {
111 performMicrotaskCheckpoint(); 114 expect(el.attributes['foo'], '');
112 expect(el.attributes['foo'], ''); 115 });
113 }); 116 });
114 117
115 observeTest('No Path', () { 118 test('oneTime', () {
119 var el = testDiv.append(new DivElement());
120 var model = toObservable({'a': '1'});
121 nodeBind(el).bind('foo', 1, oneTime: true);
122 expect('1', el.attributes['foo']);
123 });
124
125 test('No Path', () {
116 var el = testDiv.append(new DivElement()); 126 var el = testDiv.append(new DivElement());
117 var model = 1; 127 var model = 1;
118 nodeBind(el).bind('foo', model); 128 nodeBind(el).bind('foo', new PathObserver(model));
119 expect(el.attributes['foo'], '1'); 129 return new Future(() {
130 expect(el.attributes['foo'], '1');
131 });
120 }); 132 });
121 133
122 observeTest('Path unreachable', () { 134 test('Path unreachable', () {
123 var el = testDiv.append(new DivElement()); 135 var el = testDiv.append(new DivElement());
124 var model = toObservable({}); 136 var model = toObservable({});
125 nodeBind(el).bind('foo', model, 'bar'); 137 nodeBind(el).bind('foo', new PathObserver(model, 'bar'));
126 expect(el.attributes['foo'], ''); 138 return new Future(() {
139 expect(el.attributes['foo'], '');
140 });
127 }); 141 });
128 142
129 observeTest('Dashes', () { 143 test('Dashes', () {
130 var el = testDiv.append(new DivElement()); 144 var el = testDiv.append(new DivElement());
131 var model = toObservable({'a': '1'}); 145 var model = toObservable({'a': '1'});
132 nodeBind(el).bind('foo-bar', model, 'a'); 146 nodeBind(el).bind('foo-bar', new PathObserver(model, 'a'));
133 performMicrotaskCheckpoint(); 147 return new Future(() {
134 expect(el.attributes['foo-bar'], '1'); 148 expect(el.attributes['foo-bar'], '1');
149 model['a'] = '2';
135 150
136 model['a'] = '2'; 151 }).then(endOfMicrotask).then((_) {
137 performMicrotaskCheckpoint(); 152 expect(el.attributes['foo-bar'], '2');
138 expect(el.attributes['foo-bar'], '2'); 153 });
139 }); 154 });
140 155
141 observeTest('Element.id, Element.hidden?', () { 156 test('Element.id, Element.hidden?', () {
142 var element = new DivElement(); 157 var element = new DivElement();
143 var model = toObservable({'a': 1, 'b': 2}); 158 var model = toObservable({'a': 1, 'b': 2});
144 nodeBind(element).bind('hidden?', model, 'a'); 159 nodeBind(element).bind('hidden?', new PathObserver(model, 'a'));
145 nodeBind(element).bind('id', model, 'b'); 160 nodeBind(element).bind('id', new PathObserver(model, 'b'));
146 161
147 expect(element.attributes, contains('hidden')); 162 expect(element.attributes, contains('hidden'));
148 expect(element.attributes['hidden'], ''); 163 expect(element.attributes['hidden'], '');
149 expect(element.id, '2'); 164 expect(element.id, '2');
150 165
151 model['a'] = null; 166 model['a'] = null;
152 performMicrotaskCheckpoint(); 167 return new Future(() {
153 expect(element.attributes, isNot(contains('hidden')), 168 expect(element.attributes, isNot(contains('hidden')),
154 reason: 'null is false-y'); 169 reason: 'null is false-y');
155 170
156 model['a'] = false; 171 model['a'] = false;
157 performMicrotaskCheckpoint(); 172 }).then(endOfMicrotask).then((_) {
158 expect(element.attributes, isNot(contains('hidden'))); 173 expect(element.attributes, isNot(contains('hidden')));
159 174
160 model['a'] = 'foo'; 175 model['a'] = 'foo';
161 model['b'] = 'x'; 176 model['b'] = 'x';
162 performMicrotaskCheckpoint(); 177 }).then(endOfMicrotask).then((_) {
163 expect(element.attributes, contains('hidden')); 178 expect(element.attributes, contains('hidden'));
164 expect(element.attributes['hidden'], ''); 179 expect(element.attributes['hidden'], '');
165 expect(element.id, 'x'); 180 expect(element.id, 'x');
181 });
166 }); 182 });
167 183
168 observeTest('Element.id - path unreachable', () { 184 test('Element.id - path unreachable', () {
169 var element = testDiv.append(new DivElement()); 185 var element = testDiv.append(new DivElement());
170 var model = toObservable({}); 186 var model = toObservable({});
171 nodeBind(element).bind('id', model, 'a'); 187 nodeBind(element).bind('id', new PathObserver(model, 'a'));
172 expect(element.id, ''); 188 return new Future(() => expect(element.id, ''));
173 }); 189 });
174 } 190 }
175 191
176 formBindings() { 192 formBindings() {
177 inputTextAreaValueTest(String tagName) { 193 inputTextAreaValueTest(String tagName) {
178 var el = new Element.tag(tagName); 194 var el = new Element.tag(tagName);
179 testDiv.nodes.add(el); 195 testDiv.nodes.add(el);
180 var model = toObservable({'x': 42}); 196 var model = toObservable({'x': 42});
181 nodeBind(el).bind('value', model, 'x'); 197 nodeBind(el).bind('value', new PathObserver(model, 'x'));
182 expect(el.value, '42'); 198 expect(el.value, '42');
183 199
184 model['x'] = 'Hi'; 200 model['x'] = 'Hi';
185 expect(el.value, '42', reason: 'changes delivered async'); 201 expect(el.value, '42', reason: 'changes delivered async');
186 performMicrotaskCheckpoint(); 202 return new Future(() {
187 expect(el.value, 'Hi'); 203 expect(el.value, 'Hi');
188 204
189 el.value = 'changed'; 205 el.value = 'changed';
190 dispatchEvent('input', el); 206 dispatchEvent('input', el);
191 expect(model['x'], 'changed'); 207 expect(model['x'], 'changed');
192 208
193 nodeBind(el).unbind('value'); 209 nodeBind(el).unbind('value');
194 210
195 el.value = 'changed again'; 211 el.value = 'changed again';
196 dispatchEvent('input', el); 212 dispatchEvent('input', el);
197 expect(model['x'], 'changed'); 213 expect(model['x'], 'changed');
198 214
199 nodeBind(el).bind('value', model, 'x'); 215 nodeBind(el).bind('value', new PathObserver(model, 'x'));
200 model['x'] = null; 216 model['x'] = null;
201 performMicrotaskCheckpoint(); 217 }).then(endOfMicrotask).then((_) {
202 expect(el.value, ''); 218 expect(el.value, '');
219 });
220 }
221
222 inputTextAreaValueOnetime(String tagName) {
223 var el = testDiv.append(new Element.tag(tagName));
224 nodeBind(el).bind('value', 42, oneTime: true);
225 expect(el.value, '42');
203 } 226 }
204 227
205 inputTextAreaNoPath(String tagName) { 228 inputTextAreaNoPath(String tagName) {
206 var el = testDiv.append(new Element.tag(tagName)); 229 var el = testDiv.append(new Element.tag(tagName));
207 var model = 42; 230 var model = 42;
208 nodeBind(el).bind('value', model); 231 nodeBind(el).bind('value', new PathObserver(model));
209 expect(el.value, '42'); 232 expect(el.value, '42');
210 } 233 }
211 234
212 inputTextAreaPathUnreachable(String tagName) { 235 inputTextAreaPathUnreachable(String tagName) {
213 var el = testDiv.append(new Element.tag(tagName)); 236 var el = testDiv.append(new Element.tag(tagName));
214 var model = toObservable({}); 237 var model = toObservable({});
215 nodeBind(el).bind('value', model, 'a'); 238 nodeBind(el).bind('value', new PathObserver(model, 'a'));
216 expect(el.value, ''); 239 expect(el.value, '');
217 } 240 }
218 241
219 observeTest('Input.value', 242 test('Input.value',
220 () => inputTextAreaValueTest('input')); 243 () => inputTextAreaValueTest('input'));
221 observeTest('Input.value - no path', 244
245 test('Input.value - oneTime',
246 () => inputTextAreaValueOnetime('input'));
247
248 test('Input.value - no path',
222 () => inputTextAreaNoPath('input')); 249 () => inputTextAreaNoPath('input'));
223 observeTest('Input.value - path unreachable', 250
251 test('Input.value - path unreachable',
224 () => inputTextAreaPathUnreachable('input')); 252 () => inputTextAreaPathUnreachable('input'));
225 observeTest('TextArea.value', 253
254 test('TextArea.value',
226 () => inputTextAreaValueTest('textarea')); 255 () => inputTextAreaValueTest('textarea'));
227 observeTest('TextArea.value - no path', 256
257 test('TextArea.value - oneTime',
258 () => inputTextAreaValueOnetime('textarea'));
259
260 test('TextArea.value - no path',
228 () => inputTextAreaNoPath('textarea')); 261 () => inputTextAreaNoPath('textarea'));
229 observeTest('TextArea.value - path unreachable', 262
263 test('TextArea.value - path unreachable',
230 () => inputTextAreaPathUnreachable('textarea')); 264 () => inputTextAreaPathUnreachable('textarea'));
231 265
232 observeTest('Radio Input', () { 266 test('Radio Input', () {
233 var input = new InputElement(); 267 var input = new InputElement();
234 input.type = 'radio'; 268 input.type = 'radio';
235 var model = toObservable({'x': true}); 269 var model = toObservable({'x': true});
236 nodeBind(input).bind('checked', model, 'x'); 270 nodeBind(input).bind('checked', new PathObserver(model, 'x'));
237 expect(input.checked, true); 271 expect(input.checked, true);
238 272
239 model['x'] = false; 273 model['x'] = false;
240 expect(input.checked, true); 274 expect(input.checked, true);
241 performMicrotaskCheckpoint(); 275 return new Future(() {
242 expect(input.checked, false,reason: 'model change should update checked'); 276 expect(input.checked, false,reason: 'model change should update checked');
243 277
244 input.checked = true; 278 input.checked = true;
245 dispatchEvent('change', input); 279 dispatchEvent('change', input);
246 expect(model['x'], true, reason: 'input.checked should set model'); 280 expect(model['x'], true, reason: 'input.checked should set model');
247 281
248 nodeBind(input).unbind('checked'); 282 nodeBind(input).unbind('checked');
249 283
250 input.checked = false; 284 input.checked = false;
251 dispatchEvent('change', input); 285 dispatchEvent('change', input);
252 expect(model['x'], true, 286 expect(model['x'], true,
253 reason: 'disconnected binding should not fire'); 287 reason: 'disconnected binding should not fire');
254 }); 288 });
255 289 });
256 observeTest('Input.value - user value rejected', () { 290
291 test('Input.value - user value rejected', () {
257 var model = toObservable({'val': 'ping'}); 292 var model = toObservable({'val': 'ping'});
258 293
259 var el = new InputElement(); 294 var el = new InputElement();
260 nodeBind(el).bind('value', model, 'val'); 295 nodeBind(el).bind('value', new PathObserver(model, 'val'));
261 performMicrotaskCheckpoint(); 296 return new Future(() {
262 expect(el.value, 'ping'); 297 expect(el.value, 'ping');
263 298
264 el.value = 'pong'; 299 el.value = 'pong';
265 dispatchEvent('input', el); 300 dispatchEvent('input', el);
266 expect(model['val'], 'pong'); 301 expect(model['val'], 'pong');
267 302
268 // Try a deep path. 303 // Try a deep path.
269 model = toObservable({'a': {'b': {'c': 'ping'}}}); 304 model = toObservable({'a': {'b': {'c': 'ping'}}});
270 305
271 nodeBind(el).bind('value', model, 'a.b.c'); 306 nodeBind(el).bind('value', new PathObserver(model, 'a.b.c'));
272 performMicrotaskCheckpoint(); 307 }).then(endOfMicrotask).then((_) {
273 expect(el.value, 'ping'); 308 expect(el.value, 'ping');
274 309
275 el.value = 'pong'; 310 el.value = 'pong';
276 dispatchEvent('input', el); 311 dispatchEvent('input', el);
277 expect(new PathObserver(model, 'a.b.c').value, 'pong'); 312 expect(new PropertyPath('a.b.c').getValueFrom(model), 'pong');
278 313
279 // Start with the model property being absent. 314 // Start with the model property being absent.
280 model['a']['b'].remove('c'); 315 model['a']['b'].remove('c');
281 performMicrotaskCheckpoint(); 316 }).then(endOfMicrotask).then((_) {
282 expect(el.value, ''); 317 expect(el.value, '');
283 318
284 el.value = 'pong'; 319 el.value = 'pong';
285 dispatchEvent('input', el); 320 dispatchEvent('input', el);
286 expect(new PathObserver(model, 'a.b.c').value, 'pong'); 321 expect(new PropertyPath('a.b.c').getValueFrom(model), 'pong');
287 performMicrotaskCheckpoint(); 322 }).then(endOfMicrotask).then((_) {
288 323
289 // Model property unreachable (and unsettable). 324 // Model property unreachable (and unsettable).
290 model['a'].remove('b'); 325 model['a'].remove('b');
291 performMicrotaskCheckpoint(); 326 }).then(endOfMicrotask).then((_) {
292 expect(el.value, ''); 327 expect(el.value, '');
293 328
294 el.value = 'pong'; 329 el.value = 'pong';
295 dispatchEvent('input', el); 330 dispatchEvent('input', el);
296 expect(new PathObserver(model, 'a.b.c').value, null); 331 expect(new PropertyPath('a.b.c').getValueFrom(model), null);
297 }); 332 });
298 333 });
299 observeTest('(Checkbox)Input.checked', () { 334
335 test('Checkbox Input.checked', () {
300 var el = testDiv.append(new InputElement()); 336 var el = testDiv.append(new InputElement());
301 el.type = 'checkbox'; 337 el.type = 'checkbox';
302 338
303 var model = toObservable({'x': true}); 339 var model = toObservable({'x': true});
304 nodeBind(el).bind('checked', model, 'x'); 340 nodeBind(el).bind('checked', new PathObserver(model, 'x'));
305 expect(el.checked, true); 341 expect(el.checked, true);
306 342
307 model['x'] = false; 343 model['x'] = false;
308 expect(el.checked, true, reason: 'changes delivered async'); 344 expect(el.checked, true, reason: 'changes delivered async');
309 performMicrotaskCheckpoint(); 345 return new Future(() {
310 expect(el.checked, false); 346 expect(el.checked, false);
311 347
312 el.click(); 348 el.click();
313 expect(model['x'], true); 349 expect(model['x'], true);
314 performMicrotaskCheckpoint(); 350 }).then(endOfMicrotask).then((_) {
315 351
316 el.click(); 352 el.click();
317 expect(model['x'], false); 353 expect(model['x'], false);
318 }); 354 });
319 355 });
320 observeTest('(Checkbox)Input.checked - path unreachable', () { 356
357 test('Checkbox Input.checked - oneTime', () {
358 var input = testDiv.append(new InputElement());
359 input.type = 'checkbox';
360 nodeBind(input).bind('checked', true, oneTime: true);
361 expect(input.checked, true, reason: 'checked was set');
362 });
363
364 test('Checkbox Input.checked - path unreachable', () {
321 var input = testDiv.append(new InputElement()); 365 var input = testDiv.append(new InputElement());
322 input.type = 'checkbox'; 366 input.type = 'checkbox';
323 var model = toObservable({}); 367 var model = toObservable({});
324 nodeBind(input).bind('checked', model, 'x'); 368 nodeBind(input).bind('checked', new PathObserver(model, 'x'));
325 expect(input.checked, false); 369 expect(input.checked, false);
326 }); 370 });
327 371
328 observeTest('(Checkbox)Input.checked 2', () { 372 test('Checkbox Input.checked 2', () {
329 var model = toObservable({'val': true}); 373 var model = toObservable({'val': true});
330 374
331 var el = testDiv.append(new InputElement()); 375 var el = testDiv.append(new InputElement());
332 el.type = 'checkbox'; 376 el.type = 'checkbox';
333 nodeBind(el).bind('checked', model, 'val'); 377 nodeBind(el).bind('checked', new PathObserver(model, 'val'));
334 performMicrotaskCheckpoint(); 378 return new Future(() {
335 expect(el.checked, true); 379 expect(el.checked, true);
336 380
337 model['val'] = false; 381 model['val'] = false;
338 performMicrotaskCheckpoint(); 382 }).then(endOfMicrotask).then((_) {
339 expect(el.checked, false); 383 expect(el.checked, false);
340 384
341 el.click(); 385 el.click();
342 expect(model['val'], true);
343
344 el.click();
345 expect(model['val'], false);
346
347 el.onClick.listen((_) {
348 expect(model['val'], true); 386 expect(model['val'], true);
349 }); 387
350 el.onChange.listen((_) { 388 el.click();
351 expect(model['val'], true); 389 expect(model['val'], false);
352 }); 390
353 391 el.onClick.listen((_) {
354 el.dispatchEvent(new MouseEvent('click', view: window)); 392 expect(model['val'], true);
355 }); 393 });
356 394 el.onChange.listen((_) {
357 observeTest('(Checkbox)Input.checked - binding updated on click', () { 395 expect(model['val'], true);
396 });
397
398 el.dispatchEvent(new MouseEvent('click', view: window));
399 });
400 });
401
402 test('Checkbox Input.checked - binding updated on click', () {
358 var model = toObservable({'val': true}); 403 var model = toObservable({'val': true});
359 404
360 var el = new InputElement(); 405 var el = new InputElement();
361 testDiv.append(el); 406 testDiv.append(el);
362 el.type = 'checkbox'; 407 el.type = 'checkbox';
363 nodeBind(el).bind('checked', model, 'val'); 408 nodeBind(el).bind('checked', new PathObserver(model, 'val'));
364 performMicrotaskCheckpoint(); 409 return new Future(() {
365 expect(el.checked, true); 410 expect(el.checked, true);
366 411
367 el.onClick.listen((_) { 412 int fired = 0;
368 expect(model['val'], false); 413 el.onClick.listen((_) {
369 }); 414 fired++;
370 415 expect(model['val'], false);
371 el.dispatchEvent(new MouseEvent('click', view: window)); 416 });
372 }); 417
373 418 el.dispatchEvent(new MouseEvent('click', view: window));
374 observeTest('(Checkbox)Input.checked - binding updated on change', () { 419
420 expect(fired, 1, reason: 'events dispatched synchronously');
421 });
422 });
423
424 test('Checkbox Input.checked - binding updated on change', () {
375 var model = toObservable({'val': true}); 425 var model = toObservable({'val': true});
376 426
377 var el = new InputElement(); 427 var el = new InputElement();
378 testDiv.append(el); 428 testDiv.append(el);
379 el.type = 'checkbox'; 429 el.type = 'checkbox';
380 nodeBind(el).bind('checked', model, 'val'); 430 nodeBind(el).bind('checked', new PathObserver(model, 'val'));
381 performMicrotaskCheckpoint(); 431 return new Future(() {
382 expect(el.checked, true); 432 expect(el.checked, true);
383 433
384 el.onChange.listen((_) { 434 int fired = 0;
385 expect(model['val'], false); 435 el.onChange.listen((_) {
386 }); 436 fired++;
387 437 expect(model['val'], false);
388 el.dispatchEvent(new MouseEvent('click', view: window)); 438 });
389 }); 439
390 440 el.dispatchEvent(new MouseEvent('click', view: window));
391 observeTest('(Radio)Input.checked', () { 441
442 expect(fired, 1, reason: 'events dispatched synchronously');
443 });
444 });
445
446 test('Radio Input.checked', () {
392 var input = testDiv.append(new InputElement()); 447 var input = testDiv.append(new InputElement());
393 input.type = 'radio'; 448 input.type = 'radio';
394 var model = toObservable({'x': true}); 449 var model = toObservable({'x': true});
395 nodeBind(input).bind('checked', model, 'x'); 450 nodeBind(input).bind('checked', new PathObserver(model, 'x'));
396 expect(input.checked, true); 451 expect(input.checked, true);
397 452
398 model['x'] = false; 453 model['x'] = false;
399 expect(input.checked, true); 454 expect(input.checked, true);
400 performMicrotaskCheckpoint(); 455 return new Future(() {
401 expect(input.checked, false); 456 expect(input.checked, false);
402 457
403 input.checked = true; 458 input.checked = true;
404 dispatchEvent('change', input); 459 dispatchEvent('change', input);
405 expect(model['x'], true); 460 expect(model['x'], true);
406 461
407 nodeBind(input).unbind('checked'); 462 nodeBind(input).unbind('checked');
408 463
409 input.checked = false; 464 input.checked = false;
410 dispatchEvent('change', input); 465 dispatchEvent('change', input);
411 expect(model['x'], true); 466 expect(model['x'], true);
467 });
468 });
469
470 test('Radio Input.checked - oneTime', () {
471 var input = testDiv.append(new InputElement());
472 input.type = 'radio';
473 nodeBind(input).bind('checked', true, oneTime: true);
474 expect(input.checked, true, reason: 'checked was set');
412 }); 475 });
413 476
414 radioInputChecked2(host) { 477 radioInputChecked2(host) {
415 var model = toObservable({'val1': true, 'val2': false, 'val3': false, 478 var model = toObservable({'val1': true, 'val2': false, 'val3': false,
416 'val4': true}); 479 'val4': true});
417 var RADIO_GROUP_NAME = 'test'; 480 var RADIO_GROUP_NAME = 'test';
418 481
419 var container = host.append(new DivElement()); 482 var container = host.append(new DivElement());
420 483
421 var el1 = container.append(new InputElement()); 484 var el1 = container.append(new InputElement());
422 el1.type = 'radio'; 485 el1.type = 'radio';
423 el1.name = RADIO_GROUP_NAME; 486 el1.name = RADIO_GROUP_NAME;
424 nodeBind(el1).bind('checked', model, 'val1'); 487 nodeBind(el1).bind('checked', new PathObserver(model, 'val1'));
425 488
426 var el2 = container.append(new InputElement()); 489 var el2 = container.append(new InputElement());
427 el2.type = 'radio'; 490 el2.type = 'radio';
428 el2.name = RADIO_GROUP_NAME; 491 el2.name = RADIO_GROUP_NAME;
429 nodeBind(el2).bind('checked', model, 'val2'); 492 nodeBind(el2).bind('checked', new PathObserver(model, 'val2'));
430 493
431 var el3 = container.append(new InputElement()); 494 var el3 = container.append(new InputElement());
432 el3.type = 'radio'; 495 el3.type = 'radio';
433 el3.name = RADIO_GROUP_NAME; 496 el3.name = RADIO_GROUP_NAME;
434 nodeBind(el3).bind('checked', model, 'val3'); 497 nodeBind(el3).bind('checked', new PathObserver(model, 'val3'));
435 498
436 var el4 = container.append(new InputElement()); 499 var el4 = container.append(new InputElement());
437 el4.type = 'radio'; 500 el4.type = 'radio';
438 el4.name = 'othergroup'; 501 el4.name = 'othergroup';
439 nodeBind(el4).bind('checked', model, 'val4'); 502 nodeBind(el4).bind('checked', new PathObserver(model, 'val4'));
440 503
441 performMicrotaskCheckpoint(); 504 return new Future(() {
442 expect(el1.checked, true); 505 expect(el1.checked, true);
443 expect(el2.checked, false); 506 expect(el2.checked, false);
444 expect(el3.checked, false); 507 expect(el3.checked, false);
445 expect(el4.checked, true); 508 expect(el4.checked, true);
446 509
447 model['val1'] = false; 510 model['val1'] = false;
448 model['val2'] = true; 511 model['val2'] = true;
449 performMicrotaskCheckpoint(); 512 }).then(endOfMicrotask).then((_) {
450 expect(el1.checked, false); 513 expect(el1.checked, false);
451 expect(el2.checked, true); 514 expect(el2.checked, true);
452 expect(el3.checked, false); 515 expect(el3.checked, false);
453 expect(el4.checked, true); 516 expect(el4.checked, true);
454 517
455 el1.checked = true; 518 el1.checked = true;
456 dispatchEvent('change', el1); 519 dispatchEvent('change', el1);
457 expect(model['val1'], true); 520 expect(model['val1'], true);
458 expect(model['val2'], false); 521 expect(model['val2'], false);
459 expect(model['val3'], false); 522 expect(model['val3'], false);
460 expect(model['val4'], true); 523 expect(model['val4'], true);
461 524
462 el3.checked = true; 525 el3.checked = true;
463 dispatchEvent('change', el3); 526 dispatchEvent('change', el3);
464 expect(model['val1'], false); 527 expect(model['val1'], false);
465 expect(model['val2'], false); 528 expect(model['val2'], false);
466 expect(model['val3'], true); 529 expect(model['val3'], true);
467 expect(model['val4'], true); 530 expect(model['val4'], true);
531 });
468 } 532 }
469 533
470 observeTest('(Radio)Input.checked 2', () { 534 test('Radio Input.checked 2', () => radioInputChecked2(testDiv));
471 radioInputChecked2(testDiv);
472 });
473 535
474 observeTest('(Radio)Input.checked 2 - ShadowRoot', () { 536 test('Radio Input.checked 2 - ShadowRoot', () {
475 if (!ShadowRoot.supported) return; 537 if (!ShadowRoot.supported) return null;
476 538
477 var div = new DivElement(); 539 var shadowRoot = new DivElement().createShadowRoot();
478 var shadowRoot = div.createShadowRoot(); 540 return radioInputChecked2(shadowRoot)
479 radioInputChecked2(shadowRoot); 541 .whenComplete(() => unbindAll(shadowRoot));
480 unbindAll(shadowRoot);
481 }); 542 });
482 543
483 radioInputCheckedMultipleForms(host) { 544 radioInputCheckedMultipleForms(host) {
484 var model = toObservable({'val1': true, 'val2': false, 'val3': false, 545 var model = toObservable({'val1': true, 'val2': false, 'val3': false,
485 'val4': true}); 546 'val4': true});
486 var RADIO_GROUP_NAME = 'observeTest'; 547 var RADIO_GROUP_NAME = 'test';
487 548
488 var container = testDiv.append(new DivElement()); 549 var container = testDiv.append(new DivElement());
489 var form1 = new FormElement(); 550 var form1 = new FormElement();
490 container.append(form1); 551 container.append(form1);
491 var form2 = new FormElement(); 552 var form2 = new FormElement();
492 container.append(form2); 553 container.append(form2);
493 554
494 var el1 = new InputElement(); 555 var el1 = new InputElement();
495 form1.append(el1); 556 form1.append(el1);
496 el1.type = 'radio'; 557 el1.type = 'radio';
497 el1.name = RADIO_GROUP_NAME; 558 el1.name = RADIO_GROUP_NAME;
498 nodeBind(el1).bind('checked', model, 'val1'); 559 nodeBind(el1).bind('checked', new PathObserver(model, 'val1'));
499 560
500 var el2 = new InputElement(); 561 var el2 = new InputElement();
501 form1.append(el2); 562 form1.append(el2);
502 el2.type = 'radio'; 563 el2.type = 'radio';
503 el2.name = RADIO_GROUP_NAME; 564 el2.name = RADIO_GROUP_NAME;
504 nodeBind(el2).bind('checked', model, 'val2'); 565 nodeBind(el2).bind('checked', new PathObserver(model, 'val2'));
505 566
506 var el3 = new InputElement(); 567 var el3 = new InputElement();
507 form2.append(el3); 568 form2.append(el3);
508 el3.type = 'radio'; 569 el3.type = 'radio';
509 el3.name = RADIO_GROUP_NAME; 570 el3.name = RADIO_GROUP_NAME;
510 nodeBind(el3).bind('checked', model, 'val3'); 571 nodeBind(el3).bind('checked', new PathObserver(model, 'val3'));
511 572
512 var el4 = new InputElement(); 573 var el4 = new InputElement();
513 form2.append(el4); 574 form2.append(el4);
514 el4.type = 'radio'; 575 el4.type = 'radio';
515 el4.name = RADIO_GROUP_NAME; 576 el4.name = RADIO_GROUP_NAME;
516 nodeBind(el4).bind('checked', model, 'val4'); 577 nodeBind(el4).bind('checked', new PathObserver(model, 'val4'));
517 578
518 performMicrotaskCheckpoint(); 579 return new Future(() {
519 expect(el1.checked, true); 580 expect(el1.checked, true);
520 expect(el2.checked, false); 581 expect(el2.checked, false);
521 expect(el3.checked, false); 582 expect(el3.checked, false);
522 expect(el4.checked, true); 583 expect(el4.checked, true);
523 584
524 el2.checked = true; 585 el2.checked = true;
525 dispatchEvent('change', el2); 586 dispatchEvent('change', el2);
526 expect(model['val1'], false); 587 expect(model['val1'], false);
527 expect(model['val2'], true); 588 expect(model['val2'], true);
528 589
529 // Radio buttons in form2 should be unaffected 590 // Radio buttons in form2 should be unaffected
530 expect(model['val3'], false); 591 expect(model['val3'], false);
531 expect(model['val4'], true); 592 expect(model['val4'], true);
532 593
533 el3.checked = true; 594 el3.checked = true;
534 dispatchEvent('change', el3); 595 dispatchEvent('change', el3);
535 expect(model['val3'], true); 596 expect(model['val3'], true);
536 expect(model['val4'], false); 597 expect(model['val4'], false);
537 598
538 // Radio buttons in form1 should be unaffected 599 // Radio buttons in form1 should be unaffected
539 expect(model['val1'], false); 600 expect(model['val1'], false);
540 expect(model['val2'], true); 601 expect(model['val2'], true);
602 });
541 } 603 }
542 604
543 observeTest('(Radio)Input.checked - multiple forms', () { 605 test('Radio Input.checked - multiple forms', () {
544 radioInputCheckedMultipleForms(testDiv); 606 return radioInputCheckedMultipleForms(testDiv);
545 }); 607 });
546 608
547 observeTest('(Radio)Input.checked 2 - ShadowRoot', () { 609 test('Radio Input.checked - multiple forms - ShadowRoot', () {
548 if (!ShadowRoot.supported) return; 610 if (!ShadowRoot.supported) return null;
549 611
550 var shadowRoot = new DivElement().createShadowRoot(); 612 var shadowRoot = new DivElement().createShadowRoot();
551 radioInputChecked2(shadowRoot); 613 return radioInputCheckedMultipleForms(shadowRoot)
552 unbindAll(shadowRoot); 614 .whenComplete(() => unbindAll(shadowRoot));
553 }); 615 });
554 616
555 observeTest('Select.selectedIndex', () { 617 test('Select.selectedIndex', () {
556 var select = new SelectElement(); 618 var select = new SelectElement();
557 testDiv.append(select); 619 testDiv.append(select);
558 var option0 = select.append(new OptionElement()); 620 var option0 = select.append(new OptionElement());
559 var option1 = select.append(new OptionElement()); 621 var option1 = select.append(new OptionElement());
560 var option2 = select.append(new OptionElement()); 622 var option2 = select.append(new OptionElement());
561 623
562 var model = toObservable({'val': 2}); 624 var model = toObservable({'val': 2});
563 625
564 nodeBind(select).bind('selectedIndex', model, 'val'); 626 nodeBind(select).bind('selectedIndex', new PathObserver(model, 'val'));
565 performMicrotaskCheckpoint(); 627 return new Future(() {
566 expect(select.selectedIndex, 2); 628 expect(select.selectedIndex, 2);
567 629
568 select.selectedIndex = 1; 630 select.selectedIndex = 1;
569 dispatchEvent('change', select); 631 dispatchEvent('change', select);
570 expect(model['val'], 1); 632 expect(model['val'], 1);
633 });
571 }); 634 });
572 635
573 observeTest('Select.selectedIndex - path NaN', () { 636 test('Select.selectedIndex - oneTime', () {
574 var select = new SelectElement(); 637 var select = new SelectElement();
575 testDiv.append(select); 638 testDiv.append(select);
576 var option0 = select.append(new OptionElement()); 639 var option0 = select.append(new OptionElement());
640 var option1 = select.append(new OptionElement());
641 var option2 = select.append(new OptionElement());
642
643 nodeBind(select).bind('selectedIndex', 2, oneTime: true);
644 return new Future(() => expect(select.selectedIndex, 2));
645 });
646
647 test('Select.selectedIndex - invalid path', () {
648 var select = new SelectElement();
649 testDiv.append(select);
650 var option0 = select.append(new OptionElement());
577 var option1 = select.append(new OptionElement()); 651 var option1 = select.append(new OptionElement());
578 option1.selected = true; 652 option1.selected = true;
579 var option2 = select.append(new OptionElement()); 653 var option2 = select.append(new OptionElement());
580 654
581 var model = toObservable({'val': 'foo'}); 655 var model = toObservable({'val': 'foo'});
582 656
583 nodeBind(select).bind('selectedIndex', model, 'val'); 657 nodeBind(select).bind('selectedIndex', new PathObserver(model, 'val'));
584 performMicrotaskCheckpoint(); 658 return new Future(() => expect(select.selectedIndex, 0));
585 expect(select.selectedIndex, 0);
586 }); 659 });
587 660
588 observeTest('Select.selectedIndex - path unreachable', () { 661 test('Select.selectedIndex - path unreachable', () {
589 var select = new SelectElement(); 662 var select = new SelectElement();
590 testDiv.append(select); 663 testDiv.append(select);
591 var option0 = select.append(new OptionElement()); 664 var option0 = select.append(new OptionElement());
592 var option1 = select.append(new OptionElement()); 665 var option1 = select.append(new OptionElement());
593 option1.selected = true; 666 option1.selected = true;
594 var option2 = select.append(new OptionElement()); 667 var option2 = select.append(new OptionElement());
595 668
596 var model = toObservable({}); 669 var model = toObservable({});
597 670
598 nodeBind(select).bind('selectedIndex', model, 'val'); 671 nodeBind(select).bind('selectedIndex', new PathObserver(model, 'val'));
599 performMicrotaskCheckpoint(); 672 return new Future(() => expect(select.selectedIndex, 0));
600 expect(select.selectedIndex, 0);
601 }); 673 });
602 674
603 observeTest('Option.value', () { 675 test('Option.value', () {
604 var option = testDiv.append(new OptionElement()); 676 var option = testDiv.append(new OptionElement());
605 var model = toObservable({'x': 42}); 677 var model = toObservable({'x': 42});
606 nodeBind(option).bind('value', model, 'x'); 678 nodeBind(option).bind('value', new PathObserver(model, 'x'));
607 expect(option.value, '42'); 679 expect(option.value, '42');
608 680
609 model['x'] = 'Hi'; 681 model['x'] = 'Hi';
610 expect(option.value, '42'); 682 expect(option.value, '42');
611 performMicrotaskCheckpoint(); 683 return new Future(() => expect(option.value, 'Hi'));
612 expect(option.value, 'Hi');
613 }); 684 });
614 685
615 observeTest('Select.value', () { 686 test('Option.value - oneTime', () {
687 var option = testDiv.append(new OptionElement());
688 nodeBind(option).bind('value', 42, oneTime: true);
689 expect(option.value, '42');
690 });
691
692 test('Select.value', () {
616 var select = testDiv.append(new SelectElement()); 693 var select = testDiv.append(new SelectElement());
617 testDiv.append(select); 694 testDiv.append(select);
618 var option0 = select.append(new OptionElement()); 695 var option0 = select.append(new OptionElement());
619 var option1 = select.append(new OptionElement()); 696 var option1 = select.append(new OptionElement());
620 var option2 = select.append(new OptionElement()); 697 var option2 = select.append(new OptionElement());
621 698
622 var model = toObservable({ 699 var model = toObservable({
623 'opt0': 'a', 700 'opt0': 'a',
624 'opt1': 'b', 701 'opt1': 'b',
625 'opt2': 'c', 702 'opt2': 'c',
626 'selected': 'b' 703 'selected': 'b'
627 }); 704 });
628 705
629 nodeBind(option0).bind('value', model, 'opt0'); 706 nodeBind(option0).bind('value', new PathObserver(model, 'opt0'));
630 nodeBind(option1).bind('value', model, 'opt1'); 707 nodeBind(option1).bind('value', new PathObserver(model, 'opt1'));
631 nodeBind(option2).bind('value', model, 'opt2'); 708 nodeBind(option2).bind('value', new PathObserver(model, 'opt2'));
632 709
633 nodeBind(select).bind('value', model, 'selected'); 710 nodeBind(select).bind('value', new PathObserver(model, 'selected'));
634 performMicrotaskCheckpoint(); 711 return new Future(() {
635 expect(select.value, 'b'); 712 expect(select.value, 'b');
636 713
637 select.value = 'c'; 714 select.value = 'c';
638 dispatchEvent('change', select); 715 dispatchEvent('change', select);
639 expect(model['selected'], 'c'); 716 expect(model['selected'], 'c');
640 717
641 model['opt2'] = 'X'; 718 model['opt2'] = 'X';
642 performMicrotaskCheckpoint(); 719 }).then(endOfMicrotask).then((_) {
643 expect(select.value, 'X'); 720 expect(select.value, 'X');
644 expect(model['selected'], 'X'); 721 expect(model['selected'], 'X');
645 722
646 model['selected'] = 'a'; 723 model['selected'] = 'a';
647 performMicrotaskCheckpoint(); 724 }).then(endOfMicrotask).then((_) {
648 expect(select.value, 'a'); 725 expect(select.value, 'a');
726 });
649 }); 727 });
650 } 728 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698