10

For a project that I am working on I have been using a hodgepodge of JavaScript libraries. The main logic of my code is broken down into multiple commonjs modules. I use google closure to combine the modules into one output js file which I use within my AngularJS application.

The problem I am having is trying to perform tests with testacular. There error I receive is Uncaught ReferenceError: require is not defined. It is happening because, unlike google closure, testacular doesn't understand commonjs modules. There are a couple work arounds I can do, but I was hoping to make it work without having to restructure my code.

  1. I can restucture the modules so that I'm no longer using commonjs. I don't like this because it feels like a step backwards. I want my code to be modular.
  2. I can run testacular on the compiled js from google closure. I don't mind doing it this way, but I have not been able to trigger everything to work on file changes. Testacular can re-run itself on file changes, but I haven't seen anyway to make google closure re-compile on changes.
  3. Finally, I can enable commonjs module in testacular. Ideally this is the way I want to go, but it may not be the easiest.

Has anyone else run into a similar problem? I'm open for trying different things; I just don't want anything hacky.

javaclassstreamreader.spec.js:

"use strict"

var JavaClassStreamReader = require('../javaclassstreamreader.js').JavaClassStreamReader;

describe('javaclassstreamreader', function() {

  it('reader can be constructed', function() {
    var dataView = {
      byteLength : 0
    };
    //FIXME load dataView

    var reader = new JavaClassStreamReader(dataView);
    expect(reader.dataView).toBe(dataView);
    expect(reader.offset).toBe(0);
    expect(reader.maxOffset).toBe(0);
  });

});

javaclassstreamreader.js:

function JavaClassStreamReader(dataView, initialOffset, maxBytesToRead) {
  this.dataView = dataView;
  this.offset = initialOffset || 0;
  this.maxOffset = this.offset + (maxBytesToRead || this.dataView.byteLength);
}
//... code trucated ...
AstroCB
  • 12,337
  • 20
  • 57
  • 73
pgreen2
  • 3,601
  • 3
  • 32
  • 59
  • My answer says as much as your question: you have to define 'require'... As Praveen said, give us some code snippets, ... – asgoth Jan 01 '13 at 15:49
  • Sounds like a function named `require(...)` is being used in your script and the library file is not loaded where the `require` function is defined. Post relevant code. – The Alpha Jan 01 '13 at 15:55
  • 1
    `require()` is part of the commonjs specification. – pgreen2 Jan 01 '13 at 15:58

2 Answers2

2

It seems there is/was an issue with Testacular.

Could you try the following:

  • clear npm cache: npm cache clean
  • install another version of testacular: npm install -g testacular@0.5.6
asgoth
  • 35,552
  • 12
  • 89
  • 98
  • Your steps do allow me to correctly install requirejs, but I'm not using requirejs. Requirejs works with commonjs modules, but isn't the same thing. It is trying to asynchronously load my js files, but testacular already does that, or at least tries to. Hence, my problem. – pgreen2 Jan 01 '13 at 22:24
1

I was not able to make it work with require, but I do have a partial solution.

grunt.js:

/*global module:false*/
module.exports = function(grunt) {"use strict";

  // Project configuration.
  grunt.initConfig({
    pkg : '<json:package.json>',
    meta : {
      banner : '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %>\n' + '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */'
    },
    lint : {
      files : ['grunt.js', 'src/*.js', 'src/public/js/**/*.js', 'src/specs/**/*.js']
    },
    watch : {
      files : '<config:lint.files>',
      tasks : 'default'
    },
    exec : {
      ensure_generated_directory : {
        command : 'mkdir -p generated/js/'
      }
    },
    clean : {
      all : ['generated']
    },
    jshint : {
      files : '<config:lint.files>',
      options : {
        curly : true,
        eqeqeq : true,
        forin : true,
        immed : true,
        latedef : true,
        newcap : true,
        noarg : true,
        sub : true,
        undef : true,
        unused : true,
        strict : true,
        boss : true,
        eqnull : true,
        es5 : true,
        browser : true,
        jquery : true,
        devel : true
      },
      globals : {
        //jasmine
        describe : false,
        it : false,
        expect : false,
        //commonjs
        require : false,
        exports : true,
        //angular
        angular : false
      }
    },
    'closure-compiler' : {
      frontend : {
        closurePath : 'closure-compiler',
        js : ['src/*.js', 'src/public/js/**/*.js'],
        jsOutputFile : 'generated/js/complete-app.js',
        options : {
          externs : 'externs.js',
          compilation_level : 'SIMPLE_OPTIMIZATIONS',
          language_in : 'ECMASCRIPT5_STRICT',
          logging_level : 'ALL',
          debug : null,
          warning_level : 'verbose',
          summary_detail_level : 3,
          formatting : ['PRETTY_PRINT', 'PRINT_INPUT_DELIMITER'],
          common_js_entry_module : 'src/public/js/app.js',
          process_common_js_modules : null,
          process_jquery_primitives : null,
          common_js_module_path_prefix : 'src'
        }
      }
    },
    testacularServer : {
      integration : {
        options : {
          keepalive : true
        },
        configFile : 'testacular.conf.js',
        autoWatch : false,
        singleRun : true
      }
    }
  }); 

  // Default task.
  grunt.registerTask('default', 'lint exec:ensure_generated_directory closure-compiler testacularServer:integration');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-closure-compiler');
  grunt.loadNpmTasks('grunt-exec');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-testacular');
};

I can run grunt watch and I get a similar result. grunt lints, then compiles, then runs testacular. This isn't as fast as I was hoping. testacular starts and stops the server each time.

pgreen2
  • 3,601
  • 3
  • 32
  • 59
  • 1
    Could you please provide your Gruntfile as it was before adding someting to make it work (without that information your question and its solution is less worth for others). – try-catch-finally Dec 29 '14 at 12:28