Skip to content

Commit

Permalink
fix: apply custom validator on {isDragAccept,isDragReject}
Browse files Browse the repository at this point in the history
  • Loading branch information
Roland Groza authored and rolandjitsu committed May 2, 2022
1 parent 1b91e50 commit 2d33fdf
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 3 deletions.
6 changes: 4 additions & 2 deletions src/index.js
Expand Up @@ -258,9 +258,9 @@ Dropzone.propTypes = {
onError: PropTypes.func,

/**
* Custom validation function
* Custom validation function. It must return null if there's no errors.
* @param {File} file
* @returns {FileError|FileError[]}
* @returns {FileError|FileError[]|null}
*/
validator: PropTypes.func,
};
Expand Down Expand Up @@ -577,6 +577,7 @@ export function useDropzone(props = {}) {
maxSize,
multiple,
maxFiles,
validator,
});
const isDragReject = fileCount > 0 && !isDragAccept;

Expand Down Expand Up @@ -604,6 +605,7 @@ export function useDropzone(props = {}) {
maxSize,
multiple,
maxFiles,
validator,
]
);

Expand Down
28 changes: 28 additions & 0 deletions src/index.spec.js
Expand Up @@ -3441,6 +3441,34 @@ describe("useDropzone() hook", () => {
expect.anything()
);
});

it("sets {isDragAccept, isDragReject}", async () => {
const data = createDtWithFiles(images);
const validator = () => ({
code: "not-allowed",
message: "Cannot do this!",
});

const ui = (
<Dropzone validator={validator} multiple={true}>
{({ getRootProps, getInputProps, isDragAccept, isDragReject }) => (
<div {...getRootProps()}>
<input {...getInputProps()} />
{isDragAccept && "dragAccept"}
{isDragReject && "dragReject"}
</div>
)}
</Dropzone>
);

const { container } = render(ui);
const dropzone = container.querySelector("div");

await act(() => fireEvent.dragEnter(dropzone, data));

expect(dropzone).not.toHaveTextContent("dragAccept");
expect(dropzone).toHaveTextContent("dragReject");
});
});

describe("accessibility", () => {
Expand Down
26 changes: 25 additions & 1 deletion src/utils/index.js
Expand Up @@ -76,13 +76,26 @@ function isDefined(value) {
return value !== undefined && value !== null;
}

/**
*
* @param {object} options
* @param {File[]} options.files
* @param {string|string[]} [options.accept]
* @param {number} [options.minSize]
* @param {number} [options.maxSize]
* @param {boolean} [options.multiple]
* @param {number} [options.maxFiles]
* @param {(f: File) => FileError|FileError[]|null} [options.validator]
* @returns
*/
export function allFilesAccepted({
files,
accept,
minSize,
maxSize,
multiple,
maxFiles,
validator,
}) {
if (
(!multiple && files.length > 1) ||
Expand All @@ -94,7 +107,8 @@ export function allFilesAccepted({
return files.every((file) => {
const [accepted] = fileAccepted(file, accept);
const [sizeMatch] = fileMatchSize(file, minSize, maxSize);
return accepted && sizeMatch;
const customErrors = validator ? validator(file) : null;
return accepted && sizeMatch && !customErrors;
});
}

Expand Down Expand Up @@ -287,3 +301,13 @@ export function isExt(v) {
/**
* @typedef {Object.<string, string[]>} AcceptProp
*/

/**
* @typedef {object} FileError
* @property {string} message
* @property {ErrorCode|string} code
*/

/**
* @typedef {"file-invalid-type"|"file-too-large"|"file-too-small"|"too-many-files"} ErrorCode
*/
7 changes: 7 additions & 0 deletions src/utils/index.spec.js
Expand Up @@ -344,6 +344,13 @@ describe("allFilesAccepted()", () => {
expect(
utils.allFilesAccepted({ files, multiple: true, maxFiles: 1 })
).toEqual(false);

expect(
utils.allFilesAccepted({
files,
validator: () => ({ code: "not-allowed", message: "Cannot do this!" }),
})
).toEqual(false);
});
});

Expand Down

0 comments on commit 2d33fdf

Please sign in to comment.