Karma-browserify transformations are not done - unit-testing

I've got some problem with karma configuration.
The project is being developed using React and Browserify, react components are written using .jsx syntax and project is build with gulp.
Building works fine, but I want to cover ui components with unit tests using karma, jasmine and React.TestUtils.
Also, I use karma-browserify plugin. Generally, it works fine. When i do require('some-module') im my test files, module is imported.
But transformations are not done, when I import some module written in JSX syntax, I get an error:
ERROR [framework.browserify]: bundle error
ERROR [framework.browserify]: Error: Parsing file /path/to/project/src/ui/js/base/icon.jsx: Unexpected token (12:6)
What is wrong in my karma config, why transformations are missed?
module.exports = function (karma) {
karma.set({
basePath: './',
frameworks: ['browserify', 'jasmine'],
files: ['./**/*.test.js'],
preprocessors: {
'./**/*.test.js': ['browserify']
},
browserify: {
debug: true,
transform: ['reactify']
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: karma.LOG_INFO,
autoWatch: false,
browsers: ['Chrome'],
singleRun: true
});
};
P.S. I use xubuntu 14.10, node 0.12.4.
Gulp transformation task for browser works fine, it was build like this example
P.P.S. Thanks for your help in advance.

I came through this question when looking how to solve my own similar issue. It was the same error, only I'm using babelify transformation, and in my case it was a matter of having the syntax basis wrong, each transformation is an array itself, so after sometime of looking at a very non helpful error, and reading that one line I changed this:
browserify: {
debug: true,
transform: ['babelify',{presets: ["es2015","react"]}],
extensions: ['.js', '.jsx']}
Became:
browserify: {
debug: true,
transform: [['babelify',{presets: ["es2015","react"]}]],
extensions: ['.js', '.jsx']}
Not sure how helpful that can be, especially after all this time, but, there ya go

Related

Vue-test-utils | Jest: How to handle dependencies?

THE SITUATION:
I am implementing unit-testing in my Vue app, using vue-test-utils with Jest configuration.
When I am testing simple components everything is fine. But when I am testing components that import other dependencies, the test fails.
CONFIGURATION:
Vue version: 2.5.17
#vue/test-utils: 1.0.0-beta.20
cli-plugin-unit-jest: 3.0.3
babel-jest: 23.0.1
THE ERROR MESSAGE:
The exact error message depends on which dependency I am importing.
For example with epic-spinners the error is:
SyntaxError: Unexpected token import
With vue-radial-progress the error is:
SyntaxError: Unexpected token <
HOW TO REPRODUCE:
Make a fresh install of vue (with Jest as unit testing suite)
Run the example test, it should pass
Install a dependency (for example: npm install --save epic-spinners)
Import the dependency inside the HelloWorld component
Run the test again (without changing anything)
If I do these steps, the test fails with the above error message.
THE QUESTION:
How can I handle dependencies import in vue-test-utils / Jest ?
The problem was that some modules may not be compiled correctly.
The solution is to use the transformIgnorePatterns property of the Jest settings. That is, from the docs:
An array of regexp pattern strings that are matched against all source
file paths before transformation. If the test path matches any of the
patterns, it will not be transformed.
In my case, this is how I have solved the issue:
transformIgnorePatterns: [
"node_modules/(?!epic-spinners|vue-radial-progress)"
],
EDIT:
This is my jest.config.js
module.exports = {
moduleFileExtensions: [
'js',
'jsx',
'json',
'vue'
],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest',
},
transformIgnorePatterns: [
"node_modules/(?!epic-spinners|vue-radial-progress)"
// "node_modules/(?!epic-spinners)",
],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: [
'jest-serializer-vue'
],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
testURL: 'http://localhost/'
}
In addition to #FrancescoMussi's answer, after editing my jest.config.js, in case you get the error: jest-transform-stub not found, just install it. in my case I didn't had installed jest-transform-stub and jest-serializer-vue. after installing those my tests started working.
npm install --save-dev jest-serializer-vue
https://www.npmjs.com/package/jest-serializer-vue
and
npm install --save-dev jest-transform-stub
https://www.npmjs.com/package/jest-transform-stub
In addition to #FrancescoMussi's solution, if it is still not working for you, make sure your Babel config is in the correct place as per the Jest docs
I had moved my Babel config to package.json which Babel wasn't detecting due to Vue CLI installing Babel 7. Moving Babel config back to babel.config.js resolved the issue for me.

ember-cli-imagemin lossyPNG ImageMin.pngquant is not a function

I'm trying to enable the lossyPNG property in the ember-cli-imagmin addon to create a small file size for my .pngs. My EmberApp in ember-cli-build.js includes imagemin like so:
imagemin: {
interlaced: true,
optimizationLevel: 3,
progressive: true,
lossyPNG: true,
pngquant: {
speed: 1,
quality: 80
}
}
The dependencies object in my package.json includes:
{ ...
"ember-cli-imagemin": "0.4.0",
"imagemin": "3.2.2",
"imagemin-pngquant": "4.2.2",
...
}
However, whenever I run ember build I get the following error:
The Broccoli Plugin: [object Object] failed with:
TypeError: ImageMin.pngquant is not a function
This error points me to this line in broccoli-imagemin. If I set lossyPNG to false in ember-cli-build.js then I receive no error, but my pngs could be optimized further based on the results from pagespeed. What am I missing to be able to use pngquant to further optimize my png images?
broccoli-imagemin, which ember-cli-imagemin depends upon, is the problem. Since it hasn't been updated since Nov 2014, it uses an older version of imagemin, but the package.json specification allows imagemin v3.x. pngquant was removed as a default property in imagemin v3.2.0. So if you force the installation of imagemin v3.1.0 in your package.json it should work.
If you want to use a more recent version of imagemin look at this PR. I'd try to use that branch directly. You can install that branch directly from the repo with:
ember install https://github.com/kanongil/ember-cli-imagemin.git#v5-imagemin
This branch changes how imagemin works. Instead of passing options, it looks like you just pass the plugins that you want to use, and pass their options directly in to them.
var app = new EmberApp({
imagemin: {
plugins: [
require('imagemin-jpegtran')({ progressive: true }),
require('imagemin-pngquant')({speed: 1, quality: 80}),
require('imagemin-svgo')()
]
}
});

Django Webpack compiling misc JS in brand new Django/ReactJS app to make 21,500 line file

I have been following the below tutorial to get Django and ReactJS working:
http://geezhawk.github.io/using-react-with-django-rest-framework
I started a brand new Django project, added an app called home, but have otherwise done nothing else except what is outlined in the tutorial.
Anyway, when I compile the JS it creates a file that is about 21,500 lines and 800kb. My ReactJS file is only about 20 lines and there is no other JS to speak of from the Django app. It seems like it is compiling dependencies in the virtualenv or something. Anyway to prevent this?
webpack.config.js
//require our dependencies
var path = require('path')
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
module.exports = {
//the base directory (absolute path) for resolving the entry option
context: __dirname,
//the entry point we created earlier. Note that './' means
//your current directory. You don't have to specify the extension now,
//because you will specify extensions later in the `resolve` section
entry: './assets/js/index',
output: {
//where you want your compiled bundle to be stored
path: path.resolve('./assets/bundles/'),
//naming convention webpack should use for your files
filename: '[name]-[hash].js',
},
plugins: [
//tells webpack where to store data about your bundles.
new BundleTracker({filename: './webpack-stats.json'}),
//makes jQuery available in every module
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
],
module: {
loaders: [
//a regexp that tells webpack use the following loaders on all
//.js and .jsx files
{test: /\.jsx?$/,
//we definitely don't want babel to transpile all the files in
//node_modules. That would take a long time.
exclude: /node_modules/,
//use the babel loader
loader: 'babel-loader',
query: {
//specify that we will be dealing with React code
presets: ['react']
}
}
]
},
resolve: {
//tells webpack where to look for modules
modulesDirectories: ['node_modules'],
//extensions that should be used to resolve modules
extensions: ['', '.js', '.jsx']
}
}
A couple of things
React and jQuery are part of your bundle. Yes you only wrote ~20 lines of code, but you are also importing React into your project, and since you only have one entry defined, everything you import will get bundled into a single bundle (which may be fine for your needs). What's more, your Webpack config also imports jQuery globally. You can break dependencies up into their own bundle or into multiple bundles and load them on demand if needed.
You are bundling the development version of React. When Webpack runs and bundles your project it will do different things based on whether process.env evaluates to "development" or "production". The idea being to make development easier and build times faster during development. In the case of React, you are getting its development version with lots of comments and extra checks (more kilobytes) simply because your environment isn't set to "production".
Tree shaking, deduping, and minification are your friends. I'll let you look into these, but basically, tree shaking (part of Webpack 2) makes it so you only bundle the part of a library you actually use. In webpack 1.x, there's a deduping plugin that will remove duplicate sections of code, and minification will, well, minify your code. You can setup your Webpack config to run these steps only when being run in a production build environment.
Try swapping your plugins section out with this to start:
plugins: [
...(process.env === 'production' ? [
// set webpack process env to production
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') },
}),
new webpack.optimize.DedupePlugin(), // webpack 1.x only
new webpack.optimize.UglifyJsPlugin({ comments: false }),
] : []),
//tells webpack where to store data about your bundles.
new BundleTracker({filename: './webpack-stats.json'}),
//makes jQuery available in every module
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
],

Angular 2 unit tests/Karma test runner: Coverage reported only of "included: true" karma-test-shim

I only get test coverage results of any {included: true} file, which in my case is only karma-test-shim.js. I can't make my test files {included: true}, because SystemJs is supposed to load them in the karma-test-shim. Trying to make my test files {included: true} results in the "anonymous System register calls are not allowed" error. My tests run fine with {included: false}. Using SystemJS to load test files in karma-test-shim, and making test files {included: false}, is the standard format followed by Angular 2 github repos, including the angular2-quickstart repo.
I do use "system" as the module format in my tsconfig.json file instead of "commonjs", and the Electron browser instead of Chrome (via the karma-electron NPM package), alongwith a one line Electron require shim in the karma-test-shim file above the karma.loaded line - all of this together enables "requires" of node modules like fs, path, or installed ones, to work in tests without pre-bundling. My application is a desktop application with Electron and Angular 2.
Apart from these differences, I have exactly the same testing setup (karma.conf.js and karma-test-shim.js) as https://github.com/juliemr/ng2-test-seed.
Here is my basic karma.conf.js file:
module.exports = function(config) {
config.set({
basePath: 'src/', // all the files in the files config parameter, are searched for relative to this path
frameworks: ['jasmine'],
files: files, // the files parameter exported from another file
preprocessors: {'*.js': ['coverage']},
reporters: ['spec', 'coverage'], //report to console
port: 9876,
colors: true,
browsers: ['Electron'],
singleRun: false // true is necessary for CI. Set to false so the browser is on long enough to debug.
})
}

Using Karma in WebStorm

This is newbie question, but I could NOT find its answer on StackOverflow.
I am trying to use Karma in Webstorm. In my Spec file I am trying to require
dependent files, but 'require' itself is not defined!
It is running in Chrome under webstorm control. Here is my Karma.conf.js file and my Spec.js file.
The basic problem is that 'define', 'require', and 'requirejs' are all UNDEFINED. So how can I include any of them?!
karma.conf.js
// Karma configuration
// Generated on Tue Jul 19 2016 23:26:58 GMT-0700 (PDT)
requirejs = require('requirejs');
requirejs(["node-and-require"]);
requirejs("/ob/proj/uniformjs/main");
module.exports = function(config) {
requirejs("/ob/proj/uniformjs/main");
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: 'js',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'spec/**/*Spec.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// spec results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
lexcore/SimpleUnitSpec.js
describe("A Unit", function () {
var u; // The unit being tested
beforeEach(function(){
var requirejs = require("requirejs");
var SimpleUnit = requirejs("lexcore/SimpleUnit");
u = SimpleUnit();
});
it("to be created and defined", function(){
expect(u).toBeTruthy();
});
});
Generates this error:
ReferenceError: require is not defined
at Suite.<anonymous> (....
This is because require() does not exist in the browser/client-side JavaScript.
You have three options:
Use tag.
Use a CommmonJS implementation. Synchronous dependencies like Node.js
Use an AMD implementation.
npm install requirejs
This option will install the latest release.
Download r.js
If you prefer to not use npm, you can get r.js directly:
Download r.js from the the download page and place it in your project.
Get the source from the r.js repo and either generate the r.js via "node dist.js", or grab a snapshot from the dist directory.
Usage
These instructions assume an npm installation of 'requirejs'. If you are using the r.js file directly, replace require('requirejs') with require('./path/to/r.js').
Basic usage is: require('requirejs')
Pass the main js file's "require" function in the configuration to requirejs.
Example:
var requirejs = require('requirejs');
requirejs.config({
//Pass the top-level main.js/index.js require
//function to requirejs so that node modules
//are loaded relative to the top-level JS file.
nodeRequire: require
});
requirejs(['foo', 'bar'],
function (foo, bar) {
//foo and bar are loaded according to requirejs
//config, but if not found, then node's require
//is used to load the module.
});
I think Thennarasan's answer may work, so I left it selected.
But here is how I managed to solve my own problem:
(1) During running of karma init I specified use of requirejs
(2) I refactored my code to use the requirejs format
The issue at play is that 'require' does not exist in the browser,
and Karma is injecting your node code into the browser.