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
});
});
显然它并不完美(每次都会加载),但如果您只是想测试您是否正确设置了回调,那么它可以正常工作。
我有一个 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
.
"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
});
});
显然它并不完美(每次都会加载),但如果您只是想测试您是否正确设置了回调,那么它可以正常工作。