Sinon jquery stubbing

1.2k views Asked by At

There are a bunch of great blogs (like Kumar's use of Sinon that explains how Sinon can stub jquery.

However, in that particular blog by Kumar as with others there is a simple jquery (npm) require:

var $ = require('jquery');

But jquery lives in the browser and needs a handle to a window. Installed jsdom (plus python for Windows to handle a dependency) and set jquery correctly (otherwise there are no ajax methods etc on the $ variable):

var jsdom = require('jsdom')
var $ = require('jquery')(jsdom.jsdom().defaultView);

Is this the only way to stub jquery? jsdom is great but the extra (despite simple) catch of installing python breaks my automatic "testing" and involves a bunch of extra configuration on the build server. Nothing impossible or hard just wondering why people gloss over in blogs that jquery when running testing (via Mocha) with Sinon is going to need access to a window to work?

Anybody attacking the problem in another way to stub jquery?

1

There are 1 answers

4
grammar On

I'm currently working on a test suite involving jsdom, mocha, and sinon for client-side javascript (coffeescript actually, but your question is in JS). I got around the issue of requiring jQuery by having jsdom load it instead. Note that I have not tested what I have below, but it's based on my own setup. In place of 'path/to/jquery' below, I actually load a single concatenated JS file which includes all external dependencies and my entire application code. The below example is from my spec_helper file, which is the first file that mocha runs.

var jsdom = require('jsdom');
var sinon = require('sinon');
var _ = require('underscore');
var chai = require('chai');
var expect = chai.expect;
chai.use(require('sinon-chai'));
chai.should();

before(function(next){
  var config = {
    html: '<body></body>',
    scripts: ['path/to/jquery'],
    features: {
      FetchExternalResources: ['script'],
      ProcessExternalResources: ['script']
    },
    // Equivalent to document.ready event, so you know the DOM 
    // has loaded and `jQuery` is available on `window`.
    done: function(error, window) {
      // Exposes everything on `window` to `global` so its available
      // in your test suites
      _(global).defaults(window);

      next();
    }
  };

  // Creates the JSDom instance
  jsdom.env(config);
});

beforeEach(function(){
  this.sandbox = sinon.sandbox.create();
  this.clock = this.sandbox.useFakeTimers();
  this.server = sinon.fakeServer.create();
});

afterEach(function(){
  this.sandbox.restore();
  this.server.restore();
});

The idea is that you let jsdom control anything to do with window, and expose said window to global within your tests. You should now be able to stub jQuery as Kumar does in the blog post you linked to. I'm actually about to work on trying that right now, so I'll post here if I find any issues with this or any workarounds. As it stands, apparently sinon.fakeServer does not work with jsdom and mocha - see here - so stubbing the ajax method is your best bet. Apparently fakeServer and node is a goal for Sinon v2.

Hope this helps!