Component is https://github.com/valor-software/ngx-bootstrap dropdown.
in template i have this:
<span dropdown placement="bottom right">
<a id="droplist-label" href="javascript:void(0)" dropdownToggle>
<span>{{conf.title}}</span>
</a>
<ul class="dropdown-menu pull-right" *dropdownMenu>
<li *ngFor="let item of items">
<a class="dropdown-item" (click)="listClick(item.value)" href="javascript:void(0)">{{item.label}}</a>
</li>
</ul>
</span>
The ul is not added until the label is clicked - therefor i cannot access it in the test.
Calling click:
let droplist = fixture.debugElement.query(By.css('#droplist-label')).nativeElement;
droplist.click();
Does not work - if i try to look for dropdown-menu
it is empty:
it('should test if droplist has title', async(() => {
fixture.detectChanges();
let droplist = fixture.debugElement.query(By.css('#droplist-label')).nativeElement;
droplist.click();
fixture.whenStable().then(() => {
let droplistOptions = fixture.debugElement.queryAll(By.css('.dropdown-item'));
expect(droplistOptions.length).toBeGreaterThan(0);
});
}));
The directive has a hostlistener for click event it seems - how can i trigger it so the ul becomes available?
I finally solved the same pb using fakeAsync() :
it('should render submenus', fakeAsync(() => {
fixture.detectChanges(); // update the view
// trig submenus opening
let toggleButtons = fixture.debugElement.nativeElement.querySelectorAll('[dropdownToggle]');
toggleButtons.forEach(b => b.click());
tick(); // wait for async tasks to end
fixture.detectChanges(); // update the view
// then count how many items you got for each submenus.
let droplistOptions1= fixture.debugElement.nativeElement.querySelectorAll('#first-ul > li')
let droplistOptions2= fixture.debugElement.nativeElement.querySelectorAll('#second-ul > li')
let droplistOptions3= fixture.debugElement.nativeElement.querySelectorAll('#third-ul > li')
expect(droplistOptions1.length).toEqual(3);
expect(droplistOptions2.length).toEqual(5);
expect(droplistOptions3.length).toEqual(2);
}));
But I am sure it is possible to do it with an async()
: I guess you only missed a fixture.detectChanges()
at the beginning of the fixture.whenStable().then(...)
in your initial try.
Also, remember to import the BsDropdownModule into your testbed :
import { BsDropdownModule} from 'ngx-bootstrap/dropdown';
...
TestBed.configureTestingModule({
imports: [
BsDropdownModule.forRoot(),
],
...
});
This is the solution i came up with to the problem above - using children to get the elements inside.
it('should test if droplist has listed correct values', async(() => {
comp.isOpen = true;
fixture.detectChanges();
fixture.whenStable().then(() => {
let droplist = fixture.debugElement.query(By.css('.dropdown-menu'));
fixture.detectChanges();
expect(droplist.children.length).toBeGreaterThan(0);
let i = 0;
for(let item of droplist.children) {
let anchorElement = item.children[0].nativeElement;
expect(anchorElement.innerText).toBe(droplistItems[i].label);
expect(anchorElement.getAttribute('data-value')).toBe(droplistItems[i].value);
i++;
}
});
}));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With