简体   繁体   中英

ngx-bootstrap bootstrap menu is not opening in Angular4+ unit tests

The dropdown menu opens fine in the app, but does not work in unit test. I'm not sure if I have missed something but I have been looking at it for a long time and I can't find any user error. I also filed an issue in on github. https://github.com/valor-software/ngx-bootstrap/issues/4282

Here's stackblitz link: https://stackblitz.com/edit/angular-euyvq4-khflez?file=src%2Fmain.ts

to run the app

// bootstrap(); // to run karma
platformBrowserDynamic().bootstrapModule(AppModule); // to run the app

to run karma

bootstrap(); // to run karma
// platformBrowserDynamic().bootstrapModule(AppModule); // to run the app

Can anyone confirm if its a bug or user error ? Thanks in advance

I think that you are running into issues because of how the event loop works with manually executing click methods on DOM nodes.

Jake Archibald (developer advocate at Google) gave a great talk about the event loop at JSConf Asia 2018. I highly recommend watching the whole thing, but at 29:57 he talks about the issue that I believe you are having. Essentially since you are manually firing off this click event, you will need to execute your test assertion as a separate task on the event loop.

You can accomplish this with a setTimeout(...) (and using the done method) in your tests or the preferred way of doing this in Angular tests of using the fixture.whenStable() method. Changing this will allow your test to pass:

fit('should open dropdown menu', () => {
  const h2: HTMLElement = fixture.nativeElement.querySelector('button#button-basic');
  h2.click();

  fixture.whenStable().then(() => {
    fixture.detectChanges();
    expect(fixture.nativeElement.querySelectorAll('li a.dropdown-item').length).toEqual(4);
  });
});

I couldn't get your Stackblitz to work but just in case anyone else is running into issues with this, if you have dynamically generated list items (with ngFor) then you need to add another detectChanges() after tick()

 it('should show 8 items (fakeasync)', fakeAsync(() => {
    const h2: HTMLElement = fixture.nativeElement.querySelector('button#button-basic');
    h2.click();
    fixture.detectChanges();
    tick(); 
    fixture.detectChanges();
 expect(fixture.nativeElement.querySelector('[dropdown]').classList).toContain('open');
    expect(fixture.nativeElement.querySelectorAll('li a.dropdown-item').length).toEqual(8)
  }));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM