badsyntax
badsyntax

Reputation: 9650

Grunt test for UMD

I'm trying to figure out the best approach to testing a Javascript module definition using a UMD factory, similar to this: https://github.com/umdjs/umd/blob/master/returnExportsGlobal.js

I don't want to test the module itself, I want to test that the module is 'exported/created' correctly in the various environments:

  1. If CommonJS (node), is the module exported correctly?
  2. If AMD, is it defined correctly?
  3. If browser (without requirejs), is the correct global created?

I would like to run these tests using grunt and jasmine. I can use grunt-contrib-jasmine to test for points 2 and 3, but not for point 1.

I guess I can use a concoction of grunt-contrib-jasmine and grunt-jasmine-node to test for correct module definitions (specific implementation i'd still need to figure out), but it feels very messy.

At a high level, does anyone know of any existing methods to achieving this without using multiple grunt plugins?

Upvotes: 6

Views: 4419

Answers (2)

Angelos Pikoulas
Angelos Pikoulas

Reputation: 1055

You can also use uRequire and save your self from all the UMD boilerplate in all your modules, while using declarative features.

You simply write plain AMD or plain CommonJS modules (or a mix of two) and convert to UMD (or an rjs optimized combined.js that runs as-is on nodejs, Web/AMD & Web/Script) with a simple build step and config, either in CLI or in grunt.

The UMD produced is based on well known templates like https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js, with various tweaks, one of them being that you can declaratively export to window/global.

You can then convert you plain AMD or commonJS specs to UMD and/or 'combined.js' and hit both in a browser or grunt-mocha. See uBerscore for many trivial and more advanced examples.

Upvotes: 0

badsyntax
badsyntax

Reputation: 9650

In the end, i decided to go with the hybrid tasks, using grunt-contrib-jasmine for browser global and browser AMD tests, and jasmine_node for CommonJS testing. I only have one spec file which supports all 3 module type tests.

Here's my grunt config:

grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  jasmine: {
    browserGlobal: {
      src: ['src/Foo.js'],
      options: {
        specs: 'spec/**/*.spec.js'
      }
    },
    browserAMD: {
      src: ['src/Foo.js'],
      options: {
        specs: 'spec/**/*.spec.js',
        template: require('grunt-template-jasmine-requirejs')
      }
    }
  },
  jasmine_node: {
    specNameMatcher: 'spec',
    projectRoot: 'spec/'
  }
});

My jasmine spec files now support UMD:

(function (root, factory) {
  if (typeof module === 'object' && module.exports) {
    // Node/CommonJS
    factory(
      require('modulename')
    );
  } else if (typeof define === 'function' && define.amd) {
    // AMD
    define([
      'modulename'
    ], factory);
  } else {
    // Browser globals
    factory(root.ModuleName);
  }
}(this, function factory(ModuleName) {

 // Tests here
}));

And here's the UMD factory i'm using for my module:

(function (root, factory) {
  if (typeof module === 'object' && module.exports) {
    // Node/CommonJS
    module.exports = factory();
  } else if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(factory);
  } else {
    // Browser globals
    root.ModuleName = factory();
  }
}(this, function factory() {


  // public API
  return {
    foo: 'bar'
  };
}));

Upvotes: 4

Related Questions