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

Side by Side Diff: third_party/pkg/angular/test/core/scope_spec.dart

Issue 124053002: Adding Angular and dependent packages for testing (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 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
(Empty)
1 library scope_spec;
2
3 import '../_specs.dart';
4 import 'dart:convert' show JSON;
5
6
7 main() {
8 describe(r'Scope', () {
9 NgZone zone;
10
11 noop() {}
12
13 beforeEach(module(() {
14 return (NgZone _zone) {
15 zone = _zone;
16 zone.onError = (e, s, l) => null;
17 };
18 }));
19
20 describe(r'$root', () {
21 it(r'should point to itself', inject((Scope $rootScope) {
22 expect($rootScope.$root).toEqual($rootScope);
23 expect($rootScope.$root).toBeTruthy();
24 }));
25
26
27 it(r'should not have $root on children, but should inherit', inject((Scope $rootScope) {
28 var child = $rootScope.$new();
29 expect(child.$root).toEqual($rootScope);
30 expect(child._$root).toBeFalsy();
31 }));
32
33 });
34
35
36 describe(r'$parent', () {
37 it(r'should point to itself in root', inject((Scope $rootScope) {
38 expect($rootScope.$root).toEqual($rootScope);
39 }));
40
41
42 it(r'should point to parent', inject((Scope $rootScope) {
43 var child = $rootScope.$new();
44 expect($rootScope.$parent).toEqual(null);
45 expect(child.$parent).toEqual($rootScope);
46 expect(child.$new().$parent).toEqual(child);
47 }));
48 });
49
50
51 describe(r'$id', () {
52 it(r'should have a unique id', inject((Scope $rootScope) {
53 expect($rootScope.$id != $rootScope.$new().$id).toBe(true);
54 }));
55 });
56
57
58 describe(r'this', () {
59 it('should have a \'this\'', inject((Scope $rootScope) {
60 expect($rootScope['this']).toEqual($rootScope);
61 }));
62 });
63
64
65 describe(r'$new()', () {
66 it(r'should create a child scope', inject((Scope $rootScope) {
67 var child = $rootScope.$new();
68 $rootScope.a = 123;
69 expect(child.a).toEqual(123);
70 }));
71
72 it(r'should create a non prototypically inherited child scope', inject((Sc ope $rootScope) {
73 var child = $rootScope.$new(isolate: true);
74 $rootScope.a = 123;
75 expect(child.a).toEqual(null);
76 expect(child.$parent).toEqual($rootScope);
77 expect(child.$root).toBe($rootScope);
78 }));
79 });
80
81
82 describe(r'auto digest', () {
83 it(r'should auto digest at the end of the turn', inject((Scope $rootScope) {
84 var digestedValue = 0;
85 $rootScope.a = 1;
86 $rootScope.$watch('a', (newValue, oldValue, _this) {
87 digestedValue = newValue;
88 });
89 expect(digestedValue).toEqual(0);
90 zone.run(noop);
91 expect(digestedValue).toEqual(1);
92 }));
93
94 it(r'should skip auto digest if requested', inject((Scope $rootScope) {
95 var digestedValue = 0;
96 $rootScope.a = 1;
97 $rootScope.$watch('a', (newValue, oldValue, _this) {
98 digestedValue = newValue;
99 });
100 expect(digestedValue).toEqual(0);
101 zone.run(() {
102 $rootScope.$skipAutoDigest();
103 });
104 expect(digestedValue).toEqual(0);
105 zone.run(noop);
106 expect(digestedValue).toEqual(1);
107 }));
108
109 it(r'should throw exception if asked to skip auto digest outside of a turn ',
110 inject((Scope $rootScope) {
111 var digestedValue = 0;
112 $rootScope.a = 1;
113 $rootScope.$watch('a', (newValue, oldValue, _this) {
114 digestedValue = newValue;
115 });
116 expect(digestedValue).toEqual(0);
117 expect($rootScope.$skipAutoDigest).toThrow();
118 }));
119 });
120
121
122 describe(r'$watch/$digest', () {
123 it(r'should watch and fire on simple property change', inject((Scope $root Scope) {
124 var log;
125
126 $rootScope.$watch('name', (a, b, c) {
127 log = [a, b, c];
128 });
129 $rootScope.$digest();
130 log = null;
131
132 expect(log).toEqual(null);
133 $rootScope.$digest();
134 expect(log).toEqual(null);
135 $rootScope.name = 'misko';
136 $rootScope.$digest();
137 expect(log).toEqual(['misko', null, $rootScope]);
138 }));
139
140
141 it(r'should watch and fire on expression change', inject((Scope $rootScope ) {
142 var log;
143
144 $rootScope.$watch('name.first', (a, b, c) {
145 log = [a, b, c];
146 });
147 $rootScope.$digest();
148 log = null;
149
150 $rootScope.name = {};
151 expect(log).toEqual(null);
152 $rootScope.$digest();
153 expect(log).toEqual(null);
154 $rootScope.name['first'] = 'misko';
155 $rootScope.$digest();
156 expect(log).toEqual(['misko', null, $rootScope]);
157 }));
158
159
160 it(r'should delegate exceptions', () {
161 module((Module module) {
162 module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler);
163 });
164 inject((Scope $rootScope, ExceptionHandler e) {
165 LoggingExceptionHandler $exceptionHandler = e;
166 $rootScope.$watch('a', () {throw 'abc';});
167 $rootScope.a = 1;
168 $rootScope.$digest();
169 expect($exceptionHandler.errors.length).toEqual(1);
170 expect($exceptionHandler.errors[0].error).toEqual('abc');
171 });
172 });
173
174
175 it(r'should fire watches in order of addition', inject((Scope $rootScope) {
176 // this is not an external guarantee, just our own sanity
177 var log = '';
178 $rootScope.$watch('a', (a, b, c) { log += 'a'; });
179 $rootScope.$watch('b', (a, b, c) { log += 'b'; });
180 $rootScope.$watch('c', (a, b, c) { log += 'c'; });
181 $rootScope.a = $rootScope.b = $rootScope.c = 1;
182 $rootScope.$digest();
183 expect(log).toEqual('abc');
184 }));
185
186
187 it(r'should call child $watchers in addition order', inject((Scope $rootSc ope) {
188 // this is not an external guarantee, just our own sanity
189 var log = '';
190 var childA = $rootScope.$new();
191 var childB = $rootScope.$new();
192 var childC = $rootScope.$new();
193 childA.$watch('a', (a, b, c) { log += 'a'; });
194 childB.$watch('b', (a, b, c) { log += 'b'; });
195 childC.$watch('c', (a, b, c) { log += 'c'; });
196 childA.a = childB.b = childC.c = 1;
197 $rootScope.$digest();
198 expect(log).toEqual('abc');
199 }));
200
201
202 it(r'should allow $digest on a child scope with and without a right siblin g', inject(
203 (Scope $rootScope) {
204 // tests a traversal edge case which we originally missed
205 var log = [],
206 childA = $rootScope.$new(),
207 childB = $rootScope.$new();
208
209 $rootScope.$watch((a) { log.add('r'); });
210 childA.$watch((a) { log.add('a'); });
211 childB.$watch((a) { log.add('b'); });
212
213 // init
214 $rootScope.$digest();
215 expect(log.join('')).toEqual('rabra');
216
217 log.removeWhere((e) => true);
218 childA.$digest();
219 expect(log.join('')).toEqual('a');
220
221 log.removeWhere((e) => true);
222 childB.$digest();
223 expect(log.join('')).toEqual('b');
224 }));
225
226
227 it(r'should repeat watch cycle while model changes are identified', inject ((Scope $rootScope) {
228 var log = '';
229 $rootScope.$watch('c', (v, b, c) {$rootScope.d = v; log+='c'; });
230 $rootScope.$watch('b', (v, b, c) {$rootScope.c = v; log+='b'; });
231 $rootScope.$watch('a', (v, b, c) {$rootScope.b = v; log+='a'; });
232 $rootScope.$digest();
233 log = '';
234 $rootScope.a = 1;
235 $rootScope.$digest();
236 expect($rootScope.b).toEqual(1);
237 expect($rootScope.c).toEqual(1);
238 expect($rootScope.d).toEqual(1);
239 expect(log).toEqual('abc');
240 }));
241
242
243 it(r'should repeat watch cycle from the root element', inject((Scope $root Scope) {
244 var log = '';
245 var child = $rootScope.$new();
246 $rootScope.$watch((a) { log += 'a'; });
247 child.$watch((a) { log += 'b'; });
248 $rootScope.$digest();
249 expect(log).toEqual('aba');
250 }));
251
252
253 it(r'should not fire upon $watch registration on initial $digest', inject( (Scope $rootScope) {
254 var log = '';
255 $rootScope.a = 1;
256 $rootScope.$watch('a', (a, b, c) { log += 'a'; });
257 $rootScope.$watch('b', (a, b, c) { log += 'b'; });
258 $rootScope.$digest();
259 log = '';
260 $rootScope.$digest();
261 expect(log).toEqual('');
262 }));
263
264
265 it(r'should watch functions', () {
266 module((Module module) {
267 module.type(ExceptionHandler, implementedBy: LoggingExceptionHandler);
268 });
269 inject((Scope $rootScope, ExceptionHandler e) {
270 LoggingExceptionHandler exceptionHandler = e;
271 $rootScope.fn = () {return 'a';};
272 $rootScope.$watch('fn', (fn, a, b) {
273 exceptionHandler.errors.add(fn());
274 });
275 $rootScope.$digest();
276 expect(exceptionHandler.errors).toEqual(['a']);
277 $rootScope.fn = () {return 'b';};
278 $rootScope.$digest();
279 expect(exceptionHandler.errors).toEqual(['a', 'b']);
280 });
281 });
282
283
284 it(r'should prevent $digest recursion', inject((Scope $rootScope) {
285 var callCount = 0;
286 $rootScope.$watch('name', (a, b, c) {
287 expect(() {
288 $rootScope.$digest();
289 }).toThrow(r'$digest already in progress');
290 callCount++;
291 });
292 $rootScope.name = 'a';
293 $rootScope.$digest();
294 expect(callCount).toEqual(1);
295 }));
296
297
298 it(r'should return a function that allows listeners to be unregistered', i nject(
299 (Scope $rootScope) {
300 var listener = jasmine.createSpy('watch listener'),
301 listenerRemove;
302
303 listenerRemove = $rootScope.$watch('foo', listener);
304 $rootScope.$digest(); //init
305 expect(listener).toHaveBeenCalled();
306 expect(listenerRemove).toBeDefined();
307
308 listener.reset();
309 $rootScope.foo = 'bar';
310 $rootScope.$digest(); //triger
311 expect(listener).toHaveBeenCalledOnce();
312
313 listener.reset();
314 $rootScope.foo = 'baz';
315 listenerRemove();
316 $rootScope.$digest(); //trigger
317 expect(listener).not.toHaveBeenCalled();
318 }));
319
320
321 it(r'should not infinitely digest when current value is NaN', inject((Scop e $rootScope) {
322 $rootScope.$watch((a) { return double.NAN;});
323
324 expect(() {
325 $rootScope.$digest();
326 }).not.toThrow();
327 }));
328
329
330 it(r'should prevent infinite digest and should log firing expressions', in ject((Scope $rootScope) {
331 $rootScope['a'] = 0;
332 $rootScope['b'] = 0;
333 $rootScope.$watch('a = a + 1');
334 $rootScope.$watch('b = b + 1');
335
336 expect(() {
337 $rootScope.$digest();
338 }).toThrow('Watchers fired in the last 3 iterations: ['
339 '["a = a + 1","b = b + 1"],'
340 '["a = a + 1","b = b + 1"],'
341 '["a = a + 1","b = b + 1"]'
342 ']');
343 }));
344
345
346 it(r'should always call the watchr with newVal and oldVal equal on the fir st run',
347 inject((Scope $rootScope) {
348 var log = [];
349 var logger = (scope, newVal, oldVal) {
350 var val = (newVal == oldVal || (newVal != oldVal && oldVal != newVal)) ? newVal : 'xxx';
351 log.add(val);
352 };
353
354 $rootScope.$watch((s) { return double.NAN;}, logger);
355 $rootScope.$watch((s) { return null;}, logger);
356 $rootScope.$watch((s) { return '';}, logger);
357 $rootScope.$watch((s) { return false;}, logger);
358 $rootScope.$watch((s) { return 23;}, logger);
359
360 $rootScope.$digest();
361 expect(log.removeAt(0).isNaN).toEqual(true); //jasmine's toBe and toEqua l don't work well with NaNs
362 expect(log).toEqual([null, '', false, 23]);
363 log = [];
364 $rootScope.$digest();
365 expect(log).toEqual([]);
366 }));
367
368 describe('lazy digest', () {
369 var rootScope, lazyScope, eagerScope;
370
371 beforeEach(inject((Scope root) {
372 rootScope = root;
373 lazyScope = root.$new(lazy: true);
374 eagerScope = root.$new();
375 }));
376
377 it('should digest initially', () {
378 var log = '';
379 lazyScope.$watch(() {log += 'lazy;';});
380 eagerScope.$watch(() {log += 'eager;';});
381
382 rootScope.$digest();
383 expect(log).toEqual('lazy;eager;');
384
385 rootScope.$digest();
386 expect(log).toEqual('lazy;eager;eager;');
387
388 lazyScope.$dirty();
389 rootScope.$digest();
390 expect(log).toEqual('lazy;eager;eager;lazy;eager;');
391 });
392 });
393
394 describe('disabled digest', () {
395 var rootScope, childScope;
396
397 beforeEach(inject((Scope root) {
398 rootScope = root;
399 childScope = root.$new();
400 }));
401
402 it('should disable digest', () {
403 var log = '';
404 childScope.$watch(() {log += 'digest;';});
405
406 rootScope.$digest();
407 expect(log).toEqual('digest;');
408
409 childScope.$disabled = true;
410 expect(childScope.$disabled).toEqual(true);
411 rootScope.$digest();
412 expect(log).toEqual('digest;');
413
414 childScope.$disabled = false;
415 expect(childScope.$disabled).toEqual(false);
416 rootScope.$digest();
417 expect(log).toEqual('digest;digest;');
418 });
419 });
420 });
421
422
423 describe(r'$watchSet', () {
424 var scope;
425 beforeEach(inject((Scope s) => scope = s));
426
427 it('should skip empty sets', () {
428 expect(scope.$watchSet([], null)()).toBe(null);
429 });
430
431 it('should treat set of 1 as direct watch', () {
432 var lastValues = ['foo'];
433 var log = '';
434 var clean = scope.$watchSet(['a'], (values, oldValues, s) {
435 log += values.join(',') + ';';
436 expect(s).toBe(scope);
437 expect(oldValues).toEqual(lastValues);
438 lastValues = new List.from(values);
439 });
440
441 scope.a = 'foo';
442 scope.$digest();
443 expect(log).toEqual('foo;');
444
445 scope.$digest();
446 expect(log).toEqual('foo;');
447
448 scope.a = 'bar';
449 scope.$digest();
450 expect(log).toEqual('foo;bar;');
451
452 clean();
453 scope.a = 'xxx';
454 scope.$digest();
455 expect(log).toEqual('foo;bar;');
456 });
457
458 it('should detect a change to any one in a set', () {
459 var lastValues = ['foo', 'bar'];
460 var log = '';
461 var clean = scope.$watchSet(['a', 'b'], (values, oldValues, s) {
462 log += values.join(',') + ';';
463 expect(oldValues).toEqual(lastValues);
464 lastValues = new List.from(values);
465 });
466
467 scope.a = 'foo';
468 scope.b = 'bar';
469 scope.$digest();
470 expect(log).toEqual('foo,bar;');
471
472 scope.$digest();
473 expect(log).toEqual('foo,bar;');
474
475 scope.a = 'a';
476 scope.$digest();
477 expect(log).toEqual('foo,bar;a,bar;');
478
479 scope.a = 'A';
480 scope.b = 'B';
481 scope.$digest();
482 expect(log).toEqual('foo,bar;a,bar;A,B;');
483
484 clean();
485 scope.a = 'xxx';
486 scope.$digest();
487 expect(log).toEqual('foo,bar;a,bar;A,B;');
488 });
489 });
490
491
492 describe(r'$destroy', () {
493 var first = null, middle = null, last = null, log = null;
494
495 beforeEach(inject((Scope $rootScope) {
496 log = '';
497
498 first = $rootScope.$new();
499 middle = $rootScope.$new();
500 last = $rootScope.$new();
501
502 first.$watch((s) { log += '1';});
503 middle.$watch((s) { log += '2';});
504 last.$watch((s) { log += '3';});
505
506 $rootScope.$digest();
507 log = '';
508 }));
509
510
511 it(r'should ignore remove on root', inject((Scope $rootScope) {
512 $rootScope.$destroy();
513 $rootScope.$digest();
514 expect(log).toEqual('123');
515 }));
516
517
518 it(r'should remove first', inject((Scope $rootScope) {
519 first.$destroy();
520 $rootScope.$digest();
521 expect(log).toEqual('23');
522 }));
523
524
525 it(r'should remove middle', inject((Scope $rootScope) {
526 middle.$destroy();
527 $rootScope.$digest();
528 expect(log).toEqual('13');
529 }));
530
531
532 it(r'should remove last', inject((Scope $rootScope) {
533 last.$destroy();
534 $rootScope.$digest();
535 expect(log).toEqual('12');
536 }));
537
538
539 it(r'should broadcast the $destroy event', inject((Scope $rootScope) {
540 var log = [];
541 first.$on(r'$destroy', (s) => log.add('first'));
542 first.$new().$on(r'$destroy', (s) => log.add('first-child'));
543
544 first.$destroy();
545 expect(log).toEqual(['first', 'first-child']);
546 }));
547 });
548
549
550 describe(r'$eval', () {
551 it(r'should eval an expression', inject((Scope $rootScope) {
552 expect($rootScope.$eval('a=1')).toEqual(1);
553 expect($rootScope.a).toEqual(1);
554
555 $rootScope.$eval((self, locals) {self.b=2;});
556 expect($rootScope.b).toEqual(2);
557 }));
558
559
560 it(r'should allow passing locals to the expression', inject((Scope $rootSc ope) {
561 expect($rootScope.$eval('a+1', {"a": 2})).toBe(3);
562
563 $rootScope.$eval((scope) {
564 scope['c'] = scope['b'] + 4;
565 }, {"b": 3});
566 expect($rootScope.c).toBe(7);
567 }));
568 });
569
570
571 describe(r'$evalAsync', () {
572
573 it(r'should run callback before $watch', inject((Scope $rootScope) {
574 var log = '';
575 var child = $rootScope.$new();
576 $rootScope.$evalAsync((scope, _) { log += 'parent.async;'; });
577 $rootScope.$watch('value', (_, _0, _1) { log += 'parent.\$digest;'; });
578 child.$evalAsync((scope, _) { log += 'child.async;'; });
579 child.$watch('value', (_, _0, _1) { log += 'child.\$digest;'; });
580 $rootScope.$digest();
581 expect(log).toEqual('parent.async;child.async;parent.\$digest;child.\$di gest;');
582 }));
583
584 it(r'should cause a $digest rerun', inject((Scope $rootScope) {
585 $rootScope.log = '';
586 $rootScope.value = 0;
587 // NOTE(deboer): watch listener string functions not yet supported
588 //$rootScope.$watch('value', 'log = log + ".";');
589 $rootScope.$watch('value', (__, _, scope) { scope.log = scope.log + "."; });
590 $rootScope.$watch('init', (_, __, _0) {
591 $rootScope.$evalAsync('value = 123; log = log + "=" ');
592 expect($rootScope.value).toEqual(0);
593 });
594 $rootScope.$digest();
595 expect($rootScope.log).toEqual('.=.');
596 }));
597
598 it(r'should run async in the same order as added', inject((Scope $rootScop e) {
599 $rootScope.log = '';
600 $rootScope.$evalAsync("log = log + 1");
601 $rootScope.$evalAsync("log = log + 2");
602 $rootScope.$digest();
603 expect($rootScope.log).toEqual('12');
604 }));
605
606 it(r'should allow running after digest', inject((Scope $rootScope) {
607 $rootScope.log = '';
608 $rootScope.$evalAsync(() => $rootScope.log += 'eval;', outsideDigest: tr ue);
609 $rootScope.$watch(() { $rootScope.log += 'digest;'; });
610 $rootScope.$digest();
611 expect($rootScope.log).toEqual('digest;eval;');
612 }));
613
614 it(r'should allow running after digest in issolate scope', inject((Scope $ rootScope) {
615 var isolateScope = $rootScope.$new(isolate: true);
616 isolateScope.log = '';
617 isolateScope.$evalAsync(() => isolateScope.log += 'eval;', outsideDigest : true);
618 isolateScope.$watch(() { isolateScope.log += 'digest;'; });
619 isolateScope.$digest();
620 expect(isolateScope.log).toEqual('digest;eval;');
621 }));
622
623 });
624
625
626 describe(r'$apply', () {
627 it(r'should apply expression with full lifecycle', inject((Scope $rootScop e) {
628 var log = '';
629 var child = $rootScope.$new();
630 $rootScope.$watch('a', (a, _, __) { log += '1'; });
631 child.$apply(r'$parent.a=0');
632 expect(log).toEqual('1');
633 }));
634
635
636 it(r'should catch exceptions', () {
637 module((Module module) => module.type(ExceptionHandler, implementedBy: L oggingExceptionHandler));
638 inject((Scope $rootScope, ExceptionHandler e) {
639 LoggingExceptionHandler $exceptionHandler = e;
640 var log = [];
641 var child = $rootScope.$new();
642 $rootScope.$watch('a', (a, _, __) => log.add('1'));
643 $rootScope.a = 0;
644 child.$apply((_, __) { throw 'MyError'; });
645 expect(log.join(',')).toEqual('1');
646 expect($exceptionHandler.errors[0].error).toEqual('MyError');
647 $exceptionHandler.errors.removeAt(0);
648 $exceptionHandler.assertEmpty();
649 });
650 });
651
652
653 describe(r'exceptions', () {
654 var log;
655 beforeEach(module((Module module) {
656 return module.type(ExceptionHandler, implementedBy: LoggingExceptionHa ndler);
657 }));
658 beforeEach(inject((Scope $rootScope) {
659 log = '';
660 $rootScope.$watch(() { log += '\$digest;'; });
661 $rootScope.$digest();
662 log = '';
663 }));
664
665
666 it(r'should execute and return value and update', inject(
667 (Scope $rootScope, ExceptionHandler e) {
668 LoggingExceptionHandler $exceptionHandler = e;
669 $rootScope.name = 'abc';
670 expect($rootScope.$apply((scope) => scope.name)).toEqual('abc');
671 expect(log).toEqual(r'$digest;');
672 $exceptionHandler.assertEmpty();
673 }));
674
675
676 it(r'should catch exception and update', inject((Scope $rootScope, Excep tionHandler e) {
677 LoggingExceptionHandler $exceptionHandler = e;
678 var error = 'MyError';
679 $rootScope.$apply(() { throw error; });
680 expect(log).toEqual(r'$digest;');
681 expect($exceptionHandler.errors[0].error).toEqual(error);
682 }));
683 });
684
685 it(r'should proprely reset phase on exception', inject((Scope $rootScope) {
686 var error = 'MyError';
687 expect(() =>$rootScope.$apply(() { throw error; })).toThrow(error);
688 expect(() =>$rootScope.$apply(() { throw error; })).toThrow(error);
689 }));
690 });
691
692
693 describe(r'events', () {
694
695 describe(r'$on', () {
696
697 it(r'should add listener for both $emit and $broadcast events', inject(( Scope $rootScope) {
698 var log = '',
699 child = $rootScope.$new();
700
701 eventFn() {
702 log += 'X';
703 }
704
705 child.$on('abc', eventFn);
706 expect(log).toEqual('');
707
708 child.$emit(r'abc');
709 expect(log).toEqual('X');
710
711 child.$broadcast('abc');
712 expect(log).toEqual('XX');
713 }));
714
715
716 it(r'should return a function that deregisters the listener', inject((Sc ope $rootScope) {
717 var log = '',
718 child = $rootScope.$new(),
719 listenerRemove;
720
721 eventFn() {
722 log += 'X';
723 }
724
725 listenerRemove = child.$on('abc', eventFn);
726 expect(log).toEqual('');
727 expect(listenerRemove).toBeDefined();
728
729 child.$emit(r'abc');
730 child.$broadcast('abc');
731 expect(log).toEqual('XX');
732
733 log = '';
734 listenerRemove();
735 child.$emit(r'abc');
736 child.$broadcast('abc');
737 expect(log).toEqual('');
738 }));
739 });
740
741
742 describe(r'$emit', () {
743 var log, child, grandChild, greatGrandChild;
744
745 logger(event) {
746 log.add(event.currentScope.id);
747 }
748
749 beforeEach(module((Module module) {
750 return module.type(ExceptionHandler, implementedBy: LoggingExceptionHa ndler);
751 }));
752 beforeEach(inject((Scope $rootScope) {
753 log = [];
754 child = $rootScope.$new();
755 grandChild = child.$new();
756 greatGrandChild = grandChild.$new();
757
758 $rootScope.id = 0;
759 child.id = 1;
760 grandChild.id = 2;
761 greatGrandChild.id = 3;
762
763 $rootScope.$on('myEvent', logger);
764 child.$on('myEvent', logger);
765 grandChild.$on('myEvent', logger);
766 greatGrandChild.$on('myEvent', logger);
767 }));
768
769 it(r'should bubble event up to the root scope', () {
770 grandChild.$emit(r'myEvent');
771 expect(log.join('>')).toEqual('2>1>0');
772 });
773
774
775 it(r'should dispatch exceptions to the $exceptionHandler',
776 inject((ExceptionHandler e) {
777 LoggingExceptionHandler $exceptionHandler = e;
778 child.$on('myEvent', () { throw 'bubbleException'; });
779 grandChild.$emit(r'myEvent');
780 expect(log.join('>')).toEqual('2>1>0');
781 expect($exceptionHandler.errors[0].error).toEqual('bubbleException');
782 }));
783
784
785 it(r'should allow stopping event propagation', () {
786 child.$on('myEvent', (event) { event.stopPropagation(); });
787 grandChild.$emit(r'myEvent');
788 expect(log.join('>')).toEqual('2>1');
789 });
790
791
792 it(r'should forward method arguments', () {
793 child.$on('abc', (event, arg1, arg2) {
794 expect(event.name).toBe('abc');
795 expect(arg1).toBe('arg1');
796 expect(arg2).toBe('arg2');
797 });
798 child.$emit(r'abc', ['arg1', 'arg2']);
799 });
800
801
802 describe(r'event object', () {
803 it(r'should have methods/properties', () {
804 var event;
805 child.$on('myEvent', (e) {
806 expect(e.targetScope).toBe(grandChild);
807 expect(e.currentScope).toBe(child);
808 expect(e.name).toBe('myEvent');
809 event = e;
810 });
811 grandChild.$emit(r'myEvent');
812 expect(event).toBeDefined();
813 });
814
815
816 it(r'should have preventDefault method and defaultPrevented property', () {
817 var event = grandChild.$emit(r'myEvent');
818 expect(event.defaultPrevented).toBe(false);
819
820 child.$on('myEvent', (event) {
821 event.preventDefault();
822 });
823 event = grandChild.$emit(r'myEvent');
824 expect(event.defaultPrevented).toBe(true);
825 });
826 });
827 });
828
829
830 describe(r'$broadcast', () {
831 describe(r'event propagation', () {
832 var log, child1, child2, child3, grandChild11, grandChild21, grandChil d22, grandChild23,
833 greatGrandChild211;
834
835 logger(event) {
836 log.add(event.currentScope.id);
837 }
838
839 beforeEach(inject((Scope $rootScope) {
840 log = [];
841 child1 = $rootScope.$new();
842 child2 = $rootScope.$new();
843 child3 = $rootScope.$new();
844 grandChild11 = child1.$new();
845 grandChild21 = child2.$new();
846 grandChild22 = child2.$new();
847 grandChild23 = child2.$new();
848 greatGrandChild211 = grandChild21.$new();
849
850 $rootScope.id = 0;
851 child1.id = 1;
852 child2.id = 2;
853 child3.id = 3;
854 grandChild11.id = 11;
855 grandChild21.id = 21;
856 grandChild22.id = 22;
857 grandChild23.id = 23;
858 greatGrandChild211.id = 211;
859
860 $rootScope.$on('myEvent', logger);
861 child1.$on('myEvent', logger);
862 child2.$on('myEvent', logger);
863 child3.$on('myEvent', logger);
864 grandChild11.$on('myEvent', logger);
865 grandChild21.$on('myEvent', logger);
866 grandChild22.$on('myEvent', logger);
867 grandChild23.$on('myEvent', logger);
868 greatGrandChild211.$on('myEvent', logger);
869
870 // R
871 // / | \
872 // 1 2 3
873 // / / | \
874 // 11 21 22 23
875 // |
876 // 211
877 }));
878
879
880 it(r'should broadcast an event from the root scope', inject((Scope $ro otScope) {
881 $rootScope.$broadcast('myEvent');
882 expect(log.join('>')).toEqual('0>1>11>2>21>211>22>23>3');
883 }));
884
885
886 it(r'should broadcast an event from a child scope', () {
887 child2.$broadcast('myEvent');
888 expect(log.join('>')).toEqual('2>21>211>22>23');
889 });
890
891
892 it(r'should broadcast an event from a leaf scope with a sibling', () {
893 grandChild22.$broadcast('myEvent');
894 expect(log.join('>')).toEqual('22');
895 });
896
897
898 it(r'should broadcast an event from a leaf scope without a sibling', ( ) {
899 grandChild23.$broadcast('myEvent');
900 expect(log.join('>')).toEqual('23');
901 });
902
903
904 it(r'should not not fire any listeners for other events', inject((Scop e $rootScope) {
905 $rootScope.$broadcast('fooEvent');
906 expect(log.join('>')).toEqual('');
907 }));
908
909
910 it(r'should return event object', () {
911 var result = child1.$broadcast('some');
912
913 expect(result).toBeDefined();
914 expect(result.name).toBe('some');
915 expect(result.targetScope).toBe(child1);
916 });
917 });
918
919
920 describe(r'listener', () {
921 it(r'should receive event object', inject((Scope $rootScope) {
922 var scope = $rootScope,
923 child = scope.$new(),
924 event;
925
926 child.$on('fooEvent', (e) {
927 event = e;
928 });
929 scope.$broadcast('fooEvent');
930
931 expect(event.name).toBe('fooEvent');
932 expect(event.targetScope).toBe(scope);
933 expect(event.currentScope).toBe(child);
934 }));
935
936
937 it(r'should support passing messages as varargs', inject((Scope $rootS cope) {
938 var scope = $rootScope,
939 child = scope.$new(),
940 args;
941
942 child.$on('fooEvent', (a, b, c, d, e) {
943 args = [a, b, c, d, e];
944 });
945 scope.$broadcast('fooEvent', ['do', 're', 'me', 'fa']);
946
947 expect(args.length).toBe(5);
948 expect(args.sublist(1)).toEqual(['do', 're', 'me', 'fa']);
949 }));
950 });
951 });
952 });
953
954
955 describe('\$watchCollection', () {
956 var log, $rootScope, deregister;
957
958 beforeEach(inject((Scope _$rootScope_) {
959 log = [];
960 $rootScope = _$rootScope_;
961 deregister = $rootScope.$watchCollection('obj', (obj) {
962 log.add(JSON.encode(obj));
963 });
964 }));
965
966
967 it('should not trigger if nothing change', inject((Scope $rootScope) {
968 $rootScope.$digest();
969 expect(log).toEqual(['null']);
970
971 $rootScope.$digest();
972 expect(log).toEqual(['null']);
973 }));
974
975
976 it('should allow deregistration', inject((Scope $rootScope) {
977 $rootScope.obj = [];
978 $rootScope.$digest();
979
980 expect(log).toEqual(['[]']);
981
982 $rootScope.obj.add('a');
983 deregister();
984
985 $rootScope.$digest();
986 expect(log).toEqual(['[]']);
987 }));
988
989
990 describe('array', () {
991 it('should trigger when property changes into array', () {
992 $rootScope.obj = 'test';
993 $rootScope.$digest();
994 expect(log).toEqual(['"test"']);
995
996 $rootScope.obj = [];
997 $rootScope.$digest();
998 expect(log).toEqual(['"test"', '[]']);
999 });
1000
1001
1002 it('should not trigger change when object in collection changes', () {
1003 $rootScope.obj = [{}];
1004 $rootScope.$digest();
1005 expect(log).toEqual(['[{}]']);
1006
1007 $rootScope.obj[0]['name'] = 'foo';
1008 $rootScope.$digest();
1009 expect(log).toEqual(['[{}]']);
1010 });
1011
1012
1013 it('should watch array properties', () {
1014 $rootScope.obj = [];
1015 $rootScope.$digest();
1016 expect(log).toEqual(['[]']);
1017
1018 $rootScope.obj.add('a');
1019 $rootScope.$digest();
1020 expect(log).toEqual(['[]', '["a"]']);
1021
1022 $rootScope.obj[0] = 'b';
1023 $rootScope.$digest();
1024 expect(log).toEqual(['[]', '["a"]', '["b"]']);
1025
1026 $rootScope.obj.add([]);
1027 $rootScope.obj.add({});
1028 log = [];
1029 $rootScope.$digest();
1030 expect(log).toEqual(['["b",[],{}]']);
1031
1032 var temp = $rootScope.obj[1];
1033 $rootScope.obj[1] = $rootScope.obj[2];
1034 $rootScope.obj[2] = temp;
1035 $rootScope.$digest();
1036 expect(log).toEqual([ '["b",[],{}]', '["b",{},[]]' ]);
1037
1038 $rootScope.obj.removeAt(0);
1039 log = [];
1040 $rootScope.$digest();
1041 expect(log).toEqual([ '[{},[]]' ]);
1042 });
1043 });
1044
1045
1046 it('should watch iterable properties', () {
1047 $rootScope.obj = _toJsonableIterable([]);
1048 $rootScope.$digest();
1049 expect(log).toEqual(['[]']);
1050
1051 $rootScope.obj = _toJsonableIterable(['a']);
1052 $rootScope.$digest();
1053 expect(log).toEqual(['[]', '["a"]']);
1054
1055 $rootScope.obj = _toJsonableIterable(['b']);
1056 $rootScope.$digest();
1057 expect(log).toEqual(['[]', '["a"]', '["b"]']);
1058
1059 $rootScope.obj = _toJsonableIterable(['b', [], {}]);
1060 log = [];
1061 $rootScope.$digest();
1062 expect(log).toEqual(['["b",[],{}]']);
1063 });
1064
1065
1066 describe('objects', () {
1067 it('should trigger when property changes into object', () {
1068 $rootScope.obj = 'test';
1069 $rootScope.$digest();
1070 expect(log).toEqual(['"test"']);
1071
1072 $rootScope.obj = {};
1073 $rootScope.$digest();
1074 expect(log).toEqual(['"test"', '{}']);
1075 });
1076
1077
1078 it('should not trigger change when object in collection changes', () {
1079 $rootScope.obj = {'name': {}};
1080 $rootScope.$digest();
1081 expect(log).toEqual(['{"name":{}}']);
1082
1083 $rootScope.obj['name']['bar'] = 'foo';
1084 $rootScope.$digest();
1085 expect(log).toEqual(['{"name":{}}']);
1086 });
1087
1088
1089 it('should watch object properties', () {
1090 $rootScope.obj = {};
1091 $rootScope.$digest();
1092 expect(log).toEqual(['{}']);
1093
1094 $rootScope.obj['a']= 'A';
1095 $rootScope.$digest();
1096 expect(log).toEqual(['{}', '{"a":"A"}']);
1097
1098 $rootScope.obj['a'] = 'B';
1099 $rootScope.$digest();
1100 expect(log).toEqual(['{}', '{"a":"A"}', '{"a":"B"}']);
1101
1102 $rootScope.obj['b'] = [];
1103 $rootScope.obj['c'] = {};
1104 log = [];
1105 $rootScope.$digest();
1106 expect(log).toEqual(['{"a":"B","b":[],"c":{}}']);
1107
1108 var temp = $rootScope.obj['a'];
1109 $rootScope.obj['a'] = $rootScope.obj['b'];
1110 $rootScope.obj['c'] = temp;
1111 $rootScope.$digest();
1112 expect(log).toEqual([ '{"a":"B","b":[],"c":{}}', '{"a":[],"b":[],"c":" B"}' ]);
1113
1114 $rootScope.obj.remove('a');
1115 log = [];
1116 $rootScope.$digest();
1117 expect(log).toEqual([ '{"b":[],"c":"B"}' ]);
1118 });
1119 });
1120 });
1121
1122
1123 describe('perf', () {
1124 describe('counters', () {
1125
1126 it('should expose scope count', inject((Profiler perf, Scope scope) {
1127 scope.$digest();
1128 expect(perf.counters['ng.scopes']).toEqual(1);
1129
1130 scope.$new();
1131 scope.$new();
1132 var lastChild = scope.$new();
1133 scope.$digest();
1134 expect(perf.counters['ng.scopes']).toEqual(4);
1135
1136 // Create a child scope and make sure it's counted as well.
1137 lastChild.$new();
1138 scope.$digest();
1139 expect(perf.counters['ng.scopes']).toEqual(5);
1140 }));
1141
1142
1143 it('should update scope count when scope destroyed',
1144 inject((Profiler perf, Scope scope) {
1145
1146 var child = scope.$new();
1147 scope.$digest();
1148 expect(perf.counters['ng.scopes']).toEqual(2);
1149
1150 child.$destroy();
1151 scope.$digest();
1152 expect(perf.counters['ng.scopes']).toEqual(1);
1153 }));
1154
1155
1156 it('should expose watcher count', inject((Profiler perf, Scope scope) {
1157 scope.$digest();
1158 expect(perf.counters['ng.scope.watchers']).toEqual(0);
1159
1160 scope.$watch(() => 0, (_) {});
1161 scope.$watch(() => 0, (_) {});
1162 scope.$watch(() => 0, (_) {});
1163 scope.$digest();
1164 expect(perf.counters['ng.scope.watchers']).toEqual(3);
1165
1166 // Create a child scope and make sure it's counted as well.
1167 scope.$new().$watch(() => 0, (_) {});
1168 scope.$digest();
1169 expect(perf.counters['ng.scope.watchers']).toEqual(4);
1170 }));
1171
1172
1173 it('should update watcher count when watcher removed',
1174 inject((Profiler perf, Scope scope) {
1175
1176 var unwatch = scope.$new().$watch(() => 0, (_) {});
1177 scope.$digest();
1178 expect(perf.counters['ng.scope.watchers']).toEqual(1);
1179
1180 unwatch();
1181 scope.$digest();
1182 expect(perf.counters['ng.scope.watchers']).toEqual(0);
1183 }));
1184 });
1185 });
1186
1187
1188 describe('optimizations', () {
1189 var scope;
1190 var log;
1191 beforeEach(inject((Scope _scope, Logger _log) {
1192 scope = _scope;
1193 log = _log;
1194 scope['a'] = 1;
1195 scope['b'] = 2;
1196 scope['c'] = 3;
1197 scope.$watch(() {log('a'); return scope['a'];}, (value) => log('fire:a') );
1198 scope.$watch(() {log('b'); return scope['b'];}, (value) => log('fire:b') );
1199 scope.$watch(() {log('c'); return scope['c'];}, (value) {log('fire:c'); scope['b']++; });
1200 scope.$digest();
1201 log.clear();
1202 }));
1203
1204 it('should loop once on no dirty', () {
1205 scope.$digest();
1206 expect(log.result()).toEqual('a; b; c');
1207 });
1208
1209 it('should exit early on second loop', () {
1210 scope['b']++;
1211 scope.$digest();
1212 expect(log.result()).toEqual('a; b; fire:b; c; a');
1213 });
1214
1215 it('should continue checking if second loop dirty', () {
1216 scope['c']++;
1217 scope.$digest();
1218 expect(log.result()).toEqual('a; b; c; fire:c; a; b; fire:b; c; a');
1219 });
1220 });
1221
1222 describe('ScopeLocals', () {
1223 var scope;
1224
1225 beforeEach(inject((Scope _scope) => scope = _scope));
1226
1227 it('should read from locals', () {
1228 scope['a'] = 'XXX';
1229 scope['c'] = 'C';
1230 var scopeLocal = new ScopeLocals(scope, {'a': 'A', 'b': 'B'});
1231 expect(scopeLocal['a']).toEqual('A');
1232 expect(scopeLocal['b']).toEqual('B');
1233 expect(scopeLocal['c']).toEqual('C');
1234 });
1235
1236 it('should write to Scope', () {
1237 scope['a'] = 'XXX';
1238 scope['c'] = 'C';
1239 var scopeLocal = new ScopeLocals(scope, {'a': 'A', 'b': 'B'});
1240
1241 scopeLocal['a'] = 'aW';
1242 scopeLocal['b'] = 'bW';
1243 scopeLocal['c'] = 'cW';
1244
1245 expect(scope['a']).toEqual('aW');
1246 expect(scope['b']).toEqual('bW');
1247 expect(scope['c']).toEqual('cW');
1248
1249 expect(scopeLocal['a']).toEqual('A');
1250 expect(scopeLocal['b']).toEqual('B');
1251 expect(scopeLocal['c']).toEqual('cW');
1252 });
1253 });
1254 });
1255 }
1256
1257 _toJsonableIterable(Iterable source) => new _JsonableIterableWrapper(source);
1258
1259 class _JsonableIterableWrapper<T> implements Iterable<T> {
1260 final Iterable<T> source;
1261
1262 _JsonableIterableWrapper(this.source);
1263
1264 bool any(bool test(T element)) => source.any(test);
1265
1266 bool contains(Object element) => source.contains(element);
1267
1268 T elementAt(int index) => source.elementAt(index);
1269
1270 bool every(bool test(T element)) => source.every(test);
1271
1272 Iterable expand(Iterable f(T element)) => source.expand(f);
1273
1274 T get first => source.first;
1275
1276 T firstWhere(bool test(T element), {T orElse()}) =>
1277 source.firstWhere(test, orElse: orElse);
1278
1279 fold(initialValue, combine(previousValue, T element)) =>
1280 source.fold(initialValue, combine);
1281
1282 void forEach(void f(T element)) => source.forEach(f);
1283
1284 bool get isEmpty => source.isEmpty;
1285
1286 bool get isNotEmpty => source.isNotEmpty;
1287
1288 Iterator<T> get iterator => source.iterator;
1289
1290 String join([String separator = ""]) => source.join(separator);
1291
1292 T get last => source.last;
1293
1294 T lastWhere(bool test(T element), {T orElse()}) =>
1295 source.lastWhere(test, orElse: orElse);
1296
1297 int get length => source.length;
1298
1299 Iterable map(f(T element)) => source.map(f);
1300
1301 T reduce(T combine(T value, T element)) => source.reduce(combine);
1302
1303 T get single => source.single;
1304
1305 T singleWhere(bool test(T element)) => source.singleWhere(test);
1306
1307 Iterable<T> skip(int n) => source.skip(n);
1308
1309 Iterable<T> skipWhile(bool test(T value)) => source.skipWhile(test);
1310
1311 Iterable<T> take(int n) => source.take(n);
1312
1313 Iterable<T> takeWhile(bool test(T value)) => source.takeWhile(test);
1314
1315 List<T> toList({bool growable: true}) => source.toList(growable: growable);
1316
1317 Set<T> toSet() => source.toSet();
1318
1319 Iterable<T> where(bool test(T element)) => source.where(test);
1320
1321 toJson() => source.toList();
1322 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698