VulcanJS / Vulcan

🌋 A toolkit to quickly build apps with React, GraphQL & Meteor
http://vulcanjs.org
MIT License
7.98k stars 1.88k forks source link

Move to Jest #2270

Closed eric-burel closed 3 years ago

eric-burel commented 5 years ago

Hi,

Just to open a discussion about improving testing.

Right now, I only managed to setup Mocha to run with Meteor. I struggle to mock Meteor packages, mainly Mongo.

Jest is far more powerful in terms of performance, features, mocking and so on. It does not integrate directly with Meteor though.

This article describes however how to use Jest by mocking Meteor, which is actually quite easy : https://www.okgrow.com/posts/real-world-unit-testing-with-meteor-and-jest

To work with Vulcan, we would additionally need to rely on specific Webpack loader, exactly the same way we try to do with Storybook. Vulcan code would be fetched from the local install.

Drawbacks:

Advantages:

cvolant commented 5 years ago

Hi, I am currently studying different options to decide which framework I should adopt. Vulcan sounds really nice: if it supported Jest and PWA, I would go for it.

eric-burel commented 5 years ago

Vulcan is an active project so even if it may sometimes takes time, it's perpetually improving with new features and usage of the latest libs.

Concerning Jest it's a bit difficult due to the need to build a Meteor app with Webpack. But we managed to do it with Storybook (still under experiment/cleanup) so I am sure it will be ok.

Concerning PWAs, honestly people makes a huge deal about them but technically they are not complex features, basically the hardest part is caching data when offline. Thus I don't think this is the most relevant criteria when choosing a framework. You'll find example of Meteor+Apollo PWA that would adapt in Vulcan.

SachaG commented 5 years ago

Sounds good to me!

not sure what to do about Meteor.isClient, Meteor.isServer, and client/server code more broadly, so basically I am not 100% sure that this is actually doable. Maybe with 2 different configs for client side testing and server side testing, each producing a different build?

I think avoiding Meteor.isClient and Meteor.isServer is a good idea anyway. But I'm not really familiar enough with Jest to know more…

jimrandomh commented 5 years ago

What would be the implications for Vulcan-using projects which already have a significant number of unit tests? Will the frameworks coexist side by side?

eric-burel commented 5 years ago

I think in any case we would need both. So I think Jest tests would have to be isolated in a jest folder, a bit like Storybook, they won't be able to live anywhere in the code. This folder would be ignored by Meteor. So "meteor test" would run Mocha as usual, and "jest" would run jest tests. We could maintain a legacy behaviour + some specific tests with Mocha, and write new tests with Jest.

eric-burel commented 3 years ago

Gave a first shot at this:

Which sums up as those task:

Update: Using Babel is probably overkill, Jest moduleNameMapper is just fine for what we want.

Technical subtelty: the npm packages used by your local Vulcan install will be the one from your local Vulcan install. This is NOT the same behaviour as Meteor, which will use your app as the source of truth for NPM packages. Consequence? If you have annoying issue with core-js, run meteor npm install core-js in the folder that contains Vulcan, not only in your local application.

juliensl commented 3 years ago

This is a nice move ! I can't wait to see the result :D

eric-burel commented 3 years ago

I am almost there, with one slight limitation: it work only if you install node_modules with yarn. I suspect this issue is related to https://github.com/VulcanJS/Vulcan/issues/2680, basically Meteor is implying an older version of Babel/core-js for some reason.

eric-burel commented 3 years ago

It seems that we have to avoid to use "Meteor" and "Mongo" as global variables in Vulcan (which are bad practicies anyway), because it doesn't seem doable to define a global mock from Jest in this case (jest globals can't be functions so they are not sufficient), because the packages are imported and do not belong to users code. I've raised the question on this SO question related to Meteor and Jest

Edit: this might need a Babel plugin, babel-plugin-transform-globals seems the most appropriate here.

eric-burel commented 3 years ago

Ok I did not succeed with babel-plugin-transform-globals, somehow it isn't applied to the Vulcan install. Best course of action is to remove global "Meteor" and "Mongo" variables from Vulcan and instead import them from "meteor/meteor" explicitely (which is a better practice anyway)

eric-burel commented 3 years ago

Summary of what I've tempted so far

This is equivalent to what we do with Webpack for Storybook using aliases, and to what we can also do with Babel using this plugin. The path to your local Vulcan install + to your app packages are computed using the exact same function.

Problems

So, testing with Jest is an high source of complexity regarding the setup. It is technically doable, but would lead to too many confusion for end users in my opinion. If you have to be a Babel expert to run tests, than you'll have trouble trusting those test.

We may want to stick to Meteor Mocha until there is an official integration of Jest in Meteor or a Babel/Webpack plugin for Meteor code.

Tips to use Mocha more efficiently

Possible solution

haveaguess commented 3 years ago

Hi @eric-burel , thanks for this attempt, and sharing your progress. I was just about to start on this journey when I saw your comment in stackoverflow and this backlink. Figured Id see how you were getting on.

Just to understand, is this something we could do with a project that is simpler than what Vulcan is trying to do or is a dead-end even for simpler Meteor apps like ours?

Like you, I'd love to get the benefits of Jest that the author you referred to, seemed to, but don't want to lose time if it's a dead end.

eric-burel commented 3 years ago

Hi ! The problem will be even worse in a normal Meteor application, because the difficulty lies in making Meteor core features available with a Webpack build (or to mock them). It's not really a dead-end, this approach has been successful at least for client-side build, but more a lot of trouble for not much added value if you want also Jest for server-side test.

So it's definitely better to use Mocha solution, until Jest is supported by Meteor (if it ever happens). That means running Jest in Meteor, instead of trying to run Meteor code in Jest+Webpack.