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

Using Painless with Webpack #20

Open
PhiLhoSoft opened this issue Jun 14, 2016 · 6 comments
Open

Using Painless with Webpack #20

PhiLhoSoft opened this issue Jun 14, 2016 · 6 comments

Comments

@PhiLhoSoft
Copy link

Beware: I am new to Painless and to Webpack!
I have some experience with Karma, though...

I am trying to use Webpack for a small AngularJS 1 project, with ES5.
So I made a little variant of the https://github.com/preboot/angular-webpack project.
Instead of using Jasmine, I try to use Painless.
(BTW, the choice of name is poor, if I search painless test or similar, I get lot of wrong hits... 😧)

The project itself works, I can get it running in the browser. Things get trickier when I try to test...
So, I would appreciate if you could give some instructions, or even better some sample files, showing how to use Painless with Webpack and Karma.

@PhiLhoSoft
Copy link
Author

PhiLhoSoft commented Jun 14, 2016

Some relevant extracts of the project files:

package.json

    "karma": "^0.13.14",
    "karma-webpack": "^1.7.0",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-painless": "^1.3.0",
    "karma-coverage": "^0.5.3",
    "karma-phantomjs-launcher": "^1.0.0",
    "phantomjs-prebuilt": "^2.1.4",
    "angular-mocks": "^1.5.0",

    "painless": "^0.9.5",

    "webpack": "^1.12.13",
    "webpack-dev-server": "^1.14.1",

webpack.config.js

module.exports = function makeWebpackConfig()
{
    var config = {};

    /**
     * Entry
     * Reference: http://webpack.github.io/docs/configuration.html#entry
     * Should be an empty object if it's generating a test build
     * Karma will set this when it's a test build
     */
    config.entry = isTest ? {} :
    {
        app: './src/app/app.js'
    };

    /**
     * Output
     * Reference: http://webpack.github.io/docs/configuration.html#output
     * Should be an empty object if it's generating a test build.
     * Karma will handle setting it up for you when it's a test build.
     */
    config.output = isTest ? {} :
    {
        // Absolute output directory
        path: __dirname + '/dist',

        // Output path from the view of the page
        // Uses webpack-dev-server in development
        publicPath: isProd ? '/' : 'http://localhost:8080/',

        // Filename for entry points
        // Only adds hash in build mode
        filename: isProd ? '[name].[hash].js' : '[name].bundle.js',

        // Filename for non-entry points
        // Only adds hash in build mode
        chunkFilename: isProd ? '[name].[hash].js' : '[name].bundle.js'
    };

    config.module =
    {
        preLoaders: [],
        loaders:
        [
            {
                test: /\.css$/,
                loader: isTest ? 'null' : ExtractTextPlugin.extract('style', 'css?sourceMap!postcss')
            },
            {
                test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
                loader: 'file'
            },
            {
                test: /\.html$/,
                loader: 'raw'
            }
        ],
        noParse:
        [
            /sinon\.js/,
            /painless/,
        ]
    };

    if (isTest)
    {
        config.module.preLoaders.push(
        {
            test: /\.js$/,
            include: __dirname + '/src/app/',
            exclude:
            [
                /node_modules/,
                /\.test\.js$/
            ],
            loader: 'istanbul-instrumenter'
        });
    }
// [...]
};

karma.conf.js

module.exports = function karmaConfig(config)
{
    var plugins =
    [
        'karma-webpack', 'karma-sourcemap-loader',
        'karma-painless',
        'karma-phantomjs-launcher', 'karma-coverage',
    ];
    var reporters = [ 'dots', 'coverage' ];

    var configuration =
    {
        frameworks:
        [
            'painless'
        ],

        plugins: plugins,
        reporters: reporters,

        files:
        [
            'src/tests.webpack.js'
        ],
        exclude: [],

        preprocessors:
        {
            'src/tests.webpack.js': [ 'webpack', 'sourcemap' ]
        },

        browsers: [ 'PhantomJS' ],

        autoWatch: false,
        singleRun: true,

        coverageReporter:
        {
            dir: 'coverage/',
            reporters:
            [
                { type: 'text-summary' },
                { type: 'html' }
            ]
        },

        webpack: require('./webpack.config'),

        // Hide Webpack build information from output
        webpackMiddleware:
        {
            noInfo: 'errors-only'
        }
    };
    config.set(configuration);
};

tests.webpack.js

require('angular');
require('angular-mocks/angular-mocks');

var testsContext = require.context(".", true, /.test$/);
testsContext.keys().forEach(testsContext);

As you can see, I have set as "noParse" both Sinon and Painless, to avoid Webpack to parse them.
Not sure if that's the right way...
Anyway, with this setting, I have the following error:

PhantomJS 2.1.1 (Windows 8 0.0.0) ERROR
  ReferenceError: Can't find variable: require
  at D:/3rdPartySources/angular-webpack-playground/src/tests.webpack.js:34281 <- webpack:///~/painless/index.js:1:0

OK, require is not understood because Webpack couldn't parse it.
But if I remove Painless from the noParse setting, Webpack complains that require is called with a non-constant expression:

WARNING in ./~/painless/index.js
Critical dependencies:
58:19-121 the request of a dependency is an expression
 @ ./~/painless/index.js 58:19-121

Beside, it tries to parse (and complains) all files at top-level of node_modules/painless.

WARNING in ./~/painless/index.js
Critical dependencies:
58:19-121 the request of a dependency is an expression
 @ ./~/painless/index.js 58:19-121

WARNING in ./~/painless/package.json
Module parse failed: D:\Sources\angular-webpack-playground\node_modules\painless\package.json Unexpected token (2:9)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (2:9)
[...]
WARNING in ./~/painless/CHANGELOG.md
Module parse failed: D:\Sources\angular-webpack-playground\node_modules\painless\CHANGELOG.md Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected character '#' (1:00)
[...]

What I am missing?

@PhiLhoSoft
Copy link
Author

PhiLhoSoft commented Jun 14, 2016

Mmm, seems relevant: sinonjs/sinon#555 and webpack/webpack#304
Ugh! Ugly...
I wouldn't like to go back to Jasmine (it is OK, but sucks at reporting differences in objects, among other problems).

@taylorhakes
Copy link
Owner

Thanks for reporting. This appears to be an issue with painless and webpack. Painless has a dynamic require that forces webpack to include all files in the folder. I will work to fix this.

There is also an issue with sinon using UMD module definitions. I will have to fix that as well. It is going to take a few days.

Browserify works currently. You can either use that or wait a few days for a fix.

@PhiLhoSoft
Copy link
Author

I will wait... 😣
I thought it worked out of the box with Webpack, as you mention it several times in the readme... 😑

For Sinon, from what I have read, the version 2.0 should fix that (but it isn't out yet), and meanwhile, the trick I found might do the right thing:

    noParse:
    [
        /sinon\.js/, // Don't load sinon's source and its problematic requires
    //  /painless/,
    ],
    resolve:
    {
        alias:
        {
            // Loads the bundled version instead
            // (see https://github.com/webpack/webpack/issues/304)
            'sinon': 'sinon/pkg/sinon'
        }
    }

Side note: you mention "It is possible to switch out assertion and mocking libraries". For clueless people like me, it would be nice to show how... At least if we want to upgrade Chai or Sinon. 😄

@taylorhakes
Copy link
Owner

I mentioned webpack once in karma-painless. I will remove it from the readme until it's fixed.

In order to use another mocking library, you can just install another library via NPM and require it yourself. Sinon and chai will still be included as well, so that won't fix your issue. You can also do the alias thing you are doing above with browserify or webpack (when it's fixed).

@BarthesSimpson
Copy link

Is this fixed now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants