【问题标题】:How can I unit test a form containing ng-select?如何对包含 ng-select 的表单进行单元测试?
【发布时间】:2020-06-01 09:58:48
【问题描述】:

我创建了一个 Angular 表单组件,它使用 <ng-select> 作为 HTML <select> 元素的替代品。现在我想对我的组件进行单元测试。为了测试组件逻辑,我有一些方法可以在 DOM 中找到 HTML 元素并检查或修改它们的值。这适用于原生 HTML 元素。但是<ng-select> 很难。

我可以用这样的东西找到当前值,但感觉就像一个非常脆弱的解决方案。

document.querySelector("ng-select[formControlName=country] .ng-value .ng-value-label").innerText

我该如何更改选择?使用标准输入组件,您可以设置值,然后触发输入事件。 <ng-select/> 内部有一个 <input type="text" role="combobox">,但更改它的值似乎不会影响 FormControl 的值。

我不是在尝试测试 ng-select,但我确实需要验证我的组件是否对选择更改做出了适当的反应。运行自动化集成测试时,还需要在 UI 中进行选择。

【问题讨论】:

    标签: angular unit-testing angular-test angular-ngselect


    【解决方案1】:

    我偶然发现了同样的问题。克里斯是对的,ng-select 源提供了一些测试功能,我只是从中构建了这个文件。这使得只选择一个由 css-selector 查询的 select 选项可能会更容易一些。让我知道它是否适合你。

    import { DebugElement } from '@angular/core';
    import { ComponentFixture, tick } from '@angular/core/testing';
    import { By } from '@angular/platform-browser';
    
    export class TestsErrorHandler {}
    
    export enum KeyCode {
      Tab = 9,
      Enter = 13,
      Esc = 27,
      Space = 32,
      ArrowUp = 38,
      ArrowDown = 40,
      Backspace = 8
    }
    
    export function tickAndDetectChanges(fixture: ComponentFixture<any>) {
      fixture.detectChanges();
      tick();
    }
    
    export function selectOption(fixture, selector: string, arrowDowns: number) {
      triggerKeyDownEvent(getNgSelectElement(fixture, selector), KeyCode.Space); // open
      tickAndDetectChanges(fixture); // need to tick and detect changes
      for (let i = 0; i < arrowDowns; i++) {
        triggerKeyDownEvent(getNgSelectElement(fixture, selector), KeyCode.ArrowDown);
      }
      tickAndDetectChanges(fixture); dropdown fully inits after promise is resolved
      triggerKeyDownEvent(getNgSelectElement(fixture, selector), KeyCode.Enter); // select
      fixture.detectChanges();
    }
    
    export function getNgSelectElement(fixture: ComponentFixture<any>, selector: string): DebugElement {
      return fixture.debugElement.query(By.css(selector));
    }
    
    export function triggerKeyDownEvent(element: DebugElement, which: number, key = ''): void {
      element.triggerEventHandler('keydown', {
        which: which,
        key: key,
        preventDefault: () => { },
      });
    }
    

    【讨论】:

    【解决方案2】:

    您可以使用 Harness (MatselectHarness) 与 Angular Material 组件进行交互。这将使测试更加健壮:

     it('should have 20 countries in the select box', async () => {
        ...
        const select = await loader.getHarness(MatSelectHarness.with(MatSelectHarness);
        //Click the select element host
        (await selectHarness.host()).click();
        const actual = (await selectHarness.getOptions()).length;
        expect(actual).toBe(20);
      });
    

    选择一个值(角度文档中的示例代码):

    it('should switch to bug report template', async () => {
        expect(fixture.debugElement.query('bug-report-form')).toBeNull();
        const select = await loader.getHarness(MatSelect);
        await select.open();
        const bugOption = await select.getOption({text: 'Bug'});
        await bugOption.click();
        expect(fixture.debugElement.query('bug-report-form')).not.toBeNull();
      });
    

    见:using-component-harnesses

    另一种方法是将逻辑移动到服务中。可以轻松地对服务进行单元测试。

    【讨论】:

    • 我正在测试的组件不是 Material 组件。
    • 啊,我明白了。对不起。也许有人可以构建一个 NgSelectHarness。
    【解决方案3】:

    答案是查看the ng-select source 并查看测试代码。有几个更改选择值的测试示例。

    【讨论】:

    • 链接示例而不是ng-select 登陆页面不是更有帮助吗?我没有看到这些例子
    猜你喜欢
    • 2020-11-13
    • 1970-01-01
    • 2015-02-28
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    • 2014-09-21
    • 2018-11-06
    相关资源
    最近更新 更多