7

There is this Angular component:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { asyncScheduler, Observable, of, queueScheduler, scheduled } from 'rxjs';

@Component({
  selector: 'test-component',
  templateUrl: './test-component.component.html'
})
export class TestComponentComponent implements OnInit {
  value: string;

  constructor() { }

  ngOnInit(): void {
    const data$ = this.fetchDataScheduler();

    data$
      .subscribe(value => {
        this.value = value;
      });
  }

  private fetchDataScheduler(): Observable<string> {
    return scheduled(of('foo'), asyncScheduler);
  }

}

and the test is failing:

it('async - test setTimeout', fakeAsync(() => {
    expect(component.value).toBeFalsy();

    fixture.detectChanges(); // ngOnInit

    expect(component.value).toBeFalsy();
    flush();

    expect(component.value).toBe('foo');  // <- fails here
  }));

failing test

flush() should flush all macrotasks, but it does not. Why? If I use tick(), then the test is passing.

passing test

(Screenshots above provided by Jest and Wallaby plugin.)

Why is not passing with flush() but is passing with tick()?

flush:

Simulates the asynchronous passage of time for the timers in the fakeAsync zone by draining the macrotask queue until it is empty. The returned value is the milliseconds of time that would have been elapsed.

Repo is here: https://stackblitz.com/github/felikf/angular-testing-examples

Felix
  • 3,999
  • 3
  • 42
  • 66
  • Can you setup a stackblitz reproducing the problem? Based on the documentation, the `tick()` without arguments is a `flush()` command. https://angular.io/guide/testing#component-with-async-service – Athanasios Kataras Jan 08 '20 at 16:17
  • I am working on it: https://stackblitz.com/github/felikf/angular-testing-examples, it kind of works. It is possible to clone from github also. – Felix Jan 08 '20 at 20:15
  • Reported as bug: https://github.com/angular/angular/issues/34742 – Felix Jan 11 '20 at 20:08

1 Answers1

4

asyncScheduler is a setInterval which is a periodic macroTask, and currently the flush() API only flush non-periodic macroTasks such as setTimeout()

For now you should use tick() to make it work.

You can read more about it here

user1
  • 1,035
  • 1
  • 9
  • 17
  • See [here](https://medium.com/@felix.fatka/thanks-for-the-response-43c4d7acb46c) and [here](https://netbasal.medium.com/by-default-the-internal-flush-method-flushes-only-non-periodic-tasks-cf0239def42c) - the referenced issue is mine, I have just forgotten to update answer, **thank you for it**. – Felix Dec 07 '20 at 08:52