Vizer / ngx-virtual-select-field

Virtual Select Field for Angular Material
MIT License
4 stars 1 forks source link

Angular CDK testing harness #8

Open Klaster1 opened 4 months ago

Klaster1 commented 4 months ago

Angular Material exports testing harnesses for all of its component, which come in really handy when unit testing my components that rely on Angular Material. Unfortunately, ngx-virtual-select-field provides not testing harness. I suggest adding it.

Klaster1 commented 4 months ago

Here's a placeholder harness I authored for my test suite, feel free to re-use:


class NgxVirtualSelectFieldOptionHarness extends ComponentHarness {
  static hostSelector = 'ngx-virtual-select-field-option';
  static with(options: BaseHarnessFilters = {}): HarnessPredicate<NgxVirtualSelectFieldOptionHarness> {
    return new HarnessPredicate(NgxVirtualSelectFieldOptionHarness, options);
  }
  public isSelected() {
    return this.host().then((e) => e?.hasClass('ngx-virtual-select-field-option--selected'));
  }
  public async select() {
    await this.host().then((e) => e?.click());
  }
  public text() {
    return this.host().then((e) => e?.text());
  }
}

export class NgxVirtualSelectFieldHarness extends ComponentHarness {
  static hostSelector = 'ngx-virtual-select-field';
  static with(options: BaseHarnessFilters = {}): HarnessPredicate<NgxVirtualSelectFieldHarness> {
    return new HarnessPredicate(NgxVirtualSelectFieldHarness, options);
  }
  async open() {
    await this.host().then((e) => e.click());
    await new Promise((r) => setTimeout(r, 0));
  }
  async close() {
    await this.documentRootLocatorFactory()
      .locatorForOptional('.cdk-overlay-backdrop')()
      .then((e) => e?.click());
  }
  public visibleOptions = this.documentRootLocatorFactory().locatorForAll(NgxVirtualSelectFieldOptionHarness);
  async visibleOptionLabels() {
    const options = await this.visibleOptions();
    return Promise.all(options.map((o) => o.text()));
  }
  async selectVisibleOption(label: string) {
    const options = await this.visibleOptions();
    for (const option of options) {
      if ((await option.text()) === label) {
        await option.select();
      }
    }
  }
  async focus() {
    return this.host().then((e) => e.focus());
  }
  async blur() {
    return this.host().then((e) => e.blur());
  }
}

One weird thing I couldn't work around is that the first option select always has to called twice:

        await select?.selectVisibleOption('cache1');
        await select?.selectVisibleOption('cache1'); // this one
        await select?.selectVisibleOption('cache2');
        await select?.selectVisibleOption('cache2');
Vizer commented 4 months ago

Yeah, it totally makes sense. I will work on this later