【问题标题】:Angular 2+: Testing form with mat-slide-toggle - change event won't fireAngular 2+:使用 mat-slide-toggle 测试表单 - 更改事件不会触发
【发布时间】:2018-11-16 17:26:12
【问题描述】:

我不确定为什么 change 事件没有触发,因此没有触发我为 change 事件注册的函数。

我知道这在我运行时有效,但我无法在规范中得到它。

这是我正在谈论的内容的演示...正如您从日志中看到的那样,toggle 永远不会被调用: https://stackblitz.com/edit/angular-material-slide-toggle-test-utmbmy?file=app%2Fhello.component.spec.ts

大致来说,这是我的代码...

component.html:

<mat-slide-toggle [checked]="useDefault" (change)="toggle($event)"></mat-slide-toggle>

component.ts:

...
toggle(event: MatSlideToggleChange) {
  console.log('Toggle fired');
  this.useDefault = event.checked;
}

在我的 spec.ts 中:

it('should trigger toggle...', () => {
  const componentDebug = fixture.debugElement;
  const slider: MatSlideToggle = 
     componentDebug.query(By.css('form mat-slide-toggle')).componentInstance;

  console.log('before ' + slider.checked);
  slider.toggle();

  fixture.detectChanges();

  console.log('after ' + slider.checked);
  console.log('useDefault ' + component.useDefault);
});

after 日志确实打印出slider.checkedbefore 的值相反。但是,component.useDefault 保持不变,并且永远不会调用 toggle 函数中的日志记录语句,这意味着它从未触发过它。

为什么会这样,我该如何解决?

我尝试将整个内容放入fakeAsync,使用tick,将“后”代码放入fixture.whenStable()fixture.whenRenderingDone()

我在TestBedimport 中有一个NoopAnimationsModule

【问题讨论】:

  • useDefault 是什么?是来自mat-slide-toggle 的东西吗?是您创建的指令吗?
  • 好的,我更新了我的问题代码。 useDefault 只是一个错字,它应该是 [checked]="useDefault"。但是,我稍微修改了您的组件以更符合我所拥有的,即从 useDefault = true 开始。我只添加了一些日志记录语句。现在,由于我无法理解的原因,toggle 日志不再显示:stackblitz.com/edit/…
  • 尝试直接触发更改事件:componentDebug.query(By.css('mat-slide-toggle')).nativeElement.dispatchEvent(new Event('change')); 您可能还必须模拟 MatSlideToggleChange 对象。

标签: angular angular-material


【解决方案1】:

通过 css 'form mat-slide-toggle input' 选择实现了 user1902183 提到的技巧

【讨论】:

    【解决方案2】:

    你的组件.html

        <mat-slide-toggle (change)="onToggle($event)">Compare</mat-slide-toggle>
    

    在你的组件中你可以检查

        event.checked = true || false;
    

    【讨论】:

      【解决方案3】:

      使用第三方组件时,您应该信任它们来处理事件。但是,您可以使用triggereventhandler 来触发事件,而spyOn 是您想要调用的方法。

      组件

      import { Component } from '@angular/core';
      import { MatSlideToggleChange } from '@angular/material';
      
      @Component({
          selector: 'hello',
          template: `
              <mat-slide-toggle
                  [checked]="useDefault" (change)="toggle($event)"
              ></mat-slide-toggle>`
      })
      export class HelloComponent  {
          public useDefault = false;
      
          public toggle(event: MatSlideToggleChange) {
              console.log('toggle', event.checked);
              this.useDefault = event.checked;
          }
      }
      

      测试

      it('should call change method on slide change', () => {
          const componentDebug = fixture.debugElement;
          const slider = componentDebug.query(By.directive(MatSlideToggle));
          spyOn(component, 'toggle'); // set your spy
      
          slider.triggerEventHandler('change', null); // triggerEventHandler
      
          expect(component.toggle).toHaveBeenCalled(); // event has been called
      });
      

      查看通过 stackblitz 的测试:https://stackblitz.com/edit/angular-material-slide-toggle-test-spy-trigger-event?file=app/hello.component.spec.ts

      【讨论】:

      • 我不确定您相信 3rd 方组件来处理事件的观点是否正确......我可以相信他们会发出事件,但我需要测试我的绑定在模板中是正确的。因此,直接调用我的绑定函数肯定会测试该函数。但是,假设后来有人出现并编辑了我的组件模板并删除了(change)="onToggle()"。测试仍然会通过,因为我正在直接测试onToggle,但应用程序将无法工作,因为现在缺少事件绑定。我将不得不尽快发布我的解决方案...
      • 简而言之,解决方案(目前)是先执行const slider: HtmlElement = componentDebug.query(By.css('form mat-slide-toggle input')).nativeElement;,然后执行slider.click()。这实际上使MatSlideToggle 发出change 事件。我实际上认为这是MatSlideToggle 组件中的一个错误。它的toggle() 函数会翻转this.checked = !this.checked,但不会发出更改事件。我认为这是一个错误。它应该。
      • @user1902183,实际上如果你删除了(change)="onToggle()",你的测试将会失败。 (见stackblitz.com/edit/…)。 IMO,您应该对切换内部的逻辑进行单元测试,并在事件更改时调用另一个单元测试(如示例)
      • 这是相同的测试,但现在使用mat-slide-toggle input 作为选择器。一切正常,尽管我认为切换应该发出更改事件,并且不需要这种“黑客”。 stackblitz.com/edit/…
      猜你喜欢
      • 2023-01-15
      • 2020-03-25
      • 2019-01-01
      • 2018-10-06
      • 2021-11-27
      • 1970-01-01
      • 2022-10-18
      • 2017-12-15
      • 1970-01-01
      相关资源
      最近更新 更多