【问题标题】:Jasmine unit testing, how do I trigger the click event of ngx-modal-dialogJasmine单元测试,如何触发ngx-modal-dialog的点击事件
【发布时间】:2019-07-23 04:09:30
【问题描述】:

我正在开发一个 Angular 应用程序,我正在使用 Jasmine 对应用程序进行单元测试。

应用程序将ngx-modal-dialog(enter link description here) 插件用于弹出对话框,例如作为动态组件的确认框。

我想要的是触发确认或取消的点击事件,无论用户选择什么。

弹出对话框的代码如下:

export class SomeComponent {

constructor(private modalService: ModalDialogService) {}
cancleEditConfirmDialog() {
   this.modalService.openDialog(this.viewRef, {
   title: 'Discard Changes ',
   childComponent: SimpleModalComponent,
   data: {
     text: 'Changes will not be saved. Do you want to proceed?'
   },
   settings: {
     closeButtonClass: 'close theme-icon-close'
   },
   actionButtons: [
     {
       text: 'Discard',
       buttonClass: 'btn btn-success',
       onAction: () => new Promise((resolve: any) => {
         // invoke delete
         // do something such as discard changes
         resolve()
       })
     },
     {
       text: 'Cancel',
       buttonClass: 'btn btn-danger',
       onAction: () => new Promise((resolve: any) => {
         // cancel and close popup
         setTimeout(() => {
           resolve();
         }, 20);
       })
     }
   ]
 });
}
}

我如何在点击事件中触发onAction: => () 丢弃按钮 和取消按钮。

【问题讨论】:

  • 如果您使用原始 ngx-modal-dialog 设置您的 TestBed,您只需使用打开对话框的元素上的 debugElem.triggerEventHandler(‚click') 打开模式,然后您就可以访问再次作为 debugElem 取消和丢弃按钮并使用 triggerEventHandler。如果 ngx-modal-dialog 有太多依赖项,你不想添加到测试中,因为你想对组件进行浅层测试,你可以模拟 ngx-modal-dialog
  • @Erbsenkoenig 感谢您的回复。我试过了,但它是一个引导组件,所以它仍然显示为cannot find nativeElement of null
  • 你能告诉我如何模拟它
  • 我会尝试做一个stackblitz。
  • 你能帮我一个忙并编辑这个 stackblitz (stackblitz.com/edit/angular-xawnbl) 以便对话框正常工作。我以前没有使用过这个特定的模态对话框。之后我会做一些测试。

标签: javascript angular unit-testing jasmine jasmine-jquery


【解决方案1】:

在测试这个模态对话框时,如果传递给 modalService 的 viewRef 是被测试的实际组件本身,就会出现问题。这是因为模态对话框被添加到 viewRef 之外的 dom 中。因此,您只能使用 document.getElementById 访问测试中的元素,这是可能的,但您没有机会使用所有这些不错的 debugElement 功能等等。

不过有一种方法:如果在组件内使用 div 作为 viewRef 没有问题,那么可以进行测试。

stackblitz

这意味着您的模板需要如下所示:

模板

<div #parentDialog>
  <button type="button" (click)="cancleEditConfirmDialog()">Open Dialog</button>
</div>


如果是这样,组件将如下所示:

component.ts

  @ViewChild('parentDialog', {read: ViewContainerRef}) parentVCR;

  constructor(private modalService: ModalDialogService) {}

  cancleEditConfirmDialog() {
   this.modalService.openDialog(this.parentVCR, {
   title: 'Discard Changes ',
   childComponent: SimpleModalComponent,
   data: {
     text: 'Changes will not be saved. Do you want to proceed?'
   },
   settings: {
     closeButtonClass: 'close theme-icon-close'
   },
   actionButtons: [
     {
       text: 'Discard',
       buttonClass: 'btn btn-success',
       onAction: () => new Promise((resolve: any) => {
         // invoke delete
         // do something such as discard changes
         resolve()
       })
     },
     {
       text: 'Cancel',
       buttonClass: 'btn btn-danger',
       onAction: () => new Promise((resolve: any) => {
         // cancel and close popup
         setTimeout(() => {
            resolve();
         }, 20);
       })
     }
   ]});
 }



最后是你的测试用例:

测试

describe('AppComponent', () => {
  let fixture: ComponentFixture<AppComponent>;
  let component: AppComponent;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [ModalDialogModule.forRoot()],
      declarations: [ AppComponent],
      schemas: [NO_ERRORS_SCHEMA]
    });

    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;

    fixture.detectChanges();
  });

  it('open dialog and cancel', fakeAsync(() => {
     let buttonDebugElems: DebugElement[] = fixture.debugElement.queryAll(By.css('button'));
    expect(buttonDebugElems.length).toEqual(1);
    expect(buttonDebugElems[0].nativeElement.innerText).toEqual('Open Dialog');

    // Open
    buttonDebugElems[0].triggerEventHandler('click', null);
    fixture.detectChanges();

    buttonDebugElems = fixture.debugElement.queryAll(By.css('button'));
    expect(buttonDebugElems.length).toEqual(3);

    expect(buttonDebugElems[1].nativeElement.innerText).toEqual('Discard');
    expect(buttonDebugElems[2].nativeElement.innerText).toEqual('Cancel');

    // cancel
    buttonDebugElems[2].triggerEventHandler('click', null);
    // needed to wait for the promise to resolve (20 needed due to the timeout of the cancel promise)
    tick(20);

    buttonDebugElems = fixture.debugElement.queryAll(By.css('button'));
    expect(buttonDebugElems.length).toEqual(1);

     // todo expect the things the action changed inside you component.
  }));

  it('open dialog and discard', fakeAsync(() => {
    let buttonDebugElems: DebugElement[] = fixture.debugElement.queryAll(By.css('button'));
    expect(buttonDebugElems.length).toEqual(1);
    expect(buttonDebugElems[0].nativeElement.innerText).toEqual('Open Dialog');

    // open
    buttonDebugElems[0].triggerEventHandler('click', null);
    fixture.detectChanges();

    buttonDebugElems = fixture.debugElement.queryAll(By.css('button'));
    expect(buttonDebugElems.length).toEqual(3);

    expect(buttonDebugElems[1].nativeElement.innerText).toEqual('Discard');
    expect(buttonDebugElems[2].nativeElement.innerText).toEqual('Cancel');

    // discard
    buttonDebugElems[1].triggerEventHandler('click', null);
    // needed to wait for the promise to resolve
    tick();

    buttonDebugElems = fixture.debugElement.queryAll(By.css('button'));
    expect(buttonDebugElems.length).toEqual(1);

    // todo expect the things the action changed inside you component.

  }));
});

【讨论】:

  • 非常感谢您的努力和帮助。虽然,它扰乱了组件的 UI,但我让它成为了测试部分的解决方案。非常感谢。
  • 使用组件内部 div 的 viewref?您不需要将该 div 包裹在按钮周围,如果这有助于您的 UI,它可以是组件内任何位置的 div。唯一重要的是不要在构造函数中使用注入的 viewRef。不客气。
  • 它还没有帮助。尝试在现有的div 上方按钮上提供#parentDialog,但 Ui 仍然失真:(。
  • 你认为你可以在堆栈闪电战中重新创建它吗?也许在这里分叉这个并分享网址(这是我在进行测试之前查看对话框本身的那个):stackblitz.com/edit/angular-xawnbl
  • 另一种方法是将其添加到具有绝对位置的新 div 中,该位置位于视图之外或具有可见性:隐藏或类似的东西。但这只是猜测而没有看到实际问题
猜你喜欢
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-29
  • 1970-01-01
相关资源
最近更新 更多