React component using jQuery without require - jest unit tests React component using jQuery without require - jest unit tests reactjs reactjs

React component using jQuery without require - jest unit tests


I have a similar problem but I think where i've got to so far solves your problem. You need to use require inside your react files to define jQuery under $

var $ = require('jquery');MyMixin = {   trackStructEvent: function () {      args = Array.prototype.slice.call(arguments);      $('body').trigger('myEvent', args);   }module.exports = MyMixin

You then need to tell jest not to mock jquery

jest.dontMock('jquery')

Then your jest unit tests should pass (assuming they aren't verifying things that jQuery is doing - this is where my tests are falling over).

You also need to tell browserify that jQuery is external then the result will be that all your references to $ have been defined, the jquery library is loaded for testing but is not included in your browserify bundle. (use browserify-shim)


What I'm going with is:

if (process.env.NODE_ENV === 'test') window.$ = require('jquery');

I hope this helps someone!

UPDATE:

I've begun to import $ from 'jquery' in all React files that use jQuery. This removes the dependency on window.$ being the type of jQuery I expect (I have run into problems with other libraries messing with window.$. At first, I was concerned about importing jQuery everywhere, because I was afraid that this would increase my bundle size. But the way bundling works, all these imports will point to a singleton, so bundle size would not increase.


For my part, I am not interested in testing the jQuery functionality in my components. In addition, I have not included jQuery in my bundle because it is used and included all over the website my app is on. So I have, for example, done the following:

// SubmitRender.js// ...import statements...var SubmitRender = React.createClass({  componentWillMount: function () {    $('form').on('submit', (e)=>{      this.handleSubmit(e);    });  },  // ...more code...});export default SubmitRender;

.

// SubmitRender.spec.js// ...import statements...describe('SubmitRender', () => {  beforeAll(() => {    // mocking jQuery $()    global.window.$ = jest.fn(() => {return {on: jest.fn()}});  });  it('renders without error', () => {    expect( () => render(<SubmitRender />) ).not.toThrow();  });});

I know my component will not mount without calling the $ function. So I just mock out that function with jest.fn in a beforeAll(). Now, I also know that my jQuery function inside my actual component is chained. So I know that I also need to account for jQuery's .on(), so I make sure to return an object with an on function. There is no further chaining, so that is where I can stop.

If I had a more complex set of chained functions, I could do something like this:

beforeAll(() => {  // mocking jQuery $()  var fakeQuery = jest.fn(() => {    return {      on: fakeQuery,      off: fakeQuery,      click: fakeQuery    }  })  global.window.$ = fakeQuery;});