I have the following react code in my project
import React from 'react';
import { Upload } from 'antd';
const { Dragger } = Upload;
...
<Dragger
accept={ACCEPTED_FORMATS}
beforeUpload={beforeUpload}
data-testid="upload-dragger"
maxCount={1}
onChange={({ file: { status } }) => {
if (status === 'done') onUploadComplete();
}}
progress={progress}
showUploadList={false}
>
{/* here i have a button, code ommited for clarity, if needed i'll post it */}
</Dragger>
And I want to test if the callback function onUploadComplete()
was called when file.status is 'done'
.
Here is how i am doing the test right now:
- I have a jest.mock to simulate a dumb request that will always succeed
import React from 'react';
import { fireEvent, render, waitFor } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { DraggerProps } from 'antd/lib/upload';
import userEvent from '@testing-library/user-event';
import UploadCompanyLogo from '../UploadCompanyLogo'; // This is the component where the dragger is placed
jest.mock('antd', () => {
const antd = jest.requireActual('antd');
const { Upload } = antd;
const { Dragger } = Upload;
const MockedDragger = (props: DraggerProps) => {
console.log('log test');
return (
<Dragger
{...props}
action="greetings"
customRequest={({ onSuccess }) => {
setTimeout(() => {
onSuccess('ok');
}, 0);
}}
/>
);
};
return { ...antd, Upload: { ...Upload, Dragger: MockedDragger } };
});
- The test itself (same file as the mock), where it renders the component (where
antd
will be imported), simulate an upload and then checks if the callback has been called.
it('completes the image upload', async () => {
const flushPromises = () => new Promise(setImmediate);
const { getByTestId } = render(elementRenderer({ onUploadComplete }));
const file = new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' });
const uploadDragger = await waitFor(() => getByTestId('upload-dragger'));
await act(async () => {
userEvent.upload(uploadDragger, file);
});
await flushPromises();
expect(onUploadComplete).toHaveBeenCalledTimes(1);
expect(onUploadComplete).toHaveBeenCalledWith();
});
- elementRenderer
const elementRenderer = ({
onUploadComplete = () => {}
}) => (
<ApplicationProvider>
<UploadCompanyLogo
onUploadComplete={onUploadComplete}
/>
</ApplicationProvider>
);
- ApplicationProvider
import React, { PropsWithChildren } from 'react';
import { ConfigProvider as AntdProvider } from 'antd';
import { RendererProvider as FelaProvider } from 'react-fela';
import { createRenderer } from 'fela';
import { I18nextProvider } from 'react-i18next';
import antdExternalContainer, {
EXTERNAL_CONTAINER_ID,
} from 'src/util/antdExternalContainer';
import { antdLocale } from 'src/util/locales';
import rendererConfig from 'src/fela/felaConfig';
import i18n from 'src/i18n';
const ApplicationProvider = (props: PropsWithChildren<{}>) => {
const { children } = props;
return (
<AntdProvider locale={antdLocale} getPopupContainer={antdExternalContainer}>
<FelaProvider renderer={createRenderer(rendererConfig)}>
<I18nextProvider i18n={i18n}>
<div className="antd-local">
<div id={EXTERNAL_CONTAINER_ID} />
{children}
</div>
</I18nextProvider>
</FelaProvider>
</AntdProvider>
);
};
export default ApplicationProvider;
This is currently not working, but have already been improved with the help of @diedu.
The console.log()
I have put in the MockedDragger it's currently not showing. If I put a console.log()
in both component and mockedDragger, it prints the component log.
Any tips on how to proceed? I have already seen this issue and didn’t help.