Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Error: Mismatched anonymous define()" with Karma + RequireJS + Jasmine

I am stuck now for a while trying to get unit testing set up and runnning.

I have an AngularJS front-end loaded with RequireJS and r.js optimized for production, so it's all nicely in one single file. This works!

What doesn't work is getting the unit tests executed. This is nothing fancy so far, just copied a starter from a tutorial.

tests/user/user.test.js:

define(['angular', 'angular-mocks', 'app'], function(angular, app) {
  describe('Unit: UserController', function() {
    beforeEach(module('user.app'));

    it('should do something', function() {
      console.log('did it');
    });
  });
});

Then I have a karma.conf.js:

module.exports = function(config) {
  config.set({
    logLevel: config.LOG_DEBUG,
    basePath: './',

    files: [
      // r.js'd app files
      {pattern: 'dist/app.js', included: false},
      // the tests
      {pattern: 'tests/**/*.test.js', included: true},
    ],

    excluded: ['tests/main.test.js']

    frameworks: ['jasmine', 'requirejs'],

    browsers: ['PhantomJS'],

    plugins: [
      'karma-jasmine',
      'karma-junit-reporter',
      'karma-phantomjs-launcher',
      'karma-requirejs'
    ],

  });
};

A main.test.js:

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

var pathToModule = function(path) {
  var returnValue = path.replace(/^\/base\//, '').replace(/\.js$/, '');
  return returnValue;
};

Object.keys(window.__karma__.files).forEach(function(file) {
  if (TEST_REGEXP.test(file)) {
    // Normalize paths to RequireJS module names.
    allTestFiles.push(pathToModule(file));
  }
});

require.config({
  baseUrl: '/base',

  paths: {
    'angular-mocks': 'node_modules/angular-mocks/angular-mocks',
    'app': 'dist/app',
  },

  deps: allTestFiles,

  callback: function() {
    console.log('load complete');
    window.__karma__.start();
  },
});

And finally a gulp task:

var gulp  = require('gulp');
var karma = require('karma').server;

gulp.task('unit-test', function(done) {
  karma.start({
    configFile: __dirname + '/karma.conf.js',
      singleRun: true
   }, function() { done(); });
}

Here and there I added some log outputs and it shows that the files are loaded.

But I am stuck getting this Error: Mismatched anonymous define() in the tests/user/user.test.js and I don't see what is wrong. Here is the output: http://pastebin.com/evJPj9B3

If I name the unit test module like

define('namedtestorso', ['angular', 'angular-mocks', 'app'], function(angular, app) {
  ...

... I don't get an error any more but the tests are not executed. Since all examples I can recall use it as anonymous define I assume naming is not correct here. But in that case the log output is executed showing that the config callback from main.test.js is executed twice. (Is that a hint for something?)

Would be great if anyone has an idea how to fix it/get it running or even how to go on finding out what's wrong. Thanks in advance!

like image 837
robbash Avatar asked Jun 29 '15 06:06

robbash


2 Answers

I now got it running so will leave my solution here:

I think I understood a bit better now how karma works (pls tell me if I'm wrong) and so found what I had to do.

It seems to be all about putting files into the karma.conf.js so that they are available for the main.test.js to be loaded. Otherwise they are out of the "context" and cannot be accessed. But when putting in there, make sure to set the included flag to false.

Changes to the karma.conf.js:

files: [
  ...
  // Also included these dependencies. All the others are minified in the
  // app.js but if you don't do that, also include all project deps like
  // AngularJS etc.
  { pattern: 'node_modules/jasmine-core/lib/jasmine-core/boot.js', included: false },
  { pattern: 'node_modules/angular-mocks/angular-mocks.js', included: false},

  // Then I had an error in my pattern ('tests/**/*.test.js')
  // Only the `main.test.js` is supposed to be included!
  { pattern: 'tests/user/user.test.js', included: false }
  { pattern: 'tests/main.test.js', included: true }
  ...

If I'm correct Karma creates a HTML file and files with included: true will be loaded via script tags. That's why if using RequireJS it is important to set include to false since you'll get the Error: Mismatched anonymous define() if you do. So this now makes sense to me.

After solving this issue there where some other ones with modules not found. Because I used the RequireJS optimizer, I had to "map" all my modules to the main app.js files so that when the test JS files required a certain module, RequireJS could make sure that it is (or gets) loaded.

So I ended up changing the paths section in main.test.js:

paths: {
  // Added these for example
  'angular': '../dist/app',
  'angular-ui-router': '../dist/app',
  // (and also my project modules)
  ...

Right, that seems a bit hacky. In the meantime after solving this issue I also change my workflow to running the unit test on the dev files and rely on the other tools to work properly (and if not issues to be caught by e2e tests).

Hope it helps others in my situation!

like image 63
robbash Avatar answered Nov 20 '22 17:11

robbash


Exactly if you go to requirejs site this error states if you have included any script tag in html this means html provided by karma

So in karma.conf.js when you include files like : files['/base/src/scripts/xyz.js'] in my opinion it is added as a script tag and u keep on getting Error: Mismatched anonymous define() module

try pattern example:{pattern: '/base/src/scripts/xyz.js', included: false} which prevents adding js in script tags

like image 1
Siddhartha Avatar answered Nov 20 '22 18:11

Siddhartha