【问题标题】:CdkDragDrop unit testing eventsCdkDragDrop 单元测试事件
【发布时间】:2019-10-09 02:20:08
【问题描述】:

所以,我一直在为我的 Angular 应用程序进行单元测试。我正在使用 Angular Material,并且我有一个使用拖放 CDK cdk drag-drop API 的组件。

html 代码如下所示

<mat-card class="interventionCard">
  <div  cdkDropListGroup class="container">
    <div cdkDropList
         [cdkDropListData]="interventionsTodo" (cdkDropListDropped)="drop($event)" class="dragContainer">
      <div class="dragInter" *ngFor="let i of interventionsTodo" cdkDrag><img src="{{i.imgSrc}}" class="interventionIc" alt=""></div>
      <a class="resetInv" (click)="reset()"><div class="dragInter"><img src="../assets/images/simulation-intervention/noIntervention.svg" class="interventionIc" alt=""></div></a><!---->
    </div>

    <div class="dropContainer">
      <div cdkDropList [cdkDropListData]="interventionsDoneNow" (cdkDropListDropped)="drop($event)" class="dropZone">
        <div class="dragInterDropped" *ngFor="let i of interventionsDoneNow" cdkDrag><img src="{{i.imgSrc}}" class="interventionIc" alt=""></div>
      </div>
        <div class="connectorL"></div>
      <div cdkDropList [cdkDropListData]="interventionsDonePlus5" (cdkDropListDropped)="drop($event)" class="dropZone">
        <div class="dragInterDropped" *ngFor="let i of interventionsDonePlus5" cdkDrag><img src="{{i.imgSrc}}" class="interventionIc"></div>
      </div>
      <div class="connectorL"></div>
      <div cdkDropList  [cdkDropListData]="interventionsDonePlus10" (cdkDropListDropped)="drop($event)" class="dropZone">
        <div class="dragInterDropped" *ngFor="let i of interventionsDonePlus10" cdkDrag><img src="{{i.imgSrc}}" class="interventionIc" alt=""></div>
      </div>
      <div class="connectorL"></div>
      <div cdkDropList  [cdkDropListData]="interventionsDonePlus15" (cdkDropListDropped)="drop($event)" class="dropZone">
        <div class="dragInterDropped" *ngFor="let i of interventionsDonePlus15" cdkDrag><img src="{{i.imgSrc}}" class="interventionIc" alt=""></div>
      </div>
      <div class="connectorL"></div>
      <div cdkDropList  [cdkDropListData]="interventionsDonePlus20" (cdkDropListDropped)="drop($event)" class="dropZone">
        <div class="dragInterDropped" *ngFor="let i of interventionsDonePlus20" cdkDrag><img src="{{i.imgSrc}}" class="interventionIc" alt=""></div>
      </div>
      <div class="connectorL"></div>
      <div cdkDropList  [cdkDropListData]="interventionsDonePlus25" (cdkDropListDropped)="drop($event)" class="dropZone">
        <div class="dragInterDropped" *ngFor="let i of interventionsDonePlus25" cdkDrag><img src="{{i.imgSrc}}" class="interventionIc" alt=""></div>
      </div>
      <div class="connectorL"></div>
      <div cdkDropList [cdkDropListData]="interventionsDonePlus30" (cdkDropListDropped)="drop($event)" class="dropZone">
        <div class="dragInterDropped" *ngFor="let i of interventionsDonePlus30" cdkDrag><img src="{{i.imgSrc}}" class="interventionIc" alt=""></div>
      </div>
    </div>

一切都好,现在我有了调用函数drop()的cdkDropListDroppet事件

    drop(event: CdkDragDrop<{ imgSrc: string }[], any>) {
     if (event.previousContainer === event.container) {
       moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
     } else {
         if(event.container.data === this.interventionsTodo){
         this.deleteSpecificItemFromTimeline(event.previousContainer.data[0]);
         }else if(event.container.data.length <1){
           copyArrayItem(event.previousContainer.data,
             event.container.data,
             event.previousIndex,
             event.currentIndex);
         }
      }
    }

这很好用,现在我对 Angular 应用程序进行单元测试(jasmine/karma) 我正在尝试调度 CdkDragDrop 事件,以便我可以验证我的 drop() 函数的功能。

因此,在 Angular 文档中有一个关于组件 DOM 测试的小章节,其中提到您必须获取要触发事件的 htmlElement,我这样做是这样的:angular docs

    let Dbg = fixture.debugElement;
    let htE = Dbg.nativeElement.querySelector(".dragContainer");

现在我有了要触发事件的元素,所以完整的代码如下所示

    let Dbg = fixture.debugElement;
      let htE = Dbg.nativeElement.querySelector(".dragContainer");

      htE.addEventListener('CdkDragDrop', (ev:any) => {
        component.drop(ev);
      });
      let bla = htE.dispatchEvent(new Event('cdkDropListDropped'));

所以 bla 返回 true,这(如果我没有错)意味着事件已被触发,但似乎没有发生任何事情 fixture.detectchanges() 自动发生.. 我试图调试它以查看发生了什么,但侦听器函数从未被触发,我到处寻找答案,但似乎在那种事件测试中找不到任何东西..

【问题讨论】:

  • 单元测试示例的一个很好的初始资源是位于库源代码中的测试:github.com/angular/components/tree/master/src/cdk/drag-drop
  • 嗨,你能找到解决办法吗?我现在在单元测试中也遇到过类似的情况。
  • Hei Jun,所以 Alexander 提到的链接有很多关于如何测试 CdkDragDrop 的示例。但是这里的问题在于 Angular,所以如果你检查 Alex 给出的 repo 中的测试,你大多数情况下会在 @angular/core/testing 周围找到一些导入 .. 这里的问题是这个测试模块不是公开可用的,因为没有正确格式化和评论等等。所以,至于你不能真正测试你的东西..至少这是我学到的,我希望这会有所帮助

标签: angular unit-testing angular-material coded-ui-tests


【解决方案1】:

您可以使用一些模拟事件来测试您的drop 方法,而不是尝试从您的模板中触发事件。我这样做是通过使用通用的DragDropEventFactory

summary-table-side-bar.component.spec.ts 说明了相应的单元测试可能是什么样子。

【讨论】:

  • 任何用于对 cdk 拖放功能进行单元测试的 stackblitz 链接?