Search code examples
angulartypescriptunit-testingform-controlcontrolvalueaccessor

Angular Unit Test: Error: No value accessor for form control


I am abstracting each field from my form as follows (this works in development but not in my unit test)

// required.control.ts
import { FormControl, Validators } from '@angular/forms';
    
    export class RequiredControl extends FormControl {
      protected textErrors: { [key: string]: string } = {
        required: 'Mandatory field'
      };
    
      constructor(value: string | any = '') {
        super(value);
    
        this.setValidators([Validators.required]);
      }
    
      get textError() {
        let message = '';
        for (const error in this.textErrors) {
          if (error && this.hasError(error) && this.dirty) {
            message = this.textErrors[error];
    
            return message;
          }
        }
    
        return message;
      }
    
      get state() {
        return this.valid || !this.dirty ? '' : 'error';
      }
    }

This way I can clean up my form and bring the validation logic for each field to a separate file. Now, in the main component I import this file:

// my-component.component.ts
import { RequiredControl } from './required.control.ts';

@Component({})
export class MyComponent implements OnInit { // I skiped import for this OnInit

   reasonControl = new RequiredControl(null);

   constructor() {}

   ngOnInit() {
     this.requestForm = this.formBuilder.group({
      reason: this.reasonControl, // first method tried :(
      reason:this.reasonControl as FormControl, // second method tried :(
     });
   }
}

In my unit tests I have the following:

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MyComponent],
      imports: [ReactiveFormsModule, FormsModule, RouterTestingModule] 
    })
}));

I have this in my template:

enter image description here

When I run this test I get the following error:

enter image description here


Solution

  • I found the correct solution for my issue, use the ngDefaultControl in the input element, like this:

    enter image description here

    This attribute gives the necessary knowledge to the test to be able to identify this element as a FormControl in third-party components (as is my case). Adding that attribute solves the problem.