2

I have a simple custom control as below. Everything is working but the unit test is failing. How can I unit test this custom control? How can I pass a valid NgControl directive?

I have tried using providers:

[
  {
    provide: NgControl,
    useValue: new FormGroup()
  }
]

but I still get the same error.

core-edi.component.ts

import { Component, OnInit, Input, ViewChild, ElementRef, Self, Optional, forwardRef } from '@angular/core';
import {
  ControlValueAccessor, NG_VALUE_ACCESSOR, Validator, AbstractControl,
  ValidatorFn, Validators, NG_VALIDATORS, NgControl, NgForm
} from '@angular/forms';
import { Placeholder } from '@angular/compiler/src/i18n/i18n_ast';

@Component({
  selector: 'app-core-edi',
  templateUrl: './core-edi.component.html',
  styleUrls: ['./core-edi.component.css'],

})
export class CoreEdiComponent implements ControlValueAccessor, Validator, OnInit {



  @ViewChild('input') input: ElementRef;
  disabled;

  @Input() type = 'text';

  @Input() isRequired: boolean = false;
  @Input() pattern: string = null;
  @Input() label: string = null;
  @Input() placeholder: string;
  @Input() errorMsg: string;
  @Input() min: number;
  @Input() minLength: number;



  myhint: string = '10 digit number';

  constructor(@Self() public controlDir: NgControl) {
    this.controlDir.valueAccessor = this;
  }

  ngOnInit() {
    const control = this.controlDir.control;
    const validators: ValidatorFn[] = control.validator ? [control.validator] : [];
    if (this.isRequired) {
      validators.push(Validators.required);
    }
    if (this.pattern) {
      validators.push(Validators.pattern(this.pattern));
    }

    if (this.min) {
      validators.push(Validators.min(this.min));
    }

    control.setValidators(validators);
    control.updateValueAndValidity();

    this.placeholder = this.placeholder + (this.isRequired ? '*' : '');
  }

  onChange(event) { 

  }


  onTouched() {

   }

  writeValue(obj: any): void {
    this.input.nativeElement.value = obj;
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  validate(c: AbstractControl): { [key: string]: any; } {
    const validators: ValidatorFn[] = [];
    if (this.isRequired) {
      validators.push(Validators.required);
    }
    if (this.pattern) {
      validators.push(Validators.pattern(this.pattern));
    }

    if (this.min) {
      validators.push(Validators.min(this.min));
    }

    return validators;
  }

core-edi.component.html

<div class="form-label-group" fxLayout="column" fxLayoutGap="5px">

  <mat-form-field class="edi-field-width">   
        <input matInput class="form-control" 
            [type]="type" #input
            (input)="onChange($event.target.value)"
            (blur)="onTouched()"
            [disabled]="disabled"
            [placeholder]="placeholder"
            [min]="1111111111"
            [minLength] = 10
            (keyup)="mykeyup()">

            <mat-hint>Hint: {{ myhint }}</mat-hint>

 </mat-form-field>


 <span class="error"
     *ngIf="controlDir && !controlDir.control.valid 
     && controlDir.control.touched">{{errorMsg}}</span>

</div>

core-edi.component.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { CoreEdiComponent } from './core-edi.component';
import { FormsModule, ReactiveFormsModule, FormControl, NgControl, FormControlDirective } from '@angular/forms';
import { MaterialModule } from 'src/app/material/material.module';



fdescribe('CoreEdiComponent', () => {
  let component: CoreEdiComponent;
  let fixture: ComponentFixture<CoreEdiComponent>;

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

  beforeEach(() => {
    fixture = TestBed.createComponent(CoreEdiComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });


 it('should create', () => {
    expect(component).toBeTruthy();
  });

});

No provider for NgControl ("[ERROR ->]<app-core-edi></app-core-edi>"): @0:0
            at syntaxError (./node_modules/@angular/compiler/fesm5/compiler.js?:1275:17)
            at TemplateParser.parse (./node_modules/@angular/compiler/fesm5/compiler.js?:15084:19)
            at JitCompiler._parseTemplate (./node_modules/@angular/compiler/fesm5/compiler.js?:24272:37)
            at JitCompiler._compileTemplate (./node_modules/@angular/compiler/fesm5/compiler.js?:24259:23)
            at eval (./node_modules/@angular/compiler/fesm5/compiler.js?:24202:62)
            at Set.forEach (<anonymous>)
            at JitCompiler._compileComponents (./node_modules/@angular/compiler/fesm5/compiler.js?:24202:19)
            at eval (./node_modules/@angular/compiler/fesm5/compiler.js?:24120:19)
            at Object.then (./node_modules/@angular/compiler/fesm5/compiler.js?:1266:77)
            at JitCompiler._compileModuleAndAllComponents (./node_modules/@angular/compiler/fesm5/compiler.js?:24118:26)
        Expected undefined to be truthy.
            at UserContext.eval (./src/app/core/core-edi/core-edi.component.spec.ts?:30:27)
            at ZoneDelegate.invoke (./node_modules/zone.js/dist/zone.js?:390:26)
            at ProxyZoneSpec.onInvoke (./node_modules/zone.js/dist/zone-testing.js?:288:39)
jkdev
  • 11,360
  • 15
  • 54
  • 77

1 Answers1

0

I have not been through understanding how to unit test in angular yet, but maybe its in the app.module that you need to add like the ReactiveFormsModule

The answer to this helped me out

Why do I get this Template parse errors in Angular

Just my 2cents