Search code examples
angularkarma-jasmineangular-componentsangular-forms

Test a form with FormControl input


So I have a component like this:

@Component({
    selector: 'bg-formfield-markdown',
    host: {
        class: 'forminput',
        '[class.forminput-is-error]': 'isErrorState',
        '[class.forminput-locked]': 'isLockedState',
    },
    template: `<md-editor (ngModelChange)="change()" [(ngModel)]="markdown_content" [upload]="doUpload"></md-editor>`,
    styleUrls: ['./formfield-markdown.css'],
    encapsulation: ViewEncapsulation.ShadowDom
})
export class FormFieldMarkdown implements OnChanges, AfterViewInit {

in there, I pass a FormControl as @Input, like this:

@Input() control: FormControl;

I can then use this in other components like this:

<bg-formfield-markdown
    class="l-formsection-x-inputoffset"
    [control]="issueForm.rawControlMap.narrative"
    label="How did the recipient earn this badge?">
</bg-formfield-markdown>

In my Unit Test I configure the testing module like this:

TestBed.configureTestingModule({
  declarations: [
      FormFieldMarkdown,
      BgMarkdownComponent,
      MarkdownHintsDialog
  ],
  imports: [
      RouterTestingModule,
      CommonModule,
      ...COMMON_IMPORTS,
  ],
  providers: [
      ...COMMON_MOCKS_PROVIDERS_WITH_SUBS,
  ],
  schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
}).compileComponents();
fixture = TestBed.createComponent(FormFieldMarkdown);
fixture.componentInstance.control = new FormControl('', Validators.required);
fixture.detectChanges();
component = fixture.debugElement.componentInstance;

This, however, fails with the following error message:

Error: NG01203: No value accessor for form control unspecified name attribute. Find more at https://angular.io/errors/NG01203

error properties: Object({ code: -1203 })
    at _throwMissingValueAccessorError (http://localhost:9876/_karma_webpack_/vendor.js:180376:9)
    at setUpControl (http://localhost:9876/_karma_webpack_/vendor.js:180158:29)
    at NgModel._setUpStandalone (http://localhost:9876/_karma_webpack_/vendor.js:181307:5)
    at NgModel._setUpControl (http://localhost:9876/_karma_webpack_/vendor.js:181295:33)
    at NgModel.ngOnChanges (http://localhost:9876/_karma_webpack_/vendor.js:181254:12)
    at NgModel.rememberChangeHistoryAndInvokeOnChangesHook (http://localhost:9876/_karma_webpack_/vendor.js:142324:10)
    at callHookInternal (http://localhost:9876/_karma_webpack_/vendor.js:143324:10)
    at callHook (http://localhost:9876/_karma_webpack_/vendor.js:143351:5)
    at callHooks (http://localhost:9876/_karma_webpack_/vendor.js:143308:9)
    at executeInitAndCheckHooks (http://localhost:9876/_karma_webpack_/vendor.js:143262:5)

I (and also others) find this error message extremely unhelpful and can't really figure out what's going wrong. I tried adding a provider as described here to the TestBed configuration, as well as the component itself. However, I don't really know what the forwardRef should refer to; FormControl, FormFieldMarkdown, or another component altogether? The things I tried all didn't work, anyways. I also tried importing some other components and stuff, that didn't help either.

Also, this unit test should have worked some while ago, before we upgraded Angular. The whole project is open source, so feel free to check out the code for more context. I don't feel able to create a minimal example or anything of that kind, because I'm not familiar with Angular at all (and I feel like this is probably an easy fix for someone who is familiar with it).


Solution

  • Well, in the end it didn't have anything to do with the FormControl at all - I just misunderstood the error message in that regard. The problem was that my component used this markdown editor. The necessary module was properly imported in my general module, but not in my test. I thus fixed it by importing the LMarkdownEditorModule in my TestBed configuration and adding the necessary scripts, assets and imports. See this commit for details; I don't think it's too relevant, since it has nothing to do with what I originally asked for in this question.

    Maybe the learning for someone randomly stumbling upon this could be that you shouldn't try to get any information from this error message, but rather just try to produce a minimal example producing the error in order to debug it.