trurl-master / jsdom-testing-mocks

A set of tools for emulating browser behavior in jsdom environment
MIT License
116 stars 7 forks source link

[Request] Add compatibility with other libraries #44

Open dospunk opened 1 year ago

dospunk commented 1 year ago

Based on the name of this library I would have assumed that it was testing-library-agnostic, but it uses jest-specific mocking functions and therefore can't be used with other libraries like Vitest that also use the jsdom environment. I would love to see compatibility expanded, perhaps by providing a configuration option to provide the desired mocking functions or by detecting which testing library is in use.

trurl-master commented 1 year ago

Hi there @dospunk,

Thank you very much for the issue!

I would have assumed that it was testing-library-agnostic

That is the plan. I agree, I took some shortcuts, because I didn't have anything other than jest at the time. I would very much like to expand the support for other test runners

Vitest

Isn't vitest compatible with jest by default? I thought that was the case, but I never tested it.

I will try to set aside some time to look into it, unless you would like to help me out. At the very least, by describing your specific case

dospunk commented 1 year ago

@trurl-master Vitest is "compatible" with jest in that it defines most of its APIs to be compatible, but it doesn't support things like accessing the jest global variable directly so things like jest.fn() or jest.useFakeTimers() have to be replaced with vi.fn() and vi.useFakeTimers() in vitest.

A quick and dirty solution might be to have a "testingLib" variable somewhere defined like

const testingLib = jest ?? vi

but that runs into issues quickly when you consider scaling to include other frameworks that may not use the same APIs as Jest, or if Vitest and Jest's APIs start to diverge.

The best solution I've come up with is to switch to a library-agnostic mock system like sinon (I know both Jest and Vitest use their fake-timers library). The downside here is losing that easy Jest mock compatibility.

trurl-master commented 1 year ago

Hey @dospunk!

I just released a beta version that should improve the situation. For vitest at least, internally I now run all tests using jest and vi, they both work fine, but vitest has to be configured properly, i wrote a section on that in the Readme. I'd appreciate it if you'd check it out and let me know what you think!

Thank you for bringing this to my attention in any case!

dospunk commented 1 year ago

It works! Having to set toFake on vi.useFakeTimers every time is a bit clunky but just a limitation of the library I suppose. The only issue I had is having to change 'performance.now' to just 'performance' because I got a type error otherwise.

renatodeleao commented 1 year ago

@trurl-master I recreated your ResizeObserver example in Vue (using vitest + @vue/test-utils for rendering) and can't seem to make it work using the latest beta. I think I've setup the project correctly according to this repo instructions, but let me know if I'm missing something obvious:

Thanks for your work on this! Cheers ✌️

trurl-master commented 1 year ago

Hey @renatodeleao ! Thank you for creating a minimal test case, I really appreciate that!

I know little about vue, but from what I see, the code inside watch that creates the observer is not run when mount is called, so observer.observe is not called on the element and resizeObserver.resize() does nothing, i was able to make it work by adding one more await wrapper.vm.$nextTick() right after the mount. Is that normal that on the first watch call isMounted is undefined?

renatodeleao commented 1 year ago

Thank you for looking at it!

Is that normal that on the first watch call isMounted is undefined?

Yes it's normal and expected 🤦, i'm sry for polluting this thread, I should have used onMounted/onUnmounted hooks for this example anyways => here's the forked verision.

A watcher is a more common pattern for when the templateRef is not the root element of the component or if the element can be conditionally rendered (v-if) without unmounting the wrapping component instance.

trurl-master commented 1 year ago

@renatodeleao No problem, glad we were able figure it out. Don't hesitate to report any other other issues using vue, I don't have a lot of opportunities to do it myself