reakit
Version:
Toolkit for building accessible rich web apps with React
245 lines (229 loc) • 6.92 kB
text/typescript
/* eslint-disable no-console */
import * as React from "react";
import { renderHook, act } from "reakit-test-utils/hooks";
import { jestSerializerStripFunctions } from "reakit-test-utils/jestSerializerStripFunctions";
import { unstable_useFormState } from "../FormState";
expect.addSnapshotSerializer(jestSerializerStripFunctions);
test("initial state", () => {
const { result } = renderHook(() =>
unstable_useFormState({ baseId: "base" })
);
expect(result.current).toMatchInlineSnapshot(`
Object {
"baseId": "base",
"errors": Object {},
"messages": Object {},
"submitFailed": 0,
"submitSucceed": 0,
"submitting": false,
"touched": Object {},
"unstable_idCountRef": Object {
"current": 0,
},
"valid": true,
"validating": false,
"values": Object {},
}
`);
});
test("initial state values", () => {
const { result } = renderHook(() =>
unstable_useFormState({
baseId: "base",
values: { a: "a", b: { c: ["d", "e"] } },
})
);
expect(result.current).toMatchInlineSnapshot(`
Object {
"baseId": "base",
"errors": Object {},
"messages": Object {},
"submitFailed": 0,
"submitSucceed": 0,
"submitting": false,
"touched": Object {},
"unstable_idCountRef": Object {
"current": 0,
},
"valid": true,
"validating": false,
"values": Object {
"a": "a",
"b": Object {
"c": Array [
"d",
"e",
],
},
},
}
`);
});
test("update", () => {
const { result } = renderHook(() =>
unstable_useFormState({
values: { a: "a", b: { c: ["d", "e"] } },
})
);
expect(result.current.values.a).toBe("a");
act(() => result.current.update("a", "b"));
expect(result.current.values.a).toBe("b");
expect(result.current.values.b.c).toEqual(["d", "e"]);
act(() => result.current.update(["b", "c", 1] as const, "f"));
expect(result.current.values.b.c).toEqual(["d", "f"]);
});
test("update with function", () => {
const { result } = renderHook(() =>
unstable_useFormState({
values: { a: "a", b: { c: ["d", "e"] } },
})
);
expect(result.current.values.a).toBe("a");
act(() => result.current.update("a", (v) => `${v}b`));
expect(result.current.values.a).toBe("ab");
expect(result.current.values.b.c).toEqual(["d", "e"]);
act(() => result.current.update(["b", "c", 1] as const, (v) => `${v}f`));
expect(result.current.values.b.c).toEqual(["d", "ef"]);
});
test("update undefined", () => {
type Values = {
a?: string;
};
const { result } = renderHook(() =>
unstable_useFormState<Values>({
values: { a: "a" },
})
);
expect(result.current.values.a).toBe("a");
act(() => result.current.update("a", undefined));
expect(result.current.values.a).toBe("");
});
test("validate", async () => {
const { result } = renderHook(() =>
unstable_useFormState({
values: { a: "a" },
onValidate: (values) => {
if (values.a === "a") {
const error = { a: "error" };
throw error;
}
},
})
);
await act(() =>
// @ts-ignore https://github.com/DefinitelyTyped/DefinitelyTyped/pull/37426#discussion_r312717670
expect(result.current.validate()).rejects.toEqual({ a: "error" })
);
});
test("validate with updating onValidate", async () => {
jest.useFakeTimers();
const { result } = renderHook(() => {
const [message, setMessage] = React.useState("");
React.useEffect(() => {
setTimeout(() => act(() => setMessage("error")), 1000);
}, []);
return unstable_useFormState({
values: { a: "a" },
onValidate: (values) => {
if (values.a === "a") {
const error = { a: message };
throw error;
}
},
});
});
// @ts-ignore
await act(() => expect(result.current.validate()).rejects.toEqual({ a: "" }));
jest.advanceTimersByTime(1000);
await act(() =>
// @ts-ignore
expect(result.current.validate()).rejects.toEqual({ a: "error" })
);
jest.useRealTimers();
});
test("submit", async () => {
const { result } = renderHook(() =>
unstable_useFormState({
values: { a: "a" },
onSubmit: (values) => {
if (values.a === "a") {
const error = { a: "error" };
throw error;
}
},
})
);
await act(result.current.submit);
expect(result.current.errors).toEqual({ a: "error" });
});
test("submit with resetOnSubmitSucceed", async () => {
const { result } = renderHook(() =>
unstable_useFormState({
values: { a: "a" },
resetOnSubmitSucceed: true,
})
);
expect(result.current.values.a).toBe("a");
act(() => result.current.update("a", "b"));
expect(result.current.values.a).toBe("b");
await act(result.current.submit);
expect(result.current.values.a).toBe("a");
});
test("submit with updating onSubmit", async () => {
jest.useFakeTimers();
const { result } = renderHook(() => {
const [message, setMessage] = React.useState("");
React.useEffect(() => {
setTimeout(() => act(() => setMessage("error")), 1000);
}, []);
return unstable_useFormState({
values: { a: "a" },
onSubmit: (values) => {
if (values.a === "a") {
const error = { a: message };
throw error;
}
},
});
});
await act(result.current.submit);
expect(result.current.errors).toEqual({ a: "" });
jest.advanceTimersByTime(1000);
await act(result.current.submit);
expect(result.current.errors).toEqual({ a: "error" });
jest.useRealTimers();
});
test("blur", () => {
const { result } = renderHook(() =>
unstable_useFormState({ values: { a: "a", b: { c: ["d", "e"] } } })
);
expect(result.current.touched).toEqual({});
act(() => result.current.blur("a"));
expect(result.current.touched).toEqual({ a: true });
act(() => result.current.blur(["b", "c", 1] as const));
expect(result.current.touched).toEqual({ a: true, b: { c: [true] } });
});
test("push", () => {
const { result } = renderHook(() =>
unstable_useFormState({ values: { a: "a", b: { c: ["d", "e"] } } })
);
act(() => result.current.push(["b", "c"], "f"));
expect(result.current.values.b.c).toEqual(["d", "e", "f"]);
});
test("remove", () => {
const { result } = renderHook(() =>
unstable_useFormState({ values: { a: "a", b: { c: ["d", "e"] } } })
);
act(() => result.current.remove(["b", "c"], 0));
expect(result.current.values.b.c).toEqual([undefined, "e"]);
});
test("reset", () => {
const { result } = renderHook(() =>
unstable_useFormState({ values: { a: "a" } })
);
expect(result.current.values.a).toBe("a");
act(() => result.current.update("a", "b"));
expect(result.current.values.a).toBe("b");
act(result.current.reset);
expect(result.current.values.a).toBe("a");
});