Angular2: how to test a component that has an observable time interval

I have a slide show component that has an array of input for slide objects and shows each, if defined in slide.time . there are also two buttons that click on them to go to the next element and reset the timer. To do this, I use Observables as follows:

 /** * a "SUBJECT" for pausing(restarting) the slider auto-slide on user click on left and right arrows * @type {Subject} */ private pauser = new Subject(); /** * the main observable for timer (before adding the pause/reset option) * @type {Observable<T>} */ private source = Observable .interval(1000) .timeInterval() .map(function (x) { /*return x.value + ':' + x.interval;*/ return x }) .share(); /** * the final timer, which can be paused * @type {Observable<R>} */ private pausableSource = this.pauser.switchMap(paused => paused ? Observable.never() : this.source); /** * the subscription to the timer which is assigned at OnInit hook , and destroyed at OnDestroy */ private subscription; ngOnInit(){ this.subscription = this.pausableSource.subscribe(() => { //doing changes to the template and changing between slides }); this.pauser.next(false); } ngOnDestroy() { this.subscription.unsubscribe(); } 

and it works correctly. Now, to test this component, I give it some data in the test host component and want to test its functionality as follows:

 it("should show the second (.slidingImg img) element after testHost.data[0].time seconds have passed (which here, is 2 seconds)", () => { //testing }); 

I have tried many things that I found in documents or anywhere on the Internet, but none of them work for me. the problem is that I can not scoff at the passage of time so that the observed timer performs the following actions, and it never passes. two of the ways that didn't work for me are the following:

 it("should show the second (.slidingImg img) element after testHost.data[0].time seconds have passed (which here, is 2 seconds)", fakeAsync(() => { fixture.detectChanges(); tick(2500); flushMicrotasks(); fixture.detectChanges(); let secondSlidingImg = fixture.debugElement.queryAll(By.css('.slidingImg'))[1].query(By.css('img')); expect(secondSlidingImg).toBeTruthy(); //error: expected null to be truthy })); 

I got this from angular2 docs.

and

 beforeEach(() => { fixture = TestBed.createComponent(TestHostComponent); testHost = fixture.componentInstance; scheduler = new TestScheduler((a, b) => expect(a).toEqual(b)); const originalTimer = Observable.interval; spyOn(Observable, 'interval').and.callFake(function(initialDelay, dueTime) { return originalTimer.call(this, initialDelay, dueTime, scheduler); }); // or: // const originalTimer = Observable.timer; // spyOn(Observable, 'timer').and.callFake(function(initialDelay, dueTime) { // return originalTimer.call(this, initialDelay, dueTime, scheduler); // }); scheduler.maxFrames = 5000; }); it("should show the second (.slidingImg img) element after testHost.data[0].time seconds have passed (which here, is 2 seconds)", async(() => { scheduler.schedule(() => { fixture.detectChanges(); let secondSlidingImg = fixture.debugElement.queryAll(By.css('.slidingImg'))[1].query(By.css('img')); expect(secondSlidingImg).toBeTruthy(); //error: expected null to be truthy }, 2500, null); scheduler.flush(); })); 

I got this approach from this question .

therefore, I desperately need to know exactly how I should simulate the passage of time in my unit test, so that the really observed component time interval ... {/ p>

version:

 angular: "2.4.5" "rxjs": "5.0.1" "jasmine": "~2.4.1" "karma": "^1.3.0" "typescript": "~2.0.10" "webpack": "2.2.1" 
+5
source share

Source: https://habr.com/ru/post/1267260/


All Articles