angular / angular/components

bug(TestbedHarnessEnvironment): Impossible to use if component under test uses intervals

オープン
#20,785 コメント 5 件 リアクション 0 件 担当者 0 名 GitHub で見る
area: cdk/testing P3
主要言語
TypeScript
スター
25k
フォーク
6.8k
平均マージ
1日 8時間
マージ済み PR(30日)
91

説明

Use StackBlitz to reproduce your issue: **ADDED** (thanks @annieyw!), [example here](https://stackblitz.com/edit/material-testbedharness-interval?file=src/app/button-harness-example.spec.ts)

Steps to reproduce:
1. Follow [the instructions for using Harnesses](https://material.angular.io/guide/using-component-harnesses)
2. In the component under test, use `setInterval`, or the rxjs `interval(n)` or `timer(0, n)` observables
3. Your test will stall indefinitely at e.g. `await loader.getAllHarnesses(MatButtonHarness);` (from the docs linked in step 1)

#### Expected Behavior

`getAllHarnesses` completes once the component has finished initializing and had a chance to create instances of child components.

#### Actual Behavior

The call to `getAllHarnesses` never resolves, and the test times out.

#### Environment

- Angular: 10.1.2
- CDK/Material: 10.2.1
- Browser(s): N/A
- Operating System (e.g. Windows, macOS, Ubuntu): N/A (Win10)

----

As I understand it, this is because under the hood, `TestbedHarnessEnvironment` is using `ComponentFixture#whenStable`. From what I can tell, [the official stance from Angular / Zone](https://github.com/angular/angular/issues/10127) is that you should use `fakeAsync` plus `tick`, and call `discardPeriodicTasks` to ignore the (expected) pending intervals, instead of using `waitForAsync` / `whenStable`.

This [very old StackOverflow question](https://stackoverflow.com/questions/38697656/testing-angular2-components-that-use-setinterval-or-settimeout) suggests that one should never have `setInterval` in a component or service, instead using an injected service to provide periodic actions, so it can be mocked out during testing, but I've never seen anything "official" from Angular to say that intervals are unsupported.

If it's not permissible to use intervals in a component, this should be documented somewhere, with suggestions of alternative design patterns to use that are compatible with Material's test utilities. If it is permissible, `TestbedHarnessEnvironment` should be updated to include another way of determining when the owning `ComponentFixture` is "ready", or I guess kick this upstream to the Zone folks so they can make `whenStable` work with intervals.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

StackBlitz の再現環境と TestbedHarnessEnvironment のエントリポイントから始め、その ComponentFixture#whenStable の使用に焦点を当てます。fakeAsync、tick、discardPeriodicTasks に関するリンク先の Angular および Zone のガイダンスと動作を比較します。interval のケースについて、合意されたサポート対象の動作が定まれば完了です。つまり、動作する harness の経路、または制限と互換性のあるテストパターンを説明するドキュメントのいずれかです。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
angular, typescript
領域
testing
issue の種類
バグ
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。