Angular click select option in component test

I expanded on Emmy's answer a little bit. Here is a working "helper" method for selecting material drop downs.

import { By } from '@angular/platform-browser';

export default class TestUtils {
  static selectDropdown(id: string, fixture: any): void {
    const select = fixture.debugElement.query(By.css(`#${id}`)).nativeElement;
    select.click();
    fixture.detectChanges();
    const selectOptions = fixture.debugElement.queryAll(By.css(`.${id}Option`));
    selectOptions[5].nativeElement.click();
    fixture.detectChanges();
  }
}

This lets your specify the drop down you would like to select (by id) and the index you would like to select. The only caveat for this method is you have to add a class to your mat-option elements in your dropdown. Example:

<mat-option *ngFor="let trim of trims" value="{{trim}}" class="trimDropdownOption">{{trim}}</mat-option>

Just make sure the class for the mat-option contains the ID with the addition of 'Option'.

This solves an issue with Emmy's answer where if you have multiple drop downs on a single form, you can specify which mat-option you click on.

You can make use of the above extension method by referencing it in your test like so:

TestUtils.selectDropdown('yearDropdown', 1, fixture);
expect(fixture.componentInstance.onYearChange).toHaveBeenCalled();

You don't have to dispatch a change event. First you need to click on the trigger for your dropdown, i'm assuming it's your selectEl selectEl = fixture.debugElement.query(By.css('#dropdown')).

selectEl.click();
fixture.detectChanges();

After detectChanges your dropdown should be opened. Only after this will you be able to get your options from fixture, because before they where not present in your fixture.

The only way I have been able to get my options is by doing const selectOptions = fixture.debugElement.queryAll(By.css('.select-option')); where 'select-option'is the class I put on the options. I am using mat-select in my project, so this might be due to that.

You can click the first option by doing selectOptions[0].nativeElement.click();. Afterwards you need to call fixture.detectChanges() again. Now you have selected an option!

I was able to get the value that is now selected by doing selectEl.innerText.trim(). Not sure if this is the best way to do it, but it works. Trim is used to remove the whitespace.


The way to change the selected option of a dropdown is to set the dropdown value and then dispatch a change event.

You can use this answer as reference: Angular unit test select onChange spy on empty value

In your case, you should do something like this:

  const select: HTMLSelectElement = fixture.debugElement.query(By.css('#dropdown')).nativeElement;
  select.value = select.options[3].value;  // <-- select a new value
  select.dispatchEvent(new Event('change'));
  fixture.detectChanges();