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

useFakeTimers isn't working for the setInterval. #897

Open
gsamal opened this issue Jul 19, 2024 · 3 comments
Open

useFakeTimers isn't working for the setInterval. #897

gsamal opened this issue Jul 19, 2024 · 3 comments
Labels

Comments

@gsamal
Copy link

gsamal commented Jul 19, 2024

Environment

System:
    OS: Linux 5.15 Ubuntu 20.04.6 LTS (Focal Fossa)
    CPU: (8) x64 Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
    Memory: 7.71 GB / 15.38 GB
    Container: Yes
    Shell: 5.0.17 - /bin/bash
  Binaries:
    Node: 20.11.1 - ~/.nvm/versions/node/v20.11.1/bin/node
    npm: 10.2.4 - ~/.nvm/versions/node/v20.11.1/bin/npm
  Browsers:
    Chrome: 112.0.5615.49
  npmPackages:
    vitest: 1.6.0 => 1.6.0

Reproduction

Non-working code with setInterval -

  describe('Testing timers', () => {
    let triggered = false;
    beforeAll(() => {
      vi.useFakeTimers();
      setInterval(()=>{
        triggered = true;
      }, 1000)
    });
    afterAll(() => {
      vi.useRealTimers();
    });
    it.only('Should trigger the timer', () => {
      vi.advanceTimersByTime(1000);
      expect(triggered).toEqual(true); // Fails. triggered = false here
    });
  });

Working with setTimeout

  describe('Testing timers', () => {
    let triggered = false;
    beforeAll(() => {
      vi.useFakeTimers();
      setTimeout(()=>{
        triggered = true;
      }, 1000)
    });
    afterAll(() => {
      vi.useRealTimers();
    });
    it.only('Should trigger the timer', () => {
      vi.advanceTimersByTime(1000);
      expect(triggered).toEqual(true); // Successful.
    });
  });

Reproduction - https://stackblitz.com/edit/github-agxb9y-xks33q?file=test%2Fapp.nuxt.spec.ts
Works without nuxt - https://stackblitz.com/edit/vitest-dev-vitest-hr7i1i?file=test%2Ftimer.test.ts

Describe the bug

setInterval isn't triggering with fakeTimer, however setTimeout does. I have tried advanceTimersByTime, advanceTimersToNextTimer and runAllTimers but doesn't help.

Note - I don't find this issue with the Vitest itself. using defineVitestConfig is causing this behaviour.

Additional context

No response

Logs

No response

@dosubot dosubot bot added bug Something isn't working vitest-environment labels Jul 19, 2024
Copy link

dosubot bot commented Jul 19, 2024

Hey @gsamal! I'm here to help you with any bugs, questions, or contributions you may have. Let's work together to solve this issue!

The issue you're encountering with vi.useFakeTimers() and setInterval in the test-utils repository might be due to several factors:

  1. Custom Implementation of setInterval in Nuxt: The Nuxt framework has a custom implementation for setInterval that might interfere with vi.useFakeTimers(). This implementation checks if the code is running on the client side and either uses window.setInterval or throws an error/logs a message if it is running on the server side [1].

  2. Lifecycle Hooks: There are specific lifecycle hooks in the Nuxt framework that could affect the execution of setInterval when using vi.useFakeTimers(). setInterval should not be used on the server and should be wrapped with an onNuxtReady, onBeforeMount, or onMounted lifecycle hook, or ensured to be called only in the browser by checking import.meta.client [1].

  3. Environment Setup: The test-utils repository contains specific setup and teardown code that might affect the behavior of timers in tests. The setup function prepares the test environment, while the teardown function cleans up after all tests have run. This setup and teardown process could potentially influence the behavior of timers if they are dependent on the state of the file system or the environment set up by these functions [2][3].

  4. Interaction with happy-dom or jsdom: There is a known interaction between happy-dom or jsdom environments and vi.useFakeTimers() that could cause issues with setInterval. The environment setup does not explicitly address the interaction with vi.useFakeTimers(), which can lead to issues where setInterval does not behave as expected when fake timers are used [4].

To address this issue, you can try the following steps:

  1. Ensure Client-Side Execution: Make sure that setInterval is only called on the client side by wrapping it in appropriate lifecycle hooks or checking import.meta.client.

  2. Review Environment Setup: Check the setup and teardown code in your tests to ensure that they do not interfere with the behavior of timers.

  3. Use happy-dom or jsdom Configuration: Ensure that the configuration for happy-dom or jsdom is correctly set up to handle fake timers.

Here is an example of how you might modify your test to ensure setInterval is only called on the client side:

describe('Testing timers', () => {
  let triggered = false;
  beforeAll(() => {
    vi.useFakeTimers();
    if (import.meta.client) {
      setInterval(() => {
        triggered = true;
      }, 1000);
    }
  });
  afterAll(() => {
    vi.useRealTimers();
  });
  it.only('Should trigger the timer', () => {
    vi.advanceTimersByTime(1000);
    expect(triggered).toEqual(true); // Should pass if setInterval is called on the client side
  });
});

This ensures that setInterval is only executed in the client environment, which might resolve the issue with vi.useFakeTimers().

To continue talking to Dosu, mention @dosu.

@gsamal
Copy link
Author

gsamal commented Jul 19, 2024

When I tried with window.setInterval, this works. As per the above reference, it seems like we have defined our own setInterval. Is there any config in the nuxt to prevent that?

Copy link

dosubot bot commented Jul 19, 2024

No, there is no configuration in Nuxt to prevent it from using its custom setInterval implementation and allow the standard window.setInterval to be used instead. The custom implementation is designed to ensure that setInterval is not used on the server side, and it conditionally uses window.setInterval only on the client side [1].

To continue talking to Dosu, mention @dosu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant