shallow-render: Not working with library input components that have implemented ControlValueAccessor
I’m getting this error
error properties: Object({ originalStack: 'Error: No value accessor for form control with unspecified name attribute
when rendering an external library component that has ControlValueAccessor implemented. The library components structure is this
export class InputComponent extends InputBase<string> {
// and base
export abstract class InputBase<T> implements ControlValueAccessor {
Component is used like this
<my-input
#hexInput
(input)="onKey(hexInput.value)"
[(ngModel)]="currentColor"
[label]="'HEX code'"
[helperText]="'Please add a valid HEX color'"
[invalid]="invalidHex"
></my-input>
I can fix the issue by adding ngDefaultControl attribute but afaik this issue occurs only because the component is not recognized as having implemented ControlValueAccessor.
Can you please assist with this?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 22 (12 by maintainers)
Ok, so we managed to do a workaround in our app. We have around 1300 test files and manually adding
ngDefaultControlwasn’t even an option.Quick solution
The
shallowSupportForAngular10should be added in the main test entry point. In our case it wassetup-jest.tsExplanation
Let’s say we have the
<sps-example-test-control>component that prints hello on screen and logs when it is created:Now let’s use our component in test component and attach
[(ngModel)]to it:Angular 9
What we should be getting is an error, because our custom test control doesn’t implement
ControlValueAccessorinterface, which is required forngModelto function properly, right?When we run this component in our app as a normal component it behaves correctly, it throws an error:
However!!!, our test cases pass!!! What? Why? Shouldn’t the tests throw when view throws?
It turns out when we print
ngModelinstance in our tests we get the result below. It seems thatShallowfor some reason automatically created mock of our<sps-example-test-control>and automatically attached it tongModelasvalueAccessor. It should not work like this!Angular 10
In Angular 10 it was fixed, that means the test throws an error, because
Shallowdidn’t automagically treated our mock asvalueAccessor. So everything should be fine, right? 😃It turns out that all our
valueAccessorbindings are performed via provider inside@Component({providers: [{provide: NG_VALUE_ACCESSOR, ...}]})decorator, BUT because Shallow mocks all of the controls, the provider is never instantiated and thus each test case that uses our custom control is broken 😦Hell yeah! Glad this worked out. I had been meaning to tackle component-level providers for a while but it hadn’t given anyone any trouble until you mentioned it.
Thanks for reporting. I’ll get a proper 10.1.0 release out soon and update the docs.
It might be due to the base mocks not implementing
ControlValueAccessorbut in my testing, that wasn’t necessary.I just added a commit and pushed 10.1.0-1, give it a try and see if that resolves the issue.
Yeah, I can probably just solve this by implementing
ControlValueAccessorin the default component/directive mocks. I’ll try to get this done today and push a minor release.