test(ivy): add afterViewInit acceptance tests (#30445)
Migrates afterViewInit and afterViewChecked render3 tests to acceptance tests PR Close #30445
This commit is contained in:
		
							parent
							
								
									a5e06ba629
								
							
						
					
					
						commit
						257e9646d0
					
				| @ -1209,3 +1209,681 @@ describe('afterContentChecked', () => { | ||||
|     ]); | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| describe('afterViewInit', () => { | ||||
|   it('should be called on creation and not in update mode', () => { | ||||
|     let afterViewInitCalls = 0; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       ngAfterViewInit() { afterViewInitCalls++; } | ||||
|     } | ||||
| 
 | ||||
|     @Component({template: `<comp></comp>`}) | ||||
|     class App { | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     // two updates
 | ||||
|     fixture.detectChanges(); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(afterViewInitCalls).toBe(1); | ||||
| 
 | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called on root component in creation mode', () => { | ||||
|     let afterViewInitCalls = 0; | ||||
| 
 | ||||
|     @Component({template: `<p>test</p>`}) | ||||
|     class App { | ||||
|       ngAfterViewInit() { afterViewInitCalls++; } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     // two updates
 | ||||
|     fixture.detectChanges(); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(afterViewInitCalls).toBe(1); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called every time a view is initialized with ngIf', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       ngAfterViewInit() { events.push('comp'); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: `<comp *ngIf="show"></comp>`, | ||||
|     }) | ||||
|     class App { | ||||
|       show = true; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual(['comp', 'app']); | ||||
| 
 | ||||
|     fixture.componentInstance.show = false; | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual(['comp', 'app']); | ||||
| 
 | ||||
|     fixture.componentInstance.show = true; | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual(['comp', 'app', 'comp']); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called in children before parents', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'parent', | ||||
|       template: `<child [name]=name></child>`, | ||||
|     }) | ||||
|     class Parent { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('parent ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'child', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Child { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('child of parent ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|         <parent name="1"></parent> | ||||
|         <parent name="2"></parent> | ||||
|       ` | ||||
|     }) | ||||
|     class App { | ||||
|       ngAfterViewInit() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Parent, Child], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'child of parent 1', | ||||
|       'child of parent 2', | ||||
|       'parent 1', | ||||
|       'parent 2', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called in projected components before their hosts', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'projected', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Projected { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('projected ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<ng-content></ng-content>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('comp ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|         <comp name="1"><projected name="1"></projected></comp> | ||||
|         <comp name="2"><projected name="2"></projected></comp> | ||||
|       ` | ||||
|     }) | ||||
|     class App { | ||||
|       ngAfterViewInit() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp, Projected], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'projected 1', | ||||
|       'comp 1', | ||||
|       'projected 2', | ||||
|       'comp 2', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('should call afterViewInit in content children and host before next host', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'projected-child', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class ProjectedChild { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('child of projected ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'projected', | ||||
|       template: `<projected-child [name]="name"></projected-child>`, | ||||
|     }) | ||||
|     class Projected { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('projected ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<div><ng-content></ng-content></div>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('comp ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|         <comp name="1"><projected name="1"></projected></comp> | ||||
|         <comp name="2"><projected name="2"></projected></comp> | ||||
|       ` | ||||
|     }) | ||||
|     class App { | ||||
|       ngAfterViewInit() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp, Projected, ProjectedChild], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'child of projected 1', | ||||
|       'child of projected 2', | ||||
|       'projected 1', | ||||
|       'comp 1', | ||||
|       'projected 2', | ||||
|       'comp 2', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called in correct order with ngFor', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('comp ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|         <comp name="4"></comp> | ||||
|         <comp *ngFor="let number of numbers" [name]="number"></comp> | ||||
|         <comp name="5"></comp> | ||||
|       ` | ||||
|     }) | ||||
|     class App { | ||||
|       numbers = [0, 1, 2, 3]; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp], | ||||
|       imports: [CommonModule], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'comp 0', | ||||
|       'comp 1', | ||||
|       'comp 2', | ||||
|       'comp 3', | ||||
|       'comp 4', | ||||
|       'comp 5', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called in correct order with for loops with children', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'child', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Child { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('child of parent ' + this.name); } | ||||
|     } | ||||
|     @Component({ | ||||
|       selector: 'parent', | ||||
|       template: `<child [name]="name"></child>`, | ||||
|     }) | ||||
|     class Parent { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('parent ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|         <parent name="4"></parent> | ||||
|         <parent *ngFor="let number of numbers" [name]="number"></parent> | ||||
|         <parent name="5"></parent> | ||||
|       ` | ||||
|     }) | ||||
|     class App { | ||||
|       numbers = [0, 1, 2, 3]; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Parent, Child], | ||||
|       imports: [CommonModule], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'child of parent 0', | ||||
|       'parent 0', | ||||
|       'child of parent 1', | ||||
|       'parent 1', | ||||
|       'child of parent 2', | ||||
|       'parent 2', | ||||
|       'child of parent 3', | ||||
|       'parent 3', | ||||
|       'child of parent 4', | ||||
|       'child of parent 5', | ||||
|       'parent 4', | ||||
|       'parent 5', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called on directives after component', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Directive({ | ||||
|       selector: '[dir]', | ||||
|     }) | ||||
|     class Dir { | ||||
|       @Input('dir') | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('dir ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('comp ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|         <comp name="1" dir="1"></comp> | ||||
|         <comp name="2" dir="2"></comp> | ||||
|       ` | ||||
|     }) | ||||
|     class App { | ||||
|       ngAfterViewInit() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp, Dir], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'comp 1', | ||||
|       'dir 1', | ||||
|       'comp 2', | ||||
|       'dir 2', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called on directives on an element', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Directive({ | ||||
|       selector: '[dir]', | ||||
|     }) | ||||
|     class Dir { | ||||
|       @Input('dir') | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewInit() { events.push('dir ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|         <div dir="1"></div> | ||||
|         <div dir="2"></div> | ||||
|       ` | ||||
|     }) | ||||
|     class App { | ||||
|       ngAfterViewInit() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Dir], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'dir 1', | ||||
|       'dir 2', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| describe('ngAfterViewChecked', () => { | ||||
|   it('should call ngAfterViewChecked every update', () => { | ||||
|     let afterViewCheckedCalls = 0; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       ngAfterViewChecked() { afterViewCheckedCalls++; } | ||||
|     } | ||||
| 
 | ||||
|     @Component({template: `<comp></comp>`}) | ||||
|     class App { | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
| 
 | ||||
|     fixture.detectChanges(); | ||||
|     expect(afterViewCheckedCalls).toBe(1); | ||||
| 
 | ||||
|     fixture.detectChanges(); | ||||
|     expect(afterViewCheckedCalls).toBe(2); | ||||
| 
 | ||||
|     fixture.detectChanges(); | ||||
|     expect(afterViewCheckedCalls).toBe(3); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called on root component', () => { | ||||
|     let afterViewCheckedCalls = 0; | ||||
| 
 | ||||
|     @Component({template: `<p>test</p>`}) | ||||
|     class App { | ||||
|       ngAfterViewChecked() { afterViewCheckedCalls++; } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
| 
 | ||||
|     fixture.detectChanges(); | ||||
|     expect(afterViewCheckedCalls).toBe(1); | ||||
| 
 | ||||
|     fixture.detectChanges(); | ||||
|     expect(afterViewCheckedCalls).toBe(2); | ||||
| 
 | ||||
|     fixture.detectChanges(); | ||||
|     expect(afterViewCheckedCalls).toBe(3); | ||||
|   }); | ||||
| 
 | ||||
|   it('should call ngAfterViewChecked with bindings', () => { | ||||
|     let afterViewCheckedCalls = 0; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<p>{{value}}</p>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       @Input() | ||||
|       value = ''; | ||||
|       ngAfterViewChecked() { afterViewCheckedCalls++; } | ||||
|     } | ||||
| 
 | ||||
|     @Component({template: `<comp [value]="value"></comp>`}) | ||||
|     class App { | ||||
|       value = 1; | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
|     expect(afterViewCheckedCalls).toBe(1); | ||||
| 
 | ||||
|     fixture.componentInstance.value = 1337; | ||||
|     fixture.detectChanges(); | ||||
|     expect(afterViewCheckedCalls).toBe(2); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called in correct order with for loops with children', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'child', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Child { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewChecked() { events.push('child of parent ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'parent', | ||||
|       template: `<child [name]="name"></child>`, | ||||
|     }) | ||||
|     class Parent { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewChecked() { events.push('parent ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|       <parent name="4"></parent> | ||||
|       <parent *ngFor="let number of numbers" [name]="number"></parent> | ||||
|       <parent name="5"></parent> | ||||
|       ` | ||||
|     }) | ||||
|     class App { | ||||
|       numbers = [0, 1, 2, 3]; | ||||
| 
 | ||||
|       ngAfterViewChecked() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Parent, Child], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'child of parent 0', | ||||
|       'parent 0', | ||||
|       'child of parent 1', | ||||
|       'parent 1', | ||||
|       'child of parent 2', | ||||
|       'parent 2', | ||||
|       'child of parent 3', | ||||
|       'parent 3', | ||||
|       'child of parent 4', | ||||
|       'child of parent 5', | ||||
|       'parent 4', | ||||
|       'parent 5', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called on directives after component', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Directive({ | ||||
|       selector: '[dir]', | ||||
|     }) | ||||
|     class Dir { | ||||
|       @Input('dir') | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewChecked() { events.push('dir ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       selector: 'comp', | ||||
|       template: `<p>test</p>`, | ||||
|     }) | ||||
|     class Comp { | ||||
|       @Input() | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewChecked() { events.push('comp ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|       <comp name="1" dir="1"></comp> | ||||
|       <comp name="2" dir="2"></comp> | ||||
|     ` | ||||
|     }) | ||||
|     class App { | ||||
|       ngAfterViewChecked() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Comp, Dir], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'comp 1', | ||||
|       'dir 1', | ||||
|       'comp 2', | ||||
|       'dir 2', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
|   it('should be called on directives on an element', () => { | ||||
|     const events: string[] = []; | ||||
| 
 | ||||
|     @Directive({ | ||||
|       selector: '[dir]', | ||||
|     }) | ||||
|     class Dir { | ||||
|       @Input('dir') | ||||
|       name = ''; | ||||
| 
 | ||||
|       ngAfterViewChecked() { events.push('dir ' + this.name); } | ||||
|     } | ||||
| 
 | ||||
|     @Component({ | ||||
|       template: ` | ||||
|       <div dir="1"></div> | ||||
|       <div dir="2"></div> | ||||
|     ` | ||||
|     }) | ||||
|     class App { | ||||
|       ngAfterViewChecked() { events.push('app'); } | ||||
|     } | ||||
| 
 | ||||
|     TestBed.configureTestingModule({ | ||||
|       declarations: [App, Dir], | ||||
|     }); | ||||
|     const fixture = TestBed.createComponent(App); | ||||
|     fixture.detectChanges(); | ||||
| 
 | ||||
|     expect(events).toEqual([ | ||||
|       'dir 1', | ||||
|       'dir 2', | ||||
|       'app', | ||||
|     ]); | ||||
|   }); | ||||
| 
 | ||||
| }); | ||||
|  | ||||
| @ -116,858 +116,6 @@ describe('lifecycles', () => { | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('afterContentInit', () => { | ||||
|     let events: string[]; | ||||
|     let allEvents: string[]; | ||||
| 
 | ||||
|     beforeEach(() => { | ||||
|       events = []; | ||||
|       allEvents = []; | ||||
|     }); | ||||
| 
 | ||||
|     let Comp = createAfterContentInitComp('comp', function(rf: RenderFlags, ctx: any) { | ||||
|       if (rf & RenderFlags.Create) { | ||||
|         ΔprojectionDef(); | ||||
|         Δprojection(0); | ||||
|       } | ||||
|     }, 1); | ||||
| 
 | ||||
|     let Parent = createAfterContentInitComp('parent', function(rf: RenderFlags, ctx: any) { | ||||
|       if (rf & RenderFlags.Create) { | ||||
|         ΔprojectionDef(); | ||||
|         ΔelementStart(0, 'comp'); | ||||
|         { Δprojection(1); } | ||||
|         ΔelementEnd(); | ||||
|       } | ||||
|       if (rf & RenderFlags.Update) { | ||||
|         ΔelementProperty(0, 'val', Δbind(ctx.val)); | ||||
|       } | ||||
|     }, 2, 1, [Comp]); | ||||
| 
 | ||||
|     let ProjectedComp = createAfterContentInitComp('projected', (rf: RenderFlags, ctx: any) => { | ||||
|       if (rf & RenderFlags.Create) { | ||||
|         ΔprojectionDef(); | ||||
|         Δprojection(0); | ||||
|       } | ||||
|     }, 1); | ||||
| 
 | ||||
|     function createAfterContentInitComp( | ||||
|         name: string, template: ComponentTemplate<any>, consts: number = 0, vars: number = 0, | ||||
|         directives: any[] = []) { | ||||
|       return class Component { | ||||
|         val: string = ''; | ||||
|         ngAfterContentInit() { | ||||
|           events.push(`${name}${this.val}`); | ||||
|           allEvents.push(`${name}${this.val} init`); | ||||
|         } | ||||
|         ngAfterContentChecked() { allEvents.push(`${name}${this.val} check`); } | ||||
| 
 | ||||
|         static ngComponentDef = ΔdefineComponent({ | ||||
|           type: Component, | ||||
|           selectors: [[name]], | ||||
|           factory: () => new Component(), | ||||
|           consts: consts, | ||||
|           vars: vars, | ||||
|           inputs: {val: 'val'}, | ||||
|           template: template, | ||||
|           directives: directives | ||||
|         }); | ||||
|       }; | ||||
|     } | ||||
| 
 | ||||
|     class Directive { | ||||
|       ngAfterContentInit() { events.push('init'); } | ||||
|       ngAfterContentChecked() { events.push('check'); } | ||||
| 
 | ||||
|       static ngDirectiveDef = ΔdefineDirective( | ||||
|           {type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()}); | ||||
|     } | ||||
| 
 | ||||
|     function ForLoopWithChildrenTemplate(rf: RenderFlags, ctx: any) { | ||||
|       if (rf & RenderFlags.Create) { | ||||
|         ΔelementStart(0, 'parent'); | ||||
|         { Δtext(1, 'content'); } | ||||
|         ΔelementEnd(); | ||||
|         Δcontainer(2); | ||||
|         ΔelementStart(3, 'parent'); | ||||
|         { Δtext(4, 'content'); } | ||||
|         ΔelementEnd(); | ||||
|       } | ||||
|       if (rf & RenderFlags.Update) { | ||||
|         ΔelementProperty(0, 'val', 1); | ||||
|         Δselect(3); | ||||
|         ΔelementProperty(3, 'val', 4); | ||||
|         ΔcontainerRefreshStart(2); | ||||
|         { | ||||
|           for (let i = 2; i < 4; i++) { | ||||
|             let rf1 = ΔembeddedViewStart(0, 2, 0); | ||||
|             if (rf1 & RenderFlags.Create) { | ||||
|               ΔelementStart(0, 'parent'); | ||||
|               { Δtext(1, 'content'); } | ||||
|               ΔelementEnd(); | ||||
|             } | ||||
|             if (rf1 & RenderFlags.Update) { | ||||
|               ΔelementProperty(0, 'val', i); | ||||
|             } | ||||
|             ΔembeddedViewEnd(); | ||||
|           } | ||||
|         } | ||||
|         ΔcontainerRefreshEnd(); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     const directives = [Comp, Parent, ProjectedComp, Directive]; | ||||
| 
 | ||||
|     it('should be called only in creation mode', () => { | ||||
|       /** <comp>content</comp> */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'comp'); | ||||
|           { Δtext(1, 'content'); } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|       }, 2, 0, directives); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['comp']); | ||||
| 
 | ||||
|       fixture.update(); | ||||
|       expect(events).toEqual(['comp']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called on root component in creation mode', () => { | ||||
|       const comp = renderComponent(Comp, {hostFeatures: [LifecycleHooksFeature]}); | ||||
|       expect(events).toEqual(['comp']); | ||||
| 
 | ||||
|       markDirty(comp); | ||||
|       requestAnimationFrame.flush(); | ||||
|       expect(events).toEqual(['comp']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called on every init (if blocks)', () => { | ||||
|       /** | ||||
|        * % if (!skip) { | ||||
|        *   <comp>content</comp> | ||||
|        * % } | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           Δcontainer(0); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔcontainerRefreshStart(0); | ||||
|           { | ||||
|             if (!ctx.skip) { | ||||
|               let rf1 = ΔembeddedViewStart(0, 2, 0); | ||||
|               if (rf1 & RenderFlags.Create) { | ||||
|                 ΔelementStart(0, 'comp'); | ||||
|                 { Δtext(1, 'content'); } | ||||
|                 ΔelementEnd(); | ||||
|               } | ||||
|               ΔembeddedViewEnd(); | ||||
|             } | ||||
|           } | ||||
|           ΔcontainerRefreshEnd(); | ||||
|         } | ||||
|       }, 1, 0, directives); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['comp']); | ||||
| 
 | ||||
|       fixture.component.skip = true; | ||||
|       fixture.update(); | ||||
|       expect(events).toEqual(['comp']); | ||||
| 
 | ||||
|       fixture.component.skip = false; | ||||
|       fixture.update(); | ||||
|       expect(events).toEqual(['comp', 'comp']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in parents before children', () => { | ||||
|       /** | ||||
|        * <parent>content</parent> | ||||
|        * | ||||
|        * parent template: <comp><ng-content></ng-content></comp> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'parent'); | ||||
|           { Δtext(1, 'content'); } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|       }, 2, 0, directives); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['parent', 'comp']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called breadth-first in entire parent subtree before any children', () => { | ||||
|       /** | ||||
|        * <parent [val]="1">content</parent> | ||||
|        * <parent [val]="2">content</parent> | ||||
|        * | ||||
|        * parent template: <comp [val]="val"><ng-content></ng-content></comp> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'parent'); | ||||
|           { Δtext(1, 'content'); } | ||||
|           ΔelementEnd(); | ||||
|           ΔelementStart(2, 'parent'); | ||||
|           { Δtext(3, 'content'); } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', 1); | ||||
|           Δselect(2); | ||||
|           ΔelementProperty(2, 'val', 2); | ||||
|         } | ||||
|       }, 4, 0, directives); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['parent1', 'parent2', 'comp1', 'comp2']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in projected components before their hosts', () => { | ||||
|       /** | ||||
|        * <parent> | ||||
|        *   <projected>content</projected> | ||||
|        * </parent> | ||||
|        * | ||||
|        * parent template: | ||||
|        * <comp><ng-content></ng-content></comp> | ||||
|        * | ||||
|        * projected comp: <ng-content></ng-content> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'parent'); | ||||
|           { | ||||
|             ΔelementStart(1, 'projected'); | ||||
|             { Δtext(2, 'content'); } | ||||
|             ΔelementEnd(); | ||||
|           } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|       }, 3, 0, directives); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['projected', 'parent', 'comp']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in projected components and hosts before children', () => { | ||||
|       /** | ||||
|        * <parent [val]="1"> | ||||
|        *   <projected [val]="1">content</projected> | ||||
|        * </parent> | ||||
|        * * <parent [val]="2"> | ||||
|        *   <projected [val]="2">content</projected> | ||||
|        * </parent> | ||||
|        * | ||||
|        * parent template: | ||||
|        * <comp [val]="val"><ng-content></ng-content></comp> | ||||
|        * | ||||
|        * projected comp: <ng-content></ng-content> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'parent'); | ||||
|           { | ||||
|             ΔelementStart(1, 'projected'); | ||||
|             { Δtext(2, 'content'); } | ||||
|             ΔelementEnd(); | ||||
|           } | ||||
|           ΔelementEnd(); | ||||
|           ΔelementStart(3, 'parent'); | ||||
|           { | ||||
|             ΔelementStart(4, 'projected'); | ||||
|             { Δtext(5, 'content'); } | ||||
|             ΔelementEnd(); | ||||
|           } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', 1); | ||||
|           Δselect(1); | ||||
|           ΔelementProperty(1, 'val', 1); | ||||
|           Δselect(3); | ||||
|           ΔelementProperty(3, 'val', 2); | ||||
|           Δselect(4); | ||||
|           ΔelementProperty(4, 'val', 2); | ||||
|         } | ||||
|       }, 6, 0, directives); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['projected1', 'parent1', 'projected2', 'parent2', 'comp1', 'comp2']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in correct order in a for loop', () => { | ||||
|       /** | ||||
|        * <comp [val]="1">content</comp> | ||||
|        * % for(let i = 2; i < 4; i++) { | ||||
|        *   <comp [val]="i">content</comp> | ||||
|        * % } | ||||
|        * <comp [val]="4">content</comp> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'comp'); | ||||
|           { Δtext(1, 'content'); } | ||||
|           ΔelementEnd(); | ||||
|           Δcontainer(2); | ||||
|           ΔelementStart(3, 'comp'); | ||||
|           { Δtext(4, 'content'); } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', 1); | ||||
|           Δselect(3); | ||||
|           ΔelementProperty(3, 'val', 4); | ||||
|           ΔcontainerRefreshStart(2); | ||||
|           { | ||||
|             for (let i = 2; i < 4; i++) { | ||||
|               let rf1 = ΔembeddedViewStart(0, 2, 0); | ||||
|               if (rf1 & RenderFlags.Create) { | ||||
|                 ΔelementStart(0, 'comp'); | ||||
|                 { Δtext(1, 'content'); } | ||||
|                 ΔelementEnd(); | ||||
|               } | ||||
|               if (rf1 & RenderFlags.Update) { | ||||
|                 ΔelementProperty(0, 'val', i); | ||||
|               } | ||||
|               ΔembeddedViewEnd(); | ||||
|             } | ||||
|           } | ||||
|           ΔcontainerRefreshEnd(); | ||||
|         } | ||||
|       }, 5, 0, directives); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['comp2', 'comp3', 'comp1', 'comp4']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in correct order in a for loop with children', () => { | ||||
|       /** | ||||
|        * <parent [val]="1">content</parent> | ||||
|        * % for(let i = 2; i < 4; i++) { | ||||
|        *   <parent [val]="i">content</parent> | ||||
|        * % } | ||||
|        * <parent [val]="4">content</parent> | ||||
|        */ | ||||
| 
 | ||||
|       renderToHtml(ForLoopWithChildrenTemplate, {}, 5, 0, directives); | ||||
|       expect(events).toEqual( | ||||
|           ['parent2', 'comp2', 'parent3', 'comp3', 'parent1', 'parent4', 'comp1', 'comp4']); | ||||
|     }); | ||||
| 
 | ||||
|     describe('ngAfterContentChecked', () => { | ||||
| 
 | ||||
|       it('should be called every change detection run after afterContentInit', () => { | ||||
|         /** <comp>content</comp> */ | ||||
|         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|           if (rf & RenderFlags.Create) { | ||||
|             ΔelementStart(0, 'comp'); | ||||
|             { Δtext(1, 'content'); } | ||||
|             ΔelementEnd(); | ||||
|           } | ||||
|         }, 2, 0, directives); | ||||
| 
 | ||||
|         const fixture = new ComponentFixture(App); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check']); | ||||
| 
 | ||||
|         fixture.update(); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check', 'comp check']); | ||||
|       }); | ||||
| 
 | ||||
|       it('should be called on root component', () => { | ||||
|         const comp = renderComponent(Comp, {hostFeatures: [LifecycleHooksFeature]}); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check']); | ||||
| 
 | ||||
|         markDirty(comp); | ||||
|         requestAnimationFrame.flush(); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check', 'comp check']); | ||||
|       }); | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     describe('directives', () => { | ||||
|       it('should be called on directives after component', () => { | ||||
|         /** <comp directive></comp> */ | ||||
|         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|           if (rf & RenderFlags.Create) { | ||||
|             Δelement(0, 'comp', ['dir', '']); | ||||
|           } | ||||
|         }, 1, 0, directives); | ||||
| 
 | ||||
|         const fixture = new ComponentFixture(App); | ||||
|         expect(events).toEqual(['comp', 'init', 'check']); | ||||
|       }); | ||||
| 
 | ||||
|       it('should be called on directives on an element', () => { | ||||
|         /** <div directive></div> */ | ||||
|         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|           if (rf & RenderFlags.Create) { | ||||
|             Δelement(0, 'div', ['dir', '']); | ||||
|           } | ||||
|         }, 1, 0, directives); | ||||
| 
 | ||||
|         const fixture = new ComponentFixture(App); | ||||
|         expect(events).toEqual(['init', 'check']); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('afterViewInit', () => { | ||||
|     let events: string[]; | ||||
|     let allEvents: string[]; | ||||
| 
 | ||||
|     beforeEach(() => { | ||||
|       events = []; | ||||
|       allEvents = []; | ||||
|     }); | ||||
| 
 | ||||
|     let Comp = createAfterViewInitComponent('comp', (rf: RenderFlags, ctx: any) => { | ||||
|       if (rf & RenderFlags.Create) { | ||||
|         ΔprojectionDef(); | ||||
|         ΔelementStart(0, 'div'); | ||||
|         { Δprojection(1); } | ||||
|         ΔelementEnd(); | ||||
|       } | ||||
|     }, 2); | ||||
|     let Parent = createAfterViewInitComponent('parent', getParentTemplate('comp'), 1, 1, [Comp]); | ||||
| 
 | ||||
|     let ProjectedComp = createAfterViewInitComponent('projected', (rf: RenderFlags, ctx: any) => { | ||||
|       if (rf & RenderFlags.Create) { | ||||
|         Δtext(0, 'content'); | ||||
|       } | ||||
|     }, 1); | ||||
| 
 | ||||
|     function createAfterViewInitComponent( | ||||
|         name: string, template: ComponentTemplate<any>, consts: number, vars: number = 0, | ||||
|         directives: any[] = []) { | ||||
|       return class Component { | ||||
|         val: string = ''; | ||||
|         ngAfterViewInit() { | ||||
|           if (!this.val) this.val = ''; | ||||
|           events.push(`${name}${this.val}`); | ||||
|           allEvents.push(`${name}${this.val} init`); | ||||
|         } | ||||
|         ngAfterViewChecked() { allEvents.push(`${name}${this.val} check`); } | ||||
| 
 | ||||
|         static ngComponentDef = ΔdefineComponent({ | ||||
|           type: Component, | ||||
|           selectors: [[name]], | ||||
|           consts: consts, | ||||
|           vars: vars, | ||||
|           factory: () => new Component(), | ||||
|           inputs: {val: 'val'}, | ||||
|           template: template, | ||||
|           directives: directives | ||||
|         }); | ||||
|       }; | ||||
|     } | ||||
| 
 | ||||
|     class Directive { | ||||
|       ngAfterViewInit() { events.push('init'); } | ||||
|       ngAfterViewChecked() { events.push('check'); } | ||||
| 
 | ||||
|       static ngDirectiveDef = ΔdefineDirective( | ||||
|           {type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()}); | ||||
|     } | ||||
| 
 | ||||
|     const defs = [Comp, Parent, ProjectedComp, Directive]; | ||||
| 
 | ||||
|     it('should be called on init and not in update mode', () => { | ||||
|       /** <comp></comp> */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           Δelement(0, 'comp'); | ||||
|         } | ||||
|       }, 1, 0, defs); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['comp']); | ||||
| 
 | ||||
|       fixture.update(); | ||||
|       expect(events).toEqual(['comp']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called on root component in creation mode', () => { | ||||
|       const comp = renderComponent(Comp, {hostFeatures: [LifecycleHooksFeature]}); | ||||
|       expect(events).toEqual(['comp']); | ||||
| 
 | ||||
|       markDirty(comp); | ||||
|       requestAnimationFrame.flush(); | ||||
|       expect(events).toEqual(['comp']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called every time a view is initialized (if block)', () => { | ||||
|       /* | ||||
|       * % if (!skip) { | ||||
|       *   <comp></comp> | ||||
|       * % } | ||||
|       */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           Δcontainer(0); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔcontainerRefreshStart(0); | ||||
|           { | ||||
|             if (!ctx.skip) { | ||||
|               let rf1 = ΔembeddedViewStart(0, 1, 0); | ||||
|               if (rf1 & RenderFlags.Create) { | ||||
|                 Δelement(0, 'comp'); | ||||
|               } | ||||
|               ΔembeddedViewEnd(); | ||||
|             } | ||||
|           } | ||||
|           ΔcontainerRefreshEnd(); | ||||
|         } | ||||
|       }, 1, 0, defs); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['comp']); | ||||
| 
 | ||||
|       fixture.component.skip = true; | ||||
|       fixture.update(); | ||||
|       expect(events).toEqual(['comp']); | ||||
| 
 | ||||
|       fixture.component.skip = false; | ||||
|       fixture.update(); | ||||
|       expect(events).toEqual(['comp', 'comp']); | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in children before parents', () => { | ||||
|       /** | ||||
|        * <parent></parent> | ||||
|        * | ||||
|        * parent temp: <comp></comp> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           Δelement(0, 'parent'); | ||||
|         } | ||||
|       }, 1, 0, defs); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['comp', 'parent']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called for entire subtree before being called in any parent view comps', () => { | ||||
|       /** | ||||
|        * <parent [val]="1"></parent> | ||||
|        * <parent [val]="2"></parent> | ||||
|        * | ||||
|        *  parent temp: <comp [val]="val"></comp> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           Δelement(0, 'parent'); | ||||
|           Δelement(1, 'parent'); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', 1); | ||||
|           Δselect(1); | ||||
|           ΔelementProperty(1, 'val', 2); | ||||
|         } | ||||
|       }, 2, 0, defs); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['comp1', 'comp2', 'parent1', 'parent2']); | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in projected components before their hosts', () => { | ||||
|       /** | ||||
|        * <comp> | ||||
|        *   <projected></projected> | ||||
|        * </comp> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'comp'); | ||||
|           { Δelement(1, 'projected'); } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|       }, 2, 0, defs); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['projected', 'comp']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should call afterViewInit in content children and host before next host', () => { | ||||
|       /** | ||||
|        * <comp [val]="1"> | ||||
|        *   <projected [val]="1"></projected> | ||||
|        * </comp> | ||||
|        * <comp [val]="2"> | ||||
|        *   <projected [val]="2"></projected> | ||||
|        * </comp> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'comp'); | ||||
|           { Δelement(1, 'projected'); } | ||||
|           ΔelementEnd(); | ||||
|           ΔelementStart(2, 'comp'); | ||||
|           { Δelement(3, 'projected'); } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', 1); | ||||
|           Δselect(1); | ||||
|           ΔelementProperty(1, 'val', 1); | ||||
|           Δselect(2); | ||||
|           ΔelementProperty(2, 'val', 2); | ||||
|           Δselect(3); | ||||
|           ΔelementProperty(3, 'val', 2); | ||||
|         } | ||||
|       }, 4, 0, defs); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['projected1', 'comp1', 'projected2', 'comp2']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should call afterViewInit in content children and hosts before parents', () => { | ||||
|       /* | ||||
|        * <comp [val]="val"> | ||||
|        *   <projected [val]="val"></projected> | ||||
|        * </comp> | ||||
|        */ | ||||
|       const ParentComp = createAfterViewInitComponent('parent', (rf: RenderFlags, ctx: any) => { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           ΔelementStart(0, 'comp'); | ||||
|           { Δelement(1, 'projected'); } | ||||
|           ΔelementEnd(); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', Δbind(ctx.val)); | ||||
|           Δselect(1); | ||||
|           ΔelementProperty(1, 'val', Δbind(ctx.val)); | ||||
|         } | ||||
|       }, 2, 2, [Comp, ProjectedComp]); | ||||
| 
 | ||||
|       /** | ||||
|        * <parent [val]="1"></parent> | ||||
|        * <parent [val]="2"></parent> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           Δelement(0, 'parent'); | ||||
|           Δelement(1, 'parent'); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', 1); | ||||
|           Δselect(1); | ||||
|           ΔelementProperty(1, 'val', 2); | ||||
|         } | ||||
|       }, 2, 0, [ParentComp]); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['projected1', 'comp1', 'projected2', 'comp2', 'parent1', 'parent2']); | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in correct order with for loops', () => { | ||||
|       /** | ||||
|        * <comp [val]="1"></comp> | ||||
|        * % for (let i = 0; i < 4; i++) { | ||||
|        *  <comp [val]="i"></comp> | ||||
|        * % } | ||||
|        * <comp [val]="4"></comp> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           Δelement(0, 'comp'); | ||||
|           Δcontainer(1); | ||||
|           Δelement(2, 'comp'); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', 1); | ||||
|           Δselect(2); | ||||
|           ΔelementProperty(2, 'val', 4); | ||||
|           ΔcontainerRefreshStart(1); | ||||
|           { | ||||
|             for (let i = 2; i < 4; i++) { | ||||
|               let rf1 = ΔembeddedViewStart(0, 1, 0); | ||||
|               if (rf1 & RenderFlags.Create) { | ||||
|                 Δelement(0, 'comp'); | ||||
|               } | ||||
|               if (rf1 & RenderFlags.Update) { | ||||
|                 ΔelementProperty(0, 'val', i); | ||||
|               } | ||||
|               ΔembeddedViewEnd(); | ||||
|             } | ||||
|           } | ||||
|           ΔcontainerRefreshEnd(); | ||||
|         } | ||||
|       }, 3, 0, defs); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual(['comp2', 'comp3', 'comp1', 'comp4']); | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     it('should be called in correct order with for loops with children', () => { | ||||
|       /** | ||||
|        * <parent [val]="1"></parent> | ||||
|        * % for(let i = 0; i < 4; i++) { | ||||
|        *  <parent [val]="i"></parent> | ||||
|        * % } | ||||
|        * <parent [val]="4"></parent> | ||||
|        */ | ||||
|       const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|         if (rf & RenderFlags.Create) { | ||||
|           Δelement(0, 'parent'); | ||||
|           Δcontainer(1); | ||||
|           Δelement(2, 'parent'); | ||||
|         } | ||||
|         if (rf & RenderFlags.Update) { | ||||
|           ΔelementProperty(0, 'val', 1); | ||||
|           Δselect(2); | ||||
|           ΔelementProperty(2, 'val', 4); | ||||
|           ΔcontainerRefreshStart(1); | ||||
|           { | ||||
|             for (let i = 2; i < 4; i++) { | ||||
|               let rf1 = ΔembeddedViewStart(0, 1, 0); | ||||
|               if (rf1 & RenderFlags.Create) { | ||||
|                 Δelement(0, 'parent'); | ||||
|               } | ||||
|               if (rf1 & RenderFlags.Update) { | ||||
|                 ΔelementProperty(0, 'val', i); | ||||
|               } | ||||
|               ΔembeddedViewEnd(); | ||||
|             } | ||||
|           } | ||||
|           ΔcontainerRefreshEnd(); | ||||
|         } | ||||
|       }, 3, 0, defs); | ||||
| 
 | ||||
|       const fixture = new ComponentFixture(App); | ||||
|       expect(events).toEqual( | ||||
|           ['comp2', 'parent2', 'comp3', 'parent3', 'comp1', 'comp4', 'parent1', 'parent4']); | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     describe('ngAfterViewChecked', () => { | ||||
| 
 | ||||
|       it('should call ngAfterViewChecked every update', () => { | ||||
|         /** <comp></comp> */ | ||||
|         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|           if (rf & RenderFlags.Create) { | ||||
|             Δelement(0, 'comp'); | ||||
|           } | ||||
|         }, 1, 0, defs); | ||||
| 
 | ||||
|         const fixture = new ComponentFixture(App); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check']); | ||||
| 
 | ||||
|         fixture.update(); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check', 'comp check']); | ||||
|       }); | ||||
| 
 | ||||
|       it('should be called on root component', () => { | ||||
|         const comp = renderComponent(Comp, {hostFeatures: [LifecycleHooksFeature]}); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check']); | ||||
| 
 | ||||
|         markDirty(comp); | ||||
|         requestAnimationFrame.flush(); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check', 'comp check']); | ||||
|       }); | ||||
| 
 | ||||
|       it('should call ngAfterViewChecked with bindings', () => { | ||||
|         /** <comp [val]="myVal"></comp> */ | ||||
|         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|           if (rf & RenderFlags.Create) { | ||||
|             Δelement(0, 'comp'); | ||||
|           } | ||||
|           if (rf & RenderFlags.Update) { | ||||
|             ΔelementProperty(0, 'val', Δbind(ctx.myVal)); | ||||
|           } | ||||
|         }, 1, 1, defs); | ||||
| 
 | ||||
|         const fixture = new ComponentFixture(App); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check']); | ||||
| 
 | ||||
|         fixture.component.myVal = 2; | ||||
|         fixture.update(); | ||||
|         expect(allEvents).toEqual(['comp init', 'comp check', 'comp2 check']); | ||||
|       }); | ||||
| 
 | ||||
|       it('should be called in correct order with for loops with children', () => { | ||||
|         /** | ||||
|          * <parent [val]="1"></parent> | ||||
|          * % for(let i = 0; i < 4; i++) { | ||||
|        *  <parent [val]="i"></parent> | ||||
|        * % } | ||||
|          * <parent [val]="4"></parent> | ||||
|          */ | ||||
|         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|           if (rf & RenderFlags.Create) { | ||||
|             Δelement(0, 'parent'); | ||||
|             Δcontainer(1); | ||||
|             Δelement(2, 'parent'); | ||||
|           } | ||||
|           if (rf & RenderFlags.Update) { | ||||
|             ΔelementProperty(0, 'val', 1); | ||||
|             Δselect(2); | ||||
|             ΔelementProperty(2, 'val', 4); | ||||
|             ΔcontainerRefreshStart(1); | ||||
|             { | ||||
|               for (let i = 2; i < 4; i++) { | ||||
|                 let rf1 = ΔembeddedViewStart(0, 1, 0); | ||||
|                 if (rf1 & RenderFlags.Create) { | ||||
|                   Δelement(0, 'parent'); | ||||
|                 } | ||||
|                 if (rf1 & RenderFlags.Update) { | ||||
|                   ΔelementProperty(0, 'val', i); | ||||
|                 } | ||||
|                 ΔembeddedViewEnd(); | ||||
|               } | ||||
|             } | ||||
|             ΔcontainerRefreshEnd(); | ||||
|           } | ||||
|         }, 3, 0, defs); | ||||
| 
 | ||||
|         const fixture = new ComponentFixture(App); | ||||
|         expect(allEvents).toEqual([ | ||||
|           'comp2 init', 'comp2 check', 'parent2 init', 'parent2 check', 'comp3 init', 'comp3 check', | ||||
|           'parent3 init', 'parent3 check', 'comp1 init', 'comp1 check', 'comp4 init', 'comp4 check', | ||||
|           'parent1 init', 'parent1 check', 'parent4 init', 'parent4 check' | ||||
|         ]); | ||||
| 
 | ||||
|       }); | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
|     describe('directives', () => { | ||||
|       it('should be called on directives after component', () => { | ||||
|         /** <comp directive></comp> */ | ||||
|         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|           if (rf & RenderFlags.Create) { | ||||
|             Δelement(0, 'comp', ['dir', '']); | ||||
|           } | ||||
|         }, 1, 0, defs); | ||||
| 
 | ||||
|         const fixture = new ComponentFixture(App); | ||||
|         expect(events).toEqual(['comp', 'init', 'check']); | ||||
|       }); | ||||
| 
 | ||||
|       it('should be called on directives on an element', () => { | ||||
|         /** <div directive></div> */ | ||||
|         const App = createComponent('app', function(rf: RenderFlags, ctx: any) { | ||||
|           if (rf & RenderFlags.Create) { | ||||
|             Δelement(0, 'div', ['dir', '']); | ||||
|           } | ||||
|         }, 1, 0, defs); | ||||
| 
 | ||||
|         const fixture = new ComponentFixture(App); | ||||
|         expect(events).toEqual(['init', 'check']); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('onDestroy', () => { | ||||
|     let events: string[]; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user