使用 jQuery react组件而不需要 - 开玩笑的单元测试

IT技术 jquery reactjs jestjs reactjs-testutils
2021-04-28 16:13:51

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

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

这是使用 browserify 作为一组新组件的一部分导入到主站点的。由于包含这些组件的主站点将始终包含 jQuery,我不想在 browserify 中使用 jQuery,因为它会被复制。

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

ReferenceError: $ is not defined

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

有什么办法可以开玩笑地告诉我的react组件 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

我要的是:

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

我希望这可以帮助别人!

更新:

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

就我而言,我对测试组件中的 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.fnin 来模拟这个函数beforeAll()现在,我也知道我的实际组件中的 jQuery 函数是链接的。所以我知道我还需要考虑 jQuery 的.on(),所以我确保返回一个带有on函数的对象没有进一步的链接,所以这就是我可以停止的地方。

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

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