|
|
|
@ -10,142 +10,143 @@ import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit,
|
|
|
|
|
import {TestBed} from '@angular/core/testing';
|
|
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
describe('lifecycle hooks examples', () => {
|
|
|
|
|
it('should work with ngOnInit', () => {
|
|
|
|
|
// #docregion OnInit
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements OnInit {
|
|
|
|
|
ngOnInit() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
describe('lifecycle hooks examples', () => {
|
|
|
|
|
it('should work with ngOnInit', () => {
|
|
|
|
|
// #docregion OnInit
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements OnInit {
|
|
|
|
|
ngOnInit() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngOnInit', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngDoCheck', () => {
|
|
|
|
|
// #docregion DoCheck
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements DoCheck {
|
|
|
|
|
ngDoCheck() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngDoCheck', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngAfterContentChecked', () => {
|
|
|
|
|
// #docregion AfterContentChecked
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements AfterContentChecked {
|
|
|
|
|
ngAfterContentChecked() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngAfterContentChecked', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngAfterContentInit', () => {
|
|
|
|
|
// #docregion AfterContentInit
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements AfterContentInit {
|
|
|
|
|
ngAfterContentInit() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngAfterContentInit', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngAfterViewChecked', () => {
|
|
|
|
|
// #docregion AfterViewChecked
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements AfterViewChecked {
|
|
|
|
|
ngAfterViewChecked() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngAfterViewChecked', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngAfterViewInit', () => {
|
|
|
|
|
// #docregion AfterViewInit
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements AfterViewInit {
|
|
|
|
|
ngAfterViewInit() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngAfterViewInit', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngOnDestroy', () => {
|
|
|
|
|
// #docregion OnDestroy
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements OnDestroy {
|
|
|
|
|
ngOnDestroy() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngOnDestroy', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngOnChanges', () => {
|
|
|
|
|
// #docregion OnChanges
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements OnChanges {
|
|
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
@Input()
|
|
|
|
|
prop !: number;
|
|
|
|
|
|
|
|
|
|
ngOnChanges(changes: SimpleChanges) {
|
|
|
|
|
// changes.prop contains the old and the new value...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
const log = createAndLogComponent(MyComponent, ['prop']);
|
|
|
|
|
expect(log.length).toBe(1);
|
|
|
|
|
expect(log[0][0]).toBe('ngOnChanges');
|
|
|
|
|
const changes: SimpleChanges = log[0][1][0];
|
|
|
|
|
expect(changes['prop'].currentValue).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngOnInit', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function createAndLogComponent(clazz: Type<any>, inputs: string[] = []): any[] {
|
|
|
|
|
const log: any[] = [];
|
|
|
|
|
createLoggingSpiesFromProto(clazz, log);
|
|
|
|
|
|
|
|
|
|
const inputBindings = inputs.map(input => `[${input}] = true`).join(' ');
|
|
|
|
|
|
|
|
|
|
@Component({template: `<my-cmp ${inputBindings}></my-cmp>`})
|
|
|
|
|
class ParentComponent {
|
|
|
|
|
it('should work with ngDoCheck', () => {
|
|
|
|
|
// #docregion DoCheck
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements DoCheck {
|
|
|
|
|
ngDoCheck() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngDoCheck', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const fixture = TestBed.configureTestingModule({declarations: [ParentComponent, clazz]})
|
|
|
|
|
.createComponent(ParentComponent);
|
|
|
|
|
fixture.detectChanges();
|
|
|
|
|
fixture.destroy();
|
|
|
|
|
return log;
|
|
|
|
|
it('should work with ngAfterContentChecked', () => {
|
|
|
|
|
// #docregion AfterContentChecked
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements AfterContentChecked {
|
|
|
|
|
ngAfterContentChecked() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngAfterContentChecked', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngAfterContentInit', () => {
|
|
|
|
|
// #docregion AfterContentInit
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements AfterContentInit {
|
|
|
|
|
ngAfterContentInit() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngAfterContentInit', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngAfterViewChecked', () => {
|
|
|
|
|
// #docregion AfterViewChecked
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements AfterViewChecked {
|
|
|
|
|
ngAfterViewChecked() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngAfterViewChecked', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngAfterViewInit', () => {
|
|
|
|
|
// #docregion AfterViewInit
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements AfterViewInit {
|
|
|
|
|
ngAfterViewInit() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngAfterViewInit', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngOnDestroy', () => {
|
|
|
|
|
// #docregion OnDestroy
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements OnDestroy {
|
|
|
|
|
ngOnDestroy() {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
expect(createAndLogComponent(MyComponent)).toEqual([['ngOnDestroy', []]]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work with ngOnChanges', () => {
|
|
|
|
|
// #docregion OnChanges
|
|
|
|
|
@Component({selector: 'my-cmp', template: `...`})
|
|
|
|
|
class MyComponent implements OnChanges {
|
|
|
|
|
// TODO(issue/24571): remove '!'.
|
|
|
|
|
@Input() prop!: number;
|
|
|
|
|
|
|
|
|
|
ngOnChanges(changes: SimpleChanges) {
|
|
|
|
|
// changes.prop contains the old and the new value...
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// #enddocregion
|
|
|
|
|
|
|
|
|
|
const log = createAndLogComponent(MyComponent, ['prop']);
|
|
|
|
|
expect(log.length).toBe(1);
|
|
|
|
|
expect(log[0][0]).toBe('ngOnChanges');
|
|
|
|
|
const changes: SimpleChanges = log[0][1][0];
|
|
|
|
|
expect(changes['prop'].currentValue).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function createAndLogComponent(clazz: Type<any>, inputs: string[] = []): any[] {
|
|
|
|
|
const log: any[] = [];
|
|
|
|
|
createLoggingSpiesFromProto(clazz, log);
|
|
|
|
|
|
|
|
|
|
const inputBindings = inputs.map(input => `[${input}] = true`).join(' ');
|
|
|
|
|
|
|
|
|
|
@Component({template: `<my-cmp ${inputBindings}></my-cmp>`})
|
|
|
|
|
class ParentComponent {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createLoggingSpiesFromProto(clazz: Type<any>, log: any[]) {
|
|
|
|
|
const proto = clazz.prototype;
|
|
|
|
|
Object.keys(proto).forEach((method) => {
|
|
|
|
|
proto[method] = (...args: any[]) => { log.push([method, args]); };
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const fixture = TestBed.configureTestingModule({declarations: [ParentComponent, clazz]})
|
|
|
|
|
.createComponent(ParentComponent);
|
|
|
|
|
fixture.detectChanges();
|
|
|
|
|
fixture.destroy();
|
|
|
|
|
return log;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function createLoggingSpiesFromProto(clazz: Type<any>, log: any[]) {
|
|
|
|
|
const proto = clazz.prototype;
|
|
|
|
|
Object.keys(proto).forEach((method) => {
|
|
|
|
|
proto[method] = (...args: any[]) => {
|
|
|
|
|
log.push([method, args]);
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|