React + Jest - 测试 IMG 标签上的“错误”事件
React + Jest - testing `error` event on IMG tags
有什么方法可以触发 img
标签的 error
事件来测试我的 onError
回调吗?例如,给定这个组件,
import React from 'react';
/**
* Self removing <img> when the `src` or image
* does not load or is unavailable.
*
* Usage: (tip: it's how you use the <img> tag, basically)
* <Img src={} alt={} ../..>
*/
var Img = React.createClass({
/**
* Force update so `refs` will be available
*/
componentDidMount() {
this.forceUpdate();
},
render() {
// Omit any passed `onError` prop so that
// it is never overridden by mistake
var { onError, ...other } = this.props;
return (
<span ref="container">
<img {...other} onError={this._handleError} />
</span>
)
},
/**
* Remove itself when image is not found
*/
_handleError() {
this.refs.container.getDOMNode().remove();
}
});
export default Img;
和这个测试套件:
it('should remove itself when an error occurs while loading the image', function() {
// rendered = TestUtils.renderIntoDocument(<Img />);
});
我发现 React 的测试实用程序 (React.addons.TestUtils
) 非常有用,它提供了像 Simulate
(React.addons.TestUtils.Simulate
) 这样的实用程序。在这种情况下,Simulate
就可以了。
来自React's Documentation on Test Utilities:
Simulate an event dispatch on a DOM node with optional eventData event data. This is possibly the single most useful utility in ReactTestUtils.
it('should remove itself when an error occurs while loading the image', function() {
var rendered = TestUtils.renderIntoDocument(<Img />);
var img = TestUtils.findRenderedDOMComponentWithTag(rendered, 'img');
TestUtils.Simulate.error(img);
// In this case, we can try to find (again) the tag.
// `TestUtils.findRenderedDOMComponentWithTag` throws an error
// when the provided tag cannot be found.
expect(function() {
TestUtils.findRenderedDOMComponentWithTag(rendered, 'img');
}).toThrow();
});
不过以下可能是题外话。示例组件可以通过使用 state
s 来改进。
import React from 'react';
/**
* Self removing <img> when the `src` or image
* does not load or is unavailable.
*
* Usage: (tip: it's how you use the <img> tag, basically)
* <Img src={} alt={} ../..>
*/
var Img = React.createClass({
// We'll set `error` to false to load and display the image,
// only will it be true when an error occurs
getInitialState() {
return { error: false }
},
render() {
// Omit any passed `onError` prop so that
// it is never overridden by mistake
var { onError, ...other } = this.props;
return !this.state.error ? (
<span>
<img {...other} onError={this._handleError} />
</span>
) : null;
},
/**
* Set `state` error to true to remove the
* the dom nodes themselves
*/
_handleError() {
this.setState({ error: true });
}
});
export default Img;
然后使用以下测试套件:
it('should remove itself when an the image loads with an error', function() {
var rendered = TestUtils.renderIntoDocument(<Img />);
var img = TestUtils.findRenderedDOMComponentWithTag(rendered, 'img');
TestUtils.Simulate.error(img);
// When no results come out of `findRenderedDOMComponentWithTag`,
// it throws an error 'Did not find exactly one match for tag:img'
expect(function() {
TestUtils.findRenderedDOMComponentWithTag(rendered, 'img')
}).toThrow('Did not find exactly one match for tag:img');
expect(rendered.state.error).toBe(true);
});
使用 jest 和 react 测试库非常容易。
在实际代码中我们正在监听 onError 事件
const handleImgError = (e) => {
e.target.src = 'https://default-placehodler-image-path.svg';
};
<img
src='http://4040.jpg'
onError={handleImgError}
/>
在测试代码中
import { render, waitFor, fireEvent } from '@testing-library/react';
const { container } = render(<TestComponent />);
// get img element
const imgEl = container.querySelector('img');
// simulate error event on element
fireEvent.error(imgEl, {
target: imgEl,
});
// expect updated change on img element
await waitFor(() => {
expect(imgEl.src).toEqual(
'https://default-placehodler-image-path.svg'
);
});
有什么方法可以触发 img
标签的 error
事件来测试我的 onError
回调吗?例如,给定这个组件,
import React from 'react';
/**
* Self removing <img> when the `src` or image
* does not load or is unavailable.
*
* Usage: (tip: it's how you use the <img> tag, basically)
* <Img src={} alt={} ../..>
*/
var Img = React.createClass({
/**
* Force update so `refs` will be available
*/
componentDidMount() {
this.forceUpdate();
},
render() {
// Omit any passed `onError` prop so that
// it is never overridden by mistake
var { onError, ...other } = this.props;
return (
<span ref="container">
<img {...other} onError={this._handleError} />
</span>
)
},
/**
* Remove itself when image is not found
*/
_handleError() {
this.refs.container.getDOMNode().remove();
}
});
export default Img;
和这个测试套件:
it('should remove itself when an error occurs while loading the image', function() {
// rendered = TestUtils.renderIntoDocument(<Img />);
});
我发现 React 的测试实用程序 (React.addons.TestUtils
) 非常有用,它提供了像 Simulate
(React.addons.TestUtils.Simulate
) 这样的实用程序。在这种情况下,Simulate
就可以了。
来自React's Documentation on Test Utilities:
Simulate an event dispatch on a DOM node with optional eventData event data. This is possibly the single most useful utility in ReactTestUtils.
it('should remove itself when an error occurs while loading the image', function() {
var rendered = TestUtils.renderIntoDocument(<Img />);
var img = TestUtils.findRenderedDOMComponentWithTag(rendered, 'img');
TestUtils.Simulate.error(img);
// In this case, we can try to find (again) the tag.
// `TestUtils.findRenderedDOMComponentWithTag` throws an error
// when the provided tag cannot be found.
expect(function() {
TestUtils.findRenderedDOMComponentWithTag(rendered, 'img');
}).toThrow();
});
不过以下可能是题外话。示例组件可以通过使用 state
s 来改进。
import React from 'react';
/**
* Self removing <img> when the `src` or image
* does not load or is unavailable.
*
* Usage: (tip: it's how you use the <img> tag, basically)
* <Img src={} alt={} ../..>
*/
var Img = React.createClass({
// We'll set `error` to false to load and display the image,
// only will it be true when an error occurs
getInitialState() {
return { error: false }
},
render() {
// Omit any passed `onError` prop so that
// it is never overridden by mistake
var { onError, ...other } = this.props;
return !this.state.error ? (
<span>
<img {...other} onError={this._handleError} />
</span>
) : null;
},
/**
* Set `state` error to true to remove the
* the dom nodes themselves
*/
_handleError() {
this.setState({ error: true });
}
});
export default Img;
然后使用以下测试套件:
it('should remove itself when an the image loads with an error', function() {
var rendered = TestUtils.renderIntoDocument(<Img />);
var img = TestUtils.findRenderedDOMComponentWithTag(rendered, 'img');
TestUtils.Simulate.error(img);
// When no results come out of `findRenderedDOMComponentWithTag`,
// it throws an error 'Did not find exactly one match for tag:img'
expect(function() {
TestUtils.findRenderedDOMComponentWithTag(rendered, 'img')
}).toThrow('Did not find exactly one match for tag:img');
expect(rendered.state.error).toBe(true);
});
使用 jest 和 react 测试库非常容易。
在实际代码中我们正在监听 onError 事件
const handleImgError = (e) => {
e.target.src = 'https://default-placehodler-image-path.svg';
};
<img
src='http://4040.jpg'
onError={handleImgError}
/>
在测试代码中
import { render, waitFor, fireEvent } from '@testing-library/react';
const { container } = render(<TestComponent />);
// get img element
const imgEl = container.querySelector('img');
// simulate error event on element
fireEvent.error(imgEl, {
target: imgEl,
});
// expect updated change on img element
await waitFor(() => {
expect(imgEl.src).toEqual(
'https://default-placehodler-image-path.svg'
);
});