Issue
Using Angular/Jasmine/Karma I am testing a function that runs in ngOnInit that will log out a user from 15 minutes inactivity.
Here is the original code:
   #setSessionTimeout() {
      const clicks$ = fromEvent(document, 'click');
      const checkInterval = 60000; // 1 minute
      const timeLimit = 15; // 15 minutes
  
      clicks$.pipe(
        startWith('fake click'),
        switchMap(() =>
          interval(checkInterval).pipe(
            tap(value => {                                    
              console.log(value);                                                        
              if (value > timeLimit) {                                                   
                this.router.navigate(['logout']);                            
              }                                                              
            })
          )                                                                  
        )                                                                    
      ).subscribe()                                                          
    }  
Here is my test:
    fit('should log out a user after 15 minutes of inactivity', fakeAsync(() => {                                    
      tick(1000 * 60 * 60 * 60);                                                                                                                      
      fixture.detectChanges();                                                                                                                                                       
      expect(routerMock.navigate).toHaveBeenCalledWith(['logout']);                                                                  
    }));
I can not get the test to pass. It also looks like that function is not running in the test because I see no console.log out. How can I test this function properly?
Solution
Answered:
Ok, I figure it out. I had a fixture.detectChanges(); in the beforeEach() hook which was placed there by angular's cli when it created the test. If I move that fixture.detectChanges(); out of the beforeEach() and place it in the tests instead, then I can successfully test my logic successfully.
It does not make sense because there is still fixture.detectChanges(); that is called initially per a test, just in the test itself instead of the beforeEach(). Nevertheless, it was the issue and solution.
It should be noted that #setSessionTimeout() is called in ngOnInit() which complicates the testing situation. If it was a public function that I could test without ngOnInit() kicking it off, it would of not required this workaround.
Here are my tests which I successfully verified no false positives or vice versa:
it('should log out a user after 15 minutes of inactivity', fakeAsync(() => {                                                                             
      fixture.detectChanges();                                                                                                                 
      tick(1000 * 60 * 15); // reaches 14 times                                                                                                                
      fixture.detectChanges();                                                                                                                      
      tick(1000 * 60 * 15); // reaches 29 times and logs out                                                                                                                                             
      fixture.detectChanges();                                                                                        
                                                                                                                               
      expect(routerMock.navigate).toHaveBeenCalledWith(['logout']);                                                                                                    
      discardPeriodicTasks();
    }));                                                                                                                                         
                                                                                                    
    it('should not log out a user after 15 minutes of inactivity because user did a click', fakeAsync(() => {
      fixture.detectChanges();                                                                                                                   
      tick(1000 * 60 * 15); // reaches 14 times                                                                                                  
      fixture.detectChanges();                                                                                                                   
                                                                                                                                                                                                      
      document.dispatchEvent(new MouseEvent('click'));                                                                                                                                              
                                                                                                                                                 
      tick(1000 * 60 * 15); // reaches 29 and does not logout because of click                                                                                                   
      fixture.detectChanges();
                                                                                                                                              
      expect(routerMock.navigate).not.toHaveBeenCalledWith(['logout']);                                                                    
      discardPeriodicTasks();
    })); 
Answered By - dman
 
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.