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

How can we test our js components ? #256

Open
Rebolon opened this issue Feb 5, 2018 · 20 comments
Open

How can we test our js components ? #256

Rebolon opened this issue Feb 5, 2018 · 20 comments
Labels

Comments

@Rebolon
Copy link

Rebolon commented Feb 5, 2018

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

@Lyrkan
Copy link
Collaborator

Lyrkan commented Feb 5, 2018

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).

@Lyrkan Lyrkan added the question label Feb 5, 2018
@weaverryan
Copy link
Member

Hey @Lyrkan!

This is a great answer. I think we should add something to the docs to help people. Wdyt?

@Lyrkan
Copy link
Collaborator

Lyrkan commented Feb 5, 2018

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;

@Rebolon
Copy link
Author

Rebolon commented Feb 6, 2018

Thanks for the answer @Lyrkan, i'll test it quickly.

@Rebolon
Copy link
Author

Rebolon commented Feb 6, 2018

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

@Lyrkan
Copy link
Collaborator

Lyrkan commented Feb 6, 2018

@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

@weaverryan
Copy link
Member

@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 :)

@Rebolon
Copy link
Author

Rebolon commented Feb 7, 2018

thanks a lot @Lyrkan it works great now

@Rebolon Rebolon closed this as completed Feb 7, 2018
@pscheit
Copy link

pscheit commented Jul 18, 2018

would be great if this could be reopened and be fixed in a non-that-much-hacking way =)

@weaverryan
Copy link
Member

Yea, let’s re-open - this could at least be a docs issue.

In Webpack 4, the commons chunk plugin is removed.

@weaverryan weaverryan reopened this Jul 18, 2018
@Lyrkan
Copy link
Collaborator

Lyrkan commented Jul 18, 2018

@pscheit We'll have to check if that can be done more easily with Webpack 4 (see #324) since the CommonsChunkPlugin will be gone.

@pscheit
Copy link

pscheit commented Jul 18, 2018

I see, I'll recheck then, when upgrading to Webpack4

@marcovoliveira
Copy link

Any advance on this topic ?

@Kocal
Copy link
Member

Kocal commented Feb 4, 2019

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.

@Rebolon
Copy link
Author

Rebolon commented Mar 8, 2019

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).

@Lyrkan
Copy link
Collaborator

Lyrkan commented Mar 10, 2019

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-loaderthat 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

@Rebolon
Copy link
Author

Rebolon commented Mar 10, 2019

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.

@Rebolon
Copy link
Author

Rebolon commented Mar 11, 2019

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 ?

@Lyrkan
Copy link
Collaborator

Lyrkan commented Mar 11, 2019

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.

@Lyrkan
Copy link
Collaborator

Lyrkan commented Mar 11, 2019

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.

weaverryan added a commit that referenced this issue Mar 25, 2019
…kan)

This PR was merged into the master branch.

Discussion
----------

Add Encore.disableCssExtraction() to the public API

This PR adds an `Encore.disableCssExtraction()` method that allows to disable the `mini-css-extract-plugin` and use the `style-loader` instead.

It can be used to solve various problems that, until now, required a really ugly workaround that relied on our internal implementation (for instance the following commit probably broke some builds that used previous versions of it: 6867443#diff-8beacd21a12ca072bafa4e8e3f1aae6b).

Related issues: #3, #256, #348, #527

Commits
-------

347feed Add Encore.disableCssExtraction() to the public API
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

6 participants