Error : You need to include some adapter that implements __karma__.start method - karma-runner

I'm trying to run unit tests using karma and i'm getting the error You need to include some adapter that implements __karma__.start method!. I tried running with grunt and karma start commands. I did googling and all the solutions didn't work out. Not sure what i'm doing wrong. I included the right adapter which comes with karma-jasmine, which has the __karma__.start method, under plugins in karma.conf.js file. Here's my configuration file :-
module.exports = function(config){
config.set({
// root path location that will be used to resolve all relative paths in files and exclude sections
basePath : '../',
files : [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'node_modules/requirejs/require.js',
'node_modules/karma-jasmine/lib/adapter.js',
'app.js',
'mainapp/mainapp.js',
'mainapp/notes/notes.js',
'mainapp/notes/partial/create/create.js',
'mainapp/notes/partial/create/create-spec.js'
],
// files to exclude
exclude: [
'bower_components/angular/angular/*.min.js'
],
// karma has its own autoWatch feature but Grunt watch can also do this
autoWatch : false,
// testing framework, be sure to install the correct karma plugin
frameworks: ['jasmine', 'browserify', 'requirejs'],
// browsers to test against, be sure to install the correct browser launcher plugins
browsers : ['PhantomJS'],
// map of preprocessors that is used mostly for plugins
preprocessors: {
'mainapp/notes/partial/create/create-spec.js' : ['browserify']
},
reporters: ['progress'],
// list of karma plugins
plugins : [
'karma-teamcity-reporter',
'karma-chrome-launcher',
'karma-phantomjs-launcher',
'karma-babel-preprocessor',
'karma-requirejs',
'karma-jasmine',
'karma-browserify'
],
singleRun: true
})}

Using the requirejs framework turns off the automatic calling of __karma__.start. You need to create a file that a) configures RequireJS and b) calls __karma__.start to kick of the tests. Here's an example. It scans through the files that Karma is serving to find the files that contains tests. This is based on a naming convention that any file that ends with spec.js or test.js is a test file. It converts the file names to module names. It then configures RequireJS. One thing it does is pass all the test modules as deps so that all test modules are loaded right away. It sets __karma__.start as callback so that when all modules passed in deps are loaded, the tests start.
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
allTestFiles.push(file);
}
});
require.config({
baseUrl: '/base',
paths: {
'chai': 'node_modules/chai/chai',
'chai-jquery': 'node_modules/chai-jquery/chai-jquery',
'jquery': 'node_modules/jquery/dist/jquery.min',
'underscore': '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min',
'sn/sn-underscore': 'static/scripts/sn/sn-underscore',
'vendor/jquery-ui': '//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min'
},
deps: allTestFiles,
callback: window.__karma__.start
});
You need to include this file in your files parameter in your karma.conf.js file. Since you use the requirejs framework, you just need to put it first in the list. For instance, if you call the file test-main.js (as suggested in Karma's documentation):
files: [
'test-main.js',
...
]
If you load RequireJS yourself by listing it in files, you need to put test-main.js after RequireJS.

Related

Karma angular testing failed to instantiate module

I am just starting to set up some tests with Karma. I some tests working with jdDom, but did not like how it was configuring. However, I am not sure how to point to the js files correctly. As I am getting this error
Error: [$injector:modulerr] Failed to instantiate module ha.module.utility due to:
Error: [$injector:nomod] Module 'ha.module.utility' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
I started a file with jsdom that required the core modules
require('../../../src/modules/core/module.core.built.js');
require('../../../src/modules/utility/module.utility.built.js');
These scripts are where my modules reside. I am not sure where to put them in the karma file. Or if this is even the issue . Here is my karma file below. I removed the comments that come with karma init so it could be quicker to read on this post.
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: 'Scripts/',
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'jquery /jquery libraries ',
'../node_modules/angular/angular.js',
'../node_modules/angular-mocks/angular-mocks.js',
'test2/*.js',
'tests/**/*.js'
],
exclude: [
'tests/old/**',
'tests/**/*.setup.js'
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'../Templates/**/*.html' : ['ng-html2js']
},
ngHtml2JsPreprocessor: {
// setting this option will create only a single module that contains templates
// from all the files, so you can load them all with angular.mock.module('foo')
//stripPrefix: "Templates/",
//prependPrefix: "Templates/",
moduleName: 'templates'
},
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: true,
concurrency: Infinity
Basically I need these tests to find the modules.
Your modules' directives, controllers, and all other required files should be uploaded into your list of "files," like this:
files: [
'../node_modules/angular/angular.js',
'../node_modules/angular-mocks/angular-mocks.js',
'../../../src/modules/core/module.core.built.js',
'../../../src/modules/utility/module.utility.built.js',
'test2/*.js',
'tests/**/*.js'
],

jspm not loading bundles with --inject

Been experimenting with jspm and systemjs over the weekend. Everything is working fine except for the bundling jspm offers. I can load individual files, but jsmp refuses to load the bundle file (which is optimized).
I'm creating the bundle file using:
jspm bundle lib/login assets/js/1-login.js --inject
This updates the config.js file which looks like:
System.config({
baseURL: "/",
defaultJSExtensions: true,
transpiler: "babel",
babelOptions: {
"optional": [
"optimisation.modules.system"
]
},
paths: {
"github:*": "jspm_packages/github/*",
"npm:*": "jspm_packages/npm/*"
},
bundles: {
"1-login.js": [
"lib/login.js",
"lib/sample.js"
]
},
map: {....}
});
lib/login.js
import * as sample from 'lib/sample'
export function test() {
sample.testMethod();
}
lib/sample.js
import $ from 'jquery'
export function testMethod( ) {
console.log( $('body') );
}
So, according to the jsmp docs:
As soon as one of these modules is requested, the request is intercepted and the bundle is loaded dynamically first, before continuing with the module load.
It's my understanding that running
System.import('lib/login.js');
should load the bundle (and optimised file), but is doesn't - it just loads the actual file. What am I missing here? And as a bonus question, why is jquery not in the bundle list?
Well, figured out where I went wrong.
I keep all the generated assets in assets/js, but in my config.json I didn't change the baseUrl to reflect this. I did in fact have the baseUrl set correctly in package.json, which is why jspm didn't throw a lot of errors.
This was the same reason jquery wasn't loading, so problem solved :)

How to make ajax request with Karma

I have a test that calls a function which requests an external csv file. But for some reason, I can't use a relative path. For example, I have to do:
d3.csv('base/a.csv', ...
instead of being able to do :
d2.csv('a.csv', ...
The second example, works fine on the actual site, but for some reason, since Karma runs in a base directory, I have to request it from base. How can I just do a normal relative url?
Here are the parts of my karma.conf.js that I customized:
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha', 'chai'],
// list of files / patterns to load in the browser
files: [
'tests/*.js',
'bower_components/d3/d3.min.js',
'game.js',
{pattern: 'a.csv', watched: false, included: false, served: true}
],
and here is my repo

Detecting Environment When Running Karma

I have two environments I'm running my tests in (locally, and travic ci). And I need to make a few tweaks in my tests if I'm running them locally.
Is it possible to do it using Karma without having two separate configuration files?
You can programmatically call karma and pass it a configuration object, then listen the callback to close the server:
karma.server.start(config, function (exitCode){
if(exitCode){
console.err('Error in somewhere!');
}
});
The config object is basically an object that contains some properties and you can use it to enrich a skeleton configuration file you already have.
Imagine to have a configuration file like the following in 'path/to/karma.conf.js':
// Karma configuration
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '../',
// frameworks to use
frameworks: ['mocha'],
files: [ ... ].
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
// choose it before starting Karma
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
browsers: ['PhantomJS'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true,
plugins: [
'karma-mocha',
'karma-phantomjs-launcher'
]
});
};
Now I want to tweak it a bit before starting karma:
function enrichConfig(path){
var moreConfig = {
// say you want to overwrite/choose the reporter
reporters: ['progress'],
// put here the path for your skeleton configuration file
configFile: path
};
return moreConfig;
}
var config = enrichConfig('../path/to/karma.conf.js');
Currently with this technique we're generating several configuration for all our environment.
I guess you can configure your TravisCI configuration file to pass some arguments to the wrapper in order to activate some particular property in the enrichConfig function.
Update
If you want to pass parameters (e.g. the configuration file path) to your script, then just look up in the arguments array to pick it up.
Assume your script above it saved in a startKarma.js file, change your code to this:
var args = process.argv;
// the first two arguments are 'node' and 'startKarma.js'
var pathToConfig = args[2];
var config = enrichConfig(pathToConfig);
then:
$ node startKarma.js ../path/to/karma.conf.js

Uglifying for require.js with shim doesn't work on play2 with CoffeeScript

I work on Play 2.1.2 project, using Angular.js, CoffeeScript, require.js and bower to organize front-end.
With bower, I use shim in my /app/assets/javascripts/main.coffee file.
Then I deploy using play clean stage and running target/start.
The problem is: during stage phase, Play doesn't uglify resources.
In Build.scala:
val main = play.Project(appName, appVersion, appDependencies).settings(
requireJs += "main",
requireJsShim += "main.js"
)
Then after uglyfying css in stage:
Tracing dependencies for: main
Error: Load timeout for modules: angular-bootstrap,angular
http://requirejs.org/docs/errors.html#timeout
In module tree:
main
jquery
Error: Load timeout for modules: angular-bootstrap,angular
http://requirejs.org/docs/errors.html#timeout
In module tree:
main
jquery
[info] RequireJS optimization finished.
So nothing was uglified. In main.coffee:
require.config
paths:
jquery: "lib/jquery/jquery"
angular: "lib/angular/angular"
...
shim:
angular: {deps: ["jquery"], exports: "angular"}
...
define [
"angular-bootstrap"
"angular"
...
], ->
app = angular.module "app"
...
app
It works perfectly on client side, all paths are correct and so on.
requireJsShim += "main.js" also looks correct: it looks like require.js optimization takes place after compiling assets, so main.coffee or just main doesn't work.
Any ideas what are the roots of the problem? Have anyone faced it before?
I have an example application using the shim where I just answered a question very similar to yours. In a nutshell, the shim overwrites the app.build.js file.
What finally solved my problem is creating custom shim.coffee with part of require.config in it:
require.config
paths:
jquery: "lib/jquery/jquery"
angular: "lib/angular/angular"
...
Without shim part.
Then I had to explicitly define shimmed dependencies in define clauses and use requireJsShim += "shim.js" -- not the same file that I use for client-side configuration.
Then uglifying and require.js optimization begin to work!
I've encountered exactly this problem (almost; I'm not using CoffeeScript in my project), and it turns out easier to solve that I thought. To restate the issue: certain JavaScript resources—particularly those without an export setting in their shim—would produce the “Load timeout for modules” stated above. Worse, the problem appeared to be transient.
Separating the RequireJS configuration (e.g., paths, shim) from the module seemed to help, but compiling remained unreliable and it made working in development mode more complex.
I found that adding waitSeconds: 0 to the configuration object contributed to reliable builds. Why timeouts are even possible for accessing local resources during compilation is beyond me. See the RequireJS API waitSeconds documentation for details.
Here's a snippet from my RequireJS module, located in public/javascripts (your paths will likely differ).
require({
/* Fixes an unexplained bug where module loads would timeout
* at compilation. */
waitSeconds: 0,
paths: {
'angular': '../vendor/angular/angular',
'angular-animate': '../vendor/angular/angular-animate',
/* ... */
'jquery': '../vendor/jquery/jquery'
},
shim: {
'angular': {
deps: [ 'jquery' ],
exports: 'angular'
},
'angular-animate': ['angular'],
/* ... */
'jquery': {
exports: 'jQuery'
}
},
optimize: 'uglify2',
uglify2: {
warnings: false,
/* Mangling defeats Angular injection by function argument names. */
mangle: false
}
})
define(['jquery', 'angular'], function($, angular) {
/* Angular bootstrap. */
})