javascriptangularunit-testingjasminejasmine-jquery

Jasmine unit testing, how do I trigger the click event of ngx-modal-dialog


I am working on an angular application and i am Unit testing the application using Jasmine.

The application uses ngx-modal-dialog(enter link description here) plugin for Pop-up Dialog Box such as a a confirmation box as a dynamic component.

enter image description here

What i want is to trigger the click event for the confirm or cancel, whatever the user chooses.

The code for the Pop-up Dialog box is as below:

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);
       })
     }
   ]
 });
}
}

how do i trigger the onAction: => () in the click event for discard button and for cancel button.

enter image description here enter image description here


Solution

  • There is a problem, with testing this modal dialog, if the viewRef passed into the modalService is the actual component under test itself. This is because the modal dialog gets added into the dom outside the viewRef. So you could only access the elements inside the test using document.getElementById which would be possible, but you wouldn't have the chance to use all those nice debugElement features and so on.

    There is a way though: if it's not a problem to use a div inside the component as the viewRef than the test could be done.

    stackblitz

    This means your template would need to look like this:

    template

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


    If thats the case the component would look like this:

    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);
           })
         }
       ]});
     }
    



    And finally your test case:

    test

    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.
    
      }));
    });