3

In my Angular application, I'm writing some integration tests where I have an ngx-bootstrap modal

In my integration tests, I'm testing a Component which contains a button that pops up a modal. Inside a modal, there is a "Save" button which is clicked during the tests.

Inside the Modal Component, the button triggers a method on click: (click)=onSave() and this is how the Modal Component looks like:

constructor(
  protected bsModalRef: BsModalRef,
) {}


onSave() {
  // do some stuff (NOTE: this part is actually executed during the test)
  this.bsModalRef.hide();
}

Everything works fine, except that the modal won't disappear. However the onSave() method is correctly executed.

That is very strange, because if I manually click on the button after the test has finished to run, it correctly hides the modal

But during the test, despite the button correctly receives the click and triggers the execution of the onSave() method, the modal does not disapper.

Note: there are no spies involved here and, since it's an integration test, I would prefer to not mock the hide() method but to actually make it work during the test and then assert that the modal has correctly disappeared together with the other side-effects of my custom onSave() method.

Francesco Borzi
  • 56,083
  • 47
  • 179
  • 252
  • I believe there needs more details on the actual test, are you using the dispatcher api to trigger the click? – Lucho Jul 30 '19 at 22:54
  • The problem is in [this method](https://github.com/azerothcore/Keira3/blob/master/src/app/test-utils/editor-page-object.ts#L42) that is used in [this test case](https://github.com/azerothcore/Keira3/blob/master/src/app/components/editors/creature/creature-template-addon/creature-template-addon.integration.spec.ts#L140) – Francesco Borzi Aug 02 '19 at 14:01
  • Looking quickly at your test there might be some async issues, have you tried with fakeasync along with tick()? – Lucho Aug 02 '19 at 14:24
  • @Lucho when that is the case, you usually see the action completed (in this case the modal closed) then the test finishes executing. Instead, in my case the modal is still open even **after** the test completes. And even more strange is that, in the Chrome window of the karma tests, if I click on the button the modal closes correctly. – Francesco Borzi Aug 02 '19 at 14:26
  • Yes as I mentioned due to js async nature, which “expect” is failing you exactly? Then I can write an example how I mean – Lucho Aug 02 '19 at 14:31
  • @Lucho if I use for example `page.expectModalHidden()` in the test, it fails. I've tried also using `fakeAsync` and `tick()` – Francesco Borzi Aug 02 '19 at 14:42

4 Answers4

1

Can you try with this instead in your clickElement method in test utilites "page-object.ts"

from:

clickElement(element: HTMLElement): void {
    element.click();
    this.fixture.detectChanges();
  }

to:

clickElement(element: HTMLElement): void {
    element.dispatchEvent(new MouseEvent('click'));
    this.fixture.detectChanges();
  }

Example of fakeAsync & tick() test

Lucho
  • 1,455
  • 1
  • 13
  • 25
0

You need to save the the modal reference in this.modalRef when you are showing it.

constructor(private modalService: BsModalService) {}

ngOnInit() {
    this.modalRef = this.modalService.show(this.template, 
    { class: 'modal-md' });
}

save(){
     if (this.modalRef) {
        this.modalRef.hide();
     }
}
Abel Valdez
  • 2,368
  • 1
  • 16
  • 33
0

I had the same problem and I fixed it by first mocking setTimeout by

jasmine.clock().install()

Then call the:

this.modalService.hide(this.modalRef.id) 

Then call (use 300 instead of 1 if you set animated to true in the options)

jasmine.clock().tick(1)

then close up with:

jasmine.clock().uninstall()

However when I use the this.modalRef.hide() it still does not work :(

Air2
  • 369
  • 3
  • 13
0

Check in your browser console if you have an exception in your component. In my case, I had a "throw error" sample code inside an unused OnInit method.

ngOnInit(): void {
    throw new Error("Method not implemented."); //<-- Culprit
}
Luis Siri
  • 1
  • 1