Jest/Enzyme 图片加载回调未被 运行

Jest/Enzyme Image onload callback not being ran

我有一个 ImageLoader class 组件,我正在尝试测试是否正在调用 HTMLImageElement 上的 onload 函数。重要的是要注意 ImageLoader 按预期工作,我只是无法对 运行 进行测试。这是我的 class 组件的示例:

export default class ImageLoader extends React.Component {
  // Omitted for brevity

  setSrc = () => {
    const { src } = this.props;

    if (src) {
      this.tmpImg = new Image();

      // this.tmpImg.onload is never called
      this.tmpImg.onload = () => console.log('???');

      this.tmpImg.src = src;
    }
  }

  // Omitted for brevity
}

对于我的测试,我遗漏了我实际测试的内容,因为我从来没有真正进入 onload 事件(当测试 运行 时它不会 console.log除非我手动调用 this.tmpImg.onload()).

import { mount } from 'enzyme';
import ImageLoader from '../ImageLoader';

describe('ImageLoader', () => {
  it('renders', () => {
    const wrapper = mount(
      <ImageLoader src="A_URL_STRING" />,
    );

    // Omitted for brevity
  });
});

现在根据 this is issue jsdom has got rid of support for that, however towards the end a comment 说你可以通过正确的 Jest 设置来做到这一点。

我已将其添加到我的设置中,但仍然无法触发 onload 事件。

这是设置:

  "jest": {
    "testEnvironmentOptions": {
      "resources": "usable"
    }
  },

同样在 jsdom 存储库中,它讨论了加载子资源 here

更新

更让我抓狂的是我可以在 Code Sandbox here 中创建测试并且它通过了所有测试。

如果我下载它并 运行 在本地,我会得到一个 Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

需要注意的一件事是我将创建图像转移到承诺中,然后在调用 onload 时解决该承诺。

好的,感谢 Andrew 上面的评论,我明白了。

要在本地运行此功能,您必须在 package.json.

的 Jest 部分安装 canvas 软件包并设置 "testEnvironmentOptions": { "resources": "usable" },

如果由于某种原因你不能使用上面的包,你可以直接覆盖window.Image()。更改代码以使用 window.Image() 构造函数,然后以下将起作用:

ImageLoader:

export default class ImageLoader extends React.Component {

  setSrc = () => {
    const { src } = this.props;

    if (src) {
      this.tmpImg = new window.Image();

      this.tmpImg.onload = () => console.log('bimpson');

      this.tmpImg.src = src;
    }
  }

}

测试:

describe('ImageLoader', () => {
    const mockImage = {
        src: null,
        onload: () => {},
        onerror: () => {}
    };

    beforeEach(() => {
        window.Image = function() { return mockImage }
    });

    it("Loads a data url into an image element", (done) => {
        const wrapper = mount(
          <ImageLoader src="A_URL_STRING" />,
        );

        // Call onload or onerror to trigger the desired behaviour
        mockImage.onload();

        // Test for your expected behaviour after onload is called here
    });
});

显然它并不完美(每次都会加载),但如果您只是想测试您是否正确设置了回调,那么它可以正常工作。