I'm working with a build system using Angular(2), typescript, karma and SystemJs.
The application build works perfectly taking the src files from apps/samples/** to build/** this is the structure of the build directory. I run my gulp task build the files and browser-sync presents me with my app :)
apps/
samples/
app/
app.component.ts
app.module.ts
main.ts
assets/
scss/
js/ //#angular and other node libs get kept here
test/
app.component.spec.ts
index.html
systemjs.config.js
systemjs.config.extras.js
build/
app/
app.component.js
app.component.js.map
app.module.js
app.module.js.map
main.js
main.js.map
assets/
css/
js/ //#angular and other node libs get kept here
test/
app.component.spec.js
app.component.spec.js.map
index.html
systemjs.config.js
systemjs.config.extras.js
Gulpfile.babel.js
karma.conf.js
karma-test-shim.js
package.json
Now as mentioned before I have no problems with typescript or any other part of the build the problem comes when running karma I keep getting an error as follows:
Chrome 55.0.2883 (Windows 10 0.0.0) ERROR: 'Unhandled Promise rejection:', '(SystemJS) XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error loading http://localhost:9876/base/systemjs.config.js', '; Zone:', '<root>', '; Task:', 'Promise.then', '; Value:', Error{stack: '(SystemJS) XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error loading http://localhost:9876/base/systemjs.config.js', message: '(SystemJS) XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error loading http://localhost:9876/base/systemjs.config.js', originalStack: 'Error: (SystemJS) XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error loading http://localhost:9876/base/systemjs.config.js', zoneAwareStack: 'Error: (SystemJS) XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error loading http://localhost:9876/base/systemjs.config.js', name: 'Error', toString: function toString() { ... }, originalErr: Error{stack: 'Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js', message: 'XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js', originalStack: 'Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js', zoneAwareStack: 'Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js', name: 'Error', toString: function toString() { ... }}}, '(SystemJS) XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error: XHR error (404 Not Found) loading http://localhost:9876/base/systemjs.config.js
Error loading http://localhost:9876/base/systemjs.config.js'
Now i've been working from a combination of the angular quickstart project and a tutorial here https://www.agvision.ro/angular-2-karma-jasmine-unit-testing/
Here is my karma.config.js
module.exports = function(config) {
var appBase = 'build/app/'; // transpiled app JS and map files
var appSrcBase = 'apps/samples/app//'; // app source TS files
var appAssets = '/build/app/'; // component assets fetched by Angular's compiler
// Testing helpers (optional) are conventionally in a folder called `testing`
var testingBase = 'testing/'; // transpiled test JS and map files
var testingSrcBase = 'testing/'; // test source TS files
config.set({
basePath: '',
frameworks: ['jasmine'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter')
],
client: {
builtPaths: [appBase, testingBase], // add more spec base paths as needed
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
customLaunchers: {
// From the CLI. Not used here but interesting
// chrome setup for travis CI using chromium
Chrome_travis_ci: {
base: 'Chrome',
flags: ['--no-sandbox']
}
},
files: [
// System.js for module loading
'node_modules/systemjs/dist/system.src.js',
// Polyfills
'node_modules/core-js/client/shim.js',
// zone.js
'node_modules/zone.js/dist/zone.js',
'node_modules/zone.js/dist/long-stack-trace-zone.js',
'node_modules/zone.js/dist/proxy.js',
'node_modules/zone.js/dist/sync-test.js',
'node_modules/zone.js/dist/jasmine-patch.js',
'node_modules/zone.js/dist/async-test.js',
'node_modules/zone.js/dist/fake-async-test.js',
// RxJs
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
{ pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },
// Paths loaded via module imports:
// Angular itself
{ pattern: 'node_modules/#angular/**/*.js', included: false, watched: false },
{ pattern: 'node_modules/#angular/**/*.js.map', included: false, watched: false },
{ pattern: 'build/systemjs.config.js', included: false, watched: false },
{ pattern: 'build/systemjs.config.extras.js', included: false, watched: false },
'karma-test-shim.js', // optionally extend SystemJS mapping e.g., with barrels
// transpiled application & spec code paths loaded via module imports
{ pattern: appBase + '**/*.js', included: false, watched: true },
{ pattern: testingBase + '**/*.js', included: false, watched: true },
// Asset (HTML & CSS) paths loaded via Angular's component compiler
// (these paths need to be rewritten, see proxies section)
{ pattern: appBase + '**/*.html', included: false, watched: true },
{ pattern: appBase + '**/*.css', included: false, watched: true },
// Paths for debugging with source maps in dev tools
{ pattern: appSrcBase + '**/*.ts', included: false, watched: false },
{ pattern: appBase + '**/*.js.map', included: false, watched: false },
{ pattern: testingSrcBase + '**/*.ts', included: false, watched: false },
{ pattern: testingBase + '**/*.js.map', included: false, watched: false}
],
// Proxied base paths for loading assets
proxies: {
// required for component assets fetched by Angular's compiler
"/app/": appAssets
},
exclude: [],
preprocessors: {},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: true
})
}
and here is my karma-test-shim.js
// /*global jasmine, __karma__, window*/
Error.stackTraceLimit = 0; // "No stacktrace"" is usually best for app testing.
// Uncomment to get full stacktrace output. Sometimes helpful, usually not.
// Error.stackTraceLimit = Infinity; //
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
// builtPaths: root paths for output ("built") files
// get from karma.config.js, then prefix with '/base/' (default is 'app/')
var builtPaths = (__karma__.config.builtPaths || ['app/'])
.map(function (p) {
return '/base/build/' + p;
});
__karma__.loaded = function () {
};
function isJsFile(path) {
return path.slice(-3) == '.js';
}
function isSpecFile(path) {
return /\.spec\.(.*\.)?js$/.test(path);
}
// Is a "built" file if is JavaScript file in one of the "built" folders
function isBuiltFile(path) {
return isJsFile(path) &&
builtPaths.reduce(function (keep, bp) {
return keep || (path.substr(0, bp.length) === bp);
}, false);
}
var allSpecFiles = Object.keys(window.__karma__.files)
.filter(isSpecFile)
.filter(isBuiltFile);
System.config({
baseURL: 'base/',
// Extend usual application package list with test folder
packages: {'testing': {main: 'index.js', defaultExtension: 'js'}},
// Assume npm: is set in `paths` in systemjs.config
// Map the angular testing umd bundles
map: {
'#angular/core/testing': 'npm:#angular/core/bundles/core-testing.umd.js',
'#angular/common/testing': 'npm:#angular/common/bundles/common-testing.umd.js',
'#angular/compiler/testing': 'npm:#angular/compiler/bundles/compiler-testing.umd.js',
'#angular/platform-browser/testing': 'npm:#angular/platform-browser/bundles/platform-browser-testing.umd.js',
'#angular/platform-browser-dynamic/testing': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
'#angular/http/testing': 'npm:#angular/http/bundles/http-testing.umd.js',
'#angular/router/testing': 'npm:#angular/router/bundles/router-testing.umd.js',
'#angular/forms/testing': 'npm:#angular/forms/bundles/forms-testing.umd.js',
},
});
System.import('systemjs.config.js').then(function (m) {
console.log(m);
})
//.then(importSystemJsExtras)
.then(initTestBed)
.then(initTesting);
/** Optional SystemJS configuration extras. Keep going w/o it */
function importSystemJsExtras() {
return System.import('systemjs.config.extras.js')
.catch(function (reason) {
console.log(
'Warning: System.import could not load the optional "systemjs.config.extras.js". Did you omit it by accident? Continuing without it.'
);
console.log(reason);
});
}
function initTestBed() {
return Promise.all([
System.import('#angular/core/testing'),
System.import('#angular/platform-browser-dynamic/testing')
])
.then(function (providers) {
var coreTesting = providers[0];
var browserTesting = providers[1];
coreTesting.TestBed.initTestEnvironment(
browserTesting.BrowserDynamicTestingModule,
browserTesting.platformBrowserDynamicTesting());
})
}
// Import all spec files and start karma
function initTesting() {
return Promise.all(
allSpecFiles.map(function (moduleName) {
return System.import(moduleName);
})
)
.then(__karma__.start, __karma__.error);
}
Now im getting the error and have read post after post after post some mention the base/ directory that karma puts files in, some have mentioned packages and modules and more but nowere gives a definitive answer as to why karma wont load system js.
Im a neewb with angular2 and prefer the build strucutre so wont be changing that aspect, anything else would be helpfull even if im missing something really simple.
Try changing:
{ pattern: 'build/systemjs.config.js', included: false, watched: false },
{ pattern: 'build/systemjs.config.extras.js', included: false, watched: false }
to:
{ pattern: '/systemjs.config.js', included: false, watched: false },
{ pattern: '/systemjs.config.extras.js', included: false, watched: false }
Related
What needs to be changed in below karma.config in order to resolve below error
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [
// 'node_modules/#zxing/library/*.js'
// 'assets/#zxing/library/esm/browser/BrowserMultiFormatReader.js'
'assets/#zxing/library/*.js',
],
exclude: [
"assets/other.min.js"
],
preprocessors: {
'app/**/*.html': "ng-html2js",
'app/views/**/!(*spec).js': ['coverage']
},
reporters: ['progress', 'html', 'coverage'],
port: 3000,
colors: true,
autoWatch: true,
browsers: ['Chrome'],
singleRun: true,
concurrency: Infinity,
coverageReporter : {
type : 'html',
dir : 'coverage/',
subdir: '.',
check: {
global: {
....,
.....
},
each: {
....,
....
}
}
},
htmlReporter: {
outputDir: 'karma_html',
namedFiles: true,
reportName: 'sample_spec_report'
}
})
}
error
Chrome 85.0.4183 (Windows 10.0.0) ERROR
Uncaught SyntaxError: Unexpected token 'export'
at assets/#zxing/library/esm/browser.js:2
Chrome 85.0.4183 (Windows 10.0.0) ERROR
Uncaught SyntaxError: Unexpected token 'export'
at assets/#zxing/library/esm/browser.js:2
JavaScript Test Case Exit Code 1
JavaScript Test Case Fails
I'm, trying to make use of zxing.js in my Angular.1x app. MY CI/CD getting failed due to this error. library is working properly inside the app. im facing this issue the moment I use gulp karmaRunDebug. So need experts advice to resolve this. I'm struggling to fix this problem for past two.
I've no clue what needs to be done as am completely new setting up gulp and karma test environment.
zxing -> library
Thanks
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 using Karma + Mocha to run my unit tests, everything works pretty well except whenever the tests fails,
When I run a test like
expect(player).to.be.an('object');
and it fails I would expect it to say that "Object was expected but string given" or something like that, Instead all I get is (for every single failed test, no matter how it fails, even when I try to asset true with false):
SyntaxError: Unexpected token N
at Object.parse (native)
at Array.map (native)
I know for a fact that there's no syntax errors in my code, so Im guessing that's something to do with karma/mocha and the way they handle the failed tests.. I just dont know where to look.. here is my gulp task:
var karmaServer = require('karma').server;
gulp.task('test', function (done) {
gutil.log('preparing tests.');
var runOnlyOnce = true;
// check if a parameter named "watch" is passed. if so - run tests in watch mode.
if (argv.watch){
runOnlyOnce = false;
}
if (runOnlyOnce){
gutil.log('Running only once.\nTo run in "watch" mode try: gulp test --watch');
} else {
gutil.log('Running in watch mode. Oh yeah.');
}
karmaServer.start({
configFile: __dirname +'/karma.conf.js',
singleRun: runOnlyOnce
}, function(exitCode) {
gutil.log('Karma has exited with ' + exitCode);
if (exitCode != 0){
gutil.log(gutil.colors.bgRed("Test(s) failed."));
}
process.exit(exitCode);
});
});
Here is my karma.conf file:
module.exports = function (config) {
'use strict';
config.set({
basePath: '',
frameworks: ['browserify', 'mocha', 'source-map-support'],
// reporters configuration
reporters: ['mocha'],
preprocessors: {
'test/**/*.spec.js': ['browserify']
},
files: [
{pattern: 'app/**/*.js', watched: true, included: false, served: false}, // watch these files, but dont bundle them for tests
'test/**/*.spec.js'
],
browserify: {
debug: true,
transform: ['babelify']
},
plugins: [
'karma-mocha-reporter',
'karma-mocha',
'karma-phantomjs-launcher',
'karma-chrome-launcher',
'karma-browserify',
'babel-plugin-espower',
'karma-ie-launcher',
'karma-source-map-support'
],
port: 9876,
colors: true,
usePolling: true,
atomic_save: false,
autoWatch : 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,
browsers: ["Chrome"] //, "IE", 'PhantomJS'
});
};
Any help would be much appreciated!!! Thank you!
So I found the problem, all I did was to remove the debug flag from the karma.conf file..
instead of
browserify: {
debug: true,
transform: ['babelify']
},
I did:
browserify: {
debug: false,
transform: ['babelify']
},
that did the trick.
I hope this helps anyone! cheers!
Everything works (Karama, Jasmine, Underscore, Backbone, testr) as evidenced by the _UnitTestUnitTest passing. But simple testr statements always fail.
The basic _UnitTestUnitTest works!
it('works for jquery', function() {
expect( $("document")).toBeTruthy();
});
it('works for underscore', function() {
expect(_.size([1,2,3])).toEqual(3);
});
it('works for backbone', function() {
var model = Backbone.Model.extend();
expect(model).toBeTruthy();
});
it('works for testr', function() {
expect(testr).toBeTruthy();
});
However, in my other real unit test, it fails on the testr line:
AccountSummaryCollection_CLASS = testr('models/sales-rep/AccountSummaryCollection');
I'm certain i'm including my dependency of 'models/sales-rep/AccountSummaryCollection' correctly in my config (I see it hosted and getting loaded by require.js deps!!!
However, the big problem is it claims our application module is not loaded even though it is. I also tried to wrap the whole AccountSummaryUnitTest.js inside of require([‘AccountSummaryCollection’], function(){…. This produces a new error where inside a dependency (AccountSummary.js) the error “Backbone is not defined” is thrown. That makes no sense in the context because obviously the AccountSummaryCollection has already resolved Backbone.Collection. This bad resolution is what makes me suspect it is testr that is fishy.
I also tried to manually include the file using the karma config, but requirejs does not like that since it’s a conflicting define() function.
Below: serving actually means Requested by Client and the {{{dependency}}} file is my own trace to confirm they are added to the deps list in the karma-spec-runner.js.
It fails at this line:
AccountSummaryUnitCollection line 27: AccountSummaryCollection_CLASS = testr('models/sales-rep/AccountSummaryCollection');
Here's the "spec runner" javascript (basically copied from the docs, with some extra logging).
var dependencies = [];
for (var file in window.__karma__.files) {
if (window.__karma__.files.hasOwnProperty(file)) {
//
if (/Test\.js$/.test(file)) {
//traces my test files fine!
console.log("{{{testing file}}} --> "+ file );
dependencies.push(file);
}
}
}
// jam our application files into the deps
for (var file in window.__karma__.files) {
if (window.__karma__.files.hasOwnProperty(file)) {
if (file.indexOf('src/main/app/') !== -1 ) {
//traces my dep files fine!
console.log("{{{dependency}}} file --> "+ file );
dependencies.push(file);
}
}
}
require.config({
baseUrl: 'base/src/main/app/',
paths: {
'resources' : '../resources/',
'jquery' : '../resources/js/lib/jquery-2.1.0.min',
'text' : '../resources/js/lib/text-2.0.10',
'i18n' : '../resources/js/lib/i18n-2.0.4',
'd3' : '../resources/js/lib/d3.v3.1.10.min',
'AppMeasurement' : '../resources/js/lib/appMeasurement',
'underscore' : '../resources/js/lib/underscore-1.5.2',
'Backbone' : '../resources/js/lib/backbone-1.1.2.min',
'testr' : '../../test/lib/testr'
},
deps: dependencies,
shim: {
d3: {
exports: 'd3'
},
AppMeasurement: {
exports: 'AppMeasurement'
},
underscore: {
deps:["jquery"],
exports: '_'
},
Backbone: {
deps:["jquery"],
exports: 'Backbone'
},
testr:{
exports: 'testr'
}
},
callback: window.__karma__.start,
locale: "en-us"
});
Here's the karma section of my gruntfile
karma: {
unit: {
background: false,
options: {
logLevel : 'debug',
basePath:'./',
// files for karma to host
files: [
{pattern: 'src/main/resources/js/lib/**/*.js', included: false, served: true},
{pattern: 'src/main/resources/js/plugins/**/*.js', included:false, served: true },
{pattern: 'src/test/lib/sinon.js', included: false },
{pattern: 'src/test/lib/testr.js', included: false },
{pattern: 'src/test/js/stubs/**/*.js', included: false, served: true},
// manually load our application unit test & deps to examine the simplest case
{pattern:'src/main/app/models/sales-rep/AccountSummary.js', included: false },
{pattern:'src/main/app/models/sales-rep/AccountSummaryCollection.js', included: false },
{pattern: '_UnitTestUnitTest.js', included: false},
{pattern: 'src/test/js/unit/AccountSummaryCollectionUnitTest.js', included: false},
'src/test/js/karma-spec-runner.js'
],
plugins: [
"karma-jasmine",
"karma-phantomjs-launcher",
"karma-requirejs",
'karma-chrome-launcher',
],
frameworks: [
"jasmine",
"requirejs"
],
browsers: [
//"PhantomJS"
"Chrome"
]
}
}
},
Here's a sample test that fails
Note that the testr config is per unit test. Plus, this test WORKS in plain in the browser jasmine!
// tried with and without the leading require statement as noted in main question.
require( ['models/sales-rep/AccountSummaryCollection'], function() {
describe('AccountSummaryCollectionUnitTest', function () {
var AccountSummaryCollection_CLASS;
function configureTestr() {
testr.config({
whitelist: [
'models/sales-rep/AccountSummaryCollection',
'models/sales-rep/AccountSummary'
]
});
}
beforeEach(function () {
configureTestr();
console.log("initializing AccountSummaryCollection_CLASS");
//fails on following line
AccountSummaryCollection_CLASS = testr('models/sales-rep/AccountSummaryCollection');
});
You need specific versions of libs to get it to work right:
testr 1.0.2 (NOT 1.0.3!!!!!)
Backbone 1.0.0 (not 1.1.2 for some reason)
underscore 1.6
require-2.1.11 [production] (for some reason we had 2.1.2)
Then I had to include:true for underscore and backbone in the Karma config. Then the shim works with require 2.1.11 without the mismatched anonymous define error.
Additioanlly, to make sure to delay the test execution. I did not have luck with the waitSeconds (that just increases the test duration).
The key part of the require config:
// since we are forcing Backbone in the dom instead of requiring it
callback: function(){
setTimeout(function () {
window.__karma__.start();
}, 4000);
},
I'm unit testing one of my directives (angularjs) using grunt/karma/phantomjs/jasmine. My tests run fine
describe('bar foo', function () {
beforeEach(inject(function ($rootScope, $compile) {
elm = angular.element('<img bar-foo src="img1.png"/>');
scope = $rootScope.$new();
$compile(elm)();
scope.$digest();
}));
....
});
but I do get these 404s
WARN [web-server]: 404: /img1.png
WARN [web-server]: 404: /img2.png
...
Although they do nothing, they do add noise to the log output. Is there a way to fix this ? (without changing karma's logLevel of course, because I do want to see them)
That is because you need to configurate karma to load then serve them when requested ;)
In your karma.conf.js file you should already have defined files and/or patterns like :
// list of files / patterns to load in the browser
files : [
{pattern: 'app/lib/angular.js', watched: true, included: true, served: true},
{pattern: 'app/lib/angular-*.js', watched: true, included: true, served: true},
{pattern: 'app/lib/**/*.js', watched: true, included: true, served: true},
{pattern: 'app/js/**/*.js', watched: true, included: true, served: true},
// add the line below with the correct path pattern for your case
{pattern: 'path/to/**/*.png', watched: false, included: false, served: true},
// important: notice that "included" must be false to avoid errors
// otherwise Karma will include them as scripts
{pattern: 'test/lib/**/*.js', watched: true, included: true, served: true},
{pattern: 'test/unit/**/*.js', watched: true, included: true, served: true},
],
// list of files to exclude
exclude: [
],
// ...
You can have a look here for more info :)
EDIT : If you use a nodejs web-server to run your app, you can add this to karma.conf.js :
proxies: {
'/path/to/img/': 'http://localhost:8000/path/to/img/'
},
EDIT2 : If you don't use or want to use another server you can define a local proxy but as Karma doesn't provide access to port in use, dynamically, if karma starts on another port than 9876 (default), you will still get those annoying 404...
proxies = {
'/images/': '/base/images/'
};
Related issue : https://github.com/karma-runner/karma/issues/872
The confusing piece of the puzzle for me was the 'base' virtual folder. If you don't know that needs to be included in the asset paths of your fixtures you will find it hard to debug.
As-per the configuration documentation
By default all assets are served at http://localhost:[PORT]/base/
Note: this may not be true for other versions - I'm on 0.12.14 and it worked for me but the 0.10 docs dont mention it.
After specifying the files pattern:
{ pattern: 'Test/images/*.gif', watched: false, included: false, served: true, nocache: false },
I could use this in my fixture:
<img src="base/Test/images/myimage.gif" />
And I didn't need the proxy at that point.
You can create generic middleware inside your karma.conf.js
- bit over the top but did the job for me
First define dummy 1px images (I've used base64):
const DUMMIES = {
png: {
base64: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
type: 'image/png'
},
jpg: {
base64: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD3+iiigD//2Q==',
type: 'image/jpeg'
},
gif: {
base64: 'data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=',
type: 'image/gif'
}
};
Then define middleware function:
function surpassImage404sMiddleware(req, res, next) {
const imageExt = req.url.split('.').pop();
const dummy = DUMMIES[imageExt];
if (dummy) {
// Table of files to ignore
const imgPaths = ['/another-cat-image.png'];
const isFakeImage = imgPaths.indexOf(req.url) !== -1;
// URL to ignore
const isCMSImage = req.url.indexOf('/cms/images/') !== -1;
if (isFakeImage || isCMSImage) {
const img = Buffer.from(dummy.base64, 'base64');
res.writeHead(200, {
'Content-Type': dummy.type,
'Content-Length': img.length
});
return res.end(img);
}
}
next();
}
Apply middleware in your karma conf
{
basePath: '',
frameworks: ['jasmine', '#angular/cli'],
middleware: ['surpassImage404sMiddleware'],
plugins: [
...
{'middleware:surpassImage404sMiddleware': ['value', surpassImage404sMiddleware]}
],
...
}
Based on #glepretre's answer, I've created an empty .png file and added this to the config to hide 404 warnings:
proxies: {
'/img/generic.png': 'test/assets/img/generic.png'
}
To fix, in your karma.conf.js make sure to point to the served file with your proxies:
files: [
{ pattern: './src/img/fake.jpg', watched: false, included: false, served: true },
],
proxies: {
'/image.jpg': '/base/src/img/fake.jpg',
'/fake-avatar': '/base/src/img/fake.jpg',
'/folder/0x500.jpg': '/base/src/img/fake.jpg',
'/undefined': '/base/src/img/fake.jpg'
}
Even though its an old thread, it took me a couple hours to actually get my image to actually be served from karma to eliminate the 404. The comments were just not thorough enough. I believe I can clarify the solution with this screenshot. Essentially the one thing that many comments were missing is the fact that the proxy value must start with "/base", even though base is not in any of my folder pathing, nor is it in my requests.
("base" without the forward slash resulted in karma returning a 400 BAD REQUEST)
Now after running ng test, I can successfully serve "./src/assets/favicon.png" from the url: http://localhost:9876/test/dummy.png
In my project I am using the following npm package versions:
karma v4.3.0
jasmine-core v3.2.1
karma-jasmine v1.1.2
#angular/cli v8.3.5
angular v8.2.7
If you have root path somewhere in your configuration file you can also use something like this:
proxies: {
'/bower_components/': config.root + '/client/bower_components/'
}
If you are using fake URLs for your images in test, you can write a custom middleware function to return 200 for URLs that start with "$", taken from Angular's own karma.conf.js:
karma.conf.js
module.exports = function (config) {
config.set({
middleware: ['fake-url'],
plugins: [
// ...
{
'middleware:fake-url': [
'factory',
function () {
// Middleware that avoids triggering 404s during tests that need to reference
// image paths. Assumes that the image path will start with `/$`.
// Credit: https://github.com/angular/components/blob/59002e1649123922df3532f4be78c485a73c5bc1/test/karma.conf.js
return function (request, response, next) {
if (request.url.indexOf('/$') === 0) {
response.writeHead(200);
return response.end();
}
next();
};
},
],
},
]
});
}
foo.spec.ts
img.src = '/$/foo.jpg'; // No 404 warning! :-)