Skip to content

Commit

Permalink
improve [handleSubmit] to able to handle return value
Browse files Browse the repository at this point in the history
  • Loading branch information
hachibeeDI committed Feb 21, 2024
1 parent bcd4501 commit bf17c91
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 12 deletions.
66 changes: 65 additions & 1 deletion src/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,20 @@ test('zod parse value before submit', async () => {
} else {
expect('should not called').toBe(result.error);
}
return Promise.resolve('returns value');
});

const Top = () => {
return (
<div>
<AgeInputComponent controller={TestFormHook} />
<button data-testid="submit-button" onClick={handleSubmitTester} />
<button
data-testid="submit-button"
onClick={async (e) => {
const returnedValue = await handleSubmitTester(e);
expect(returnedValue).toBe('returns value');
}}
/>
</div>
);
};
Expand All @@ -123,6 +130,63 @@ test('zod parse value before submit', async () => {
});
});

test('able to handle parse error on submit', async () => {
const TestFormHook = createTestHook();

const INPUT_AGE = 'aaaa';
const EXPECTED_ISSUE = {
code: 'custom',
message: 'Invalid input',
path: ['age'],
};

const handleSubmitTester = TestFormHook.handleSubmit((e) => (result) => {
if (result.success) {
expect('should not succeed').toBe(false);
} else {
expect(result.success).toBe(false);
expect(result.error).toStrictEqual([EXPECTED_ISSUE]);
}
return Promise.resolve('returns value');
});

const Top = () => {
return (
<div>
<AgeInputComponent controller={TestFormHook} />
<button
data-testid="submit-button"
onClick={async (e) => {
const returnedValue = await handleSubmitTester(e);
expect(returnedValue).toBe('returns value');
}}
/>
</div>
);
};

render(<Top />);

const ageInput: HTMLInputElement = screen.getByTestId('age-input');
await userEvent.type(ageInput, INPUT_AGE);

await waitFor(() => {
const ageInput: HTMLInputElement = screen.getByTestId('age-input');
expect(ageInput.value).toBe(INPUT_AGE);
});

const submitButton = screen.getByTestId('submit-button');
await userEvent.click(submitButton);

await waitFor(() => {
console.log('waiting');
TestFormHook.api.actions.peek((s) => {
expect(s.value.age).toBe(INPUT_AGE);
expect(s.errors.age).toBe(EXPECTED_ISSUE.message);
});
});
});

test('User is able to re-initialize the form state', async () => {
const TestFormHook = createTestHook();

Expand Down
30 changes: 19 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,11 @@ export type Controller<State extends StateRestriction> = {
type FormHook<State extends StateRestriction, Schema extends ZodType<any, any, any>> = {
controller: Controller<State>;

handleSubmit: (
handleSubmit: <R>(
handler: (
e: BaseSyntheticEvent,
) => (
val: {success: true; data: zodInfer<Schema>; error: undefined} | {success: false; error: ReadonlyArray<ZodIssue>},
) => void | Promise<void>,
) => (e: BaseSyntheticEvent) => void;
) => (val: {success: true; data: zodInfer<Schema>; error: undefined} | {success: false; error: ReadonlyArray<ZodIssue>}) => R,
) => (e: BaseSyntheticEvent) => Promise<R>;

api: Subscriber<FullFormState<State>, FormControllerBehavior<State>>;
} & Controller<State>;
Expand All @@ -276,12 +274,10 @@ export function createFormHook<StateBeforeValidation extends StateRestriction, S
}, []);
},
useSelector: store.useSelector,
handleSubmit: (
handleSubmit: <R>(
handler: (
e: BaseSyntheticEvent,
) => (
val: {success: true; data: zodInfer<Schema>; error: undefined} | {success: false; error: ReadonlyArray<ZodIssue>},
) => void | Promise<void>,
) => (val: {success: true; data: zodInfer<Schema>; error: undefined} | {success: false; error: ReadonlyArray<ZodIssue>}) => R,
) => {
return (e: BaseSyntheticEvent) => {
const eventHandled = handler(e);
Expand All @@ -292,8 +288,20 @@ export function createFormHook<StateBeforeValidation extends StateRestriction, S
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return eventHandled({success: true, data: result.data, error: undefined});
}
void eventHandled({success: false, error: result.error.issues});
store.actions.handleIssues(result.error.issues);

const handled: any = eventHandled({success: false, error: result.error.issues});
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (typeof handled['then'] === 'function') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
return handled.then((x: any) => {
store.actions.handleIssues(result.error.issues);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return x;
}) as R;
} else {
store.actions.handleIssues(result.error.issues);
return handled as R;
}
});
};
},
Expand Down

0 comments on commit bf17c91

Please sign in to comment.