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)