TypeError: input.setFocus is not a function when I run all Jasmine unit tests associated with the Angular component
TypeError: input.setFocus is not a function when I run all Jasmine unit tests associated with the Angular component
使用 @ViewChild
装饰器,我抓住 ion-input
元素以使用 setFocus()
方法设置焦点。这按预期工作。我不知道为什么,但我想不通为什么组件的所有 Jasmine 单元测试都失败了。我试过模拟 setFocus()
方法,但没有成功。谁能帮我解决这个问题并知道我做错了什么?
带有 @ViewChild
参考的模板 #input_username
<ion-input id="inputusername"
#input_username
color="dark"
role="textbox"
aria-label=""
class="input"
placeholder=""
type="text"
formControlName="name"
ngDefaultControl>
</ion-input>
设置焦点的组件方法setFocus()
private _setFocusDefaultInput(input: ElementRef): void {
const ionInput = input['el']; // get the DOM element from Ionic
ionInput.setFocus();
}
_setFocusDefaultInput()
方法在ngAfterViewInit()
方法内部调用
ngAfterViewInit(): void {
setTimeout(() => {
this._setFocusDefaultInput(this.inputUsername);
}, 800);
}
当我 运行 属于该组件的所有 Jasmine 单元测试时收到的错误消息:
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
我尝试使用以下代码模拟 setFocus()
方法,但没有成功
测试台配置
{
provide: ElementRef,
useClass: ElementRefMock
},
{
provide: IonInput,
useClass: IonInputMock
}
嘲笑类
class ElementRefMock {
setFocus(){}
el: {
setFocus: () => {}
};
}
class IonInputMock {
setFocus(){}
el: {
setFocus: () => {}
};
我认为每个单独的测试都比 800 毫秒的超时运行得更快,因此输入的视图被破坏了,但您仍然想在大约 800 毫秒后引用它。假设测试耗时 200 毫秒,焦点逻辑运行 600 毫秒,但在 200 毫秒内视图已被破坏,我们指的是不存在的东西。
试试这个调试:
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();
}
之前的答案解决了我的问题,但我找到了一个新的解决方案,它不再需要 setTimeout 方法来将焦点正确设置在 Ionic 输入字段上。我 运行 遇到的 Jasmine 单元测试问题也已通过此实现得到解决
我把ElementRef
接口换成IonInput
接口直接调用setFocus()
:
@ViewChild('input_username') inputUsername: IonInput;
</pre>
我实现了 ionViewDidEnter()
Ionic 生命周期方法。在所有 Ionic 元素都已成功渲染到 DOM 之前,不会调用此方法。那是我想将焦点设置在 Ionic 输入字段上的时候:
ionViewDidEnter(): void {
this.inputUsername.setFocus();
}
</pre>
使用 @ViewChild
装饰器,我抓住 ion-input
元素以使用 setFocus()
方法设置焦点。这按预期工作。我不知道为什么,但我想不通为什么组件的所有 Jasmine 单元测试都失败了。我试过模拟 setFocus()
方法,但没有成功。谁能帮我解决这个问题并知道我做错了什么?
带有 @ViewChild
参考的模板 #input_username
<ion-input id="inputusername"
#input_username
color="dark"
role="textbox"
aria-label=""
class="input"
placeholder=""
type="text"
formControlName="name"
ngDefaultControl>
</ion-input>
设置焦点的组件方法setFocus()
private _setFocusDefaultInput(input: ElementRef): void {
const ionInput = input['el']; // get the DOM element from Ionic
ionInput.setFocus();
}
_setFocusDefaultInput()
方法在ngAfterViewInit()
方法内部调用
ngAfterViewInit(): void {
setTimeout(() => {
this._setFocusDefaultInput(this.inputUsername);
}, 800);
}
当我 运行 属于该组件的所有 Jasmine 单元测试时收到的错误消息:
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
我尝试使用以下代码模拟 setFocus()
方法,但没有成功
测试台配置
{
provide: ElementRef,
useClass: ElementRefMock
},
{
provide: IonInput,
useClass: IonInputMock
}
嘲笑类
class ElementRefMock {
setFocus(){}
el: {
setFocus: () => {}
};
}
class IonInputMock {
setFocus(){}
el: {
setFocus: () => {}
};
我认为每个单独的测试都比 800 毫秒的超时运行得更快,因此输入的视图被破坏了,但您仍然想在大约 800 毫秒后引用它。假设测试耗时 200 毫秒,焦点逻辑运行 600 毫秒,但在 200 毫秒内视图已被破坏,我们指的是不存在的东西。
试试这个调试:
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();
}
之前的答案解决了我的问题,但我找到了一个新的解决方案,它不再需要 setTimeout 方法来将焦点正确设置在 Ionic 输入字段上。我 运行 遇到的 Jasmine 单元测试问题也已通过此实现得到解决
我把
ElementRef
接口换成IonInput
接口直接调用setFocus()
:@ViewChild('input_username') inputUsername: IonInput; </pre>
我实现了
ionViewDidEnter()
Ionic 生命周期方法。在所有 Ionic 元素都已成功渲染到 DOM 之前,不会调用此方法。那是我想将焦点设置在 Ionic 输入字段上的时候:ionViewDidEnter(): void { this.inputUsername.setFocus(); } </pre>