I want to test onDrop method from react-dropzone library in React component. I am using Jest, React Testing Library. I'm creating mock file and I'm trying to drop this files in input, but in console.log files are still equal to an empty array. Do you have any ideas?
package.json
"typescript": "^3.9.7",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.0.4",
"@types/jest": "^26.0.13",
"jest": "^26.4.2",
"ts-jest": "^26.3.0",
"react-router-dom": "^5.1.2",
"react-dropzone": "^10.1.10",
"@types/react-dropzone": "4.2.0",
ModalImportFile.tsx
import React, { FC, useState } from "react";
import { Box, Button, Dialog, DialogContent, DialogTitle, Grid } from "@material-ui/core";
import { useDropzone } from "react-dropzone";
import AttachFileIcon from "@material-ui/icons/AttachFile";
import DeleteIcon from "@material-ui/icons/Delete";
interface Props {
isOpen: boolean;
}
interface Events {
onClose: () => void;
}
const ModalImportFile: FC<Props & Events> = props => {
const { isOpen } = props as Props;
const { onClose } = props as Events;
const [files, setFiles] = useState<Array<File>>([]);
const { getRootProps, getInputProps, open } = useDropzone({
onDrop: (acceptedFiles: []) => {
setFiles(
acceptedFiles.map((file: File) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
}),
),
);
},
noClick: true,
noKeyboard: true,
});
const getDragZoneContent = () => {
if (files && files.length > 0)
return (
<Box border={1} borderRadius={5} borderColor={"#cecece"} p={2} mb={2}>
<Grid container alignItems="center" justify="space-between">
<Box color="text.primary">{files[0].name}</Box>
<Box ml={1} color="text.secondary">
<Button
startIcon={<DeleteIcon color="error" />}
onClick={() => {
setFiles([]);
}}
/>
</Box>
</Grid>
</Box>
);
return (
<Box border={1} borderRadius={5} borderColor={"#cecece"} p={2} mb={2} style={{ borderStyle: "dashed" }}>
<Grid container alignItems="center">
<Box mr={1} color="text.secondary">
<AttachFileIcon />
</Box>
<Box color="text.secondary">
<Box onClick={open} component="span" marginLeft="5px">
Download
</Box>
</Box>
</Grid>
</Box>
);
};
const closeHandler = () => {
onClose();
setFiles([]);
};
return (
<Dialog open={isOpen} onClose={closeHandler}>
<Box width={520}>
<DialogTitle>Import</DialogTitle>
<DialogContent>
<div data-testid="container" className="container">
<div data-testid="dropzone" {...getRootProps({ className: "dropzone" })}>
<input data-testid="drop-input" {...getInputProps()} />
{getDragZoneContent()}
</div>
</div>
</DialogContent>
</Box>
</Dialog>
);
};
export default ModalImportFile;
ModalImportFile.test.tsx
import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import ModalImportFile from "../../components/task/elements/ModalImportFile";
const props = {
isOpen: true,
onClose: jest.fn(),
};
beforeEach(() => jest.clearAllMocks());
describe("<ModalImportFile/>", () => {
it("should drop", async () => {
render(<ModalImportFile {...props} />);
const file = new File([JSON.stringify({ ping: true })], "ping.json", { type: "application/json" });
const data = mockData([file]);
function dispatchEvt(node: any, type: any, data: any) {
const event = new Event(type, { bubbles: true });
Object.assign(event, data);
fireEvent(node, event);
}
function mockData(files: Array<File>) {
return {
dataTransfer: {
files,
items: files.map(file => ({
kind: "file",
type: file.type,
getAsFile: () => file,
})),
types: ["Files"],
},
};
}
const inputEl = screen.getByTestId("drop-input");
dispatchEvt(inputEl, "dragenter", data);
});
}
With the rokki`s answer (https://stackoverflow.com/a/64643985/9405587), I rewrote the test component for easier understanding.
ModalImportFile.test.tsx
import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import ModalImportFile from "../../components/task/elements/ModalImportFile";
const props = {
isOpen: true,
onClose: jest.fn(),
};
beforeEach(() => jest.clearAllMocks());
describe("<ModalImportFile/>", () => {
it("should drop", async () => {
render(<ModalImportFile {...props} />);
window.URL.createObjectURL = jest.fn().mockImplementation(() => "url");
const inputEl = screen.getByTestId("drop-input");
const file = new File(["file"], "ping.json", {
type: "application/json",
});
Object.defineProperty(inputEl, "files", {
value: [file],
});
fireEvent.drop(inputEl);
expect(await screen.findByText("ping.json")).toBeInTheDocument();
}
How about changing fireEvent(node, event);
to fireEvent.drop(node, event);
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With