使用jQuery反应组件而不需要 - jest单元测试

时间:2014-11-28 13:01:40

标签: jquery reactjs jestjs reactjs-testutils

我有一个非常简单的React mixin,它使用jQuery来触发事件

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

使用browserify将其导入主站点,作为一组新组件的一部分。由于拥有这些组件的主站点将始终包含jQuery,我不希望jQuery与browserify一起使用,因为它将被复制。

这在行为方面不是问题 - 但是当运行jest以使用此mixin对组件进行单元测试时会引发问题。

ReferenceError: $ is not defined

我知道我可以通过浏览器包含jQuery来解决这个问题,但是这会将2个副本加载到我的网站中。

有没有什么方法可以告诉我的反应组件jQuery已经存在于窗口而不用担心呢?

3 个答案:

答案 0 :(得分:7)

我有类似的问题,但我认为到目前为止我已经解决了你的问题。 您需要在您的react文件中使用require来定义$

下的jQuery
jest.dontMock('jquery')

然后你需要告诉jest不要模拟jquery

{{1}}

然后你的jest单元测试应该通过(假设他们没有验证jQuery正在做的事情 - 这是我的测试正在落空的地方)。

你还需要告诉browserify jQuery是外部的,然后结果将是你已经定义了所有对$的引用,jquery库被加载用于测试但是不包含在你的browserify包中。 (使用browserify-shim

答案 1 :(得分:2)

我要做的是:

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

我希望这有助于某人!

更新:

我在所有使用jQuery的React文件中开始import $ from 'jquery'。这消除了对窗口的依赖。$是我期望的jQuery类型(我遇到了其他库弄乱窗口的问题。$。起初,我担心到处导入jQuery,因为我担心这会增加我的捆绑大小。但捆绑的工作方式,所有这些导入将指向单身,所以捆绑大小不会增加。

答案 2 :(得分:2)

就我而言,我对测试组件中的jQuery功能不感兴趣。另外,我没有在我的包中包含jQuery,因为它被使用并包含在我的应用程序所在的网站上。例如,我做了以下事情:

// 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();
  });
});

我知道如果不调用$函数,我的组件将无法挂载。所以我只是在jest.fn中使用beforeAll()模拟该功能。现在,我也知道我的实际组件中的jQuery函数是链接的。所以我知道我还需要考虑jQuery&#39; .on(),所以我确保返回一个带有on函数的对象。没有进一步的链接,所以我可以停下来。

如果我有一组更复杂的链式函数,我可以这样做:

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