Question: Angular Material provides [component harnesses](https://material.angular.io/guide/using-component-harnesses) for testing, which lets you interact with their components by `await`ing promises, like this:

```js
  it('should click button', async () => {
    const matButton = await loader.getHarness(MatButtonHarness);
    await matButton.click();
    expect(...);
  });

```

But what if the button click triggers a delayed operation? Normally I would use `fakeAsync()`/`tick()` to handle it:

```js
  it('should click button', fakeAsync(() => {
    mockService.load.and.returnValue(of(mockResults).pipe(delay(1000)));
    // click button
    tick(1000);
    fixture.detectChanges();
    expect(...);
  }));

```

But is there any way I can do both in the same test?

Wrapping the `async` function inside `fakeAsync()` gives me "Error: The code should be running in the fakeAsync zone to call this function", presumably because once it finishes an `await`, it's no longer in the same function I passed to `fakeAsync()`.

Do I need to do something like this -- starting a fakeAsync function after the await? Or is there a more elegant way?

```js
  it('should click button', async () => {
    mockService.load.and.returnValue(of(mockResults).pipe(delay(1000)));
    const matButton = await loader.getHarness(MatButtonHarness);

    fakeAsync(async () => {
      // not awaiting click here, so I can tick() first
      const click = matButton.click(); 
      tick(1000);
      fixture.detectChanges();
      await click;
      expect(...);
    })();
  });

```

Answer: 
`fakeAsync(async () => {...})` is a valid construct.

Moreover, Angular Material team is [explicitly testing this scenario](https://github.com/angular/components/blob/b9f761a7283e7525cb569118e4fa0e937cf0d37f/src/cdk/testing/tests/testbed.spec.ts#L87).

```js
it('should wait for async operation to complete in fakeAsync test', fakeAsync(async () => {
        const asyncCounter = await harness.asyncCounter();
        expect(await asyncCounter.text()).toBe('5');
        await harness.increaseCounter(3);
        expect(await asyncCounter.text()).toBe('8');
      }));

```
I just released a test helper that lets you do exactly what you're looking for. Among other features, it allows you to use material harnesses in a `fakeAsync` test and control the passage of time as you describe.

The helper automatically runs what you pass to its `.run()` method in the fake async zone, and it can handle `async/await`. It would look like this, where you create the `ctx` helper in place of `TestBed.createComponent()` (wherever you have done that):

```js
it('should click button', () => {
  mockService.load.and.returnValue(of(mockResults).pipe(delay(1000)));
  ctx.run(async () => {
    const matButton = await ctx.getHarness(MatButtonHarness);
    await matButton.click();
    ctx.tick(1000);
    expect(...);
  });
});

```

The library is called `@s-libs/ng-dev`. Check out the documentation for this particular helper [here](https://simontonsoftware.github.io/s-libs/ng-dev/classes/componentcontextnext.html) and let me know about any issues via github [here](https://github.com/simontonsoftware/s-libs).