问题
I have a very simple React mixin which uses jQuery to trigger an event
MyMixin = {
trackStructEvent: function () {
args = Array.prototype.slice.call(arguments);
$('body').trigger('myEvent', args);
}
module.exports = MyMixin
This is imported into the main site as part of a new set of components using browserify. As the main site holding these components will always include jQuery, I don't want to require jQuery with browserify, as it will be duplicated.
This isn't an issue in terms of behaviour - however it causes problems when running jest to unit test the components using this mixin throwing the error.
ReferenceError: $ is not defined
I know I can fix this by including jQuery through browserify, but that will load 2 copies into my site.
Is there any way in jest to tell my react component that jQuery already exists on the window and not to worry about it?
回答1:
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)
回答2:
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.
回答3:
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;
});
来源:https://stackoverflow.com/questions/27189254/react-component-using-jquery-without-require-jest-unit-tests