Skip to content

Commit

Permalink
feat: dummy test
Browse files Browse the repository at this point in the history
  • Loading branch information
Viktoriya Bilovus authored and Viktoriya Bilovus committed Sep 29, 2020
1 parent 77e0c8c commit ef83d49
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 21 deletions.
148 changes: 148 additions & 0 deletions src/core/hooks/use-formts.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { assert, IsExact } from "conditional-type-checks";

import { createFormSchema } from "../builders/create-form-schema";

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

// dummy test for temporal implementation
describe("use-formts", () => {
const Schema = createFormSchema(fields => ({
theString: fields.string(),
theChoice: fields.choice("A", "B", "C"),
theNum: fields.number(),
theBool: fields.bool(),
theArrayString: fields.array(fields.string()),
theArrayChoice: fields.array(fields.choice("a", "b", "c")),
theArrayArrayString: fields.array(fields.array(fields.string())),
theInstance: fields.instanceOf(Date),
}));

const [fields, get, set] = useFormts({
Schema,
initialValues: {
theNum: 12,
theArrayArrayString: [["here"], ["comes", "the", "sun"]],
theArrayChoice: ["a"],
},
});

it("state is properly initialized", () => {
expect(fields.theString).toEqual("");
expect(fields.theChoice).toEqual("A");
expect(fields.theNum).toEqual(12);
expect(fields.theBool).toEqual(false);
expect(fields.theArrayString).toEqual([]);
expect(fields.theArrayChoice).toEqual(["a"]);
expect(fields.theArrayArrayString).toEqual([
["here"],
["comes", "the", "sun"],
]);
expect(fields.theInstance).toEqual(null);
});

it("get should work for non-arrays", () => {
expect(get(Schema.theString)).toEqual("");
expect(get(Schema.theChoice)).toEqual("A");
expect(get(Schema.theNum)).toEqual(12);
expect(get(Schema.theBool)).toEqual(false);
expect(get(Schema.theInstance)).toEqual(null);
});

it("get should work for one-element array", () => {
const root = get(Schema.theArrayChoice.root);
assert<IsExact<typeof root, ("a" | "b" | "c")[]>>(true);

const first = get(Schema.theArrayChoice.nth(0));
assert<IsExact<typeof first, "a" | "b" | "c">>(true);

expect(root).toEqual(["a"]);
expect(first).toEqual("a");
expect(get(Schema.theArrayChoice.nth(1))).toEqual(undefined);
});

it("get should work for no-element array", () => {
const root = get(Schema.theArrayString.root);
const first = get(Schema.theArrayString.nth(0));

expect(root).toEqual([]);
expect(first).toEqual(undefined);
});

it("get should work for 2D array", () => {
const root = get(Schema.theArrayArrayString.root);
const first = get(Schema.theArrayArrayString.nth(0).root);
const firstOfFirst = get(Schema.theArrayArrayString.nth(0).nth(0));

const second = get(Schema.theArrayArrayString.nth(1).root);
const secondOfSecond = get(Schema.theArrayArrayString.nth(1).nth(1));

const wrong = get(Schema.theArrayArrayString.nth(19).nth(10));

expect(root).toEqual([["here"], ["comes", "the", "sun"]]);
expect(first).toEqual(["here"]);
expect(firstOfFirst).toEqual("here");

expect(second).toEqual(["comes", "the", "sun"]);
expect(secondOfSecond).toEqual("the");

expect(wrong).toEqual(undefined);
});

it("set should work for string", () => {
const shape = set(Schema.theString, "set");

expect(shape.theString).toEqual("set");
expect(shape.theChoice).toEqual("A");
expect(shape.theNum).toEqual(12);
expect(shape.theBool).toEqual(false);
expect(shape.theArrayString).toEqual([]);
expect(shape.theArrayChoice).toEqual(["a"]);
expect(shape.theArrayArrayString).toEqual([
["here"],
["comes", "the", "sun"],
]);
expect(shape.theInstance).toEqual(null);
});

it("set should work for choice", () => {
// !TS will allow to pass any string here
const shape = set(Schema.theChoice, "C");

expect(shape.theString).toEqual("");
expect(shape.theChoice).toEqual("C");
expect(shape.theNum).toEqual(12);
expect(shape.theBool).toEqual(false);
expect(shape.theArrayString).toEqual([]);
expect(shape.theArrayChoice).toEqual(["a"]);
expect(shape.theArrayArrayString).toEqual([
["here"],
["comes", "the", "sun"],
]);
expect(shape.theInstance).toEqual(null);
});

it("set should work for array", () => {
const shape = set(Schema.theArrayChoice.root, ["b", "b"]);

expect(shape.theString).toEqual("");
expect(shape.theChoice).toEqual("A");
expect(shape.theNum).toEqual(12);
expect(shape.theBool).toEqual(false);
expect(shape.theArrayString).toEqual([]);
expect(shape.theArrayChoice).toEqual(["b", "b"]);
expect(shape.theArrayArrayString).toEqual([
["here"],
["comes", "the", "sun"],
]);
expect(shape.theInstance).toEqual(null);
});

it("set should work for array element", () => {
const shape = set(Schema.theArrayArrayString.nth(1).nth(1), "THE");

expect(shape.theArrayArrayString).toEqual([
["here"],
["comes", "THE", "sun"],
]);
});
});
23 changes: 11 additions & 12 deletions src/core/hooks/use-formts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,18 @@ export type FormtsOptions<Values extends object, Err> = {
initialValues?: DeepPartial<Values>;
};

/**
* Hook used to create form controller - should be used in main form component.
*
* @returns tuple containing:
* - `FieldHandleSchema` - tree of field handles used to interact with fields of the form
* - `FormHandle` - used to interact with the form as a whole rather than with individual fields
* - `FormtsProvider` - component enabling usage of `useField` hooks in nested components
*/
export const useFormts = <Values extends object, Err>(
options: FormtsOptions<Values, Err>
) => {
): [
Values,
<T, Err>(desc: FieldDescriptor<T, Err>) => T,
<T, Err>(desc: FieldDescriptor<T, Err>, value: T) => Values
] => {
const formState = createInitialState(options.Schema, options.initialValues);
return [formState, getter(formState), setter(formState)];
const get = getter(formState);
const set = setter(formState);

return [formState, get, set];
};

const getter = <Values extends object>(state: Values) => <T, Err>(
Expand All @@ -43,7 +42,7 @@ const getter = <Values extends object>(state: Values) => <T, Err>(

const setter = <Values extends object>(state: Values) => <T, Err>(
desc: FieldDescriptor<T, Err>,
value: T
): T => {
value: {} & T
): Values => {
return set(state, impl(desc).path, value) as any;
};
9 changes: 0 additions & 9 deletions src/utils/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,6 @@ export const entries = <T extends object>(o: T): [keyof T, T[keyof T]][] =>
export const keys = <T extends object>(o: T): (keyof T)[] =>
Object.keys(o) as (keyof T)[];

export const record = <T extends string | number | symbol, V>(
keys: T[],
value: V
): Record<T, V> =>
keys.reduce((acc, key) => {
acc[key] = value;
return acc;
}, {} as Record<T, V>);

// dummy impl
export const get = (o: object, path: string) => {
const pathSegments = getPathSegments(path);
Expand Down

0 comments on commit ef83d49

Please sign in to comment.