带有Karma-Jasmine的单元测试垫菜单

时间:2020-04-28 14:32:15

标签: angular angular-material jasmine angular-cdk

我有一个Mat-menu,其中内容可能与用户有关。 我尝试编写单元测试,但是从我看到的结果来看,茉莉花看不到CDK div,因此我无法获取菜单项。

我的模板:

    <button id="account" mat-icon-button [matMenuTriggerFor]="menu" aria-label="Profile">
        <mat-icon>person</mat-icon>
    </button>

      <mat-menu #menu="matMenu">
        <button mat-menu-item *ngxPermissionsOnly="PERMISSION.USER_LIST" id="user-list" (click)="usersList()">
          <mat-icon>recent_actors</mat-icon>
        </button>
        <button mat-menu-item *ngxPermissionsOnly="PERMISSION.INFORMATIONS" id="informations" (click)="infoList()">
          <mat-icon>info</mat-icon>
        </button>
        <button mat-menu-item id="logout" (click)="logout()">
          <mat-icon>exit_to_app</mat-icon>
        </button>
      </mat-menu>

单元测试:

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

     const providers: any[] = headerProviders;

     beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [
            HeaderComponent,
            NgxPermissionsRestrictStubDirective
          ],
          providers: providers,
          imports: [
            BrowserAnimationsModule,
            BrowserModule,
            CommonModule,
            CommonSogetrelModule,
            FlexLayoutModule,
            SharedMaterialModule,
            RouterTestingModule.withRoutes([])
          ]
        })
          .compileComponents()
          .then(() => {
            fixture = TestBed.createComponent(HeaderComponent);
            component = fixture.componentInstance;
          });
      }));

    it('should not display elements which needs permissions', () => {
        fixture.nativeElement.querySelector('#account').click();
        fixture.detectChanges();
        expect(logoutBtn).toBeTruthy('Le bouton Déconnexion doit être affiché');
        expect(fixture.debugElement.nativeElement.querySelector('#user-list')).toBeFalsy();

      });

我尝试过

    console.info(fixture.nativeElement.parentNode);
    const menu = fixture.nativeElement.parentNode.querySelector('.mat-menu-panel');
    expect(menu).toBeTruthy();

通过console.info可以看到的是页面上没有CDK div,因此显然找不到.mat-menu-panel

关于如何测试Mat-menu内容的任何想法?

Thx

3 个答案:

答案 0 :(得分:1)

我认为您应该尝试使用 MatMenuHarness

https://material.angular.io/components/menu/api#MatMenuHarness

it('should not display elements which needs permissions', async () => {
    let loader: HarnessLoader = TestbedHarnessEnvironment.loader(fixture);
    fixture.detectChanges();
    let menu = await testHarness.loader.getHarness(MatMenuHarness);
    let items = await menu.getItems();
    expect(items.length).toBe(1);
  });

答案 1 :(得分:1)

MatMenuHarness 是测试 mat-menu 的正确方法,但它有一个微小的不直观的细节。鉴于:

<div class="view-contract__portal-header">
  <h2>Counterparties</h2>
  <button
    mat-stroked-button
    color="primary"
    data-testid="add-counterparty"
    [matMenuTriggerFor]="menu"
  >
    <mat-icon>add</mat-icon> Add counterparty
  </button>
</div>

<mat-menu #menu="matMenu" data-testid="add-counterparty-menu">
  <button
    *ngFor="let role of roles"
    mat-menu-item
    [attr.data-testid]="'add-counterparty-' + role"
    (click)="addCounterparty(role)"
  >
    {{ role }}
  </button>
</mat-menu>

然后应该通过查找应用了 matMenuTriggerFor 属性的元素而不是实际的 mat-menu 元素来实例化 MatMenuHarness。

addCounterpartyMenu = await loader.getHarness<MatMenuHarness>(
  MatMenuHarness.with({
    selector: `[data-testid="add-counterparty"]`,
  }),
);

答案 2 :(得分:0)

我认为问题在于您正在同一时钟交互中进行所有操作,因此,直到下一个时钟才会更新DOM。

要处理此问题,可以使用Angular的fakeAysnctick

我认为我们可以像这样用fakeAsync重写您的测试:

    it('should not display elements which needs permissions', fakeAsync(() => {
        fixture.nativeElement.querySelector('#account').click();
        tick();
        fixture.detectChanges();
        expect(logoutBtn).toBeTruthy('Le bouton Déconnexion doit être affiché');
        expect(fixture.debugElement.nativeElement.querySelector('#user-list')).toBeFalsy();
      }));

我认为这应该适用。