angularjestjsangular-spectator

Spectator Angular testing - pass input before ngOnInit


I am using Spectator to write my Angular 8 tests and Jest to run them. According to the README I can use setInput() to assign my value to the name of the field, which works. The problem is that The input is being validated AFTER the component is created, but I need it before that because I use it for initialization in my ngOnInit method:

// item.component.ts

@Input() items: Items[] = [];

ngOnInit(): void {
    // do something with this.items
    // read query param 'page' and use it for something
}

with

// item.component.spec.ts

let spectator: SpectatorRouting<ItemComponent>;
const createComponent = createRoutingFactory({
    component: ItemComponent,
    queryParams: {page: 1}
});

beforeEach(() => spectator = createComponent());

it('test items', () => {
    spectator.setRouteQueryParam('page', '2');
    spectator.setInput("items", myItemsList); 
});

The spectator will set the queryParam page and Input items correctly, but only after the component is already created. During the component creation ngOnInit will initialize with page == 1 and items == [].

I could create the spectator component within each method and pass the queryParams separately, but I can't find a way to pass the input in the createRoutingFactory arguments.

Alternatively I could use a host component factory to pass my input parameters, but then I lose the ability to pass query params I believe.


Solution

  • You can set detectChanges=false in the createRoutingFactory options. This will make createComponent() not calling onInit() automatically, and in your tests you should call spectator.detectChanges() after setting the inputs (or stubing/mocking services spys):

    // item.component.spec.ts
    
    let spectator: SpectatorRouting<ItemComponent>;
    const createComponent = createRoutingFactory({
        component: ItemComponent,
        queryParams: {page: 1},
        detectChanges: false // set this to avoid calling onInit() automatically
    });
    
    beforeEach(() => spectator = createComponent());
    
    it('test items', () => {
        spectator.setRouteQueryParam('page', '2');
        // spectator.inject(AnyService).doSomething.andReturn()... // stub services if needed
        spectator.setInput("items", myItemsList); 
        spectator.detectChanges(); // Now onInit() will be called
    });