2

I am trying to unit test this method I created that is raised when a checkbox in a series of checkbox is changed. We take the event passed, determine the value and if the checkbox was checked checked and then amend a Form Array value depending if the FormArray contains or doesn't contain the value of the checkbox. The Component inherits its parentForm, so I mock this in the Component's Unit Test.

My problem is the const checkArray: FormArray code below is alway an empty array in my Unit Test. Here is the method:

checkboxChange($event: any): void {
    const checkArray: FormArray = this.parentForm.controls['roles'] as FormArray;
    if ($event.source.value && $event.source.checked) {
      checkArray.push(new FormControl($event.source.value));
    } else if ($event.source.value && !$event.source.checked) {
      checkArray.controls.forEach((item: FormControl, index: number) => {
        if (item.value === $event.source.value) {
          checkArray.removeAt(index);
          return;
        }
      });
    }
  }

Okay, so in my Unit Test I try to recreate the form, in its initiate state I keep it empty as I use it for other tests. Then I before my tests for the above code I try to set my form item value.

beforeEach(() => {
    fixture = TestBed.createComponent(RolesCheckboxesComponent);
    component = fixture.componentInstance;
    component.parentForm = new FormGroup({
        roles: new FormArray([])
    });
    fixture.detectChanges();
});

describe('checkboxChange', () => {
    it('should remove a role that is already present then add it again', async(() => {
      fixture.whenStable().then(() => {
        component.parentForm.controls['roles'].patchValue(
          [new FormControl('system_admin'), new FormControl('i_and_e_shop')]
        );
        // component.parentForm.controls['roles'].value.push(new FormControl('system_admin'));
        //  component.parentForm.controls['roles'].value.push(new FormControl('i_and_e_shop'));
        fixture.detectChanges(component.parentForm.controls['roles'].value);
        component.checkboxChange({ source: { value: 'i_and_e_shop', checked: false } });
        expect(component.parentForm.controls['roles'].value)
          .toEqual(['system_admin']);

        component.checkboxChange({ source: { value: 'i_and_e_shop', checked: true } });
        expect(component.parentForm.controls['roles'].value).toEqual(['system_admin', 'i_and_e_shop']);
      });
    }));
  });

The problem with my unit test is that when my method is tested component.parentForm.controls['roles'] is empty, in the application it is populated with FormControls. I have tried pushing, patching the value of the FormArray but nothing I do seems to work. Can anyone give some advice on how I can recreate the this.parentForm.controls['roles'] as FormArray; so it isn't empty?

If I haven't explained this well or I need to explain more please let me know and I shall reword my question.

Mike Sav
  • 14,805
  • 31
  • 98
  • 143

1 Answers1

2

Before my tests I had to reassign the form

beforeEach(() => {
      component.parentForm = new FormGroup({
        roles: new FormArray(
          [ new FormControl('system_admin'), new FormControl('i_and_e_shop') ])
      });
      fixture.detectChanges();
    });
Mike Sav
  • 14,805
  • 31
  • 98
  • 143