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

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

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

Powered by Google App Engine
This is Rietveld 408576698