Skip to content

Commit

Permalink
feat(core): field handles v1 (#13)
Browse files Browse the repository at this point in the history
* feat(core): [wip] creating field descriptors

* feat: field-handle-schema creator draft

* feat(core): field-handle creator improved; hide implementation details

Co-authored-by: Viktoriya Bilovus <vbilovus@Vikas-MacBook-Pro-2.local>
Co-authored-by: Mikołaj Klaman <mklaman@virtuslab.com>
  • Loading branch information
3 people authored Oct 7, 2020
1 parent 76be30b commit 57c2a2d
Show file tree
Hide file tree
Showing 13 changed files with 318 additions and 175 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"@commitlint/config-conventional": "^11.0.0",
"@testing-library/react-hooks": "^3.4.2",
"@types/jest": "~26.0.14",
"@types/react": "^16.9.49",
"@types/react": "^16.9.50",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"add": "^2.0.6",
Expand Down
248 changes: 111 additions & 137 deletions src/core/hooks/use-formts/use-formts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,26 @@ import { createFormSchema } from "../../builders/create-form-schema";

import { useFormts } from "./use-formts";

describe("use-formts", () => {
describe("useFormts", () => {
const Schema = createFormSchema(fields => ({
theString: fields.string(),
theChoice: fields.choice("A", "B", "C"),
theNum: fields.number(),
theBool: fields.bool(),
theInstance: fields.instanceOf(Date),
theArray: fields.array(fields.string()),
theObject: fields.object({ foo: fields.string() }),
theObject: fields.object({
foo: fields.string(),
}),
theObjectArray: fields.object({ arr: fields.array(fields.string()) }),
}));

it("returns values initialized to defaults", () => {
it("returns form handle with values initialized to defaults", () => {
const hook = renderHook(() => useFormts({ Schema }));

expect(hook.result.current.values).toEqual({
const [, form] = hook.result.current;

expect(form.values).toEqual({
theString: "",
theChoice: "A",
theNum: "",
Expand All @@ -31,7 +35,7 @@ describe("use-formts", () => {
});
});

it("returns values initialized to defaults merged with custom initial values", () => {
it("returns form handle with values initialized to defaults merged with custom initial values", () => {
const hook = renderHook(() =>
useFormts({
Schema,
Expand All @@ -44,7 +48,9 @@ describe("use-formts", () => {
})
);

expect(hook.result.current.values).toEqual({
const [, form] = hook.result.current;

expect(form.values).toEqual({
theString: "",
theChoice: "C",
theNum: 42,
Expand All @@ -56,7 +62,7 @@ describe("use-formts", () => {
});
});

it("allows for getting values by corresponding FieldDescriptor", () => {
it("allows for getting values using corresponding field handles", () => {
const hook = renderHook(() =>
useFormts({
Schema,
Expand All @@ -69,157 +75,125 @@ describe("use-formts", () => {
})
);

const { getField } = hook.result.current;
expect(getField(Schema.theChoice)).toEqual("C");
expect(getField(Schema.theNum)).toEqual(42);
expect(getField(Schema.theArray.root)).toEqual([
"here",
"comes",
"the",
"sun",
]);
expect(getField(Schema.theArray.nth(42))).toEqual(undefined);
expect(getField(Schema.theObject.root)).toEqual({ foo: "bar" });
expect(getField(Schema.theObject.foo)).toEqual("bar");
expect(getField(Schema.theObjectArray.root)).toEqual({ arr: [] });
const [fields] = hook.result.current;

expect(fields.theChoice.value).toEqual("C");
expect(fields.theNum.value).toEqual(42);
expect(fields.theArray.value).toEqual(["here", "comes", "the", "sun"]);
expect(fields.theArray.children[42]?.value).toEqual(undefined);
expect(fields.theObject.value).toEqual({ foo: "bar" });
expect(fields.theObject.children.foo.value).toEqual("bar");
expect(fields.theObjectArray.value).toEqual({ arr: [] });
});

it("allows for setting values by corresponding FieldDescriptor", () => {
it("allows for setting values using corresponding field handles and keeps track of touched state", () => {
const hook = renderHook(() => useFormts({ Schema }));

expect(hook.result.current.values).toEqual({
theString: "",
theChoice: "A",
theNum: "",
theBool: false,
theInstance: null,
theArray: [],
theObject: { foo: "" },
theObjectArray: { arr: [] },
});

act(() => {
hook.result.current.setField(Schema.theNum, 42);
});
expect(hook.result.current.values).toEqual({
theString: "",
theChoice: "A",
theNum: 42,
theBool: false,
theInstance: null,
theArray: [],
theObject: { foo: "" },
theObjectArray: { arr: [] },
});
{
const [fields, form] = hook.result.current;
expect(form.values).toEqual({
theString: "",
theChoice: "A",
theNum: "",
theBool: false,
theInstance: null,
theArray: [],
theObject: { foo: "" },
theObjectArray: { arr: [] },
});
expect(fields.theString.isTouched).toBe(false);
expect(fields.theChoice.isTouched).toBe(false);
expect(fields.theNum.isTouched).toBe(false);
expect(fields.theBool.isTouched).toBe(false);
expect(fields.theInstance.isTouched).toBe(false);
expect(fields.theArray.isTouched).toBe(false);
expect(fields.theObject.isTouched).toBe(false);
expect(fields.theObject.children.foo.isTouched).toBe(false);
expect(fields.theObjectArray.isTouched).toBe(false);
expect(fields.theObjectArray.children.arr.isTouched).toBe(false);
}

act(() => {
hook.result.current.setField(Schema.theArray.root, [
"gumisie",
"teletubisie",
]);
});
expect(hook.result.current.values).toEqual({
theString: "",
theChoice: "A",
theNum: 42,
theBool: false,
theInstance: null,
theArray: ["gumisie", "teletubisie"],
theObject: { foo: "" },
theObjectArray: { arr: [] },
const [fields] = hook.result.current;
fields.theNum.setValue(42);
});

act(() => {
hook.result.current.setField(Schema.theObject.foo, "42");
});
expect(hook.result.current.values).toEqual({
theString: "",
theChoice: "A",
theNum: 42,
theBool: false,
theInstance: null,
theArray: ["gumisie", "teletubisie"],
theObject: { foo: "42" },
theObjectArray: { arr: [] },
});
{
const [fields, form] = hook.result.current;
expect(fields.theNum.value).toBe(42);
expect(fields.theNum.isTouched).toBe(true);
expect(form.values).toEqual({
theString: "",
theChoice: "A",
theNum: 42,
theBool: false,
theInstance: null,
theArray: [],
theObject: { foo: "" },
theObjectArray: { arr: [] },
});
}

act(() => {
hook.result.current.setField(Schema.theObjectArray.arr.nth(0), "hello");
const [fields] = hook.result.current;
fields.theArray.setValue(["gumisie", "teletubisie"]);
});
expect(hook.result.current.values).toEqual({
theString: "",
theChoice: "A",
theNum: 42,
theBool: false,
theInstance: null,
theArray: ["gumisie", "teletubisie"],
theObject: { foo: "42" },
theObjectArray: { arr: ["hello"] },
});
});

it("keeps track of fields touched state", () => {
const hook = renderHook(() => useFormts({ Schema }));

{
const { isTouched } = hook.result.current;
expect(isTouched(Schema.theString)).toBe(false);
expect(isTouched(Schema.theChoice)).toBe(false);
expect(isTouched(Schema.theNum)).toBe(false);
expect(isTouched(Schema.theBool)).toBe(false);
expect(isTouched(Schema.theInstance)).toBe(false);
expect(isTouched(Schema.theArray.root)).toBe(false);
expect(isTouched(Schema.theObject.root)).toBe(false);
expect(isTouched(Schema.theObject.foo)).toBe(false);
expect(isTouched(Schema.theObjectArray.root)).toBe(false);
expect(isTouched(Schema.theObjectArray.arr.root)).toBe(false);
}

{
act(() => {
hook.result.current.setField(Schema.theNum, 42);
const [fields, form] = hook.result.current;
expect(fields.theArray.value).toEqual(["gumisie", "teletubisie"]);
expect(fields.theArray.isTouched).toBe(true);
expect(fields.theArray.children[0]?.value).toBe("gumisie");
expect(fields.theArray.children[1]?.value).toBe("teletubisie");
expect(fields.theArray.children[2]?.value).toBe(undefined);
expect(fields.theArray.children[0]?.isTouched).toBe(true);
expect(fields.theArray.children[1]?.isTouched).toBe(true);
expect(fields.theArray.children[2]?.isTouched).toBe(undefined);
expect(form.values).toEqual({
theString: "",
theChoice: "A",
theNum: 42,
theBool: false,
theInstance: null,
theArray: ["gumisie", "teletubisie"],
theObject: { foo: "" },
theObjectArray: { arr: [] },
});
expect(hook.result.current.isTouched(Schema.theNum)).toBe(true);
}

{
act(() => {
hook.result.current.setField(Schema.theArray.root, [
"gumisie",
"teletubisie",
]);
});
const { isTouched } = hook.result.current;

expect(isTouched(Schema.theArray.root)).toBe(true);
expect(isTouched(Schema.theArray.nth(0))).toBe(true);
expect(isTouched(Schema.theArray.nth(1))).toBe(true);
expect(isTouched(Schema.theArray.nth(2))).toBe(false);
}
act(() => {
const [fields] = hook.result.current;
fields.theObject.children.foo.setValue("42");
});

{
act(() => {
hook.result.current.setField(Schema.theObject.foo, "42");
const [fields, form] = hook.result.current;
expect(fields.theObject.value).toEqual({ foo: "42" });
expect(fields.theObject.isTouched).toBe(true);
expect(fields.theObject.children.foo.value).toEqual("42");
expect(fields.theObject.children.foo.isTouched).toBe(true);
expect(form.values).toEqual({
theString: "",
theChoice: "A",
theNum: 42,
theBool: false,
theInstance: null,
theArray: ["gumisie", "teletubisie"],
theObject: { foo: "42" },
theObjectArray: { arr: [] },
});
const { isTouched } = hook.result.current;

expect(isTouched(Schema.theObject.foo)).toBe(true);
expect(isTouched(Schema.theObject.root)).toBe(true);
}
});

{
act(() => {
hook.result.current.setField(Schema.theObjectArray.root, {
arr: ["a", "b", "c"],
});
});
const { isTouched } = hook.result.current;
it("exposes options of choice fields", () => {
const hook = renderHook(() => useFormts({ Schema }));

expect(isTouched(Schema.theObjectArray.root)).toBe(true);
expect(isTouched(Schema.theObjectArray.arr.root)).toBe(true);
expect(isTouched(Schema.theObjectArray.arr.nth(0))).toBe(true);
expect(isTouched(Schema.theObjectArray.arr.nth(1))).toBe(true);
expect(isTouched(Schema.theObjectArray.arr.nth(2))).toBe(true);
}
const [fields] = hook.result.current;

expect(fields.theChoice.options).toEqual({
A: "A",
B: "B",
C: "C",
});
});
});
Loading

0 comments on commit 57c2a2d

Please sign in to comment.