3

Trying to write a unit test where in my component, i update a value in a FormGroup in a FormArray. However, when running the test i am presented with the error:

Cannot Read Prop value of undefined

Running the app, the code compiles fine and the value is updated when user triggered on GUI. Error appears to link to this line:

_.find(this.myForm.value.settings, {task: 'Set Alarm}).visible = true;

Component:

nominatedArray = [];
myForm: FormGroup;

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      title: ['title'],
      settings: fb.array([
        fb.group({
          completed: fb.control(false),
          task: fb.control('Set Alarm'),
          visible: fb.control(false)
        }),
        fb.group({
          completed: fb.control(false),
          task: fb.control('Brush teeth'),
          visible: fb.control(false)
        }),
        fb.group({
          completed: fb.control(false),
          task: fb.control('Shower'),
          visible: fb.control(false)
        })
      ])
    })
  }  

public updateVis() {
   // TEST IS FAILING AT 'VALUE' LINE BELOW
    _.find(this.myForm.value.settings, {task: 'Set Alarm}).visible = true;
}

Test.spec:

it('should update value, () => {

    component.myForm = this.fb.group({
      title: ['title'],
      settings: fb.array([
        fb.group({
          completed: fb.control(false),
          task: fb.control('Set Alarm'),
          visible: fb.control(false)
        }),
        fb.group({
          completed: fb.control(false),
          task: fb.control('Brush teeth'),
          visible: fb.control(false)
        }),
        fb.group({
          completed: fb.control(false),
          task: fb.control('Shower'),
          visible: fb.control(false)
        })
      ])
    })

    component.updateVis();

    expect(component.myForm.value.settings[0].visible).toBeFalsy();

});
Oam Psy
  • 8,555
  • 32
  • 93
  • 157
  • Hey, could you please recreate the issue inside a stackblitz or codepen? Otherwise please share a bit more information on how your test setup looks like. I'm a bit curious why you override the form inside you test with the same values that where set inside the component's constructor. That seems a bit odd. And while accessing the FormBuilder directly with `fb` works inside the constructor, this might not work inside the test. But that depends on your setup. – Erbsenkoenig Jun 15 '20 at 08:29
  • 1
    `_.find(this.myForm.value.settings, {task: 'Set Alarm}).visible = true;` you can not update value like this for form control. you need to find the control and do patchValue() on it. Like: `this.myForm.get('settings').controls.find(c => c.get('task').value == 'Set Alarm').patchValue({visible: true});` – mr.vea Jun 17 '20 at 14:24

2 Answers2

0

can you just try below : As i think you have don't have to initialize form. simple when component is created component.form will be there for you.

component.myForm = this.fb.group({ -- and this.fb -- i think you may have issues with this line in your spec file.

it('should update value, () => {
    console.log(component.form); // share value if this test case didn't work
    component.updateVis();

    expect(component.myForm.value.settings[0].visible).toBeFalsy();

});

or

 it('should update value, () => {

        component.updateVis();
        fixture.detectChanges();
    console.log(component.myForm.value); // share this value if solution didn't work
       expect(component.myForm.value.settings[0].visible).toBeFalsy();

    });
LogicBlower
  • 1,250
  • 1
  • 8
  • 14
0

I don't know whether the code for updating the value of the form-control is correct or not.

But if it is correct then the issue would be of initializing the form.

The form is still not initialized and you try to read the property value of it.

So you can first check the form initialization and then try to update the value of visible to true.

So you should replace your updateVis() method as the following:

public updateVis() {
 // TEST IS FAILING AT 'VALUE' LINE BELOW
  if(this.myForm)
   {
   _.find(this.myForm.value.settings, {task: 'Set Alarm}).visible = true;
   }
   else{
    setTimeout(() => {
       this.updateVis()
    }, 200);
  }

This would check the the form, if not found then would wait for 200 ms and again call the method updateVis().

Minal Shah
  • 1,402
  • 1
  • 5
  • 13