Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - Forcing a reactive form to be valid in a unit test

Tags:

I am using Angular v4.4.4. In a component, after a button is clicked in the template, the form is saved assuming the reactive form is valid. Something like (pseudo-code):

public onSave(): void {
    if (this.myForm.valid) {
        this._createFoo();
    }
}

private _createFoo(): void {
    this._fooService.createItem(this.foo).subscribe(result => {
        // stuff happens...
    });
}

In the related unit test I need to force the form to be valid so I can confirm the service is being called. Something like this:

it('should create Foo', () => {
    const spy = spyOn(_fooService, 'createItem').and.callThrough();
    component.foo = new Foo();
    fixture.detectChanges();
    const bookButton = fixture.debugElement.query(By.css('#bookButton'));
    expect(bookButton !== null).toBeTruthy('missing Book button');
    bookButton.triggerEventHandler('click', null);
    expect(spy).toHaveBeenCalled();
});

This will fail because myForm is never set as valid.

In this particular case I do not want to give every input in the form a value. I just need to watch and see if the service subscription occurs. How can I force the form to be valid?

like image 735
ebakunin Avatar asked Oct 04 '17 20:10

ebakunin


People also ask

How do you make a reactive form valid?

Validating input in reactive formslink. In a reactive form, the source of truth is the component class. Instead of adding validators through attributes in the template, you add validator functions directly to the form control model in the component class.

How do you write a test case for reactive form?

Step 1: Get the login form from component. Step 2: Create a dummy login form default value object. Step 3: At-last, compare both the form group values with dummy object. Step 2: Get the username value from the component form builder.

What is SpyOn in Angular unit testing?

Test the Component logic using SpyOn. SpyOn is a Jasmine feature that allows dynamically intercepting the calls to a function and change its result. This example shows how spyOn works, even if we are still mocking up our service.

What makes a FormGroup valid?

The profileForm as a FormGroup is valid, when all of it's controls are valid. So each FormControl has a validator Validator. required on it which either returns a valid state or an invalid state. The FormGroup then collects those values and if all of them are valid, it sets the form to valid .


2 Answers

Why not just clear the validators list?

// If there are any async validators
//
this.myForm.clearAsyncValidators();
// If there are any normal validators
//
this.myForm.clearValidators();
// Doing the validation on all the controls to put them back to valid
//
this.formGroup.updateValueAndValidity();

This will ensure your form has no validators, thus being valid.

like image 156
realappie Avatar answered Oct 02 '22 22:10

realappie


If someone is still struggling with this:

As @realappie answer suggests, we should clear all sync/async validators. But the validators in most cases are on the controls and not the form itself . So, just loop all the controls perform this operation on each control.

From the test file it should look like:

const controls = component.myForm.controls;

for (const control in controls) {
    // Clear sync validators - use clearAsyncValidators() for async
    // validators
    controls[control].clearValidators();
    // should update just the control and not everything
    controls[control].updateValueAndValidity({ onlySelf: true });
}
component.myForm.updateValueAndValidity();
like image 43
Krasimira Kirilova Avatar answered Oct 02 '22 23:10

Krasimira Kirilova