jeudi 3 mai 2018

How can I test an Angular 4 component that change its state within a setTimeout and switchMap?

I'm trying to test a countdown component which runs within a setTimeout and gets the interval of the timeout from a subscription:

constructor(private countdownService: CountdownService) {} 

public ngOnInit() {
        this.interval = this.conf.DISPLAY_SECS ? this.intervalSeconds : this.intervalMinutes;
        this.startCountDown();
    }

private startCountDown(): void {
    this.subscriber = this.countdownService.getCountDownData()
        .do((data: Array<any>) => {
            this.displayCountdown = data['displayCountdown'];
            this.serverDate = new Date(data['serverDate']);
            this.bankHolidays = data['bankHolidays'];
            this.now = this.serverDate.getTime();
            this.setTimeCountdown();
        })
        .switchMap(() => this.intervalSubj)
        .subscribe((interval) => {
            setTimeout(() => {
                this.now += interval;
                this.setTimeCountdown();
            }, interval)
        });
}

I emit a new value, if needed, inside:

public setIsLastHour(days: number, hours: number, mins: number): void {
        this.isLastHour = false;
        if ((days + hours) === 0) {
            this.interval = this.intervalSeconds;
            this.intervalSubj.next(this.interval);
            this.isLastHour = true;
            return;
        }
        this.interval = this.conf.DISPLAY_SECS || (days === 0 && hours === 1 && mins < 2) ? this.intervalSeconds : this.intervalMinutes;
        this.intervalSubj.next(this.interval);
    }

which it's called inside setTimeCountdown function:

private setTimeCountdown(): void {
        const startTimesec = this.getTheNextUsefulTime();

        const days = Math.trunc(startTimesec / (3600 * 24));
        const str_days = days < 10 ? `0${days}` : days;
        this.timeCountdown.days = str_days.toString().split('');
        this.calculateDeliveryDay(days);

        const hours = Math.trunc((startTimesec / 3600) - days * 24);
        const str_hours = hours < 10 ? `0${hours}` : hours;
        this.timeCountdown.hours = str_hours.toString().split('');

        const mins = Math.trunc((startTimesec / 60) - (days * 24 + hours) * 60);
        const str_mins = mins < 10 ? `0${mins}` : mins;
        this.timeCountdown.mins = str_mins.toString().split('');

        const secs = Math.trunc(startTimesec - (((days * 24 + hours) * 60) + mins) * 60);
        const str_secs = secs < 10 ? `0${secs}` : secs;
        this.timeCountdown.secs = str_secs.toString().split('');

        this.isMoreThanOneDay = days > 0 && hours > 1;

        this.setIsLastHour(days, hours, mins);
        if (Math.round(startTimesec) === 0) {
            this.startCountDown();
        }
    }

When I test the component "everything" works fine, apart when I want to check the time value after a certain amount of time

it('after 1min we should see the "01h:29m" on the countdown', fakeAsync(() => {
    initComponent(true);
    setTimeout(() => {
          console.log(comp, getTimeStr(), comp['now']);
          fixture.detectChanges();
    }, 60000);

    tick(60000);
    flushMicrotasks();
    expect(`${getTimeStr('h')}:${getTimeStr('m')}`).toBe('01:29');
}));

${getTimeStr('h')}:${getTimeStr('m')} is right, but I'm getting an error message Error: 1 timer(s) still in the queue so the test fails

Any guess?

Aucun commentaire:

Enregistrer un commentaire