无法使用 CDK 测试工具测试 Angular Material Select 组件

Unable to test Angular Material Select Component using CDK Test Harness

我正在尝试为使用 Angular Material 组件的组件编写一些测试。我阅读了有关 CDK Test Harness https://material.angular.io/guide/using-component-harnesses 的信息,我想基于此获取 Mat Select 组件中的选项数。

<mat-card>
  <mat-card-content>
    <form [formGroup]="filterLikelihoodForm" (ngSubmit)="onSearchClick()">
      <div class="container">
        <div class="row align-items-center">
          <div class="col-sm">
            <mat-form-field class="full-width" id="periodField">
              <mat-label>Select Period</mat-label>
              <mat-select formControlName="period" id="period">
                <mat-option *ngFor="let period of periodList" [value]="period.id">
                  {{ period.monthName }}
                </mat-option>
              </mat-select>
              <mat-error *ngIf="f.period.errors">
                Please select a valid period
              </mat-error>
            </mat-form-field>
          </div>
          <div class="col-sm">
            <mat-form-field class="full-width">
              <input
                matInput
                type="number"
                formControlName="finishedDeals"
                placeholder="Enter no of finished deals"
              />
              <mat-error *ngIf="f.finishedDeals.errors">
                Please enter a valid number
              </mat-error>
            </mat-form-field>
          </div>
          <div class="col-sm">
            <button
              mat-flat-button
              color="primary"
              [disabled]="filterLikelihoodForm.invalid"
              class="full-width"
            >
              Search
            </button>
          </div>
        </div>
      </div>
    </form>
  </mat-card-content>
</mat-card>

这是我的规范文件代码:

import { HarnessLoader } from "@angular/cdk/testing";
import { TestbedHarnessEnvironment } from "@angular/cdk/testing/testbed";
import { TestBed, async, ComponentFixture } from "@angular/core/testing";
import { FilterLikelihoodComponent } from "./filter-likelihood.component";
import { MatFormFieldHarness } from "@angular/material/form-field/testing";
import { MatFormFieldModule } from "@angular/material/form-field";
import { ReactiveFormsModule } from "@angular/forms";
import { MatSelectModule } from "@angular/material/select";
import { MatCardModule } from "@angular/material/card";
import { MatButtonModule } from "@angular/material/button";
import { MatInputModule } from "@angular/material/input";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
import { periodListMock } from "./mock/filter-likelihood.mock";
import { MatSelectHarness } from "@angular/material/select/testing";
import { MatButtonHarness } from "@angular/material/button/testing";
import { Component } from "@angular/core";
import { MatInputHarness } from "@angular/material/input/testing";

describe("Filter Likelihood Component", () => {
  let testHostComponent: TestHostComponent;
  let testHostFixture: ComponentFixture<TestHostComponent>;

  let component: FilterLikelihoodComponent;
  let fixture: ComponentFixture<FilterLikelihoodComponent>;
  let loader: HarnessLoader;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [FilterLikelihoodComponent, TestHostComponent],
      imports: [
        ReactiveFormsModule,
        MatFormFieldModule,
        MatSelectModule,
        MatCardModule,
        MatButtonModule,
        MatInputModule,
        NoopAnimationsModule,
      ],
    }).compileComponents();
  }));

  beforeEach(() => {
    testHostFixture = TestBed.createComponent(TestHostComponent);
    testHostComponent = testHostFixture.componentInstance;
    testHostFixture.detectChanges();

    loader = TestbedHarnessEnvironment.loader(testHostFixture);
  });

  it("should have correct period label", async () => {
    const expectedLabel = "Select Period";
    const periodFieldHarness = await loader.getHarness<MatFormFieldHarness>(
      MatFormFieldHarness.with({ selector: "#periodField" })
    );
    const actual = await periodFieldHarness.getLabel();
    expect(actual).toBe(expectedLabel);
  });

  it("should have 3 recent periods in the dropdown", async () => {
    const expectedCount = 3;
    const selectHarness = await loader.getHarness<MatSelectHarness>(
      MatSelectHarness
    );
    const actual = ((await selectHarness.getOptions()).length);
    expect(actual).toBe(expectedCount);
  });

  it("should have a search button", async () => {
    const expectedLabel = "Search";
    const buttonHarness = await loader.getHarness<MatButtonHarness>(
      MatButtonHarness
    );
    const actual = await buttonHarness.getText();
    expect(actual).toBe(expectedLabel);
  });

  it("should have 10 finished deals by default", async () => {
    const expectedFinishedDeals = 10;
    const inputHarness = await loader.getHarness<MatInputHarness>(
      MatInputHarness
    );
    const actual = await inputHarness.getValue();
    expect(parseInt(actual)).toBe(expectedFinishedDeals);
  });

  it("should have a enabled button by default", async () => {
    const expectedDisabledState = false;
    const buttonHarness = await loader.getHarness<MatButtonHarness>(
      MatButtonHarness
    );
    const actual = await buttonHarness.isDisabled();
    expect(actual).toBe(expectedDisabledState);
  });

  @Component({
    selector: `host-component`,
    template: `<app-filter-likelihood
      [periodList]="periodList"
      [initialFinishedDeals]="defaultFinishedDeals"
    ></app-filter-likelihood>`,
  })
  class TestHostComponent {
    periodList = new Helper().mockPeriodList;
    defaultFinishedDeals = 10;
  }
});

class Helper {
  mockPeriodList = periodListMock;
}

标题为 "should have 3 recent periods in the dropdown" 的第二个规范失败了,因为我得到的选项总是计数为 0。

谁能帮我找出错误并让我知道使用 Mat 测试工具编写此规范的正确方法?

提前致谢!

在对 Select 安全带 API 进行一些修补后,我解决了这个问题。 我已经更新了规范以获取宿主元素,然后触发了点击事件。

  it("should have 3 recent periods in the dropdown", async () => {
    const expectedCount = 3;
    const selectHarness = await loader.getHarness<MatSelectHarness>(
      MatSelectHarness
    );

    //Click the select element host
    await (await selectHarness.host()).click();
    const actual = (await selectHarness.getOptions()).length;
    expect(actual).toBe(expectedCount);
  });

您正在尝试在打开 select 元素之前获取选项数。

const selectHarness = await loader.getHarness<MatSelectHarness>(MatSelectHarness);
const count = (await selectHarness.getOptions()).length;  // count will be 0
await selectHarness.open();  // you can open matselect element via open method
const count = (await selectHarness.getOptions()).length;  // count will be as expected