I have some test files with tests I'd like to run against my app.
I am attempting to use karma, karma-webpack, karma-babel-preprocessor, karma-chrome-launcher, and jasmine in my testing. My app depends on many things, including backbone, marionette, etc. My app is built using webpack, and I am attempting to use webpack to bundle my files together for testing. (I initially wanted to see if I could skip this step, i.e. simply import a file to be tested, but it seems this is impossible.)
My test script looks like
package.json (scripts section)
"test": "./node_modules/karma/bin/karma start",
The rest of the files:
karma.conf.js
var webpackConfig = require('./config/webpack/webpack.test.conf.js');
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [
{ pattern: 'test/**/*.spec.js', watched: true },
{ pattern: 'test/*.spec.js', watched: true }
],
exclude: [
],
preprocessors: {
'test/**/*.spec.js': ['webpack'],
'test/*.spec.js': ['webpack']
},
webpack: webpackConfig,
webpackMiddleware: {
stats: 'errors-only'
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
concurrency: Infinity
})
}
test/test.spec.js This file is seen
describe("A suite", function () {
it("contains spec with an expectation", function () {
expect(true).toBe(true);
});
});
describe("Another suite", function () {
it("contains another spec with an expectation", function () {
expect(true).toBe(false);
});
});
test/models/devicegroup.spec.js This file is not seen
import backbone from 'backbone';
describe("backbone", function () {
it("containsasdfasdfasdfasdfspec with an expectation", function ()
{
expect(true).toBe(false);
});
});
My folder structure is:
- karma.conf.js
- test/
- - test.spec.js
- - models/
- - - devicegroup.spec.js
- public/
- - js/
- - - app.js
When my files don't have import statements at the top, karma will run and pass/fail as expected. Putting an import statement at the top will cause karma to ignore the file. No errors are thrown.
How can I make karma / karma-webpack run my tests that have import statements / what is the karma-safe way to import modules into my tests?
When test/models/devicegroup.spec.js does not have an import statement:
// import backbone from 'backbone';
describe("backbone", function () {
it("contains with an expectation", function () {
expect(true).toBe(false);
});
});
the terminal output is: (notice one less test is run)
When test/models/devicegroup.spec.js does have an import statement:
import backbone from 'backbone';
describe("backbone", function () {
it("contains with an expectation", function () {
expect(true).toBe(false);
});
});
the terminal output is:
I see no errors in the browser Karma opens.
EDIT:
I have experimented by adding my source files to the files and preprocessors attributes in my karma.conf.js file, as per this repo example. There was no change in behavior other than a massively increased testing time.
karma.conf.js
files: [
{ pattern: 'public/js/**/*.js', watched: true},
{ pattern: 'test/**/*.spec.js', watched: true },
// each file acts as entry point for the webpack configuration
],
preprocessors: {
// add webpack as preprocessor
'public/js/**/*.js': ['webpack'],
'test/**/*.spec.js': ['webpack'],
},
EDIT2:
For the sake of experimentation (and based off this person's struggles), I have tried the above karma.conf.js in every possible combination - only test files in files and preprocessors, only source files, test files in one but not the other, source files in one but not the other, none, both. No good results, though occasionally new errors.
Little late, but I ran into the same problem, and was searching for hours, why my imports prevent the test suite from being executed. karma-webpack-4.0.0-rc.2 brought the enlightenment by providing error messages!!
I my case a couple of modules where not found, angular-mock, jquery, angular and more.
How to fix
Put there modules into the files array in your karma.config like:
files = [
"node_modules/jquery/dist/jquery.js",
"node_modules/angular/angular.js",
"node_modules/angular-mocks/angular-mocks.js",
{ pattern: "test/**/*.ts", watched: false }
I hope, this helps someone.
EDIT
My current versions of the testing related packages:
"#types/jasmine": "^2.8.8",
"jasmine": "^3.2.0",
"jasmine-core": "^3.2.1",
"jasmine-reporters": "2.3.2",
"jasmine-ts": "^0.2.1",
"karma": "3.0.0",
"karma-chrome-launcher": "2.2.0",
"karma-jasmine": "1.1.2",
"karma-junit-reporter": "1.2.0",
"karma-phantomjs-launcher": "1.0.4",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.32",
"karma-webpack": "^4.0.0-rc.2",
"typescript": "3.0.3",
"webpack": "4.17.2",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "3.1.8"
Related
I'm trying to write tests for m nodejs simple application with karma and jasmine as a framework. I'm using karma-coverage for preprocessor.
Here is the structure of the project:
package.json
{
"name": "tests",
"version": "1.0.0",
"description": "tests with karma in jasmine framework",
"directories": {
"test": "test"
},
"scripts": {
"test": "karma start karma.conf.js"
},
"author": "",
"license": "MIT",
"devDependencies": {
"jasmine-core": "^3.4.0",
"karma": "^4.2.0",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^1.1.2",
"karma-jasmine": "^2.0.1"
}
}
karma.conf.js
// Karma configuration
// Generated on Sat Aug 17 2019 09:37:53 GMT+0500 (Uzbekistan Standard Time)
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'js/*.js',
'test/*.test.js'
],
// list of files / patterns to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/*.test.js': ['coverage']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],
// 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: true,
// 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,
// optionally, configure the reporter
coverageReporter: {
type: 'html',
dir: 'coverage/'
}
})
}
Whenever I run npm test I'm getting the following error:
custom-lodash.js
class CustomLodash {
compact(array) {
let newArray = [];
for (let i = 0; i < array.length; i++) {
if (!array[i] || array[i] === undefined || array[i] === null) {
continue;
}
this.push(array[i])(newArray);
}
return newArray;
}
}
let _ = new CustomLodash;
module.exports = {
compact: _.compact
};
custom-lodash.test.js
describe("CustomLodash", function () {
let utils;
//This will be called before running each spec
beforeEach(function () {
console.log('before each');
utils = new CustomLodash();
});
describe("when calc is used to peform basic math operations", function () {
it("creates an array with all falsey values removed", function () {
// expect(utils.compact([0, 1, false, 2, '', 3])).toBe([1, 2, 3]);
let compact = utils.compact([0, 1, false, 2, '', 3]);
console.log('before each in it is: ', compact);
expect(compact).toEqual([1, 2, 3]);
//console.log('is defined ', expect(compact).toEqual([1, 2, 3]));
});
})
});
As you can see, the console.log is giving output, which means the file is being read. But, when I call toBe() or toEqual() I can see that the output is undefined (checked this in console.log too).
Any help is really appreciated. I searched for many answers and realted questions, but can't fix this one.
I want to share with my solution to this case.
Adding browserify worked for me. Also, I added watchify to watch files for incremental compilation.
Browserify was born to make your Node code in the browser. Till date
it only supports the node flavour of commons (including JSON support)
and provides in-built shims for many node core modules. Everything
else is a different package.
Here is how my package.json looks like after adding packages to run my ES6 code both in browser and Node:
"dependencies": {
"browserify": "^16.2.3",
"jasmine-core": "^3.2.1",
"karma": "^4.2.0",
"karma-chrome-launcher": "^3.1.0",
"karma-browserify": "^5.3.0",
"karma-commonjs": "^1.0.0",
"karma-coverage": "^1.1.2",
"karma-jasmine": "^2.0.1"
"watchify": "^3.11.0"
}
Don't forget to add browserify in your karma.config.js configuration as follows:
add it to your frameworks list
add it your preprocessors list.
Example:
preprocessors: {
'src/**/*.js': ['coverage'],
'js/**/*.js': ['browserify'],
'test/**/*.[sS]pec.js': ['browserify']
}
One can solve this kind of problem with ES6 by building webpack, but as browserify is much more likely to work with minimal configuration I chose using it as a solution in this situation. Hope it will help someone.
I am new to Grunt and have been struggling all day to make this work:
This is my Gulpfile.js:
'use strict';
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Automatically load required Grunt tasks
require('jit-grunt')(grunt);
module.exports = function(grunt) {
// Define the configuration for all the tasks
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: {
src: [
'Gruntfile.js',
'app/scripts/{,*/}*.js'
]
}
}
});
grunt.registerTask('build', [
'jshint'
]);
grunt.registerTask('default', ['build']);
};
This my package.json:
{
"name": "conFusion",
"private": true,
"devDependencies": {
"grunt": "^1.0.1",
"grunt-contrib-jshint": "^1.0.0",
"jit-grunt": "^0.10.0",
"jshint-stylish": "^2.2.1",
"time-grunt": "^1.4.0"
},
"engines": {
"node": ">=0.10.0"
}
}
And this is the error message i get:
grunt build
Loading "Gruntfile.js"
tasks...ERROR >>
ReferenceError: grunt is not defined
Warning: Task "build" not found.Use--force to continue.
Aborted due to warnings.
Pls guys, I need help. I am working on windows 10, so am using the command line there.
module.exports = function(grunt) {
That is where you define a grunt variable. It is an argument to the function you created.
But you try to use it here:
require('time-grunt')(grunt);
and here:
require('jit-grunt')(grunt);
This is outside the function where the variable does not exist.
Move those lines inside the function.
I am getting a file table overflow issue while running the Karma tests, and I have no clue how to debug this.
karma.conf.js:
module.exports = function (config) {
config.set({
frameworks: ['jspm', 'jasmine'],
files: [
'node_modules/karma-babel-preprocessor/node_modules/babel-core/browser-polyfill.js',
'node_modules/jasmine-async-sugar/jasmine-async-sugar.js'
],
jspm: {
config: 'jspm.conf.js',
loadFiles: ['src/app/app.js', 'src/app/**/*.spec.js'], //'src/app/**/!(*.e2e|*.po).js'
serveFiles: ['src/app/**/*.+(js|html|css|json)'] // *.{a,b,c} to *.+(a|b|c) https://github.com/karma-runner/karma/issues/1532
},
proxies: {
'/test/': '/base/test/',
'/src/app/': '/base/src/app/',
'/jspm_packages/': '/base/jspm_packages/'
},
//reporters: process.argv.slice(2).find((argv) => argv.includes('--nocoverage') || argv.includes('--no-coverage')) ? ['dots', 'junit'] : ['dots', 'junit', 'coverage'],
// use dots reporter, as Travis terminal does not support escaping sequences;
// when using Travis publish coverage to coveralls
reporters: coveralls ? ['dots', 'junit', 'coverage', 'coveralls'] : nocoverage ? ['dots'] : ['dots', 'junit', 'coverage'],
junitReporter: {
outputDir: 'test-reports/unit-test-report/',
suite: 'unit'
},
preprocessors: {
// source files, that you wanna generate coverage for - do not include tests or libraries
// (these files will be instrumented by Istanbul)
'src/**/!(*.spec|*.mock|*-mock|*.e2e|*.po|*.test).js': ['babel', 'coverage']
},
// transpile with babel since the coverage reporter throws error on ES6 syntax
babelPreprocessor: {
options: {
stage: 1,
sourceMap: 'inline'
}
},
coverageReporter: {
instrumenters: { isparta : require('isparta') },
instrumenter: {
'src/**/*.js': 'isparta'
},
dir: 'test-reports/coverage/',
subdir: normalizationBrowserName,
reporters: [
{type: 'html'}, // will generate html report
{type: 'json'}, // will generate json report file and this report is loaded to make sure failed coverage cause gulp to exit non-zero
{type: 'lcov'}, // will generate Icov report file and this report is published to coveralls
{type: 'text-summary'} // it does not generate any file but it will print coverage to console
]
},
browsers: [process.env.TRAVIS ? 'Firefox' : 'Chrome'],
browserNoActivityTimeout: 50000
});
function normalizationBrowserName(browser) {
return browser.toLowerCase().split(/[ /-]/)[0];
}
};
package.json:
"karma": "0.13.14",
"karma-jspm": "2.0.1",
"karma-jasmine": "0.3.6",
"karma-coverage": "douglasduteil/karma-coverage#next",
"karma-coveralls": "1.1.2",
"karma-ie-launcher": "0.2.0",
"karma-junit-reporter": "0.3.8",
"karma-chrome-launcher": "0.2.1",
"karma-safari-launcher": "0.1.1",
"karma-firefox-launcher": "0.1.6",
"karma-phantomjs-launcher": "0.2.1",
"karma-babel-preprocessor": "5.2.2"
test-unit.js:
gulp.task('karma', (cb) => {
// remove 'coverage' directory before each test
del.sync(path.test.testReports.coverage);
// run the karma test
const server = new Server({
configFile: path.test.config.karma,
browsers: BROWSERS.split(','),
singleRun: !argv.watch,
autoWatch: !!argv.watch
}, function(code) {
// make sure failed karma tests cause gulp to exit non-zero
if(code === 1) {
LOG(COLORS.red('Error: unit test failed '));
return process.exit(1);
}
cb();
});
server.start();
});
Error:
[08:44:36] 'karma' errored after 2.48 s [08:44:36] Error: ENFILE: file
table overflow, scandir '/Users/Abhi/Documents/projects/test/src/app'
at Error (native) at Object.fs.readdirSync (fs.js:808:18) at
GlobSync._readdir
(/Users/Abhi/Documents/projects/test/node_modules/karma/node_modules/glob/sync.js:275:41)
at GlobSync._processGlobStar
(/Users/Abhi/Documents/projects/test/node_modules/karma/node_modules/glob/sync.js:330:22)
at GlobSync._process
(/Users/Abhi/Documents/projects/test/node_modules/karma/node_modules/glob/sync.js:128:10)
at new GlobSync
(/Users/Abhi/Documents/projects/test/node_modules/karma/node_modules/glob/sync.js:46:10)
at new Glob
(/Users/Abhi/Documents/projects/test/node_modules/karma/node_modules/glob/glob.js:111:12)
at
/Users/Abhi/Documents/projects/test/node_modules/karma/lib/file-list.js:161:14
at Array.map (native) at [object Object].List._refresh
(/Users/Abhi/Documents/projects/test/node_modules/karma/lib/file-list.js:153:37)
at [object Object].List.refresh
(/Users/Abhi/Documents/projects/test/node_modules/karma/lib/file-list.js:252:27)
at [object Object].Server._start
(/Users/Abhi/Documents/projects/test/node_modules/karma/lib/server.js:177:12)
at [object Object].invoke
(/Users/Abhi/Documents/projects/test/node_modules/karma/node_modules/di/lib/injector.js:75:15)
at [object Object].Server.start
(/Users/Abhi/Documents/projects/test/node_modules/karma/lib/server.js:101:18)
at Gulp.
(/Users/Abhi/Documents/projects/test/gulp/tasks/test-unit.js:53:12) at
module.exports
(/Users/Abhi/Documents/projects/test/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:34:7)
at Gulp.Orchestrator._runTask
(/Users/Abhi/Documents/projects/test/node_modules/gulp/node_modules/orchestrator/index.js:273:3)
at Gulp.Orchestrator._runStep
(/Users/Abhi/Documents/projects/test/node_modules/gulp/node_modules/orchestrator/index.js:214:10)
at Gulp.Orchestrator.start
(/Users/Abhi/Documents/projects/test/node_modules/gulp/node_modules/orchestrator/index.js:134:8)
at
/Users/Abhi/Documents/projects/test/node_modules/gulp/bin/gulp.js:129:20
at nextTickCallbackWith0Args (node.js:419:9) at process._tickCallback
(node.js:348:13)
Karma Issue Tracker: https://github.com/karma-runner/karma/issues/1979
Abhi,
I spent a good afternoon on this and found a workaround, to what i have admit is a best guess issue that i have zero idea WHY is happening.
My issue was with the globs inside of serveFiles and loadFiles in the Karma config. To fix i did my own globbing using glob.sync to generate the arrays as i needed and this WORKED!
module.exports = function(config) {
var options = {cwd:"www"};
var glob = require("glob");
var filesToServe = glob.sync("./src/**/*.#(js|ts|css|scss|html)", options);
var specsToLoad = glob.sync("./src/**/*.#(spec.ts)", options).map(function(file){
return file.substr(2);
});
config.set({
basePath: 'www',
frameworks: ['jspm', 'jasmine'],
jspm: {
config: './test/config.js',
loadFiles: ['test/boot.ts'].concat(specsToLoad),
serveFiles: filesToServe,
},
files: [
'http://cdn.auth0.com/js/lock-8.2.min.js'
],
proxies: {
'/src/': '/base/src/',
'/.test/': '/base/.test/'
},
port: 9876,
logLevel: config.LOG_DISABLE,
colors: true,
autoWatch: true,
browsers: ['Chrome'],
plugins: [
'karma-jspm',
'karma-jasmine',
'karma-chrome-launcher',
'karma-spec-reporter'
],
reporters: ['spec'],
singleRun: true
});
};
The filesToServe and specsToLoad are treated slightly differently, i needed to remove the ./ from the files to load as it interferes with SystemJS's loading internally (this can be recognised by it trying to load a .ts.js file). Also i've got my work in a sub folder, 'www' which you might not need e.g. remove the cwd.
Hopefully you can see what i've done here and it helps you find a workaround. If anyone knows why something like glob is breaking i'd love to know.
To prove it was glob i did a simple test, using
require(glob)("src/**/*",function(file){ console.log(file); });
This triggered the same error, clearly NOTHING to do with too many files or a file table issue. If this pops up in other places, i'm going to have to clean install the OS again i think. However in my code base i use globs in other places, without any issue. I had wondered if it perhaps was the difference between using the 'sync' version of the process...
A day of wading through options to end up here... i had hoped to find a better answer.
K
I'm having trouble setting up a test config with Karma + Browserify for some React components. Mentioning code is written in ES6 and I've upgraded to latest Babel version (6+), which I assume is the root of all evil in this config.
Since Babel is now split and has this plugin-based approach (presets), I'm not sure how I should specify this in the karma.conf file.
My current config looks like this:
module.exports = function(config) {
config.set({
basePath: '',
browsers: ['PhantomJS'],
frameworks: ['browserify', 'jasmine'],
files: [
'app/js/**/*',
'app/__tests__/**/*'
],
preprocessors: {
'app/js/**/*': ['browserify'],
'app/__tests__/**/*': ['browserify']
},
browserify: {
debug: true,
transform: ['babelify']
},
singleRun: true
});
};
However this fails with a bundle error (Unexpected token while parsing file...). Also I get You need to include some adapter that implements __karma__.start method! error message.
It's funny that this happens for some very simple components.
Eg simple React file:
import React from 'react';
class FooterComponent extends React.Component {
render() {
return (
<footer>
This is the application's footer
</footer>
);
}
}
export default FooterComponent;
And the test file doesn't even import it. It's just an always passing test like:
describe('Testing `Footer` component.', () => {
describe('Method: none', function() {
it('Should be a passing test', function() {
expect(true).toBe(true);
});
});
});
The Babel/Browserify related packages in package.json are:
{
"babel-preset-es2015": "^6.0.15",
"babel-preset-react": "^6.0.15",
"babelify": "^7.2.0",
"browserify": "^12.0.1",
}
Any ideas are appreciated. Especially since this used to work before upgrading to Babel 6+.
Cheers!
Add a .babelrc file to your root directory:
{
presets: ['es2015', 'react']
}
I'm trying to write a test for my Angular controller, I'm using jasmine karma and angular-mocks, but keeps on getting the error ReferenceError: Can't find variable: module.
I had a bit of a search, but I already have the angular-mocks in my bower.
What could I be missing here?
The following is my code:
#controller
angular.module('cook_book_ctrl', [])
.controller('cookBookCtrl', function($scope, CookBook, CookBookRecipesService){
$scope.cookbookoptions = true;
CookBook.list()
.success(function(data){
$scope.recipeList = data;
CookBookRecipesService.loadCookBookRecipes($scope.recipeList);
})
.error(function(error){
})
});
#controller test
describe('CookBook controller spec', function(){
var $httpBackend, $rootScope, createController, authRequestHandler
beforeEach(module('cook_book_ctrl'));
})
#bower.json
{
"name": "HelloIonic",
"private": "true",
"devDependencies": {
"ionic": "driftyco/ionic-bower#1.0.0",
"ionic-service-analytics": "master",
"ionic-service-core": "~0.1.4",
"angular-mocks": "1.3.13"
},
"dependencies": {
"ng-cordova-oauth": "~0.1.2",
"ng-tags-input": "~2.3.0",
"angular": "~1.4.0",
"underscore": "~1.8.3",
"materialize": "~0.97.0"
},
"resolutions": {
"angular": "~1.4.0"
}
}
beforeEach(module('cook_book_ctrl'));
})
UPDATE: Screenshot added for clarity
Besides installing angular-mocks through bower, remember to add reference to angular-mocks.js in your karma config file, like below
config.set({
basePath: '../',
port: '8000',
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
...
]
In my case it was also about wrong order of files path in karma.conf.js.
Was:
// list of files / patterns to load in the browser
files: [
'tests/*.test.js', // this should not be as first!
'bower_components/angular/angular.min.js',
'bower_components/angular-mocks/angular-mocks.js',
'app/*.js',
],
Should be:
// list of files / patterns to load in the browser
files: [
'bower_components/angular/angular.min.js',
'bower_components/angular-mocks/angular-mocks.js',
'app/*.js',
'tests/*.test.js' // now it's cool
],
Maybe obvious thing or maybe not? ;-)