Skip to content

Commit

Permalink
fix: now MockRender's proxy component respects outside params changes
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Dec 13, 2020
1 parent 8909a7c commit 9297cd1
Show file tree
Hide file tree
Showing 10 changed files with 535 additions and 251 deletions.
101 changes: 101 additions & 0 deletions examples/TestLifecycleHooks/fixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {
AfterContentChecked,
AfterContentInit,
AfterViewChecked,
AfterViewInit,
ChangeDetectionStrategy,
Component,
Injectable,
Input,
NgModule,
OnChanges,
OnDestroy,
OnInit,
} from '@angular/core';

// A dummy service we are going to replace with its mock copy and to use for assertions.
@Injectable()
export class TargetService {
protected called = false;

public afterContentChecked() {
this.called = true;
}

public afterContentInit() {
this.called = true;
}

public afterViewChecked() {
this.called = true;
}

public afterViewInit() {
this.called = true;
}

public ctor() {
this.called = true;
}

public onChanges() {
this.called = true;
}

public onDestroy() {
this.called = true;
}

public onInit() {
this.called = true;
}
}

@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'target',
template: ``,
})
export class TargetComponent
implements OnInit, OnDestroy, OnChanges, AfterViewInit, AfterViewChecked, AfterContentInit, AfterContentChecked {
@Input() public input: string | null = null;

public constructor(protected readonly service: TargetService) {
this.service.ctor();
}

public ngAfterContentChecked(): void {
this.service.afterContentChecked();
}

public ngAfterContentInit(): void {
this.service.afterContentInit();
}

public ngAfterViewChecked(): void {
this.service.afterViewChecked();
}

public ngAfterViewInit(): void {
this.service.afterViewInit();
}

public ngOnChanges(): void {
this.service.onChanges();
}

public ngOnDestroy(): void {
this.service.onDestroy();
}

public ngOnInit(): void {
this.service.onInit();
}
}

@NgModule({
declarations: [TargetComponent],
exports: [TargetComponent],
providers: [TargetService],
})
export class TargetModule {}
112 changes: 5 additions & 107 deletions examples/TestLifecycleHooks/test.spec.ts
Original file line number Diff line number Diff line change
@@ -1,113 +1,11 @@
import {
AfterContentChecked,
AfterContentInit,
AfterViewChecked,
AfterViewInit,
ChangeDetectionStrategy,
Component,
Injectable,
Input,
NgModule,
OnChanges,
OnDestroy,
OnInit,
} from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';

// A dummy service we are going to replace with its mock copy and to use for assertions.
@Injectable()
class TargetService {
protected called = false;

public afterContentChecked() {
this.called = true;
}

public afterContentInit() {
this.called = true;
}

public afterViewChecked() {
this.called = true;
}

public afterViewInit() {
this.called = true;
}

public ctor() {
this.called = true;
}

public onChanges() {
this.called = true;
}

public onDestroy() {
this.called = true;
}

public onInit() {
this.called = true;
}
}

@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'target',
template: ``,
})
class TargetComponent
implements
OnInit,
OnDestroy,
OnChanges,
AfterViewInit,
AfterViewChecked,
AfterContentInit,
AfterContentChecked {
@Input() public input: string | null = null;

public constructor(protected readonly service: TargetService) {
this.service.ctor();
}

public ngAfterContentChecked(): void {
this.service.afterContentChecked();
}

public ngAfterContentInit(): void {
this.service.afterContentInit();
}

public ngAfterViewChecked(): void {
this.service.afterViewChecked();
}

public ngAfterViewInit(): void {
this.service.afterViewInit();
}

public ngOnChanges(): void {
this.service.onChanges();
}

public ngOnDestroy(): void {
this.service.onDestroy();
}

public ngOnInit(): void {
this.service.onInit();
}
}

@NgModule({
declarations: [TargetComponent],
exports: [TargetComponent],
providers: [TargetService],
})
class TargetModule {}
import {
TargetComponent,
TargetModule,
TargetService,
} from './fixtures';

describe('TestLifecycleHooks', () => {
ngMocks.faster();
Expand Down
93 changes: 93 additions & 0 deletions examples/TestLifecycleHooks/test.string.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { TestBed } from '@angular/core/testing';
import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';

import {
TargetComponent,
TargetModule,
TargetService,
} from './fixtures';

describe('TestLifecycleHooks:string', () => {
ngMocks.faster();

// Do not forget to return the promise of MockBuilder.
beforeEach(() => MockBuilder(TargetComponent, TargetModule));

it('triggers lifecycle hooks correctly via MockRender w/ params', () => {
// First let's suppress detectChanges.
const fixture = MockRender(
'<target [input]="input"></target>',
{ input: '' },
{
detectChanges: false,
},
);

const service: TargetService = TestBed.get(TargetService);

// By default nothing should be initialized, but ctor.
expect(service.ctor).toHaveBeenCalledTimes(1); // changed
expect(service.onInit).toHaveBeenCalledTimes(0);
expect(service.onDestroy).toHaveBeenCalledTimes(0);
expect(service.onChanges).toHaveBeenCalledTimes(0);
expect(service.afterViewInit).toHaveBeenCalledTimes(0);
expect(service.afterViewChecked).toHaveBeenCalledTimes(0);
expect(service.afterContentInit).toHaveBeenCalledTimes(0);
expect(service.afterContentChecked).toHaveBeenCalledTimes(0);

// Now let's render the component.
fixture.detectChanges();

// This calls everything except onDestroy and onChanges.
expect(service.ctor).toHaveBeenCalledTimes(1);
expect(service.onInit).toHaveBeenCalledTimes(1); // changed
expect(service.onDestroy).toHaveBeenCalledTimes(0);
expect(service.onChanges).toHaveBeenCalledTimes(1); // changed
expect(service.afterViewInit).toHaveBeenCalledTimes(1); // changed
expect(service.afterViewChecked).toHaveBeenCalledTimes(1); // changed
expect(service.afterContentInit).toHaveBeenCalledTimes(1); // changed
expect(service.afterContentChecked).toHaveBeenCalledTimes(1); // changed

// Let's change it.
fixture.componentInstance.input = 'change';
fixture.detectChanges();

// Only OnChange, AfterViewChecked, AfterContentChecked
// should be triggered.
expect(service.ctor).toHaveBeenCalledTimes(1);
expect(service.onInit).toHaveBeenCalledTimes(1);
expect(service.onDestroy).toHaveBeenCalledTimes(0);
expect(service.onChanges).toHaveBeenCalledTimes(2); // changed
expect(service.afterViewInit).toHaveBeenCalledTimes(1);
expect(service.afterViewChecked).toHaveBeenCalledTimes(2); // changed
expect(service.afterContentInit).toHaveBeenCalledTimes(1);
expect(service.afterContentChecked).toHaveBeenCalledTimes(2); // changed

// Let's cause more changes.
fixture.detectChanges();
fixture.detectChanges();

// Only AfterViewChecked, AfterContentChecked should be triggered.
expect(service.ctor).toHaveBeenCalledTimes(1);
expect(service.onInit).toHaveBeenCalledTimes(1);
expect(service.onDestroy).toHaveBeenCalledTimes(0);
expect(service.onChanges).toHaveBeenCalledTimes(2);
expect(service.afterViewInit).toHaveBeenCalledTimes(1);
expect(service.afterViewChecked).toHaveBeenCalledTimes(4); // changed
expect(service.afterContentInit).toHaveBeenCalledTimes(1);
expect(service.afterContentChecked).toHaveBeenCalledTimes(4); // changed

// Let's destroy it.
fixture.destroy();

// This all calls except onDestroy and onChanges.
expect(service.ctor).toHaveBeenCalledTimes(1);
expect(service.onInit).toHaveBeenCalledTimes(1);
expect(service.onDestroy).toHaveBeenCalledTimes(1); // changed
expect(service.onChanges).toHaveBeenCalledTimes(2);
expect(service.afterViewInit).toHaveBeenCalledTimes(1);
expect(service.afterViewChecked).toHaveBeenCalledTimes(4);
expect(service.afterContentInit).toHaveBeenCalledTimes(1);
expect(service.afterContentChecked).toHaveBeenCalledTimes(4);
});
});
Loading

0 comments on commit 9297cd1

Please sign in to comment.