From ffb8edd164781ed66d60a90d7f7a2468040284e0 Mon Sep 17 00:00:00 2001 From: David Epely Date: Mon, 19 Dec 2022 12:51:53 +0100 Subject: [PATCH] try fix side effect on field level async validation --- src/Field.test.js | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/src/Field.test.js b/src/Field.test.js index afd0810..9ad7523 100644 --- a/src/Field.test.js +++ b/src/Field.test.js @@ -4,6 +4,7 @@ import "@testing-library/jest-dom/extend-expect"; import { ErrorBoundary, Toggle, wrapWith } from "./testUtils"; import Form from "./ReactFinalForm"; import Field from "./Field"; +import { useFormState } from "."; const onSubmitMock = (values) => {}; @@ -1161,6 +1162,159 @@ describe("Field", () => { expect(getByTestId("validating")).toHaveTextContent("Not Validating"); }); + it("should have validating state false after a field has been unregistred during mixed async validation", async () => { + const Test = () => { + const [hasField, setHasField] = React.useState(true); + const state = useFormState({ subscription: { validating: true } }); + + return ( +
+ {!hasField && ( + (value ? undefined : "Required")} + data-testid="lastname" + /> + )} + {hasField && ( + { + await timeout(5); + return value === "erikras" ? "Username taken" : undefined; + }} + data-testid="name" + /> + )} +
+ {state.validating === true ? "Spinner" : "Not Validating"} +
+ +
+ ); + }; + + const { getByTestId, queryByTestId } = render( +
+ {({ handleSubmit }) => ( + + + + )} + , + ); + + expect(getByTestId("validating")).toHaveTextContent("Spinner"); + await sleep(6); + expect(getByTestId("name").value).toBe(""); + + // validating state is ok as long as a Field with async validation is visible + expect(getByTestId("validating")).toHaveTextContent("Not Validating"); + fireEvent.change(getByTestId("name"), { target: { value: "erik" } }); + + expect(getByTestId("validating")).toHaveTextContent("Spinner"); + await sleep(6); + + expect(getByTestId("validating")).toHaveTextContent("Not Validating"); + + // validating state is KO if Field is unregistered while validating + fireEvent.change(getByTestId("name"), { target: { value: "erikr" } }); + + expect(getByTestId("validating")).toHaveTextContent("Spinner"); + fireEvent.click(getByTestId("hide")); + expect(queryByTestId("name")).not.toBeInTheDocument(); + + // when an other field with sync validation is present, it should not have side effect on the async validation + expect(queryByTestId("lastname")).toBeInTheDocument(); + expect(getByTestId("validating")).toHaveTextContent("Spinner"); + + await sleep(6); + + expect(getByTestId("validating")).toHaveTextContent("Not Validating"); + }); + + it("should have validating state false after a field has been unregistred during full async validation", async () => { + const Test = () => { + const [hasField, setHasField] = React.useState(true); + const state = useFormState({ subscription: { validating: true } }); + + return ( +
+ {!hasField && ( + { + await timeout(5); + return value ? undefined : "Required"; + }} + data-testid="lastname" + /> + )} + {hasField && ( + { + await timeout(5); + return value === "erikras" ? "Username taken" : undefined; + }} + data-testid="name" + /> + )} +
+ {state.validating === true ? "Spinner" : "Not Validating"} +
+ +
+ ); + }; + + const { getByTestId, queryByTestId } = render( +
+ {({ handleSubmit }) => ( + + + + )} + , + ); + + expect(getByTestId("validating")).toHaveTextContent("Spinner"); + await sleep(6); + expect(getByTestId("name").value).toBe(""); + + // validating state is ok as long as a Field with async validation is visible + expect(getByTestId("validating")).toHaveTextContent("Not Validating"); + fireEvent.change(getByTestId("name"), { target: { value: "erik" } }); + + expect(getByTestId("validating")).toHaveTextContent("Spinner"); + await sleep(6); + + expect(getByTestId("validating")).toHaveTextContent("Not Validating"); + + // validating state is KO if Field is unregistered while validating + fireEvent.change(getByTestId("name"), { target: { value: "erikr" } }); + + expect(getByTestId("validating")).toHaveTextContent("Spinner"); + fireEvent.click(getByTestId("hide")); + expect(queryByTestId("name")).not.toBeInTheDocument(); + + // when an other field with sync validation is present, it should not have side effect on the async validation + expect(queryByTestId("lastname")).toBeInTheDocument(); + expect(getByTestId("validating")).toHaveTextContent("Spinner"); + + await sleep(6); + + expect(getByTestId("validating")).toHaveTextContent("Not Validating"); + }); + it("not call record-level validation on Field mount", () => { const validate = jest.fn(); const { getByText } = render(