How can we test our js components ?
Rebolon opened this issue · 20 comments
Hi,
I build vuejs or react components and i need to be able to run tests and i'm wondering how to do unit/e2e tests when we use encore
. I don't find anythig about this in the documentation.
Any idea ?
thanks a lot
Hey @Rebolon,
Here is a small example I made a while ago that uses Karma/Jasmine: https://github.com/Lyrkan/encore-typescript-karma
If you look at the karma.conf.js
file you'll see that you need to call Encore.configureRuntimeEnvironment
before requiring your webpack.config.js
file in order for Encore to know about which environment you want to use during your tests (you'll get an error if you forget to do that).
Hey @Lyrkan!
This is a great answer. I think we should add something to the docs to help people. Wdyt?
Hi Ryan,
I thought about it when I was toying around with karma but wasn't really happy with some of the tweaks needed to make it work.
For instance, without that part the ManifestPlugin tries to create its files using an invalid path... still not sure why:
// Set writeToFileEmit option of the ManifestPlugin to false
for (const plugin of webpackConfig.plugins) {
if ((plugin instanceof ManifestPlugin) && plugin.opts) {
plugin.opts.writeToFileEmit = false;
}
}
Or the fact that you are supposed to remove the entry point since Karma handles it itself:
// Remove entry property (handled by Karma)
delete webpackConfig.entry;
i've tried and get the following error:
{
"message": "Uncaught ReferenceError: webpackJsonp is not defined\nat assets/js/vuejs/tests/index.js:1:1\n\nReferenceError: webpackJsonp is not defined\n at assets/js/vuejs/tests/index.js:1:1",
"str": "Uncaught ReferenceError: webpackJsonp is not defined\nat assets/js/vuejs/tests/index.js:1:1\n\nReferenceError: webpackJsonp is not defined\n at assets/js/vuejs/tests/index.js:1:1"
}
Here is the PR which will improve the lisibility:
https://github.com/Rebolon/php-sf-flex-webpack-encore-vuejs/compare/feature/test-with-karma?expand=1
@Rebolon It looks like it's caused by the CommonsChunkPlugin (which is used because you call createSharedEntry
in your webpack.config.js
file), see codymikol/karma-webpack#24
I guess you could try removing it manually in your karma.conf.js
file:
// webpack.config.js
const Encore = require('@symfony/webpack-encore')
const ManifestPlugin = require('@symfony/webpack-encore/lib/webpack/webpack-manifest-plugin')
+ const webpack = require('webpack');
// Initialize Encore before requiring the .config file
Encore.configureRuntimeEnvironment('dev-server')
// Retrieve webpack config
const webpackConfig = require('./webpack.config')
// Set writeToFileEmit option of the ManifestPlugin to false
for (const plugin of webpackConfig.plugins) {
if ((plugin instanceof ManifestPlugin) && plugin.opts) {
plugin.opts.writeToFileEmit = false
}
}
+ // Remove CommonsChunkPlugin
+ webpackConfig.plugins = webpackConfig.plugins.filter(plugin => !(plugin instanceof webpack.optimize.CommonsChunkPlugin));
// Remove entry property (handled by Karma)
delete webpackConfig.entry
@Lyrkan I don’t know a lot about this, but it looks nasty - a lot of hacking to get it working. Is this unique to Karma, or is it something that will affect most test frameworks? Is there something we can add to Encore. This is the kind of stuff that it could (in theory) make easier :)
would be great if this could be reopened and be fixed in a non-that-much-hacking way =)
Yea, let’s re-open - this could at least be a docs issue.
In Webpack 4, the commons chunk plugin is removed.
I see, I'll recheck then, when upgrading to Webpack4
Any advance on this topic ?
Personally, I build my assets before running Cypress.
Then I boot a Symfony dev server in test env (APP_ENV=test bin/console ...
) and then I run Cypress.
Hello, with webpack4 no tests about vuejs are running...
I posted a thread on stackoverflow to describe the problem:
https://stackoverflow.com/questions/55060013/vuejs-karma-webpack-4-no-test-are-run
I created a specific webpack config for tests, so i only add what i needs (for instance only vueLoader and sassLoader). The problem is that karma stop reading test files when the file does an import of a signle file component. It's like if kara tryed to used the original file, whereas it should be preprocessed by webpack (or like if webpack didn't preprocessed the file).
Hey @Rebolon,
I think I found where your issue comes from... not sure yet why it happens though.
Could you try removing the <style>
from your components before running the tests?
If I'm right, they should pass and, in this case, I may have a workaround :)
The issue seems to be related to the fact that we always use the mini-css-extract-plugin
(which extracts styles to CSS files). For some reason karma-webpack
(I think) doesn't really like that and doesn't even try to load the resulting file...
There is another loader called style-loader
that works by injecting styles into the page and does not create a separate file. No easy way yet (we could probably change that) to use this loader instead of the one from mini-css-extract-plugin
, but you can do it manually (it may break in a future version of Encore though):
// Replace the mini-css-extract-plugin's loader by the style-loader
const styleExtensions = ['/\\.css$/', '/\\.s[ac]ss$/', '/\\.less$/', '/\\.styl$/'];
for (const rule of webpackConfig.module.rules) {
if (rule.test && rule.oneOf && styleExtensions.includes(rule.test.toString())) {
rule.oneOf.forEach((oneOf) => {
oneOf.use[0] = 'style-loader';
})
}
}
And here is a working example: https://github.com/Lyrkan/encore-typescript-vue
Hi @Lyrkan ,
I can confirm you that removing 'style' node allow karma to run the tests.
I didn't try the workaround with 'style-loader' but i will do it quickly.
Hope you will find a way to make Encore works !
Thks a lot. I will post a new response when i'll test the workaround.
It's ok for me with 'style-loader'.
Thank's a lot @Lyrkan
Do you want me to close the issue or let it open until Encore fix the problem ?
Let it open for now, I'm thinking about adding an Encore.disableCssExtract()
method in order to make that last part a bit more easy (and sustainable) to implement. IIRC it would also be a useful thing to have for HMR.
I'm still unsure about why karma-webpack
silently fails when the mini-css-extract-plugin
is used though... could be a bug on their side.
Okay so I really think that's a bug in karma-webpack
...
What happens is that when you import a CSS file and the mini-css-extract-plugin
is enabled you get multiple outputs for a given entry, for instance [ 'test/index.css', 'test/index.js' ]
.
In this case, the current stable version of karma-webpack
(3.0.5
) wrongly assumes that the first file of that array is the JS one, which is not always the case: https://github.com/webpack-contrib/karma-webpack/blob/670f1534151feddeca8b493ae8d01be6a34e9d35/src/karma-webpack.js#L262-L264
I found a PR that was supposed to fix this, it was merged but no 3.x
version was released since then: codymikol/karma-webpack#360
Since then they worked on a 4.x
(currently in RC), and 5.x
(currently in alpha), so I'm not sure if they still plan to release something in 3.x
. It should work fine with 4.0.0-rc.6
though.