Jordan McDonald
Jordan McDonald

Reputation: 1131

Unit Testing select menu change event (not getting updated value)

Trying to get my select menus change event to fire correctly with the correct value. It seems to be firing but the value is not changing.

I have this select menu in my component:

<select id="seasonDropDown" style="width:200px;height: 36px;" aria-label="Select a Season" (change)="changeSeason($event.target.value)">
        <option *ngFor="let item of seasons" [value]="item.id" [selected]="item.id === seasonId">Season {{item.id}}</option>
    </select>

I have this change event:

  public changeSeason(seasonId: number) {
    this.test = 'blah';  //for testing sake
    console.log('change season ' + seasonId)
    this.seasonId = seasonId;
    this.notify.emit(this.seasonId);
  }

I have tried testing it like the code below but commponent.seasonId never changes from its default value. It should get changed in changeSeason method. I know the method is firing because when I test expect(component.test).toEqual('blah') it will pass:

    it('should emit new season on change event', fakeAsync(() => {

        let select = fixture.debugElement.query(By.css('#seasonDropDown')).nativeElement;

        select.value = 2;
        select.selectedValue = 2;

        fixture.detectChanges();

        select.dispatchEvent(new Event('change'));
        tick();

        fixture.detectChanges();


        expect(component.seasonId).toEqual(2);
        //expect(component.test).toEqual('blah');  this will pass so I know the 
        //changeSeason event is actually getting called 
  }));

Upvotes: 2

Views: 3262

Answers (1)

Juraj Plavcan
Juraj Plavcan

Reputation: 181

Before grabbing select element in your test you should run

fixture.detectChanges();

to have properly linked html elements to your component and its event handlers. Have a look at my reproduction on stackblitz. Here's just the test:

it('should emit new season on change event', () => {
  fixture.detectChanges();
  let select = fixture.debugElement.query(By.css('#seasonDropDown')).nativeElement as HTMLSelectElement;

  select.selectedIndex = 1;  // {id:2}
  select.dispatchEvent(new Event('change'));
  fixture.detectChanges();

  expect(+component.seasonId).toEqual(2);
  expect(component.test).toBe('blah');
});

Note that I used selectedIndex property of HTMLSelectElement to select 2nd option to simulate a changed selection (together with distachEvent(...)).

I hope this helps someone.

Upvotes: 6

Related Questions