@@ -2335,6 +2335,155 @@ export function main() {
2335
2335
} ) ) ;
2336
2336
2337
2337
2338
+ it ( 'should call `$doCheck()` on controller' , async ( ( ) => {
2339
+ const controllerDoCheckA = jasmine . createSpy ( 'controllerDoCheckA' ) ;
2340
+ const controllerDoCheckB = jasmine . createSpy ( 'controllerDoCheckB' ) ;
2341
+
2342
+ // Define `ng1Directive`
2343
+ const ng1DirectiveA : angular . IDirective = {
2344
+ template : 'ng1A' ,
2345
+ bindToController : false ,
2346
+ controller : class { $doCheck ( ) { controllerDoCheckA ( ) ; } }
2347
+ } ;
2348
+
2349
+ const ng1DirectiveB : angular . IDirective = {
2350
+ template : 'ng1B' ,
2351
+ bindToController : true ,
2352
+ controller : class { constructor ( ) { ( this as any ) [ '$doCheck' ] = controllerDoCheckB ; } }
2353
+ } ;
2354
+
2355
+ // Define `Ng1ComponentFacade`
2356
+ @Directive ( { selector : 'ng1A' } )
2357
+ class Ng1ComponentAFacade extends UpgradeComponent {
2358
+ constructor ( elementRef : ElementRef , injector : Injector ) {
2359
+ super ( 'ng1A' , elementRef , injector ) ;
2360
+ }
2361
+ }
2362
+
2363
+ @Directive ( { selector : 'ng1B' } )
2364
+ class Ng1ComponentBFacade extends UpgradeComponent {
2365
+ constructor ( elementRef : ElementRef , injector : Injector ) {
2366
+ super ( 'ng1B' , elementRef , injector ) ;
2367
+ }
2368
+ }
2369
+
2370
+ // Define `Ng2Component`
2371
+ @Component ( { selector : 'ng2' , template : '<ng1A></ng1A> | <ng1B></ng1B>' } )
2372
+ class Ng2Component {
2373
+ }
2374
+
2375
+ // Define `ng1Module`
2376
+ const ng1Module = angular . module ( 'ng1Module' , [ ] )
2377
+ . directive ( 'ng1A' , ( ) => ng1DirectiveA )
2378
+ . directive ( 'ng1B' , ( ) => ng1DirectiveB )
2379
+ . directive ( 'ng2' , downgradeComponent ( { component : Ng2Component } ) ) ;
2380
+
2381
+ // Define `Ng2Module`
2382
+ @NgModule ( {
2383
+ declarations : [ Ng1ComponentAFacade , Ng1ComponentBFacade , Ng2Component ] ,
2384
+ entryComponents : [ Ng2Component ] ,
2385
+ imports : [ BrowserModule , UpgradeModule ]
2386
+ } )
2387
+ class Ng2Module {
2388
+ ngDoBootstrap ( ) { }
2389
+ }
2390
+
2391
+ // Bootstrap
2392
+ const element = html ( `<ng2></ng2>` ) ;
2393
+
2394
+ bootstrap ( platformBrowserDynamic ( ) , Ng2Module , element , ng1Module ) . then ( adapter => {
2395
+ // Initial change
2396
+ expect ( controllerDoCheckA . calls . count ( ) ) . toBe ( 1 ) ;
2397
+ expect ( controllerDoCheckB . calls . count ( ) ) . toBe ( 1 ) ;
2398
+
2399
+ // Run a `$digest`
2400
+ // (Since it's the first one since the `$doCheck` watcher was added,
2401
+ // the `watchFn` will be run twice.)
2402
+ digest ( adapter ) ;
2403
+ expect ( controllerDoCheckA . calls . count ( ) ) . toBe ( 3 ) ;
2404
+ expect ( controllerDoCheckB . calls . count ( ) ) . toBe ( 3 ) ;
2405
+
2406
+ // Run another `$digest`
2407
+ digest ( adapter ) ;
2408
+ expect ( controllerDoCheckA . calls . count ( ) ) . toBe ( 4 ) ;
2409
+ expect ( controllerDoCheckB . calls . count ( ) ) . toBe ( 4 ) ;
2410
+ } ) ;
2411
+ } ) ) ;
2412
+
2413
+ it ( 'should not call `$doCheck()` on scope' , async ( ( ) => {
2414
+ const scopeDoCheck = jasmine . createSpy ( 'scopeDoCheck' ) ;
2415
+
2416
+ // Define `ng1Directive`
2417
+ const ng1DirectiveA : angular . IDirective = {
2418
+ template : 'ng1A' ,
2419
+ bindToController : false ,
2420
+ controller : class {
2421
+ constructor ( private $scope : angular . IScope ) { $scope [ '$doCheck' ] = scopeDoCheck ; }
2422
+ }
2423
+ } ;
2424
+
2425
+ const ng1DirectiveB : angular . IDirective = {
2426
+ template : 'ng1B' ,
2427
+ bindToController : true ,
2428
+ controller : class {
2429
+ constructor ( private $scope : angular . IScope ) { $scope [ '$doCheck' ] = scopeDoCheck ; }
2430
+ }
2431
+ } ;
2432
+
2433
+ // Define `Ng1ComponentFacade`
2434
+ @Directive ( { selector : 'ng1A' } )
2435
+ class Ng1ComponentAFacade extends UpgradeComponent {
2436
+ constructor ( elementRef : ElementRef , injector : Injector ) {
2437
+ super ( 'ng1A' , elementRef , injector ) ;
2438
+ }
2439
+ }
2440
+
2441
+ @Directive ( { selector : 'ng1B' } )
2442
+ class Ng1ComponentBFacade extends UpgradeComponent {
2443
+ constructor ( elementRef : ElementRef , injector : Injector ) {
2444
+ super ( 'ng1B' , elementRef , injector ) ;
2445
+ }
2446
+ }
2447
+
2448
+ // Define `Ng2Component`
2449
+ @Component ( { selector : 'ng2' , template : '<ng1A></ng1A> | <ng1B></ng1B>' } )
2450
+ class Ng2Component {
2451
+ }
2452
+
2453
+ // Define `ng1Module`
2454
+ const ng1Module = angular . module ( 'ng1Module' , [ ] )
2455
+ . directive ( 'ng1A' , ( ) => ng1DirectiveA )
2456
+ . directive ( 'ng1B' , ( ) => ng1DirectiveB )
2457
+ . directive ( 'ng2' , downgradeComponent ( { component : Ng2Component } ) ) ;
2458
+
2459
+ // Define `Ng2Module`
2460
+ @NgModule ( {
2461
+ declarations : [ Ng1ComponentAFacade , Ng1ComponentBFacade , Ng2Component ] ,
2462
+ entryComponents : [ Ng2Component ] ,
2463
+ imports : [ BrowserModule , UpgradeModule ]
2464
+ } )
2465
+ class Ng2Module {
2466
+ ngDoBootstrap ( ) { }
2467
+ }
2468
+
2469
+ // Bootstrap
2470
+ const element = html ( `<ng2></ng2>` ) ;
2471
+
2472
+ bootstrap ( platformBrowserDynamic ( ) , Ng2Module , element , ng1Module ) . then ( adapter => {
2473
+ // Initial change
2474
+ expect ( scopeDoCheck ) . not . toHaveBeenCalled ( ) ;
2475
+
2476
+ // Run a `$digest`
2477
+ digest ( adapter ) ;
2478
+ expect ( scopeDoCheck ) . not . toHaveBeenCalled ( ) ;
2479
+
2480
+ // Run another `$digest`
2481
+ digest ( adapter ) ;
2482
+ expect ( scopeDoCheck ) . not . toHaveBeenCalled ( ) ;
2483
+ } ) ;
2484
+ } ) ) ;
2485
+
2486
+
2338
2487
it ( 'should call `$onDestroy()` on controller' , async ( ( ) => {
2339
2488
const controllerOnDestroyA = jasmine . createSpy ( 'controllerOnDestroyA' ) ;
2340
2489
const controllerOnDestroyB = jasmine . createSpy ( 'controllerOnDestroyB' ) ;
@@ -2525,17 +2674,24 @@ export function main() {
2525
2674
} ) ;
2526
2675
} ) ) ;
2527
2676
2528
- it ( 'should be called in order `$onChanges()` > `$onInit()` > `$postLink()`' , async ( ( ) => {
2677
+ it ( 'should be called in order `$onChanges()` > `$onInit()` > `$doCheck()` > `$postLink()`' ,
2678
+ async ( ( ) => {
2529
2679
// Define `ng1Component`
2530
2680
const ng1Component : angular . IComponent = {
2531
- template : '{{ $ctrl.calls.join(" > ") }}' ,
2681
+ // `$doCheck()` will keep getting called as long as the interpolated value keeps
2682
+ // changing (by appending `> $doCheck`). Only care about the first 4 values.
2683
+ template : '{{ $ctrl.calls.slice(0, 4).join(" > ") }}' ,
2532
2684
bindings : { value : '<' } ,
2533
2685
controller : class {
2534
2686
calls : string [ ] = [ ] ;
2535
2687
2536
- $onChanges ( ) { this . calls . push ( '$onChanges' ) ; } $onInit ( ) {
2537
- this . calls . push ( '$onInit' ) ;
2538
- } $postLink ( ) { this . calls . push ( '$postLink' ) ; }
2688
+ $onChanges ( ) { this . calls . push ( '$onChanges' ) ; }
2689
+
2690
+ $onInit ( ) { this . calls . push ( '$onInit' ) ; }
2691
+
2692
+ $doCheck ( ) { this . calls . push ( '$doCheck' ) ; }
2693
+
2694
+ $postLink ( ) { this . calls . push ( '$postLink' ) ; }
2539
2695
}
2540
2696
} ;
2541
2697
@@ -2573,7 +2729,8 @@ export function main() {
2573
2729
const element = html ( `<ng2></ng2>` ) ;
2574
2730
2575
2731
bootstrap ( platformBrowserDynamic ( ) , Ng2Module , element , ng1Module ) . then ( ( ) => {
2576
- expect ( multiTrim ( element . textContent ) ) . toBe ( '$onChanges > $onInit > $postLink' ) ;
2732
+ expect ( multiTrim ( element . textContent ) )
2733
+ . toBe ( '$onChanges > $onInit > $doCheck > $postLink' ) ;
2577
2734
} ) ;
2578
2735
} ) ) ;
2579
2736
} ) ;
0 commit comments