dimanche 4 mars 2018

Angular+Jasmine: Cannot spy on ActivatedRoute.queryParams

How can I spy on a stubbed Angular Service method that is expected to return an Observable such as ActivatedRoute.queryParams. Here is my failing spec:

import { TestBed, ComponentFixture } from "@angular/core/testing";
import { RivalChartComponent } from "./rival-chart-component";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { ActivatedRoute, RouterModule, Router } from "@angular/router";
import { appRoutes } from "../app.routes";
import { Observable } from 'rxjs/Observable';

import 'rxjs/add/observable/of';

describe('RivalChartComponent', () => {

    let component: RivalChartComponent;
    let fixture: ComponentFixture<RivalChartComponent>;

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [
                RivalChartComponent
            ],
            imports: [FormsModule, ReactiveFormsModule],
            providers: [
                {provide: ActivatedRoute, useValue: {queryParams: Observable.of({tags:'all'})}},
                {provide: Router, useValue: {}}
            ]
        });
        fixture = TestBed.createComponent(RivalChartComponent);
        component = fixture.componentInstance;
    });

    it('should init selectedTags as empty string when no query parameter is set', () => {
        spyOn(fixture.debugElement.injector.get(ActivatedRoute), 'queryParams').and.returnValue(Observable.of({tags:null}));
        component.ngOnInit();
        expect(component.selectedTags.value).toEqual('')
    });

});

And here is the corresponding source code:

import { Component, OnInit } from '@angular/core';
import { Rival } from '../domain/rival';
import { Route, ActivatedRoute, Router } from '@angular/router';
import { FormGroup, FormControl } from '@angular/forms';
import { CompairValidators } from '../validators/CompairValidators';

@Component({
    moduleId: module.id,
    selector: 'cp-rival-chart',
    templateUrl: 'rival-chart.html'

})
export class RivalChartComponent implements OnInit {

    rivals: Array<Rival> = [];
    selectedTags: FormControl;

    constructor(private route: ActivatedRoute, private router: Router) {
        this.selectedTags = new FormControl('', CompairValidators.trimmedArrayMinLengthValidator(3,1));
    }

    ngOnInit() {
        this.updateInputFromQueryParams();
    }

    updateInputFromQueryParams() {
        this.route.queryParams.subscribe((params) => {
            this.selectedTags.patchValue(this.createInputTagsFromUrlTags(params.tags));
        });
    }

    createInputTagsFromUrlTags(tags: String): string {
        if (!tags) {
            return '';
        }
        const tagsArray = tags.split('+');
        const cleanedTags = tagsArray
            .filter((tag) => tag && tag.trim());
        return '#' + cleanedTags.join(' #');
    }

}

The code is expected to initialize the selectedTags FormControl from the query parameter named tags given by the ActivatedRoute service. When there is no query parameter given it should initialize selectedTags with an empty String. In order to test it I would like to spy on the ActivatedRoutes.queryParams method and return an empty String for the key tags but unfortunately it does not work. Instead the initially passed ActivatedRoute stub's Observable gets called which returns the String 'all' for the key tags. Consequently my test fails with the following message:

Expected '#all' to equal ''.

You might think why the ActivatedRoute stub does not directly return an empty or null string. That's because there are actually other tests in my spec which I did not add here in order to focus on my main problem.

Aucun commentaire:

Enregistrer un commentaire