Offer sync rendering for testing purposes
See original GitHub issueI’m trying to test my implementations of toasts, namely the rendering (using snapshots but this is not especially relevant). The problem is that if i call the toast function in my test then render the output the toasts are not present in the output. I believe this might be because the library is event driven and so async (though could be wrong). What i would like is access to an API that allows me to test the rendered output of the call to toast
synchronously. Because toast exports only a function (not React components) its not clear how this can be achieved with the library currently. Could you consider either a) documenting how this can be achieved with the existing API without hacks such as setTimeout
being required in tests, or b) update the API / library to provide some test utils for testing notification rendering synchronously?
Here is my test implementation. Note the snapshots are written using chai-jest-snapshot
Sync tests
// Test spec
it('correctly renders a success notification', () => {
class App extends Component {
notify = () => {
toast("Wow so easy !")
};
render(){
return (
<div>
{this.notify()}
<ToastContainer />
</div>
);
}
}
wrapper = mount(<App />);
expect(toJson(wrapper)).to.matchSnapshot();
});
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`correctly renders a success notification 1`] = `
<App>
<div>
<ToastContainer
autoClose={5000}
bodyClassName={null}
className={null}
closeButton={
<CloseButton
ariaLabel="close"
/>
}
closeOnClick={true}
draggable={true}
draggablePercent={80}
hideProgressBar={false}
newestOnTop={false}
pauseOnHover={true}
pauseOnVisibilityChange={true}
position="top-right"
progressClassName={null}
rtl={false}
style={null}
toastClassName={null}
transition={[Function]}
>
<div
className="Toastify"
/>
</ToastContainer>
</div>
</App>
`;
Async tests
// Test spec
it('correctly renders a success notification', () => {
class App extends Component {
notify = () => {
toast("Wow so easy !")
};
render(){
return (
<div>
{this.notify()}
<ToastContainer />
</div>
);
}
}
wrapper = mount(<App />);
// Note async - not feasible real-world solution
setTimeout(() => {
wrapper.update();
expect(toJson(wrapper)).to.matchSnapshot();
}, 5);
});
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`correctly renders a warning notification 1`] = `
<App>
<div>
<ToastContainer
autoClose={5000}
bodyClassName={null}
className={null}
closeButton={
<CloseButton
ariaLabel="close"
/>
}
closeOnClick={true}
draggable={true}
draggablePercent={80}
hideProgressBar={false}
newestOnTop={false}
pauseOnHover={true}
pauseOnVisibilityChange={true}
position="top-right"
progressClassName={null}
rtl={false}
style={null}
toastClassName={null}
transition={[Function]}
>
<div
className="Toastify"
>
<TransitionGroup
childFactory={[Function]}
className="Toastify__toast-container Toastify__toast-container--top-right"
component="div"
key="container-top-right"
style={Object {}}
>
<div
className="Toastify__toast-container Toastify__toast-container--top-right"
style={Object {}}
>
<Toast
autoClose={5000}
bodyClassName={null}
className={null}
closeButton={
<CloseButton
ariaLabel="close"
closeToast={[Function]}
type="default"
/>
}
closeOnClick={true}
closeToast={[Function]}
draggable={true}
draggablePercent={80}
hideProgressBar={false}
id={1}
in={true}
isDocumentHidden={false}
key=".$toast-1"
onClose={[Function]}
onExited={[Function]}
onOpen={[Function]}
pauseOnHover={true}
position="top-right"
progressClassName={null}
role="alert"
rtl={false}
transition={[Function]}
type="default"
updateId={null}
>
<Animation
appear={true}
in={true}
onExited={[Function]}
position="top-right"
preventExitTransition={false}
unmountOnExit={true}
>
<Transition
appear={true}
enter={true}
exit={true}
in={true}
mountOnEnter={false}
onEnter={[Function]}
onEntered={[Function]}
onEntering={[Function]}
onExit={[Function]}
onExited={[Function]}
onExiting={[Function]}
timeout={
Object {
"enter": 750,
"exit": 750,
}
}
unmountOnExit={true}
>
<div
className="Toastify__toast Toastify__toast--default"
onClick={[Function]}
onMouseDown={[Function]}
onMouseEnter={[Function]}
onMouseLeave={[Function]}
onTouchStart={[Function]}
onTransitionEnd={[Function]}
>
<div
className="Toastify__toast-body"
role="alert"
>
Wow so easy !
</div>
<CloseButton
ariaLabel="close"
closeToast={[Function]}
type="default"
>
<button
aria-label="close"
className="Toastify__close-button Toastify__close-button--default"
onClick={[Function]}
type="button"
>
✖
</button>
</CloseButton>
<ProgressBar
className={null}
closeToast={[Function]}
delay={5000}
hide={false}
isRunning={true}
rtl={false}
type="default"
>
<div
className="Toastify__progress-bar Toastify__progress-bar--default"
onAnimationEnd={[Function]}
style={
Object {
"animationDuration": "5000ms",
"animationPlayState": "running",
"opacity": 1,
}
}
/>
</ProgressBar>
</div>
</Transition>
</Animation>
</Toast>
</div>
</TransitionGroup>
</div>
</ToastContainer>
</div>
</App>
`;
Issue Analytics
- State:
- Created 5 years ago
- Comments:11 (5 by maintainers)
Top GitHub Comments
Hello, I’ve made a common component sort of thing for Rendering the toast. This is what it returns.
I’m trying to write test cases for the above snippet where I just run the method that triggers the Toast
e.g:- Toast() will trigger the above function.
I’m testing it using ReactTestUtils and jest .
The test that I have written is :
and when I try console log the tree.toJSON() this is what it returns
How do I test what is being rendered in the toast? Or what is the text that toast renders?
Indeed, the unmount should reset the id of the toast, at least this is what I plan to do 😁.
Also, notice that with the following implementation, your are calling
toast
before theToastContainer
is mounted(first route):In that case, when the container is not mounted the notification are stacked and rendered as soon as the container is mounted. This explain the inconsistency for your test regardless the toastId issue.