Search code examples
angulartestingangular-materialangular-testangular-changedetection

Wrapped mat-radio component tests input checked property not working


Hi I am trying to wrap the mat radio button and write unit test but im now blocked on this: "should uniquely select radios by a name".

I am trying to test the wrapped component with some basic test to check that all functionality is working correctly.

but when I set the checked input of my component it does not seem to propagate to the mat-radio-button wrapped when i test


  it('should uniquely select radios by a name', () => {
    seasonRadioInstances[0].checked = true;
    weatherRadioInstances[1].checked = true; 


    fixture.detectChanges();
// now the mat-radio-button should be updated but is not
    expect(seasonRadioInstances[0].checked).toBe(true);
    expect(seasonRadioInstances[1].checked).toBe(false);
    expect(seasonRadioInstances[2].checked).toBe(false);
    expect(weatherRadioInstances[0].checked).toBe(false);
    expect(weatherRadioInstances[1].checked).toBe(true);
    expect(weatherRadioInstances[2].checked).toBe(false);
}))

@Component({
  template: `
        <my-wrap-radio-button name="season" value="spring">Spring</my-wrap-radio-button>
        <my-wrap-radio-button name="season" value="summer">Summer</my-wrap-radio-button>
        <my-wrap-radio-button name="season" value="autum">Autumn</my-wrap-radio-button>

        <my-wrap-radio-button name="weather" value="warm">Spring</my-wrap-radio-button>
        <my-wrap-radio-button name="weather" value="hot">Summer</my-wrap-radio-button>
        <my-wrap-radio-button name="weather" value="cool">Autumn</my-wrap-radio-button>

        <span id="xyz">Baby Banana</span>
        <span id="abc">A smaller banana</span>
        <my-wrap-radio-button
          name="fruit"
          value="banana"
        >
        </my-wrap-radio-button>
        <my-wrap-radio-button name="fruit" value="raspberry">Raspberry</my-wrap-radio-button>
        <my-wrap-radio-button id="nameless" value="no-name">No name</my-wrap-radio-button>
      `,
})
class StandaloneRadioButtons {
  ariaLabel: string = 'Banana';
  ariaLabelledby: string = 'xyz';
  ariaDescribedby: string = 'abc';
}

where im going wrong with this wrap? i suppose this is a "ChangeDetection" issue, but i cannot i only update the inputs, find how to fix it... i am trying to tick and fixture when stable but no one is working.

here I have reproduced the issue with tests:

https://stackblitz.com/edit/bjdbyf?file=src%2Fapp%2Fradio-example.spec.ts


Solution

  • I fixed the test. Just add detectChanges in the test after fixture.detectChanges for each radio instance."

    Here's the code:

        it('should uniquely select radios by a name', () => {
          seasonRadioInstances[0].checked = true;
          weatherRadioInstances[1].checked = true;
    
          detectChanges();
    
          expect(seasonRadioInstances[0].checked).toBe(true);
          expect(seasonRadioInstances[1].checked).toBe(false);
          expect(seasonRadioInstances[2].checked).toBe(false);
          expect(weatherRadioInstances[0].checked).toBe(false);
          expect(weatherRadioInstances[1].checked).toBe(true);
          expect(weatherRadioInstances[2].checked).toBe(false);
    
          seasonRadioInstances[1].checked = true;
    
          detectChanges();
    
          expect(seasonRadioInstances[0].checked).toBe(false);
          expect(seasonRadioInstances[1].checked).toBe(true);
          expect(seasonRadioInstances[2].checked).toBe(false);
          expect(weatherRadioInstances[0].checked).toBe(false);
          expect(weatherRadioInstances[1].checked).toBe(true);
          expect(weatherRadioInstances[2].checked).toBe(false);
    
          weatherRadioInstances[2].checked = true;
    
          detectChanges();
    
          expect(seasonRadioInstances[0].checked).toBe(false);
          expect(seasonRadioInstances[1].checked).toBe(true);
          expect(seasonRadioInstances[2].checked).toBe(false);
          expect(weatherRadioInstances[0].checked).toBe(false);
          expect(weatherRadioInstances[1].checked).toBe(false);
          expect(weatherRadioInstances[2].checked).toBe(true);
    
          function detectChanges() {
            // need to force detectChanges in components
            seasonRadioInstances.forEach(r => r['_changeDetector'].detectChanges());
            weatherRadioInstances.forEach(r => r['_changeDetector'].detectChanges());
            fixture.detectChanges();
          }
        });