0

The code I'm trying to test relies on RequireJs loader plugins. Example with requirejs/text:

require(['text!templates/foo'], function (data) {
  // handle loaded data
});

For a specific unit test, I'm trying to mock the response for text!templates/foo and override with one relevant for the test:

it('should load a template', function (done) {

  // TODO: mock 'text!templates/foo' here to return 'mock_data'

  // templateViewer uses the text plugin internally to do the actual loading
  templateViewer.templateFor('foo', function (error, templateData) {
    expect(templateData).toEqual('mock_data');
    done();
  });

});

I've looked at RequireJs dependency mock solutions, especially Squire.js but it seems they are all suited for mocking regular dependencies and not plugin responses.

I've also looked at stub libraries like sinon to maybe replace the actual require call but that seems problematic.

What's the recommended practice? I prefer not to replace the entire text plugin with a mock one in my requirejs configuration, just override some of its responses in specific tests.

My setup is node+mocha+requirejs

Edit

Please see this example fiddle project to see my issue with Squire:

http://runnable.com/VUBoI0ex6v9Gs-BJ/squirejs-with-plugins-for-node-js-and-hello-world

Community
  • 1
  • 1
talkol
  • 12,564
  • 11
  • 54
  • 64

1 Answers1

2

This will mock what you'd get from requiring text!foo/x.html. Plugins are not special, you just need to mock the entire path, including the plugin name.

var requirejs = require("requirejs");
var assert = require("assert");

requirejs.config({
    baseUrl: __dirname,
    packages: [
        {
            name: "squire",
            location: "node_modules/squirejs",
            main: "src/Squire"
        }
    ]
});

var x;
before(function (done) {
    requirejs(["squire"], function (Squire) {
        var injector = new Squire();

        injector.mock("text!foo/x.html", "foo").require(["text!foo/x.html"],
                                                   function (_x) {
            x = _x;
            done();
        });
    });
});

it("foo", function () {
    assert.equal(x, "foo");
});

The problem you run into with the example code you added to your question is that you use the global require instead of using a require passed by your loader. You should add require as a dependency:

define(['require', ....], function (require, ....) {

The require module is special and reserved by RequireJS. It returns a reference to the require function. You must use it, for instance, when you use RequireJS's contexts so that a module loaded in a specific context uses a require function that is bound to that context. SquireJS also needs you to do this so that it can trap your calls to require. The global require bypasses SquireJS.

Louis
  • 146,715
  • 28
  • 274
  • 320
  • Tried that, not working since the plugin is used with require() and not define(). Please see this example fiddle: http://runnable.com/VUBoI0ex6v9Gs-BJ/squirejs-with-plugins-for-node-js-and-hello-world – talkol Apr 29 '15 at 05:15
  • "Not working?" The code I've put in my answer was tested and runs perfectly fine. – Louis Apr 29 '15 at 10:15
  • Take a look at the runnable I posted. Your code works perfectly of course, but the use-case I have is slightly different. The runnable shows the difference. – talkol Apr 29 '15 at 10:32
  • You, my friend, are awesome! Thanks a million, I completely missed the part about passing require in RequireJs docs – talkol Apr 29 '15 at 18:22