Issue
With a @ViewChild
decorator I grab the ion-input
element to set focus with the setFocus()
method. And this works as expected. I don't know why, but I can't figure out why all the Jasmine unit tests of the component fails. I've tried mocking the setFocus()
method, but without success. Can anyone help me with this and know what I'm doing wrong?
Template with the @ViewChild
reference #input_username
<ion-input id="inputusername"
#input_username
color="dark"
role="textbox"
aria-label=""
class="input"
placeholder=""
type="text"
formControlName="name"
ngDefaultControl>
</ion-input>
Component method that sets the focus with setFocus()
private _setFocusDefaultInput(input: ElementRef): void {
const ionInput = input['el']; // get the DOM element from Ionic
ionInput.setFocus();
}
The _setFocusDefaultInput()
method is called inside the ngAfterViewInit()
method
ngAfterViewInit(): void {
setTimeout(() => {
this._setFocusDefaultInput(this.inputUsername);
}, 800);
}
Error message I get when I run ALL the Jasmine unit tests that belongs to this component:
Failed: input.setFocus is not a function
error properties: Object({ longStack: 'TypeError: input.setFocus is not a function
at LoginPage._setFocusDefaultInput (src/app/login/login/login.page.ts:123:11)
at src/app/login/login/login.page.ts:54:12
at ZoneDelegate.invokeTask (node_modules/zone.js/dist/zone.js:429:1)
at AsyncTestZoneSpec.onInvokeTask (node_modules/zone.js/dist/zone-testing.js:1231:33)
at ProxyZoneSpec.onInvokeTask (node_modules/zone.js/dist/zone-testing.js:328:43)
at ZoneDelegate.invokeTask (node_modules/zone.js/dist/zone.js:428:1)
at Object.onInvokeTask (node_modules/zone.js/dist/zone.js:307:88)
at ZoneDelegate.invokeTask (nod ...
TypeError: input.setFocus is not a function
I'v tried to mock the setFocus()
method with the following code, but without success
TestBed configuration
{
provide: ElementRef,
useClass: ElementRefMock
},
{
provide: IonInput,
useClass: IonInputMock
}
Mocking classes
class ElementRefMock {
setFocus(){}
el: {
setFocus: () => {}
};
}
class IonInputMock {
setFocus(){}
el: {
setFocus: () => {}
};
Solution
I am thinking that each individual test runs faster than the timeout of 800ms and so the view of the input is destroyed but you still want to refer to it about 800ms later. Let's say a test took 200ms, 600ms the focus logic runs but within the 200ms the view has been destroyed and we are referring to something that does not exist.
Try this to debug:
private _setFocusDefaultInput(input: ElementRef): void {
const ionInput = input['el']; // get the DOM element from Ionic
// See what you get for the ionInput
console.log(ionInput);
// If ionInput is undefined, put a question mark between the . and setFocus
// This way, it won't run if ionInput is undefined or null
// You can of course put an if check as well.
ionInput?.setFocus();
}
Answered By - AliF50
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.