angularjestjsrxjsangular-spectator

RxJS debounceTime(0) causes unit tests failed


Added debounceTime(0) since without it my changes were not reflected to the ui properly, additionally benefit was combineLatest optiomization but it broke my unit tests.


get nativeWindow(): Window {
    return window;
}

private resize$ = fromEvent(this.nativeWindow, 'resize').pipe(
        debounceTime(50),
        map(event => event.target as Window),
        startWith(this.nativeWindow),
        untilDestroyed(this)
    );


protected dimensions$: Observable<{ width: number; height: number }> = combineLatest([this.resize$]).pipe(
        withLatestFrom(this.elementRef$),
        debounceTime(0),
        map(([, ref]) => ({ width: ref.nativeElement.offsetWidth, height: ref.nativeElement.offsetHeight })),
        filter(dim => dim.width > 0)
    );

Example unit test which worked before. I'm using @ngneat/spectator

  it('should display cropped image', () => {
                host.setHostInput({
                    assetCrop: {
                        type: 'CROP',
                        x: 100,
                        y: 100,
                        width: 200,
                        height: 200
                    }
                });
                    expect(crop?.backgroundPosition).toBe('-100px -100px');
                    expect(crop?.backgroundSize).toBe('1000px 1000px');
            });

I tried with fakeAsync and tick as well as whenStable but no successfully


Solution

  • So after investigating a problem it seems that the problem was without debounceTime(0) the stream tried to get dimensions before the resizing process finished. Adding setTimeout made it work but I'm not satisfied with the solution.

        ngAfterViewInit(): void {
            setTimeout(() => {
                this.#imageWrapperDimensions$.next({
                    width: this.elementRef.nativeElement.offsetWidth,
                    height: this.elementRef.nativeElement.offsetHeight
                });
            });
        }
    
        private resize$: Observable<{ width: number; height: number }> = this.ngZone.runOutsideAngular(() =>
            fromEvent(this.window, 'resize').pipe(
                debounceTime(50),
                map(event => event.target as Window),
                startWith(this.window),
                map(() => ({ width: this.elementRef.nativeElement.offsetWidth, height: this.elementRef.nativeElement.offsetHeight })),
                untilDestroyed(this)
            )
        );
    
        #imageWrapperDimensions$ = new Subject<{ width: number; height: number }>();
    
        protected imageWrapperDimensions$: Observable<{ width: number; height: number }> = merge(
            this.resize$,
            this.#imageWrapperDimensions$
        ).pipe(filter(dim => dim.width > 0));