diff --git a/packages/core/test/acceptance/lifecycle_spec.ts b/packages/core/test/acceptance/lifecycle_spec.ts
index 7c94c95435..a99d80120a 100644
--- a/packages/core/test/acceptance/lifecycle_spec.ts
+++ b/packages/core/test/acceptance/lifecycle_spec.ts
@@ -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: `
test
`,
+ })
+ class Comp {
+ ngAfterViewInit() { afterViewInitCalls++; }
+ }
+
+ @Component({template: ``})
+ 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: `test
`})
+ 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: `test
`,
+ })
+ class Comp {
+ ngAfterViewInit() { events.push('comp'); }
+ }
+
+ @Component({
+ template: ``,
+ })
+ 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: ``,
+ })
+ class Parent {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('parent ' + this.name); }
+ }
+
+ @Component({
+ selector: 'child',
+ template: `test
`,
+ })
+ class Child {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('child of parent ' + this.name); }
+ }
+
+ @Component({
+ template: `
+
+
+ `
+ })
+ 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: `test
`,
+ })
+ class Projected {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('projected ' + this.name); }
+ }
+
+ @Component({
+ selector: 'comp',
+ template: ``,
+ })
+ class Comp {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('comp ' + this.name); }
+ }
+
+ @Component({
+ template: `
+
+
+ `
+ })
+ 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: `test
`,
+ })
+ class ProjectedChild {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('child of projected ' + this.name); }
+ }
+
+ @Component({
+ selector: 'projected',
+ template: ``,
+ })
+ class Projected {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('projected ' + this.name); }
+ }
+
+ @Component({
+ selector: 'comp',
+ template: `
`,
+ })
+ class Comp {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('comp ' + this.name); }
+ }
+
+ @Component({
+ template: `
+
+
+ `
+ })
+ 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: `test
`,
+ })
+ class Comp {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('comp ' + this.name); }
+ }
+
+ @Component({
+ template: `
+
+
+
+ `
+ })
+ 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: `test
`,
+ })
+ class Child {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('child of parent ' + this.name); }
+ }
+ @Component({
+ selector: 'parent',
+ template: ``,
+ })
+ class Parent {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('parent ' + this.name); }
+ }
+
+ @Component({
+ template: `
+
+
+
+ `
+ })
+ 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: `test
`,
+ })
+ class Comp {
+ @Input()
+ name = '';
+
+ ngAfterViewInit() { events.push('comp ' + this.name); }
+ }
+
+ @Component({
+ template: `
+
+
+ `
+ })
+ 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: `
+
+
+ `
+ })
+ 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: `test
`,
+ })
+ class Comp {
+ ngAfterViewChecked() { afterViewCheckedCalls++; }
+ }
+
+ @Component({template: ``})
+ 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: `test
`})
+ 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: `{{value}}
`,
+ })
+ class Comp {
+ @Input()
+ value = '';
+ ngAfterViewChecked() { afterViewCheckedCalls++; }
+ }
+
+ @Component({template: ``})
+ 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: `test
`,
+ })
+ class Child {
+ @Input()
+ name = '';
+
+ ngAfterViewChecked() { events.push('child of parent ' + this.name); }
+ }
+
+ @Component({
+ selector: 'parent',
+ template: ``,
+ })
+ class Parent {
+ @Input()
+ name = '';
+
+ ngAfterViewChecked() { events.push('parent ' + this.name); }
+ }
+
+ @Component({
+ template: `
+
+
+
+ `
+ })
+ 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: `test
`,
+ })
+ class Comp {
+ @Input()
+ name = '';
+
+ ngAfterViewChecked() { events.push('comp ' + this.name); }
+ }
+
+ @Component({
+ template: `
+
+
+ `
+ })
+ 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: `
+
+
+ `
+ })
+ 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',
+ ]);
+ });
+
+});
diff --git a/packages/core/test/render3/lifecycle_spec.ts b/packages/core/test/render3/lifecycle_spec.ts
index 7cd4f67d2b..0989f3db3a 100644
--- a/packages/core/test/render3/lifecycle_spec.ts
+++ b/packages/core/test/render3/lifecycle_spec.ts
@@ -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, 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', () => {
- /** content */
- 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) {
- * content
- * % }
- */
- 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', () => {
- /**
- * content
- *
- * parent template:
- */
- 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', () => {
- /**
- * content
- * content
- *
- * parent template:
- */
- 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', () => {
- /**
- *
- * content
- *
- *
- * parent template:
- *
- *
- * projected comp:
- */
- 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', () => {
- /**
- *
- * content
- *
- * *
- * content
- *
- *
- * parent template:
- *
- *
- * projected comp:
- */
- 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', () => {
- /**
- * content
- * % for(let i = 2; i < 4; i++) {
- * content
- * % }
- * content
- */
- 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', () => {
- /**
- * content
- * % for(let i = 2; i < 4; i++) {
- * content
- * % }
- * content
- */
-
- 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', () => {
- /** content */
- 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', () => {
- /** */
- 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', () => {
- /** */
- 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, 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', () => {
- /** */
- 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) {
- *
- * % }
- */
- 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 temp:
- */
- 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 temp:
- */
- 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', () => {
- /**
- *
- *
- *
- */
- 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', () => {
- /**
- *
- *
- *
- *
- *
- *
- */
- 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', () => {
- /*
- *
- *
- *
- */
- 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]);
-
- /**
- *
- *
- */
- 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', () => {
- /**
- *
- * % for (let i = 0; i < 4; i++) {
- *
- * % }
- *
- */
- 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', () => {
- /**
- *
- * % for(let i = 0; i < 4; i++) {
- *
- * % }
- *
- */
- 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', () => {
- /** */
- 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', () => {
- /** */
- 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', () => {
- /**
- *
- * % for(let i = 0; i < 4; i++) {
- *
- * % }
- *
- */
- 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', () => {
- /** */
- 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', () => {
- /** */
- 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[];