| 
									
										
										
										
											2021-03-11 18:43:23 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import {ProfilerEvent, setProfiler} from '@angular/core/src/render3/profiler'; | 
					
						
							|  |  |  | import {TestBed} from '@angular/core/testing'; | 
					
						
							|  |  |  | import {expect} from '@angular/core/testing/src/testing_internal'; | 
					
						
							|  |  |  | import {onlyInIvy} from '@angular/private/testing'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 13:46:57 -07:00
										 |  |  | import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, Component, DoCheck, ErrorHandler, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild} from '../../src/core'; | 
					
						
							| 
									
										
										
										
											2021-03-11 18:43:23 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | onlyInIvy('Ivy-specific functionality').describe('profiler', () => { | 
					
						
							|  |  |  |   class Profiler { | 
					
						
							|  |  |  |     profile() {} | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let profilerSpy: jasmine.Spy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   beforeEach(() => { | 
					
						
							|  |  |  |     const profiler = new Profiler(); | 
					
						
							|  |  |  |     profilerSpy = spyOn(profiler, 'profile').and.callThrough(); | 
					
						
							|  |  |  |     setProfiler(profiler.profile); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   afterAll(() => setProfiler(null)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function findProfilerCall(condition: ProfilerEvent|((args: any[]) => boolean)) { | 
					
						
							|  |  |  |     let predicate: (args: any[]) => boolean = _ => true; | 
					
						
							|  |  |  |     if (typeof condition !== 'function') { | 
					
						
							|  |  |  |       predicate = (args: any[]) => args[0] === condition; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       predicate = condition; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return profilerSpy.calls.all().map((call: any) => call.args).find(predicate); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('change detection hooks', () => { | 
					
						
							|  |  |  |     it('should call the profiler for creation and change detection', () => { | 
					
						
							|  |  |  |       @Component({selector: 'my-comp', template: '<button (click)="onClick()"></button>'}) | 
					
						
							|  |  |  |       class MyComponent { | 
					
						
							|  |  |  |         onClick() {} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       TestBed.configureTestingModule({declarations: [MyComponent]}); | 
					
						
							|  |  |  |       const fixture = TestBed.createComponent(MyComponent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(profilerSpy).toHaveBeenCalled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const templateCreateStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.TemplateCreateStart && | 
					
						
							|  |  |  |               args[1] === fixture.componentInstance); | 
					
						
							|  |  |  |       const templateCreateEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.TemplateCreateEnd && args[1] === fixture.componentInstance); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(templateCreateStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(templateCreateEnd).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const templateUpdateStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.TemplateUpdateStart && | 
					
						
							|  |  |  |               args[1] === fixture.componentInstance); | 
					
						
							|  |  |  |       const templateUpdateEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.TemplateUpdateEnd && args[1] === fixture.componentInstance); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(templateUpdateStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(templateUpdateEnd).toBeTruthy(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should invoke the profiler when the template throws', () => { | 
					
						
							|  |  |  |       @Component({selector: 'my-comp', template: '{{ throw() }}'}) | 
					
						
							|  |  |  |       class MyComponent { | 
					
						
							|  |  |  |         throw() { | 
					
						
							|  |  |  |           throw new Error(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       TestBed.configureTestingModule({declarations: [MyComponent]}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       let myComp: MyComponent; | 
					
						
							|  |  |  |       expect(() => { | 
					
						
							|  |  |  |         const fixture = TestBed.createComponent(MyComponent); | 
					
						
							|  |  |  |         myComp = fixture.componentInstance; | 
					
						
							|  |  |  |         fixture.detectChanges(); | 
					
						
							|  |  |  |       }).toThrow(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(profilerSpy).toHaveBeenCalled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const templateCreateStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.TemplateCreateStart && args[1] === myComp); | 
					
						
							|  |  |  |       const templateCreateEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.TemplateCreateEnd && args[1] === myComp); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(templateCreateStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(templateCreateEnd).toBeTruthy(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('outputs and events', () => { | 
					
						
							|  |  |  |     it('should invoke the profiler on event handler', () => { | 
					
						
							|  |  |  |       @Component({selector: 'my-comp', template: '<button (click)="onClick()"></button>'}) | 
					
						
							|  |  |  |       class MyComponent { | 
					
						
							|  |  |  |         onClick() {} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       TestBed.configureTestingModule({declarations: [MyComponent]}); | 
					
						
							|  |  |  |       const fixture = TestBed.createComponent(MyComponent); | 
					
						
							|  |  |  |       const myComp = fixture.componentInstance; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const clickSpy = spyOn(myComp, 'onClick'); | 
					
						
							|  |  |  |       const button = fixture.nativeElement.querySelector('button')!; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       button.click(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(clickSpy).toHaveBeenCalled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const outputStart = findProfilerCall(ProfilerEvent.OutputStart); | 
					
						
							|  |  |  |       const outputEnd = findProfilerCall(ProfilerEvent.OutputEnd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(outputStart[1]).toEqual(myComp!); | 
					
						
							|  |  |  |       expect(outputEnd[1]).toEqual(myComp!); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should invoke the profiler on event handler even when it throws', () => { | 
					
						
							|  |  |  |       @Component({selector: 'my-comp', template: '<button (click)="onClick()"></button>'}) | 
					
						
							|  |  |  |       class MyComponent { | 
					
						
							|  |  |  |         onClick() { | 
					
						
							|  |  |  |           throw new Error(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const handler = new ErrorHandler(); | 
					
						
							|  |  |  |       const errorSpy = spyOn(handler, 'handleError'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       TestBed.configureTestingModule( | 
					
						
							|  |  |  |           {declarations: [MyComponent], providers: [{provide: ErrorHandler, useValue: handler}]}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const fixture = TestBed.createComponent(MyComponent); | 
					
						
							|  |  |  |       const myComp = fixture.componentInstance; | 
					
						
							|  |  |  |       const button = fixture.nativeElement.querySelector('button')!; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       button.click(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(errorSpy).toHaveBeenCalled(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const outputStart = findProfilerCall(ProfilerEvent.OutputStart); | 
					
						
							|  |  |  |       const outputEnd = findProfilerCall(ProfilerEvent.OutputEnd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(outputStart[1]).toEqual(myComp!); | 
					
						
							|  |  |  |       expect(outputEnd[1]).toEqual(myComp!); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it('should invoke the profiler on output handler execution', async () => { | 
					
						
							|  |  |  |       @Component({selector: 'child', template: ''}) | 
					
						
							|  |  |  |       class Child { | 
					
						
							|  |  |  |         @Output() childEvent = new EventEmitter(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Component({selector: 'my-comp', template: '<child (childEvent)="onEvent()"></child>'}) | 
					
						
							|  |  |  |       class MyComponent { | 
					
						
							|  |  |  |         @ViewChild(Child) child!: Child; | 
					
						
							|  |  |  |         onEvent() {} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       TestBed.configureTestingModule({declarations: [MyComponent, Child]}); | 
					
						
							|  |  |  |       const fixture = TestBed.createComponent(MyComponent); | 
					
						
							|  |  |  |       const myComp = fixture.componentInstance; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       myComp.child!.childEvent.emit(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const outputStart = findProfilerCall(ProfilerEvent.OutputStart); | 
					
						
							|  |  |  |       const outputEnd = findProfilerCall(ProfilerEvent.OutputEnd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(outputStart[1]).toEqual(myComp!); | 
					
						
							|  |  |  |       expect(outputEnd[1]).toEqual(myComp!); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe('lifecycle hooks', () => { | 
					
						
							|  |  |  |     it('should call the profiler on lifecycle execution', () => { | 
					
						
							| 
									
										
										
										
											2021-05-06 13:46:57 -07:00
										 |  |  |       class Service implements OnDestroy { | 
					
						
							|  |  |  |         ngOnDestroy() {} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       @Component({selector: 'my-comp', template: '{{prop}}', providers: [Service]}) | 
					
						
							| 
									
										
										
										
											2021-03-11 18:43:23 -08:00
										 |  |  |       class MyComponent implements OnInit, AfterViewInit, AfterViewChecked, AfterContentInit, | 
					
						
							| 
									
										
										
										
											2021-05-06 13:46:57 -07:00
										 |  |  |                                    AfterContentChecked, OnChanges, DoCheck, OnDestroy { | 
					
						
							| 
									
										
										
										
											2021-03-11 18:43:23 -08:00
										 |  |  |         @Input() prop = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-06 13:46:57 -07:00
										 |  |  |         constructor(private service: Service) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-11 18:43:23 -08:00
										 |  |  |         ngOnInit() {} | 
					
						
							|  |  |  |         ngDoCheck() {} | 
					
						
							| 
									
										
										
										
											2021-05-06 13:46:57 -07:00
										 |  |  |         ngOnDestroy() {} | 
					
						
							| 
									
										
										
										
											2021-03-11 18:43:23 -08:00
										 |  |  |         ngOnChanges() {} | 
					
						
							|  |  |  |         ngAfterViewInit() {} | 
					
						
							|  |  |  |         ngAfterViewChecked() {} | 
					
						
							|  |  |  |         ngAfterContentInit() {} | 
					
						
							|  |  |  |         ngAfterContentChecked() {} | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       @Component({selector: 'my-parent', template: '<my-comp [prop]="prop"></my-comp>'}) | 
					
						
							|  |  |  |       class MyParent { | 
					
						
							|  |  |  |         prop = 1; | 
					
						
							|  |  |  |         @ViewChild(MyComponent) child!: MyComponent; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       TestBed.configureTestingModule({declarations: [MyParent, MyComponent]}); | 
					
						
							|  |  |  |       const fixture = TestBed.createComponent(MyParent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const myParent = fixture.componentInstance; | 
					
						
							|  |  |  |       const myComp = fixture.componentInstance.child; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const ngOnInitStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookStart && args[2] === myComp.ngOnInit); | 
					
						
							|  |  |  |       const ngOnInitEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookEnd && args[2] === myComp.ngOnInit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(ngOnInitStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(ngOnInitEnd).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const ngOnDoCheckStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookStart && args[2] === myComp.ngDoCheck); | 
					
						
							|  |  |  |       const ngOnDoCheckEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookEnd && args[2] === myComp.ngDoCheck); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(ngOnDoCheckStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(ngOnDoCheckEnd).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const ngAfterViewInitStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookStart && args[2] === myComp.ngAfterViewInit); | 
					
						
							|  |  |  |       const ngAfterViewInitEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookEnd && args[2] === myComp.ngAfterViewInit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(ngAfterViewInitStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(ngAfterViewInitEnd).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const ngAfterViewCheckedStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.LifecycleHookStart && | 
					
						
							|  |  |  |               args[2] === myComp.ngAfterViewChecked); | 
					
						
							|  |  |  |       const ngAfterViewCheckedEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookEnd && args[2] === myComp.ngAfterViewChecked); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(ngAfterViewCheckedStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(ngAfterViewCheckedEnd).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const ngAfterContentInitStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.LifecycleHookStart && | 
					
						
							|  |  |  |               args[2] === myComp.ngAfterContentInit); | 
					
						
							|  |  |  |       const ngAfterContentInitEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookEnd && args[2] === myComp.ngAfterContentInit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(ngAfterContentInitStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(ngAfterContentInitEnd).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const ngAfterContentCheckedStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.LifecycleHookStart && | 
					
						
							|  |  |  |               args[2] === myComp.ngAfterContentChecked); | 
					
						
							|  |  |  |       const ngAfterContentChecked = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.LifecycleHookEnd && | 
					
						
							|  |  |  |               args[2] === myComp.ngAfterContentChecked); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(ngAfterContentCheckedStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(ngAfterContentChecked).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Verify we call `ngOnChanges` and the corresponding profiler hooks
 | 
					
						
							|  |  |  |       const onChangesSpy = spyOn(myComp, 'ngOnChanges'); | 
					
						
							|  |  |  |       profilerSpy.calls.reset(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       myParent.prop = 2; | 
					
						
							|  |  |  |       fixture.detectChanges(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const ngOnChangesStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.LifecycleHookStart && args[2] && | 
					
						
							|  |  |  |               args[2].name && args[2].name.indexOf('OnChangesHook') >= 0); | 
					
						
							|  |  |  |       const ngOnChangesEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.LifecycleHookEnd && args[2] && args[2].name && | 
					
						
							|  |  |  |               args[2].name.indexOf('OnChangesHook') >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(onChangesSpy).toHaveBeenCalled(); | 
					
						
							|  |  |  |       expect(ngOnChangesStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(ngOnChangesEnd).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-05-06 13:46:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       fixture.destroy(); | 
					
						
							|  |  |  |       const ngOnDestroyStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookStart && args[2] === myComp.ngOnDestroy); | 
					
						
							|  |  |  |       const ngOnDestroyEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => | 
					
						
							|  |  |  |               args[0] === ProfilerEvent.LifecycleHookEnd && args[2] === myComp.ngOnDestroy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(ngOnDestroyStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(ngOnDestroyEnd).toBeTruthy(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const serviceNgOnDestroyStart = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.LifecycleHookStart && | 
					
						
							|  |  |  |               args[2] === Service.prototype.ngOnDestroy); | 
					
						
							|  |  |  |       const serviceNgOnDestroyEnd = findProfilerCall( | 
					
						
							|  |  |  |           (args: any[]) => args[0] === ProfilerEvent.LifecycleHookEnd && | 
					
						
							|  |  |  |               args[2] === Service.prototype.ngOnDestroy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       expect(serviceNgOnDestroyStart).toBeTruthy(); | 
					
						
							|  |  |  |       expect(serviceNgOnDestroyEnd).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-03-11 18:43:23 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   it('should call the profiler on lifecycle execution even after error', () => { | 
					
						
							|  |  |  |     @Component({selector: 'my-comp', template: ''}) | 
					
						
							|  |  |  |     class MyComponent implements OnInit { | 
					
						
							|  |  |  |       ngOnInit() { | 
					
						
							|  |  |  |         throw new Error(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     TestBed.configureTestingModule({declarations: [MyComponent]}); | 
					
						
							|  |  |  |     const fixture = TestBed.createComponent(MyComponent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(() => { | 
					
						
							|  |  |  |       fixture.detectChanges(); | 
					
						
							|  |  |  |     }).toThrow(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const lifecycleStart = findProfilerCall(ProfilerEvent.LifecycleHookStart); | 
					
						
							|  |  |  |     const lifecycleEnd = findProfilerCall(ProfilerEvent.LifecycleHookEnd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     expect(lifecycleStart).toBeTruthy(); | 
					
						
							|  |  |  |     expect(lifecycleEnd).toBeTruthy(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); |