Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am trying to create a basic test to verify that I can create a controller or service.

My app is is the following directory

app/js/app.js

My controllers are in the following directory

app/js/controllers/

Here is my karma.conf.js file

        files: [
        'Scripts/jquery-2.1.1.min.js',
        'Scripts/require.js',
        'Scripts/angular.js',
        'Scripts/angular-mocks.js',
        { pattern: 'app/js/*.js', included: false },
        { pattern: 'app/js/**/*.js', included: false },
        { pattern: 'app/js/**/**/*.js', included: false },
        { pattern: 'app/js/**/**/**/*.js', included: false },
        { pattern: 'test/specs/**/*.js', included: false },
         'test/test-main.js',
    ],

    // list of files to exclude
    exclude: [
         'app/js/main.js'
    ],

test-main.js

var testFiles = [];
for (var file in window.__karma__.files) {
console.log(file);
if (/Spec\.js$/.test(file)) {
    testFiles.push(file);
}
}

requirejs.config({
paths: {
    // External libraries
    'jquery': '../../Scripts/jquery-2.1.1.min',
    'angular': '../../Scripts/angular',
    'angular-mocks': '../../Scripts/angular-mocks',
    'ngRoute': '../../Scripts/angular-route.min',
    'angular-animate': '../../Scripts/angular-animate.min',
   'angular-cookies': '../../Scripts/angular-cookies.min',

},
baseUrl: '/base/app/js',

shim: {
    'angular': {
        exports: 'angular',
        deps: ['jquery']
    },
    'angular-mocks': { exports: 'angular-mocks', deps: ['angular']  },
    'angular-animate': { exports: 'angular-animate', deps: ['angular'] },
    'ngRoute': { exports: 'ngRoute', deps: ['angular'] },
    'angular-cookies': { exports: 'angular-cookies', deps: ['angular'] },
},

  // dynamically load all test files
deps: testFiles,

  // we have to kickoff jasmine, as it is asynchronous
  callback: window.__karma__.start
});

I added this line...

console.log(file)

To make sure the file was loaded into

window.__karma__.files

and it is.

The test lives in test/specs/

define(['angular', 'angular-mocks'], (angular, ngMock: ng.IMockStatic) => {
var module = ngMock.module;
var inject: (...fns: Function[]) => any = ngMock.inject;

describe("Create an Application", function () {
    var scope, q, routeParams;
    var location;
    var app;
    beforeEach(function () {

        app = angular.module('App', []);
        inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
            scope = $rootScope;
            q = $q;
            routeParams = {};
            location = $location;
        });
    });

    it('Test Application Created', function () {
        expect(true).toBe(true);
    });
});
});

My app file looks like this....

import angular = require('angular');
import angularRoute = require('angular-route');
import angularAnimate = require('angular-animate');
import ds = require('services/DataService');

var app = angular.module('app', [
    'ngRoute',
    'ngAnimate',
    'ngCookies',
    'kendo.directives',
    'breeze.angular',
    'ui.bootstrap'
]);

export = app;

the error that i get when I try to run the test is

failed to instantiate module app due to: Module 'app' is not available! You either misspelled the module name or forgot to load it.

I am assuming it is not loading but not sure how I can tell. Is this the best way to accomplish my testing?

Any help is greatly appreciated!

Thanks so much!

Grunt output

share|improve this question

2 Answers 2

If you are using Karma with Jasmine, you may be having the problem of Jasmine being too eager.

This can be fixed by making two changes, originally described in an article I wrote when I was doing a similar thing, Combining TypeScript, Jasmine and RequireJS.

In boot.js you need to comment out the env.execute(); method call:

window.onload = function() {
    if (currentWindowOnload) {
        currentWindowOnload();
    }
    htmlReporter.initialize();
    //env.execute();
};

This is because the window.onload event can happen before require.js has loaded everything.

Once you have loaded the modules you need, you can then call:

// Hai Jasmine - ready to go!
jasmine.getEnv().execute();
share|improve this answer
    
Thanks for the input but in the test-main.js file for require, I have this line callback: window.__karma__.start Does that delay the start of jasmine until require has loaded everything? –  ChrisSmathers Nov 6 '14 at 11:52
    
You may still need to comment out env.execute(); in Jasmine's boot.js file. –  Steve Fenton Nov 6 '14 at 12:42

This is what it gets compiled with your code and the -m amd switch

    describe("Create an Application", function () {
        var scope, q, routeParams;
        var controller, location;
        var route;

        beforeEach(function () {
            module('app', ['ngRoute', 'ngAnimate', 'ngCookies', 'kendo.directives', 'breeze.angular', 'ui.bootstrap']);
            inject(function ($rootScope, $q, $location) {
                scope = $rootScope;
                q = $q;
                routeParams = {};
                location = $location;
            });
            //   controller = new controller.ApplicationService(q, scope, route, location, _datasvc, _searchsvc);
        });
        it('Test Application Created', function () {
            expect(true).toBe(true);
        });
    });

is not a module, and its synchronous

But. in a module works

define(['angular','angular-mocks'],(angular,ngMock:ng.IMockStatic)=>{
    var module = ngMock.module;
    var inject: (...fns: Function[])=>any =  ngMock.inject;

    describe("Create an Application", function () {
        var scope, q, routeParams;
        var  location;
        var app;
        beforeEach(function () {

            app = angular.module('App', []);
            inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
                scope = $rootScope;
                q = $q;
                routeParams = {};
                location = $location;
            });
        });

        it('Test Application Created', function () {
            expect(true).toBe(true);
        });
    });
});

Or alternatively in a more TypeScripty w/ES6esque way :

    import ngMock = require('angular-mocks');
    import angular = require('angular');
    var module = ngMock.module;
    var inject: (...fns: Function[])=>any =  ngMock.inject;

    describe("Create an Application", function () {
        var scope, q, routeParams;
        var  location;

        beforeEach(function () {
            var app = angular.module('app', []);
            inject(function ($rootScope, $q: ng.IQService, $location: ng.ILocationService) {
                scope = $rootScope;
                q = $q;
                routeParams = {};
                location = $location;
            });
        });
        it('Test Application Created', function () {
            expect(true).toBe(true);
        });
    });

check that you are loading angular as in a script tag
'files:[Scripts/angular.js',... , that's why you get WARNING:tried load angular more than once Put it in a { pattern: 'Scripts/angular.js', included: false ...], you need to work out the requirejs.confg until the deps chain are satisfied. in order., and thats one of the reasons why you set the shim config with 'angular-mocks': { exports: 'angular-mocks', deps: ['angular'] },
so when requiring angular-mocks angular is required too , have a look at [this github repo](https://github.com/tnajdek/angular-requirejs- seed), ...And once you have an instance attached to angular.module /mock.module in your spec , check Steve's answer again , If you can't find boot.js , you might be using jasmine bundled with the Karma adapter. in that case it should work given you have sorted out the require test-maiin.js / config / "NG_DEFER_BOOTSTRAP!" /resumeBootstrap story

share|improve this answer
    
Thanks for the feedback, I think you are pointing me in the right direction but I am still getting an error Cannot read property 'module' of undefined at line 2, which is var module = ngMock.module; –  ChrisSmathers Nov 6 '14 at 11:56
    
check that I'm requiring 'angular-mocks' that I configured on my 'test-main.js' , you call it 'angularMocks' , it should export angular.mock –  Dan Nov 6 '14 at 12:14
    
Yeah, I noticed that and change my naming to match yours. I updated my question with the updates I made. I also attached the output from grunt. Thanks again for all your help. I will be nice to get this working! –  ChrisSmathers Nov 6 '14 at 16:13
    
added comments. I hope it helps :) –  Dan Nov 6 '14 at 17:31
    
Thanks for the input, I have to work on another project for a couple of days so I have to put this down. I will take a look at the github link and compare that to my project. I do have one question for you...What is"...fns" I have never seen that before. Thanks for all your help! I will keep you posted on my progress over the next week. –  ChrisSmathers Nov 10 '14 at 11:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.