I am working with karma & jasmine for unit testing my javascript pages. After all configuration done i was able to run the test cases. However, the expect statement is falining stating undefined. even though i hard code 2 strings in the expect, its failing. I tried toBe & toEqual but without success. Below is my code:
describe('Sanity Test', function() {
var scope;
beforeEach(angular.mock.module('serviceApp'));
beforeEach(angular.mock.inject(function($rootScope, $controller) {
scope = $rootScope.$new();
$controller('welcomeController', {
$scope : scope
});
}));
it('Sanity test Jasmine"', function() {
scope.text = 'Hi';
expect('Hi').toEqual('Hi');
});
});
Error:
INFO [launcher]: Starting browser Chrome
INFO [Chrome 30.0.1599 (Windows 7)]: Connected on socket DjMqv6LulftBpkJ2ph7g
Chrome 30.0.1599 (Windows 7) Sanity Test Sanity test Jasmine" FAILED
expect undefined toEqual "Hi"
.....src/main/webapp/test/spec/controllers/welcome.test.js:15:3: expected "Hi" but was undefined
Chrome 30.0.1599 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.424 secs / 0.025 secs)
Been struggling for last 2 days.
May be something to do with the karma version i was using. I moved to mac with a slightly older version of karma and everything worked smooth.
I was getting undefined messages like this for all my tests in an Ionic project which ran with grunt. It ended up being because my karma settings were configured to use mocha and chai instead of jasmine. Just edit your configuration (whether its gulpfile.js, Gruntfile.js or karma.my.js) from
frameworks: ['mocha', 'chai'],
to
frameworks: ['jasmine'],
Related
I have three gulp tasks: watch, build, test. I'd like to have my watch running and when a file is saved, it is built and then tested (duh).
What is happening is that despite being set up to run build as a dependency of test, I need to save the file twice in order for the latest build to be the one that is tested.
I can reproduce this by starting the watch, making a change to somewhere in the client JS code (like adding a console log) and then watching the resulting output. The first save will not have any console output. Just saving the file again (no changes made) will cause the test to be re-run and the console output to display.
I have also noticed cases where the first build+test cycle will be the correct build (i.e. will have the console log statement), but after that, it takes two saves to make sure the latest code is the one being tested.
Spec files are immune to this because they are not built and instead used directly (sorta, they're transpiled first).
So, am I going crazy here? These should be run consecutively, right?
The log would suggest that's the case:
[12:05:54] Starting 'build:client:js'...
[12:05:54] Finished 'build:client:js' after 13 ms
[12:05:54] Starting 'test:client'...
19 09 2016 12:05:54.808:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
19 09 2016 12:05:54.808:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
19 09 2016 12:05:54.841:INFO [launcher]: Starting browser PhantomJS
19 09 2016 12:05:55.381:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#Zklau3qmk75NKg2HAAAB with id 61545463
LOG: 'test'
.
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 1 of 1 SUCCESS (0.002 secs / 0.029 secs)
[12:05:55] Finished 'test:client' after 775 ms
Build:
Basic build for AngularJS App, nothing too strange here.
gulp.task('build:client:js', () => {
gulp.src('app/sections/client/**/!(*.spec|*.e2e).js')
.pipe(sourceMaps.init())
.pipe(eslint())
.pipe(eslint.formatEach())
.pipe(babel({presets: ['es2015']}))
.pipe(ngAnnotate())
.pipe(concat('client.js'))
.pipe(uglify())
.pipe(sourceMaps.write())
.pipe(gulp.dest(paths.build))
});
Test:
This is set up so that, ideally, build runs and completes first.
gulp.task('test:client', ['build:client:js'], (done) => {
const src = {};
src['client'] = 'app/sections/client';
const config = getTestConfig(src);
new karmaServer(config, done).start();
});
Watch:
This should only need to run test because build is a dependency of test.
gulp.task('watch:client:js', () => {
gulp.watch('app/sections/client/**/*.js', ['test:client']);
});
Also, to be totally transparent, most of my watch>build>test gulp tasks are being generated dynamically based off a paths file. It basically returns JSON that is then used by functions to create the gulp tasks. The output below is the result of that generation, but I'm not sure that physically writing each task out like this would make any difference.
You can experiment with or see more here.
In the task 'build:client:js', you should return the stream so that gulp knows when the task actually ends.
gulp.task('build:client:js', () => {
return gulp.src('app/sections/client/**/!(*.spec|*.e2e).js')
.pipe(sourceMaps.init())
.pipe(eslint())
.pipe(eslint.formatEach())
.pipe(babel({presets: ['es2015']}))
.pipe(ngAnnotate())
.pipe(concat('client.js'))
.pipe(uglify())
.pipe(sourceMaps.write())
.pipe(gulp.dest(paths.build))
});
I don't see expected output for a passed run, the assertions are not listed. I expect to see the assertion in this line "1 spec, 0 failures".
The output:
[18:28:06] I/hosted - Using the selenium server at http://localhost:4444/wd/hub
[18:28:06] I/launcher - Running 1 instances of WebDriver
Started
.
1 spec, 0 failures
Finished in 0.854 seconds
[18:28:08] I/launcher - 0 instance(s) of WebDriver still running
[18:28:08] I/launcher - chrome #01 passed
Expected end of run output as seen on protractor's web site, http://www.protractortest.org/#/ "Run the test"):
1 test, 3 assertions, 0 failures
The spec:
describe('Viewing index.html', function() {
'use strict';
beforeEach(function(){
browser.get('/');
});
it('should have pages in left nav', function() {
expect(element.all(by.repeater('page in adminClient.selectedSite.pages')).count()).toBeGreaterThan(0);
});
});
I verified that the by.repeater locator worked:
element.all(by.repeater('page in adminClient.selectedSite.pages')).count()
.then(function(count){
console.log('page count: ' + count);
});
[UPDATE] According to this SO, it is a version issue and there is a recommendation to inject jasmine reporters on the onPrepare hook but that created more runtime errors for me.
stack overflow question
My protractor config:
exports.config = {
allScriptsTimeout: 11000,
chromeOnly: true,
chromeDriver: 'node_modules/protractor/bin/selenium/chromedriver_2.21',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['tests/e2e/*-spec.js'],
capabilities: {
'browserName': 'chrome'
},
baseUrl: 'http://localhost:8889/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000
}
};
To see the spec names and assertions you must pass the --verbose flag to protractor. If you are using grunt or something to run protractor, you'll need to specify this flag in your config.
EDIT
After reading your edit I believe I have found the solution to your issue. I've tried it with a project of my own and it appears to work.
The underlying problem is that you are likely using protractor 3, which no longer supports many of the previous options particularly within jasmineNodeOpts. To correct this issue, you should downgrade your version of protractor to 2, the latest version is 2.5.1
Here's the related issue on protractor's github repository. It also mentions a custom reporter within the onPrepare hook like you were talking about, but a different one: jasmine-spec-reporter. I got that working as well with a slightly different configuration than what you are using but it does not display the assertions, just has a much better output for the tests, which I quite like:
jasmineNodeOpts: {
print: function () {} // remove dots for each test
},
onPrepare: function () {
var SpecReporter = require('jasmine-spec-reporter');
jasmine.getEnv().addReporter(new SpecReporter({displayStackTrace: true}));
}
This is my module declaration:
(angular.module 'services.date', [])
.service '$date', () ->
# stuff
this
This is my injection code:
describe 'Service: dateService', () ->
dateService = null
beforeEach module 'services.date'
beforeEach inject (_$date_) ->
dateService = _$date_
describe 'Test', () ->
it 'should test stuff', () ->
(expect true).toBe true
If I run this code I get this error:
Firefox 37.0.0 (Ubuntu 0.0.0) Service: dateService Test should test stuff FAILED
minErr/<#/home/pv/Sites/web/ngbp-coffee/vendor/angular/angular.js:68:12
loadModules/<#/home/pv/Sites/web/ngbp-coffee/vendor/angular/angular.js:4411:15
forEach#/home/pv/Sites/web/ngbp-coffee/vendor/angular/angular.js:336:11
loadModules#/home/pv/Sites/web/ngbp-coffee/vendor/angular/angular.js:4372:5
createInjector#/home/pv/Sites/web/ngbp-coffee/vendor/angular/angular.js:4297:11
workFn#/home/pv/Sites/web/ngbp-coffee/vendor/angular-mocks/angular-mocks.js:2172:44
Now here's the interesting part: If I comment out the injection code, the test passes:
describe 'Service: dateService', () ->
# dateService = null
# beforeEach module 'services.date'
# beforeEach inject (_$date_) ->
# dateService = _$date_
describe 'Test', () ->
it 'should test stuff', () ->
(expect true).toBe true
// after running
Firefox 37.0.0 (Ubuntu 0.0.0): Executed 1 of 1 SUCCESS (0.003 secs / 0.002 secs)
Done, without errors.
What is it about how I'm injecting the service that's wrong? Please help.
UPDATE
It looks like the $injector service cannot recognize my other service. If I do
$injector.has '$date'
I get false
WTF am I doing wrong?????
The "Underscore Wrapping" is only useful when you do not want to hide your variable (dateService) with the injected reference (_ $date _). Meaning that using _ $date _ is only useful if you want to call your variable "$date" (not dateService).
However, it does not solve your issue. $injector should have '$date'. I guess we can't help you without more code. Something is probably wrong with your factory declaration or with the configuration file given to Karma, as, obviously, "$date" has not been loaded.
The same code is working for me (with an empty factory, however).
I am setting up a project with Gulp to run unit tests with Mocha, including Angular tests. I have the basic set up working (indexOf, etc.), however when I include angular-mocks I get this error or a node-module error:
ReferenceError in 'gulp-mocha': "Window is not defined"
I've tried including angular-module-mocks, using gulp-mocha-phantomjs... but the result is the same. (With mocha-phantomjs my error was 'Init timeout'.) I've seen many examples of configurations with Mocha and Angular or Gulp and Karma but have not yet found a solution for Gulp, Mocha and Angular alone.
I'm thinking of something similar to this Karma solution to correctly load angular-mocks by specifying it in a config file and forcing Gulp to load it (Angular testing with Karma: "module is not defined"). However, even if this would work, it seems like gulp-mocha does not support loading a configuration file (mocha.opts - https://github.com/sindresorhus/gulp-mocha/issues/26). I would be happy to hear a more straightforward solution.
I am using angular-mocks 1.2.22 and gulp-mocha 1.1.0.
Code snippets:
var mocha = require('gulp-mocha');
gulp.task('test', function () {
return gulp.src('test/*.js', {read: false})
.pipe(mocha({reporter: 'nyan', timeout: 400}));
});
test/test.js
var assert = require('assert');
var angular_mocks = require('angular-mocks'); //Fails only when this line is present
//tests
What finally worked for me with Gulp/Browserify/Mocha was using Karma and Mocha combined.
Specifically, I used gulp-karma, and defined the configuration at karma.config.js and used a dummy file for gulp.src as others have done:
gulp.task('test', function () {
return gulp.src('./foobar.js').pipe(karma({
configFile:'karma.config.js',
action: 'run'
}))
.on('error', handleErrors);
});
Then I used this karma.config.js file. I needed the npm modules karma-mocha, karma-chai, and karma-bro. (With only the first two, I was getting 'require is not defined'. Then of course I tried including karma-requirejs, but that does not work with Browserify. Then I tried karma-commonjs, which still didn't work. Then I tried karma-browserify, and got a strange error involving bundle() that no one seems to have solved (https://github.com/xdissent/karma-browserify/issues/46). Karma-bro did the trick.)
I also needed to preprocess each file referenced in the tests as well as the tests themselves. (For using phantomJS also include karma-phantomjs-launcher. And I am using the bower version of angular-mocks simply because it is more recent: v1.2.25 compared to 1.2.22 for npm - but the npm version might work.)
module.exports = function(config) {
config.set({
basePath: '',
// frameworks to use
frameworks: ['browserify', 'mocha', 'chai'],
// list of files / patterns to load in the browser
files: [
'node_modules/angular/lib/angular.min.js',
'bower_components/angular-mocks/angular-mocks.js',
'source/javascript/controllers/*.js',
'source/javascript/*.js',
'test/*.js'
],
reporters: ['progress'],
port: 9876,
colors: true,
autoWatch: true,
browsers: ['PhantomJS'],
preprocessors: {
'source/javascript/controllers/*.js': ['browserify'],
'source/javascript/*.js': ['browserify'],
'test/*.js': ['browserify']
}
});
};
And finally this test passes. At the end I needed to make sure the names of my modules and controllers were consistent (capitals etc.) to resolve 'Module not defined' errors. For debugging I replaced node_modules/angular/lib/angular.min.js with node_modules/angular/lib/angular.js in the files.
describe('Angular', function() {
describe('App Controllers', function() {
beforeEach(angular.mock.module('App'));
describe('MessageCtrl', function() {
it('should retrieve the correct amount of messsages', angular.mock.inject(function($controller) {
var scope = {},
ctrl = $controller('MessageCtrl', {$scope:scope});
assert.equal(scope.messages.length, 2);
}));
});
});
});
I do get this: 'WARNING: Tried to load angular more than once.' I can live with it.
I have been trying to run some tests with karma but have not been able to get it to work. After trying to get it to work with my application, I tried running it with the most simple possible test, and yet, it still does not finish.
Here is my karma.conf.js file:
// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html
module.exports = function(config) {
config.set({
// base path, that will be used to resolve files and exclude
basePath: '',
// testing framework to use (jasmine/mocha/qunit/...)
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
// 'app/bower_components/angular/angular.js',
// // 'app/bower_components/angular/angular-mocks.js',
// 'app/scripts/*.js',
// 'app/scripts/controllers/main.js',
// // 'test/mock/**/*.js',
// 'test/spec/**/*.js',
// // 'app/scripts/**/*.js,'
'testing.js'
],
// list of files / patterns to exclude
exclude: ['angular-scenario.js'],
// web server port
port: 8080,
// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers: ['Chrome'],
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};
and here is the testing.js file :
describe("hello", function(){
it("Should fail automatically", function(){
expect(false).toBe(true)
});
});
The result I get without fail is:
$ karma start karma.conf.js
INFO [karma]: Karma v0.10.9 server started at http://localhost:8080/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 30.0.1599 (Mac OS X 10.7.5)]: Connected on socket dGANukHhgkPC3YyhyUrU
INFO [Chrome 30.0.1599 (Mac OS X 10.7.5)]: Connected on socket HC8iGMv-VmeYX2UAyUrV
It never seems to go on and tell me how many of my tests succeeded or not.
Thanks for all of the help. Hopefully I will have some hair left at the end of this, haha.
This is the expected behaviour.
single_run : true means run the tests once and exit.
single_run : false means don't exit (this is not obvious).
autowatch : true means trigger running tests when a file changes.
If you have both autowatch and single_run set to false (like you do), then running
karma start
will just have karma initialize and wait for something to trigger it to run.
In order to trigger running the tests you need to open a new console and do
karma run
(Or set one of the above mentioned flags to 'true')
I ran into the same problem. I ended up installing the version of node that was suggested here: http://karma-runner.github.io/0.10/intro/faq.html. So now, I am running node.js version 0.10.38 with karma server version 1.4.28 and Chrome is happy with that.