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

Docs: weird interaction between Vitest vi.setSystemTime and VTU mount #2074

Closed
aentwist opened this issue May 23, 2023 · 8 comments · Fixed by #2100
Closed

Docs: weird interaction between Vitest vi.setSystemTime and VTU mount #2074

aentwist opened this issue May 23, 2023 · 8 comments · Fixed by #2100
Labels
bug Something isn't working

Comments

@aentwist
Copy link
Contributor

aentwist commented May 23, 2023

Describe the bug

When using mount before vi.setSystemTime, the mounted component behaves erratically. When using mount after vi.setSystemTime, it works as expected. At the very least this needs to be documented prominently. It just cost me 4 hours, and I see numerous other related issues that have been addressed in the past. Ideally, the calls would be order-indifferent.

To Reproduce

https://github.com/aentwist/set-system-time-bug

It is minimal so I'll include it here.

Get going with a component.

<template>
  <div class="home-view">
    <button type="button" @click="showMessage = !showMessage">Toggle</button>
    <div v-if="showMessage">hello, world</div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const showMessage = ref(false);
</script>

Add a test.

import { describe, expect, it, vi } from "vitest";
import { mount } from "@vue/test-utils";
import HomeView from "../HomeView.vue";

describe("HomeView", () => {
  it("shows a message when the button is toggled", async () => {
    vi.useFakeTimers();
    vi.setSystemTime("2000-01-01T00:00Z");

    const wrapper = mount(HomeView);

    const btn = wrapper.find("button");
    expect(btn).toBeTruthy();

    await btn.trigger("click");
    console.log(wrapper.text());
    expect(wrapper.text()).toContain("hello, world");

    vi.useRealTimers();
  });
});

The test works, as expected. Now move vi.setSystemTime to after mount. The test fails. See the console output in both cases.

Expected behavior

DOM updates

Actual

DOM doesn't update when called in the bugged order

@aentwist aentwist added the bug Something isn't working label May 23, 2023
@cexbrayat
Copy link
Member

I think I know what's going on, and I think this is expected.

Vue (core) compares the timestamp of the events to workaround an edge bug: https://github.com/vuejs/core/blob/main/packages/runtime-dom/src/modules/events.ts#L100-L104

So when you mount the component, the current date is used for invoker.attached.
When you set the system time after that, all the date comparisons are going to return false.

I don't think we can do much in VTU to workaround that.
Would you like to open a PR to add a note about this in the documentation? We would greatly appreciate the help!

@lmiller1990
Copy link
Member

lmiller1990 commented Jun 5, 2023

I was about to post the same thing - I think this is tied to Vue core.

It's not clear what setSystemTime actually does in Vitest: https://vitest.dev/api/vi.html#vi-setsystemtime.

I strongly doubt it actually changes the time on the OS level. I wonder what it's doing 🤔

As an aside, relying on the system time in any test is not a great idea, changing that can mess up a lot of libraries (not just Vue). I learned this the hard way. What kind of test are you writing?

I see numerous other related issues that have been addressed in the past

Which other issues? I can't see any others, at least not in Test Utils.

@aentwist
Copy link
Contributor Author

aentwist commented Jun 5, 2023

Related to vitest-dev/vitest#649, #1854, vuejs/vue-test-utils#2005

This issue might be elsewhere but I opened it here because 2005 -> 649 -> 1854, which is here.

@lmiller1990 see vitest-dev/vitest#506

See also vitest-dev/vitest#3228

If someone can confirm that there is currently 'nothing to be done', let's reclassify this and I'll try to update the docs.

@cexbrayat
Copy link
Member

@aentwist The issues you mention are vaguely related, but not exactly: your case is in fact a pure issue with how Vue works, not how VTU or Vitest work.
I confirm that we won't be able to help on VTU side, and the best we can do is to add a warning in the documentation 👍

@aentwist aentwist changed the title Bug: weird interaction between Vitest vi.setSystemTime and VTU mount Docs: weird interaction between Vitest vi.setSystemTime and VTU mount Jun 5, 2023
@cexbrayat
Copy link
Member

@aentwist Are you still willing to update the docs to add a mention of the problem so we can close the issue?

@aentwist
Copy link
Contributor Author

aentwist commented Jun 20, 2023

Yes. After a quick look... where do we want it (besides in the API docs)? It feels wrong to put it on the front page but that is really the only place it fits in the guide since the guide is learn by example and each page is hyper-specific. Would feel way better in the Vitest docs but unfortunately that doesn't make sense.

@lmiller1990
Copy link
Member

lmiller1990 commented Jun 20, 2023

Maybe FAQ? https://test-utils.vuejs.org/guide/faq/

We could rename the page "Common Issues" perhaps? Or in the Vitest docs under setSystemTime: https://vitest.dev/api/vi.html#vi-setsystemtime

It might be good to find out what the function actually does if we are adding a note about it - I'm not sure how it works under the hood, but I don't think Vitest can actually change the system time, this would greatly mess up a lot of things like SSL certificates, various encryption libraries, etc.

@aentwist
Copy link
Contributor Author

I didn't even look at that page because it is "FAQ". But based on the current content it's a perfect fit! Thanks! Maybe "Troubleshooting" or something.

It might be good to find out what the function actually does

Yeahhh not sure how generic I should make the note either. Already extended it to similarly mocking timers with Vitest even though I very specifically saw this when mocking dates with Vitest. I did this because they both use vi.setSystemTime. I wonder whether this goes beyond Vitest. Ah well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants