Here's my config file:
module.exports = function(config) {
config.set({
basePath: './',
autoWatch: true,
frameworks: ['jasmine'],
files: [
'../public_html/libs/mylib/lib.js',
'../public_html/libs/mylib/utility.js',
'../public_html/libs/mylib/config/*.js',
'../public_html/libs/mylib/enumerations.js',
'../public_html/libs/mylib/apiComm.js',
'../public_html/libs/mylib/baseObject.js',
'../public_html/libs/mylib/book.js',
'../public_html/libs/mylib/file.js',
'../public_html/libs/mylib/library.js',
'../public_html/libs/mylib/publishing.js',
'../public_html/libs/mylib/topic.js',
'../test/*Spec.js'
],
reporters: ['progress', 'coverage'],
preprocessors: {
'../public_html/libs/mylib/topic.js': ['coverage']
},
port: 9876,
colors: true,
browsers: ['Chrome'],
captureTimeout: 60000,
singleRun: false
});
};
Whenever I run karma start config/karma.config.js it runs the unit tests and creates the coverage folder in the correct place. However, it dumps the topic.js.html file in the same directory as topic.js. Why?
I know this is late reply, but it might help someone else as well.
Move your config file up one folder and change the "../public_html" to "public_html"
I just got done dealing with this.
Yes you need to have the...
coverageReporter: {
type : 'html',
dir : 'coverage/'
}
...as Acosta stated, but your also instructing Istanbul when writing the report files to go up one directory and then into the public_html folder. If the the karma.conf.js file is located in the same folder as the app and test folders then your reports should render in the proper location.
you need to add coverageReporter,
coverageReporter: {
type : 'html',
dir : 'coverage/'
}
O you also may add a collection of reporters
coverageReporter: {
reporters: [
//{ type: 'html', dir: 'TestOutputFolder/' },
{ type: 'text-summary', dir: 'TestOutputFolder/' },
{ type: 'cobertura', dir: 'TestOutputFolder/' }
]
},
Related
I am using Karma with the karma-webpack plugin for bundling and transpiling with babel. When a test has an error, I get a nice message with a line number for the bundle, like the following:
Service: DocumentService
✗ gets the correct number of advisors clients
TypeError: undefined is not an object (evaluating 'GLOBALS.TESTING_ENV') (line
37)
This is great, but I cannot find where to access the bundle file and inspect the lines described.
I tried using the output option in the webpack config, but that doesn't seem to do anything.
Here is my karma.conf:
module.exports = function(config) {
config.set({
basePath: __dirname + '/',
frameworks: ['phantomjs-shim', 'jasmine'],
files: [
'./test/**/*spec.js'
],
preprocessors: {
'src/**/*.js': ['webpack'],
'test/**/*.js': ['webpack']
},
webpack: {
mode: 'development',
output: {
path: path.resolve(__dirname, './build/'),
filename: 'app-[name].js',
chunkFilename: 'app-vendors.[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader']
}
]
}
},
reporters: ['spec'],
specReporter: {
suppressErrorSummary: false,
suppressFailed: false,
suppressPassed: false,
suppressSkipped: false,
showSpecTiming: false,
failFast: false
},
autoWatch: false,
browsers: ['PhantomJS'],
singleRun: true,
...
})
}
Where does the test bundle file build to? Is there a way I can configure it so that I can inspect the bundle?
Struggled with this as well and after revisiting this issue I finally solved it for me.
The files are not written to the disk because karma uses webpack-dev-middleware by default which keeps all files in memory. If you want the files to be emitted to the filesystem try
webpackMiddleware: {
writeToDisk: true,
}
Though in its current version karma-webpack overrides the output path with path.join(os.tmpdir(), '_karma_webpack_', indexPath, '/').
I have the following structure in my application:
Web (Asp net core)
|
|--wwwroot
|--ClientApp
| |--app
| | |-- ... (typescript modules, *.spec.js files etc.)
| |
| |--karma.config.js
| |--test-main.js
|
|--Controllers
|--config.json files for web etc.
In the console I'm in the ClientApp folder when running:
npm test
I get the following error:
File C:\Users\...\Web\karma.conf.js does not exist!
Why does it try to look for the karma.conf.js file in the Web folder?
How can I tell it to look in the right place? Even if I CD to the app folder I get the exact same error.
If I try to place the karma.conf.js file where it expects it, I get a bunch of other errors like:
cannot find module requirejs
I'm horribly confused, would really appreciate some help.
karma.conf.js file:
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine', 'requirejs'],
files: [
'test-main.js',
{pattern: 'test/**/*spec.js', included: false},
{pattern: '*.js', included: false}
],
exclude: [
],
preprocessors: {
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome', 'Firefox'],
singleRun: false,
concurrency: Infinity
})
}
test-main.js:
var allTestFiles = []
var TEST_REGEXP = /(spec|test)\.js$/i
Object.keys(window.__karma__.files).forEach(function (file) {
if (TEST_REGEXP.test(file)) {
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '')
allTestFiles.push(normalizedTestModule)
}
})
require.config({
baseUrl: '/base',
deps: allTestFiles,
callback: window.__karma__.start
})
Just go into your package.json and edit the test script to point to the location of your karma config.
"scripts": {
"test": "karma start ./path/to/karma.conf.js"
}
I created an Aurelia app using the Aurelia CLI (au new) and would like to set up code coverage (preferably with karma-coverage, but if that's not possible I'll use whatever).
I first npm install karma-coverage --save-dev then copy the test.js task over to a cover.js (so that I can run au cover).
cover.js
import {Server as Karma} from 'karma';
import {CLIOptions} from 'aurelia-cli';
// import project from "../aurelia.json";
export function cover(done) {
new Karma({
// This is the same as what's in karma.conf.js after running
// Except I added the 'src\\**\\*.js' part
files: [
'scripts\\vendor-bundle.js',
{pattern: 'test\\unit\\**\\*.js', included: false},
'test/aurelia-karma.js',
'scripts\\app-bundle.js',
'scripts\\materialize-bundle.js',
{pattern: 'src\\**\\*.js', included: false}
],
configFile: __dirname + '/../../karma.conf.js',
singleRun: !CLIOptions.hasFlag('watch'),
reporters: ['progress', 'coverage'],
//logLevel: 'debug',
preprocessors: {
// [project.unitTestRunner.source]: [project.transpiler.id], // Is this actually needed? Nothing changes if I add or remove this...
'src/**/*.js': ['babel', 'coverage']
},
coverageReporter: {
includeAllSources: true,
reporters: [
{type: 'html', dir: 'coverage'},
{type: 'text'}
]
}
}, done).start();
}
export default cover;
This... gets me somewhere?
But I don't think the tests are being linked to the individual src files (they're instead being linked to app-bundle.js).
Is there any way to get code coverage at the src file level (i.e. not bundle level) for an Aurelia app?
Other Files of Interest
app.js
export class App {
constructor() {
this.message = 'Hello World!';
}
}
karma.conf.js
"use strict";
const path = require('path');
const project = require('./aurelia_project/aurelia.json');
let testSrc = [
{ pattern: project.unitTestRunner.source, included: false },
'test/aurelia-karma.js'
];
let output = project.platform.output;
let appSrc = project.build.bundles.map(x => path.join(output, x.name));
let entryIndex = appSrc.indexOf(path.join(output, project.build.loader.configTarget));
let entryBundle = appSrc.splice(entryIndex, 1)[0];
let files = [entryBundle].concat(testSrc).concat(appSrc); console.log(files);
module.exports = function(config) {
config.set({
basePath: '',
frameworks: [project.testFramework.id],
files: files,
exclude: [],
preprocessors: {
[project.unitTestRunner.source]: [project.transpiler.id]
},
'babelPreprocessor': { options: project.transpiler.options },
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
// client.args must be a array of string.
// Leave 'aurelia-root', project.paths.root in this order so we can find
// the root of the aurelia project.
client: {
args: ['aurelia-root', project.paths.root]
}
});
};
From your terminal screenshot, it looks like you're getting coverage on your individual files src/app.js (12.5%), src/environment.js (0%) and src/main.js (12.5%) in addition to the bundle file. It has to do with that extra line you added including the files that are in src/.
I suspect that if you go to your coverage directory and view that in the browser, you'll see more detailed results.
I'm not sure about the Aurelia app specifically, but to get individual file coverage, you want to have your tests run against your original files instead of the bundled version and you want that same path to your original files to also be in preprocessors.
files: [
...
'src/**/*.js',
'path/to/tests/*.spec.js'
...
],
preprocessors: {
'src/**/*.js': ['coverage']
}
This pattern (which you've done) is what tells Karma to load the individual files, and include them in the coverage. At this point, I wouldn't bother loading the bundled application code since you have all the raw stuff being loaded.
Also be sure to load them in the order they're probably bundled in so that you can be sure Karma can initialize the app in the first place.
files: [
'src/app.js',
'src/environment.js',
'src/main.js'
]
And if you are putting your specs named myTest.spec.js next to the files they test, you can use src/!(*.spec).js to make sure that you are including application code without the tests.
I finally got it working, but it required a lot of under-the-hood modifications =\
First I had to install the following packages
npm install karma-coverage --save-dev
npm install karma-requirejs --save-dev
npm install babel-plugin-istanbul --save-dev
aurelia_project/tasks/cover.js
This is based on test.js.
Add requirejs to the list of frameworks (from the karma-requirejs package)
Add the individual src/test files (with included: false) as well as test/aurelia-karma-cover.js, which does the actual requireing of test files.
Modified aurelia-karma.js into aurelia-karma-cover.js to not include /test/unit/setup.js (it was giving me trouble with aurelia-browser-pal dependencies)
Remove "coverage" from src file preprocessing (babel-plugin-istanbul will now handle instrumentation of code - see statement at the end for details).
import {Server as Karma} from 'karma';
import {CLIOptions} from 'aurelia-cli';
import project from "../aurelia.json";
export function cover(done) {
new Karma({
configFile: __dirname + '/../../karma.conf.js',
frameworks: [project.testFramework.id, 'requirejs'],
files: [
{pattern: 'src\\**\\*.js', included: false},
{pattern: 'test\\unit\\**\\*.js', included: false},
// This file actually loads the spec files via require - it's based on aurelia-karma.js
// but removes setup.js and its dependencies
'test/aurelia-karma-cover.js'
],
exclude: [
'src/environment.js',
'src/main.js',
'src/resources/index.js'
],
preprocessors: {
'src/**/*.js': ['babel'],
},
reporters: ['progress', 'coverage'],
singleRun: !CLIOptions.hasFlag('watch'),
coverageReporter: {
includeAllSources: true,
reporters: [
{type: 'html', dir: 'coverage'},
{type: 'text'}
]
}
}, done).start();
}
export default cover;
test/unit/aurelia-karma-cover.js
Just change var allTestFiles = ['/base/test/unit/setup.js']; to var allTestFiles = []; to avoid aurelia-pal-browser dependency errors.
aurelia_project/aurelia.json
Add "istanbul" to the transpiler.options.plugins list if using babel-plugin-istanbul.
* Without babel-plugin-istanbul, code coverage works on post-transpiled code, which adds boilerplate that can't really be tested. This allows you to get to 100% code coverage ;)
#lebolo These were the adjustments I had to make to get things working here:
aurelia_project/tasks/cover.js
Included a constant to vendors path in the beginning of cover function:
const VENDORS_PATH = __dirname + '/../../node_modules/';
Used VENDORS_PATH to include libs I depend on, in files:
files: [
{pattern: VENDORS_PATH + 'moment/min/moment.min.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'test/unit/**/*.js', included: false},
'test/aurelia-karma-cover.js'
]
Included test files in preprocessors:
preprocessors: {
'src/**/*.js': ['babel'],
'test/unit/**/*.js': ['babel']
}
test/unit/aurelia-karma-cover.js
Change the way url is built in requirejs.load function:
url = '/base/' + url; => url = ['/base', root, url].join('/');
Included one more function to config requirejs paths and calling it after patchRequireJS() call:
function configRequire() {
var VENDORS_PATH = '../node_modules/';
requirejs.config({
paths: {
'moment': VENDORS_PATH + 'moment/min/moment.min'
}
});
}
I like to generate a coverage report for my typescript source files with karma-coverage. My unit tests are written in javascript and I'm using the Jasmine Test framework.
My folder structure looks like this:
node_modules/
app/
app.js
app.js.map
app.ts
components/
controllers/
SampleController.ts
directives/
filters/
services/
unittests/
karma.conf.js
components/
controllers/
SampleControllerTest.js
directives/
filters/
services/
My karma.conf.js
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
plugins: [
'karma-jasmine',
'karma-ng-html2js-preprocessor',
'karma-coverage',
'karma-phantomjs-launcher',
'karma-sourcemap-loader'
],
preprocessors: {
'../app/directives/controls/**/*Template.html' : [ 'ng-html2js' ],
// source files, that you wanna generate coverage for
// do not include tests or libraries
// (these files will be instrumented by Istanbul)
'../app/app.js' : ['sourcemap', 'coverage' ],
},
reporters: ['progress', 'coverage'],
// web server port
port: 9876,
coverageReporter: {
type : 'html',
dir : 'coverage/'
},
// and some other stuff
});
};
Currently my coverage report delivers sufficient metrics but not related to the single typescript files but the app.js.
I suppose that I either messed up something with the preprocessor config or that I need to specify the source map.
Anny hints?
Using karma-istanbul-remap does the trick for me.
karma.conf.js:
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
plugins: [
'karma-jasmine',
'karma-ng-html2js-preprocessor',
'karma-coverage',
'karma-phantomjs-launcher',
'karma-remap-istanbul'
],
preprocessors: {
'../app/directives/controls/**/*Template.html' : [ 'ng-html2js' ],
// source files, that you wanna generate coverage for
// do not include tests or libraries
// (these files will be instrumented by Istanbul)
'../app/app.js' : ['coverage' ],
},
reporters: ['progress', 'coverage', 'karma-remap-istanbul'],
// web server port
port: 9876,
coverageReporter: {
type : 'json',
subdir : '.',
dir : 'coverage/',
file : 'coverage.json'
},
remapIstanbulReporter: {
src: 'coverage/coverage.json',
reports: {
lcovonly: 'coverage/lcov.info',
html: 'coverage/html/report'
},
timeoutNotCreated: 5000, // default value
timeoutNoMoreFiles: 1000 // default value
},
// and some other stuff
});
};
I am trying to setup unit testing for a JavaScript plugin that is based on AngularJS. The plugin is bundled with Browserify via Gulp. It depends on external libraries that are injected with wiredep and gulp-inject from the bower_components folder. This is all working beautifully in the generated bundle, but if I try to run a Karma unit test via gulp, I get the following error:
Uncaught TypeError: angular.module is not a function at /tmp/94dbea5947f4758ab1ee6935e2f4b3f1.browserify:365 <- app/js/services/index.js:9:0
In this file, angular is loaded with var angular = require('angular');, and a console.log(angular) gives an empty object.
My karma.conf.js:
'use strict';
const istanbul = require('browserify-istanbul');
const isparta = require('isparta');
const mainBowerFiles = require('main-bower-files');
const karmaBaseConfig = {
basePath: '../',
frameworks: ['jasmine', 'browserify'],
preprocessors: {
'app/js/**/*.js': ['browserify', 'coverage'],
'**/*.html': ['ng-html2js']
},
browserify: {
debug: true,
extensions: ['.js'],
transform: [
[["babelify", {"ignore": "/\/bower_components\//"}]],
'browserify-ngannotate',
'bulkify',
'debowerify',
'brfs',
istanbul({
instrumenter: isparta,
ignore: ['**/bower_components/**', '**/node_modules/**', '**/test/**']
})
]
},
ngHtml2JsPreprocessor: {
stripPrefix: 'app/',
moduleName: 'templates'
},
plugins: [
'karma-jasmine',
'karma-coverage',
'karma-browserify',
'karma-ng-html2js-preprocessor',
'karma-chrome-launcher'
],
files: mainBowerFiles({
filter: '**/*.js',
paths: {
bowerDirectory: 'bower_components',
bowerrc: '.bowerrc',
bowerJson: 'bower.json'
}
}).concat([
// app-specific code
'app/js/main.js',
// 3rd-party resources
'node_modules/angular-mocks/angular-mocks.js',
// test files
'test/unit/**/*.js'
]),
exclude: [],
reporters: ['progress', 'coverage'],
port: 9876,
colors: true,
autoWatch: false,
browsers: ['Chrome'],
singleRun: true
};
const customLaunchers = {
chrome: {
base: 'SauceLabs',
browserName: 'chrome'
}
};
const ciAdditions = {
sauceLabs: {
testName: 'Karma Unit Tests',
startConnect: false,
build: process.env.TRAVIS_BUILD_NUMBER,
tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER
},
browsers: Object.keys(customLaunchers),
customLaunchers: customLaunchers,
reporters: ['progress', 'coverage', 'saucelabs']
};
module.exports = function (config) {
const isCI = process.env.CI;
config.set(isCI ? Object.assign(karmaBaseConfig, ciAdditions) : karmaBaseConfig);
};
All main application files are located under app/, bower files in bower_components/, node modules in node_modules/ and test specs in test/unit/.
It is based on this boilerplate: https://github.com/jakemmarsh/angularjs-gulp-browserify-boilerplate.
The error occurs just after Karma has launched Chrome, but before any unit test are executed (I checked with console.log in the unit test).
Any help would be greatly appreciated.
Finally solved it.
unit.js (gulp unit task):
'use strict';
import config from '../config';
import path from 'path';
import gulp from 'gulp';
import {Server} from 'karma';
gulp.task('unit', ['copy-bower-components',
'styles',
'images',
'fonts',
'api',
'views',
'browserify',
'inject'
], function (done) {
new Server({
configFile: path.resolve(__dirname, '../..', config.test.karma),
singleRun: true
}, function (exitCode) {
console.log('Karma has exited with ' + exitCode);
done();
}).start();
});
The key here was to run browserify before the unit tests are started. karma.conf.js:
// Karma configuration
// Generated on Sat Jan 23 2016 16:43:48 GMT+0100 (CET)
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', 'browserify'],
// list of files / patterns to load in the browser
files: [
"bower_components/tether/dist/js/tether.js",
"bower_components/jquery/jquery.js",
"bower_components/bootstrap/dist/js/bootstrap.js",
"bower_components/jquery-ui/jquery-ui.js",
"bower_components/rangy/rangy-core.js",
"bower_components/rangy/rangy-classapplier.js",
"bower_components/rangy/rangy-highlighter.js",
"bower_components/rangy/rangy-selectionsaverestore.js",
"bower_components/rangy/rangy-serializer.js",
"bower_components/rangy/rangy-textrange.js",
"bower_components/angular/angular.js",
"bower_components/textAngular/dist/textAngular.js",
"bower_components/textAngular/dist/textAngular-sanitize.js",
"bower_components/textAngular/dist/textAngularSetup.js",
"bower_components/KaTeX/dist/katex.min.js",
"bower_components/angular-bootstrap/ui-bootstrap-tpls.js",
"bower_components/angular-translate/angular-translate.js",
"bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js",
"bower_components/angular-cookies/angular-cookies.js",
"bower_components/angular-translate-storage-cookie/angular-translate-storage-cookie.js",
"bower_components/angular-translate-storage-local/angular-translate-storage-local.js",
"bower_components/angular-translate-handler-log/angular-translate-handler-log.js",
"bower_components/angular-dynamic-locale/src/tmhDynamicLocale.js",
"bower_components/angular-tour/dist/angular-tour-tpls.min.js",
"bower_components/ng-sortable/dist/ng-sortable.js",
"bower_components/moment/moment.js",
"bower_components/angular-moment/angular-moment.js",
"bower_components/KaTeX/dist/contrib/auto-render.min.js",
'dist/js/main.js',
'node_modules/angular-mocks/angular-mocks.js',
'test/unit/**/*.spec.js'
],
browserify: {
debug: true,
transform: [
'babelify',
'brfs',
'bulkify'
]
},
// list of files to exclude
exclude: ['karma.conf.js'],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/unit/**/*.spec.js': ['browserify']
},
// test 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,
urlRoot: '/__karma__/'
})
};