【问题标题】:React component using jQuery without require - jest unit tests使用 jQuery 的 React 组件而不需要 - 开玩笑的单元测试
【发布时间】:2015-01-27 03:33:23
【问题描述】:

我有一个非常简单的 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

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

有什么办法可以告诉我的 react 组件 jQuery 已经存在于窗口中而不用担心它?

【问题讨论】:

  • 你试过var $ = window.jQuery吗?
  • 另一种方法是在browserify中使用external选项
  • @David - 在我的组件中使用external 似乎可以正常工作,但我无法让它玩得很好。现在我已经添加了一个检查 $ 在调用它之前定义。我不会把它作为答案,因为它不是问题的真正解决方案。它只是让我安全地通过我的笑话
  • 我也对这个问题的答案感兴趣,对我来说,它本身就是已经加载的 React。也许你的测试顶部的 global.React = require('react/addons') 会做......
  • 或者在你的情况下 global.$ = require('jquery') :)

标签: jquery reactjs jestjs reactjs-testutils


【解决方案1】:

就我而言,我对在我的组件中测试 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();
  });
});

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

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

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

【讨论】:

    【解决方案2】:

    我要做的是:

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

    我希望这对某人有帮助!

    更新:

    我已经开始在所有使用 jQuery 的 React 文件中使用import $ from 'jquery'。这消除了对 window.$ 是我期望的 jQuery 类型的依赖(我遇到了其他库与 window.$ 混淆的问题。起初,我担心到处导入 jQuery,因为我担心这会增加我的捆绑包大小。但是捆绑的工作方式,所有这些导入都指向一个单例,因此捆绑包大小不会增加。

    【讨论】:

      【解决方案3】:

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

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

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

      jest.dontMock('jquery')
      

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

      您还需要告诉 browserify jQuery 是外部的,结果将是您对 $ 的所有引用都已定义,jquery 库已加载以进行测试,但未包含在您的 browserify 包中。 (使用browserify-shim

      【讨论】:

      • 我们最终从我们的站点中删除了 jQuery,现在我们已经设置了完整的反应,因此不需要 DOM 操作。这看起来确实可以解决我们遇到的问题,并且由于它解决了您的问题,因此成为公认的答案是有意义的。谢谢!
      猜你喜欢
      • 2017-07-13
      • 1970-01-01
      • 2021-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-11
      • 2015-06-28
      • 2019-11-22
      相关资源
      最近更新 更多