Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debounceTime does not emit with jasmine.clock.tick in v7 #6382

Closed
dpurp opened this issue May 8, 2021 · 9 comments
Closed

debounceTime does not emit with jasmine.clock.tick in v7 #6382

dpurp opened this issue May 8, 2021 · 9 comments
Labels
7.x Issues and PRs for version 7.x

Comments

@dpurp
Copy link

dpurp commented May 8, 2021

Bug Report

\cc @leggechr

Current Behavior
In v7, debounceTime does not emit any values when installing the jasmine clock and using tick. (This works in v6)

Expected behavior
rxjs is compatible with jasmine.clock, or there is a documented workaround.

Reproduction
Note the reproductions below contain examples using the jasmine clock (which fails in v7) and the native clock (which succeeds).

v7: https://stackblitz.com/edit/rxjs-v7-debouncetime?file=test.ts
v6: https://stackblitz.com/edit/rxjs-v6-debouncetime?file=test.ts

describe('failing time tests with jasmine clock', () => {
  beforeEach(() => {
    jasmine.clock().install();
  });

  afterEach(() => {
    jasmine.clock().uninstall();
  });

  it('debounces time', async () => {
    const duration = 10;
    const source = new Subject<string>();
    const debouncedSource$ = source.pipe(
      debounceTime(duration),
      shareReplay(1)
    );
    debouncedSource$.subscribe();

    source.next('should not be emitted');
    source.next('expected value');
    jasmine.clock().tick(duration + 1); // Wait for debounce to happen.

    expect(await firstValueFrom(debouncedSource$)).toEqual('expected value');
  });
});
@cartant
Copy link
Collaborator

cartant commented May 8, 2021

Thanks. This is a bug. setInterval is captured in the interval provider:

setInterval(...args) {
const { delegate } = intervalProvider;
return (delegate?.setInterval || setInterval)(...args);
},
clearInterval(handle) {
const { delegate } = intervalProvider;
return (delegate?.clearInterval || clearInterval)(handle);
},

Instead, the provider should obtain the setInterval and clearInterval functions via globalThis.

@cartant cartant added bug Confirmed bug and removed bug Confirmed bug labels May 8, 2021
@cartant
Copy link
Collaborator

cartant commented May 8, 2021

Nope. That's not the problem. The debounceTime implementation now uses the scheduler's now function:

const targetTime = lastTime! + dueTime;
const now = scheduler.now();
if (now < targetTime) {

and

lastValue = value;
lastTime = scheduler.now();

So the issue is that Jasmine purports to mock the clock, but it does not patch Date.now.

@benlesh

@cartant cartant added the 7.x Issues and PRs for version 7.x label May 8, 2021
@cartant
Copy link
Collaborator

cartant commented May 8, 2021

Apparently, Jasmine now has a mockDate method:

beforeEach(() => {
  jasmine.clock().install()
  jasmine.clock().mockDate();
});

Calling that resolves the issue.

@benlesh
Copy link
Member

benlesh commented May 8, 2021

Ugh. Jasmine. There's a reason we stopped using it on this project. Haha.

@dpurp
Copy link
Author

dpurp commented May 9, 2021

Thanks for figuring this out for me. I confirmed it worked on a subset of tests and am rolling out the fix to the rest of the codebase.

@matheo
Copy link

matheo commented Sep 19, 2023

@benlesh the operator is broken in jest too.
something can be done over here to fix the failing tests please?

@ortegamarcel
Copy link

@matheo @avast-ye found a work around for it: change debounceTime(x) to debounce(() => interval(x)).

You can also mock it inside your tests:

import { interval } from 'rxjs';
import { debounce } from 'rxjs/operators';
import * as rxjsOperators from 'rxjs/operators';

// inside beforeEach
jest.spyOn(rxjsOperators, 'debounceTime').mockImplementation((timeout) => debounce(() => interval(timeout)));

Found here.

@AntonioEduardo1998
Copy link

I know the issue is closed, but has anyone found a definitive solution? I just upgraded to v7 and am facing the same problem using Jest.
Using debounce(() => timer(time)) seems to work, but I'm not sure if the behavior stays the same.

@villanuevadani
Copy link

Hey @AntonioEduardo1998 @ortegamarcel , thank you a lot for these ideas! Do you know if there is any recent approach that is able as well to use fakeAsync with debounceTime or something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
7.x Issues and PRs for version 7.x
Projects
None yet
Development

No branches or pull requests

7 participants