Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fire selectionChange event on an Angular Material MatSelect from test code

I have a Component which embeds an Angular Material MatSelect element.

In a test that I am writing, I need to simulate the selection of a certain option and make sure that the selectionChange Observable associated to that MatSelect element actually fires.

So far my code is

const mySelect: MatSelect = fixture.nativeElement.querySelector('#mySelect');
mySelect.value = 'new value';

But unfortunately this is not making the mySelect.selectionChange notify, and therefore my test work. Any idea on how this could be performed is very welcome.

like image 530
Picci Avatar asked Oct 20 '25 12:10

Picci


1 Answers

I would simply access the MatSelect in the component you want to test via @ViewChild so you can easily use it in your unit test.

/** For testing purposes */
@ViewChild(MatSelect) public matSelect: MatSelect;

And in your test I would select the desired option via _selectViaInteraction(), this simulates that the option was selected by the user.

it('test selectionChange', () => {    
  // make sure the mat-select has the expected mat-options
  const options: MatOption[] = component.matSelect.options.toArray();
  expect(options.length).toBe(3);
  expect(options[0].viewValue).toBe('Steak');
  expect(options[1].viewValue).toBe('Pizza');
  expect(options[2].viewValue).toBe('Tacos');

  // set up a spy on the function that will be invoked via selectionChange
  const spy = spyOn(component, 'onChange').and.callThrough();
  expect(spy).not.toHaveBeenCalled();

  // select the option
  options[1]._selectViaInteraction();
  fixture.detectChanges();

  // selectionChange was called and the option is now selected    
  expect(spy).toHaveBeenCalledTimes(1);
  expect(options[1].selected).toBe(true);
});

You can find a stackblitz here.

like image 142
Fabian Küng Avatar answered Oct 23 '25 02:10

Fabian Küng