| OLD | NEW |
| (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 } |
| OLD | NEW |