Hi hackers,
Not quite sure if I am doing the right thing, but I am hitting this failed test:

Component:
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import ReactPlayer from 'react-player';
import Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton';
import DragIndicator from '@material-ui/icons/DragIndicator';
import Edit from '@material-ui/icons/Edit';
import Delete from '@material-ui/icons/Delete';
import CircularProgress from '@material-ui/core/CircularProgress';
import AWS from 'aws-sdk';
import styles from './VideoOutlineElement.style';
const credentials = {
accessKeyId: process.env.REACT_APP_ACCESS_KEY_ID,
secretAccessKey: process.env.REACT_APP_SECRET_ACCESS_KEY,
};
AWS.config.update({
credentials,
region: 'us-east-1',
});
const s3 = new AWS.S3();
const VideoOutlineElement = ({
title,
details,
videoSource,
}) => {
const classes = styles();
const [signedUrl, setSignedUrl] = useState('');
useEffect(() => {
const getSignedObject = async () => {
const signedRequest = await s3.getSignedUrl('getObject', {
Bucket: 'scb-video-source-development', // Alternative: `scb-video-source-${process.env.REACT_APP_STAGE}`
Key: videoSource.key,
});
setSignedUrl(signedRequest);
};
getSignedObject();
}, [videoSource]);
return (
<div>
<div className={classes.videoDescription}>
<div className={classes.dragIndicator}>
<IconButton
aria-label="Move Element"
className={classes.dragIndicatorIcon}
>
<DragIndicator />
</IconButton>
</div>
<div className={classes.subHeader}>
<Typography
variant="subtitle1"
className={classes.title}
>
{title}
</Typography>
</div>
<div className={classes.actions}>
<IconButton
aria-label="Edit Element"
className={classes.actionIcons}
>
<Delete />
</IconButton>
<IconButton
aria-label="Delete Element"
className={classes.actionIcons}
>
<Edit />
</IconButton>
</div>
</div>
<div
className={classes.videoPlayer}
>
{
signedUrl && (
<ReactPlayer
url={signedUrl}
controls
playing={false}
width="100wv"
height="100hv"
/>
)
}
{
!signedUrl && (<CircularProgress size={24} />)
}
</div>
<div>
<Typography
variant="subtitle2"
className={classes.details}
>
{details}
</Typography>
</div>
</div>
);
};
VideoOutlineElement.defaultProps = {
title: '',
details: '',
videoSource: {
url: '',
key: '',
contentType: '',
},
};
VideoOutlineElement.propTypes = {
title: PropTypes.string,
details: PropTypes.string,
videoSource: PropTypes.object,
};
export default VideoOutlineElement;
Test:
import React from 'react';
import { cleanup, render } from '@testing-library/react';
import { renderHook, act } from '@testing-library/react-hooks';
import VideoOutlineElement from './VideoOutlineElement.component';
afterEach(cleanup);
test('VideoOutlineElement - Simulate signedUrl response', () => {
const s3ObjectUrl = 'f4ba62f7-ee0d-4f2b-b97d-631be258ec21.mp4';
const props = {
title: 'test title',
details: 'test details',
videoSource: {
url: s3ObjectUrl,
key: s3ObjectUrl,
contentType: 'viceo/mp4',
},
};
const { result } = renderHook(() => VideoOutlineElement(props));
let [signedUrl, setSignedUrl] = result.current;
expect(signedUrl).toEqual('');
act(() => {
setSignedUrl(s3ObjectUrl);
});
[signedUrl, setSignedUrl] = result.current;
expect(signedUrl).toEqual(s3ObjectUrl);
});
It looks like your trying to test a component with renderHook? That not the scope of this library, which is centred around testing custom hooks.
You will probably have an easier time with testing-library/react and rendering the component.
I just got it working:
import React from 'react';
import { render, cleanup, act } from '@testing-library/react';
import VideoOutlineElement from './VideoOutlineElement.component';
afterEach(cleanup);
it('fetches and displays data', async () => {
const s3ObjectUrl = 'f4ba62f7-ee0d-4f2b-b97d-631be258ec21.mp4';
const props = {
title: 'test course',
details: 'test details',
videoSource: {
url: s3ObjectUrl,
key: s3ObjectUrl,
contentType: 'video/mp4',
},
};
await act(async () => {
render(<VideoOutlineElement {...props} />);
});
});
I'm going to close this as it seems to be unrelated to this library. I recommend heading of to @testing-library/react's Spectrum chat for support questions if you have anything furth on this.
For what it's worth, I think the await act(async () => { ... }); is unecessary in your test as I'm fairly sure @testing-library/react will automatically wrap a render call in act and you're not actually awaiting anything in the async callback so it's just returning immediately. There might be some intricacies I'm missing though, so please diregard if you know better.
I had the same issue, but the await act wrapping around my render did not help unfortunately. (act shouldn't be awaited actually, this causes another console error).
I also have a useEffect that calls an async function. This seems to be a problematic case for react-testing-library.
Most helpful comment
I just got it working:
https://reactjs.org/docs/test-utils.html#overview ^^^