0

I am trying to run unit test cases for my controllers, I have tried the following but getting the below error, please let me know to run this test successfully. Thanks in advance.

spec.js:

describe('MainCtrl', function() {
  beforeEach(module('app-module'));
  var $controller;
  beforeEach(inject(function(_$controller_){ 
    $controller = _$controller_;
  }));

  describe('$scope.titleofapp', function() {
    var $scope, controller;
    beforeEach(function() {
      $scope = {};
      controller = $controller('MainCtrl', { $scope: $scope });
    });

    it('sets the title of app to "app-module" module', function() {
      $scope.titleofapp();
      expect($scope.title).toEqual('My Test App !');
    });
  });
});

app.js:

define(['angular', './app-module'], function(angular, appModule) {
    'use strict';
    return appModule.controller('MainCtrl', ['$http', '$q', 'appService', '$stateParams', function($http, $q, $stateParams, appService){
        $scope.titleofapp = function(){
        $scope.title = 'My Test App !';}
   }]);  
});

Below is my karma.conf.js file configuration:

karma.conf.js:

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine','requirejs'],

    files: [
            'node_modules/requirejs/require.js',
            'node_modules/karma-requirejs/lib/adapter.js',
            'node_modules/angular/angular.js',
            'node_modules/angular-mocks/angular-mocks.js',
           'public/app/app.js',
           'public/tests/spec.js'
         ],

    exclude: [
    ],

    plugins: [
            'karma-requirejs',
            'karma-chrome-launcher',
            'karma-jasmine'
          ],
    preprocessors: {
    },
    reporters: ['progress'],

    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
     singleRun: false,
    concurrency: Infinity
  })
}

I have configured requirejs like above and getting the below error now: Error:

    Uncaught Error: Mismatched anonymous define() module: function (angular, appModule) {
      'use strict';
    return appModule.controller('MainCtrl', ['$http', '$q', 'appService', '$stateParams', function($http, $q, $stateParams, appService){
        $scope.titleofapp = function(){
        $scope.title = 'My Test App !';}

      }]);
  }
  http://requirejs.org/docs/errors.html#mismatch
  at node_modules/requirejs/require.js:165
4
  • Looks like you are using requireJS but you haven't included it in files array. Commented Aug 22, 2017 at 11:52
  • 1
    did you look at guide how to run karma with require.js? i can't talk on angular stuff, but concerning requirejs karma is configured imporperly
    – xmike
    Commented Aug 23, 2017 at 8:36
  • @xmike, I have added requirejs and getting the error: Uncaught Error: Mismatched anonymous define() module: function, and updated the post, please let me know about it, thanks in advance.
    – Sana
    Commented Aug 23, 2017 at 9:22
  • @StanislavKvitash, I have configured requirejs like above updated post, getting the below error: Uncaught Error: Mismatched anonymous define() module: function, please let me know about it to solve. Thanks in advance.
    – Sana
    Commented Aug 23, 2017 at 9:23

1 Answer 1

0

Here is your karma.conf.js file I've edited to make possible run with RequireJS. Comments styled as // -- mostly (except when trailing) the stuff that I commented out, and styled as /* */ -- are real comments about what's the purpose of specific line presence or absence. I hope all that commenting will help to understand what's going on.

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine','requirejs'],

    files: [
        /* not needed because you've told to use requirejs higher in frameworks */
//        'node_modules/requirejs/require.js',

        /* i assume this one in no need in your case but could be yes */
//        'node_modules/karma-requirejs/lib/adapter.js',

        /* as far as i understand angular.js is amd loadable so don't load it directly */
//        'node_modules/angular/angular.js',

        /* i am not sure about this one and how it should be launched so commented it out for now */
//        'node_modules/angular-mocks/angular-mocks.js',

        /* will be loaded by tests*/
//        'public/app/app.js',

        /* tests should not be loaded directly eigther */
//        'public/tests/spec.js'

        /* now configure karma with what will be servable */
        {pattern: 'node_modules/**/*.js', included: false}, // all stuff from what npm installed
        {pattern: 'src/**/*.js', included: false}, // your source filed
        {pattern: 'tests/**/*Test.js', included: false},    // your tests or specs

        /* this is the only file to be loaded directly */
        'tests/test-main.js' // karma will load this file and it will do all the stuff
     ],

    exclude: [
    ],

    /* karma will load all sibling npm modules with name karma-* so these lines not needed i believe */
//    plugins: [
//        'karma-requirejs',
//        'karma-chrome-launcher',
//        'karma-jasmine'
//    ],
    preprocessors: {
    },
    reporters: ['progress'],

    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    concurrency: Infinity
  })
}

Then here I made a sample code for main-test.js file.

var allTestFiles = [];
var TEST_REGEXP = /base\/tests\/.*(spec|test)\.js$/i;

// Get a list of all the test files to include
/* as far as i remember window.__karma__.files contains array of all servable files */
Object.keys(window.__karma__.files).forEach(function (file) {
    //console.log('original path', file);
    if (TEST_REGEXP.test(file)) {
        /* below i commented out file path modification suggested at http://karma-runner.github.io/1.0/plus/requirejs.html
         * personally i never needed that. Your case might be different so you can play around with this part
         */
        var normalizedTestModule = file;//'/base/' + file.replace(/^\/base\/|\.js$/g, '')
        //console.log('normalized path', normalizedTestModule);
        allTestFiles.push(normalizedTestModule);
    }
});

//console.log(allTestFiles); // list all test filed that will be run

/* now confifure requirejs so it could do the job 
 * for more details please visit http://requirejs.org/docs/api.html#config
 */
require.config({
    // Karma serves files under /base, which is the basePath from your config file
    /* i prefer this to be default */
    baseUrl: '/base/src',
    paths: {
        /* could be this to do stuff like
         * define(['node_modules/cool-module/module.js], function(Module){
         * 
         * });
         */
        node_modules: '/base/node_modules',

        /* below is just examples that what it could be if you needed those */
//        jquery: '/base/node_modules/jquery/dist/jquery',
//        underscore: '/base/node_modules/underscore/underscore',
//        backbone: '/base/node_modules/backbone/backbone',
//        text: '/base/node_modules/requirejs-text/text',
//        templates: '/base/src/templates'
    },

    /* Dynamically load all test files
     * An array of dependencies to load. Useful when require is defined as a 
     * config object before require.js is loaded, and you want to specify 
     * dependencies to load as soon as require() is defined. Using deps 
     * is just like doing a require([]) call, but done as soon as the loader 
     * has processed the configuration. It does not block any other require() 
     * calls from starting their requests for modules, it is just a way to 
     * specify some modules to load asynchronously as part of a config block.
     * (http://requirejs.org/docs/api.html#config-deps)
     */
    deps: allTestFiles,

    /*  A function to execute after deps have been loaded. Useful when require 
     * is defined as a config object before require.js is loaded, and you want 
     * to specify a function to require after the configuration's deps array 
     * has been loaded.
     * http://requirejs.org/docs/api.html#config-callback
     * Could be as simple as 
     *     callback: window.__karma__.start
     * but i do it via additional wrapper so i can require something specific 
     * for the whole test suite (like jasmine-jquery), you will the sample below
     */
    callback: startTestWithJasmineJquery
});

function startTestWithJasmineJquery(){
    require(['node_modules/jasmine-jquery/lib/jasmine-jquery'], function(){
        /* now jasmine-jquery is loaded and its features are available
         * so we can window.__karma__.start -- it will actually run tests
         */
        window.__karma__.start();
    });
}

Please note that all config options assume folder and some specific files structure as:

node_modules/
src/
tests/
    test-main.js
karma-conf.js

Please also note again that this is very basic config I've provided and there might be some specific stuff relative to angular or your project logic and needs and thus there might be some (or many) changes to be made.

1
  • Thanks for your help and explanation above, it is resolved many issues now.
    – Sana
    Commented Aug 23, 2017 at 12:59

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