问题描述
我正在使用 ng2-idle 在一段时间后自动注销用户.我在我的 appComponent 构造函数中初始化它:
import {Idle, DEFAULT_INTERRUPTSOURCES} from '@ng-idle/core';导出类 AppComponent {构造函数(私人空闲:空闲){idle.setIdle(21600);idle.setTimeout(1);idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);idle.onTimeout.subscribe(() => { this.logout(); });};
成功登录后,我使用 this.idle.watch()
在我的 LoginComponent 中启动它(空闲被注入到构造函数中).
这一切正常,但是当我去运行我的量角器测试时,它们超时了,我想是因为量角器等待超时结束,这需要一段时间,因为我将 ng2-idle 设置为 6 小时!
错误:超时 - 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时内未调用异步回调.
如果我不使用 Idle.watch()
初始化,则测试运行.
我想要做的是在我的量角器配置文件的 onPrepare
块中设置 Idle.stop();
并将其重置为 Idle.watch();
在我的 onComplete
块中完成测试后.
我在量角器 conf 文件中尝试了 var idle = require('@ng-idle/core');
但它让我回到以下内容:
参考错误:文档未定义
那么如何在量角器配置文件中要求 ng2-idle 模块?
我无法为您提出的问题提供解决方案.但是我将为您提供一种不同的方法来解决这个问题.在为我的团队设置量角器时,我在使用 ng-idle 实施会话超时策略后遇到了同样的问题.在关于如何解决这个问题的一些心痛之后,我意识到可以使用 Angular zone API 来解决这个问题.这是我的 appcomponent 与解决方案.请参阅区域中的 runOutsideAngular 和 run 方法.
请注意,所有状态更改都包含在 run 方法中.否则,更改检测将不起作用,并且包括倒数计时器在内的所有状态字段都不会更新 UI.
此解决方案涉及修改使用 ng-idle 的应用程序,因为根据我目前的理解,这无法在量角器中完成.
@Component( {选择器:'app-root',templateUrl: './app.component.html',styleUrls : ['./app.component.scss']})导出类 AppComponent 实现 OnInit、OnDestroy{idleState = '未开始.';idleStateTitle = '';idleStateBtnText = '';超时=假;@ViewChild( DialogComponent ) 对话框:DialogComponent;构造函数(私人空闲:空闲,私有位置策略:位置策略,私有 authUtils: AuthUtils,私人 ngZone: NgZone ){this.ngZone.runOutsideAngular(() => {//空闲计时器设置为28分钟,超时倒计时将运行2分钟.idle.setIdle( 28 * 60 );idle.setTimeout(120);});//当空闲开始时显示带有倒数计时器的对话框idle.onIdleStart.subscribe(() =>{this.idleState = '';this.idleStateTitle = '您的会话即将过期.';this.idleStateBtnText = '保持登录状态';this.ngZone.run(() => this.dialog.show());});//用户停止空闲idle.onIdleEnd.subscribe( () =>{this.idleState = '不再空闲.';});//在到期前两分钟显示超时警告idle.onTimeoutWarning.subscribe( ( 倒计时 ) =>{this.ngZone.run(() => { this.idleState = '您的会话将在 ' + 倒计时 + ' 秒后超时!'});});//会话超时idle.onTimeout.subscribe(() =>{this.ngZone.run(() =>{this.idleStateTitle = "您的会话已过期.";this.idleState = '要继续,请重新登录';this.timedOut = true;this.idleStateBtnText = '重新登录';});});}重启(){this.ngZone.runOutsideAngular(() => {this.idle.watch();});this.ngZone.run(() =>{this.idleState = '开始.';this.idleStateTitle = "";this.idleStateBtnText = '';this.timedOut = false;});}title = '项目';/*** <p>通过从用户服务获取用户令牌来刷新令牌.还要在这里重置空闲状态计时器.</p>*/刷新令牌(){this.authUtils.refreshToken();this.reset();}/*** 处理超时*/进程超时(){this.dialog.hide(null);如果(this.timedOut){AuthUtils.invalidateSession();让 origin = window.location.origin;window.location.href = origin + this.locationStrategy.getBaseHref() + "?_="+ (Math.floor(Math.random() * 10000));}别的{this.refreshToken();}}ngOnInit(): 无效{this.reset();}ngOnDestroy(): 无效{this.ngZone.runOutsideAngular(() =>{this.idle.stop();});}}
我使用 browser.waitForAngularEnabled(false)
并在 beforeEach
和 afterEach
茉莉花例程中禁用和启用它们取得了部分成功.但它们是片状的,并不适用于所有测试.
我检查了 ng2-idle 问题跟踪器,发现此 这里
I'm using ng2-idle to auto logout users after a period of time. I initialise it in my appComponent constructor:
import {Idle, DEFAULT_INTERRUPTSOURCES} from '@ng-idle/core';
export class AppComponent {
constructor(
private idle:Idle) {
idle.setIdle(21600);
idle.setTimeout(1);
idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);
idle.onTimeout.subscribe(() => { this.logout(); });
};
Upon successful login I start it up in my LoginComponent using this.idle.watch()
(Idle is injected into the constructor).
This all works fine but when I go to run my protractor tests they timeout, I think because protractor is left waiting for the timeout to end which will take a while since I set ng2-idle to 6 hours!
If I don't initialise using Idle.watch()
then the tests run.
What I want to do is to set Idle.stop();
in the onPrepare
block in my protractor config file and reset it to Idle.watch();
after the tests are complete in my onComplete
block.
I have tried var idle = require('@ng-idle/core');
in the protractor conf file but it throws me back the following:
So how can I require the ng2-idle module in protractors config file?
I cannot provide you a solution for the question you asked. But I will provide you a different approach to solve this problem. While setting up Protractor for my team, I encountered the same issue after implementing a session timeout strategy using ng-idle. After some heartburn on how to solve this, I realized Angular zone API can be used to resolve this. Here is my appcomponent with a solution.See runOutsideAngular and run methods in the zone.
Notice that all state changes are wrapped inside the run method. If not, the change detection will not work and none of the state fields including count down timer will not update UI.
This solution involves modifying the application which uses ng-idle as this cannot be done within Protractor in my current understanding.
@Component( {
selector : 'app-root',
templateUrl: './app.component.html',
styleUrls : [ './app.component.scss' ]
} )
export class AppComponent implements OnInit, OnDestroy{
idleState = 'Not started.';
idleStateTitle = '';
idleStateBtnText = '';
timedOut = false;
@ViewChild( DialogComponent ) dialog: DialogComponent;
constructor( private idle: Idle,
private locationStrategy: LocationStrategy,
private authUtils: AuthUtils,
private ngZone: NgZone ){
this.ngZone.runOutsideAngular(() => {
//Idle timer is set to 28 minutes and timeout count down timer will run for 2 minutes.
idle.setIdle( 28 * 60 );
idle.setTimeout( 120 );
});
//When idling starts display the dialog with count down timer
idle.onIdleStart.subscribe( () =>{
this.idleState = '';
this.idleStateTitle = 'Your session is about to expire.';
this.idleStateBtnText = 'Stay Logged In';
this.ngZone.run(() => this.dialog.show());
} );
//User stopped idling
idle.onIdleEnd.subscribe( () =>{
this.idleState = 'No longer idle.';
} );
//Show timeout warning two minutes before expiry
idle.onTimeoutWarning.subscribe( ( countdown ) =>{
this.ngZone.run(() => { this.idleState = 'Your session will time out in ' + countdown + ' seconds! '});
} );
//Session Timed out
idle.onTimeout.subscribe( () =>{
this.ngZone.run( () =>{
this.idleStateTitle = "Your session has expired.";
this.idleState = 'To Continue, log back in';
this.timedOut = true;
this.idleStateBtnText = 'Log in Again';
} );
});
}
reset(){
this.ngZone.runOutsideAngular(() => {
this.idle.watch();
});
this.ngZone.run( () =>{
this.idleState = 'Started.';
this.idleStateTitle = "";
this.idleStateBtnText = '';
this.timedOut = false;
});
}
title = 'Projects';
/**
* <p>Refresh Token by getting user token from the user service. Also reset the idle state timer here.</p>
*/
refreshToken(){
this.authUtils.refreshToken();
this.reset();
}
/**
* Handle timeout
*/
processTimeout(){
this.dialog.hide( null );
if( this.timedOut ){
AuthUtils.invalidateSession();
let origin = window.location.origin;
window.location.href = origin + this.locationStrategy.getBaseHref() + "?_="+ (Math.floor(Math.random() * 10000));
}
else{
this.refreshToken();
}
}
ngOnInit(): void{
this.reset();
}
ngOnDestroy(): void{
this.ngZone.runOutsideAngular(() =>{
this.idle.stop();
});
}
}
I had some partial success using browser.waitForAngularEnabled(false)
and disabling and enabling them within beforeEach
and afterEach
jasmine routines. but they were flaky and did not work for all tests.
Edit: I checked ng2-idle issue tracker and found there is an open defect for this here
这篇关于停止 ng2-idle 进行量角器测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!