In my Angular Component I am using a 3rd party Component that is part of a form, a simplified template would look like this:
<form novalidate autofill="off" [formGroup]="addPhoneForm">
<div>
<int-phone-prefix [locale]="'en'" [defaultCountry]="'us'" formControlName="phoneNumber"></int-phone-prefix>
</div>
<div>
<input type="text"formControlName="phoneName">
</div>
</form>
Everything works great... until it is time to write tests for my component's methods. I know that I need to mock the 3rd party component to prevent it complaining about the component not being a known element. I also don't want to not use [NO_ERRORS_SCHEMA] as the 3rd party component is part of my FormGroup. So in my test file I add a mock like so before I set up my test suite, notice how I add a formControlName to the mock template, how I add the mock to the declarations array and how I even use forwardRef in my providers array so the mock will be considered part of my form....
// Mock Component
@Component({
template: '<input type="text" formControlName="phoneNumber">',
// tslint:disable-next-line
selector: 'int-phone-prefix',
})
class IntPhonePrefixComponent {
constructor() { }
}
describe('AddPhoneComponent', () => {
let component: AddPhoneComponent;
let fixture: ComponentFixture<AddPhoneComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AddPhoneComponent, IntPhonePrefixComponent],
imports: [
FormsModule,
ReactiveFormsModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => IntPhonePrefixComponent),
}
]
})
.compileComponents();
}));
However, despite the mock and including it in my providers array and the declarations array I still get the following error when I run my test suite.
Error: No value accessor for form control with name: 'phoneNumber'
Can someone please tell me what I am doing wrong?
Your providers array are in the wrong place: it's the int-phone-prefix that should have the NG_VALUE_ACCESSOR, not the testing module itself.
The simplest solution would be to stub the three required ControlValueAccessor methods for the stub IntPhonePrefixComponent (and move the provide: NG_VALUE_ACCESSOR // etc. fragment to its decorator). I'm not arguing that it's the best or the most elegant one, probably not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With