diff --git a/src/components/Form/Form.stories.tsx b/src/components/Form/Form.stories.tsx index 6707f0b..74f8d33 100644 --- a/src/components/Form/Form.stories.tsx +++ b/src/components/Form/Form.stories.tsx @@ -527,6 +527,41 @@ export const WithDynamicInitialValues: StoryObj = { ] }; +export const WithResetButton: StoryObj = { + args: { + content: { + name: { + kind: 'string', + label: 'Name', + variant: 'input' + }, + contactMethod: { + kind: 'string', + label: 'Preferred Contact Method', + options: { + email: 'Email', + phone: 'Phone', + mail: 'Mail' + }, + variant: 'radio' + }, + comments: { + kind: 'string', + label: 'Comments', + variant: 'textarea' + } + }, + resetBtn: true, + onSubmit: (data) => { + alert(JSON.stringify(data, null, 2)); + }, + validationSchema: $SimpleExampleFormData.extend({ + contactMethod: z.enum(['email', 'phone', 'mail']).optional(), + comments: z.string().optional() + }) + } +}; + export const WithPreventReset: StoryObj> = { args: { content: { diff --git a/src/components/Form/Form.test.tsx b/src/components/Form/Form.test.tsx index 3b3beee..a2a6b33 100644 --- a/src/components/Form/Form.test.tsx +++ b/src/components/Form/Form.test.tsx @@ -235,4 +235,99 @@ describe('Form', () => { await waitFor(() => expect(onSubmit).toHaveBeenCalledOnce()); }); }); + describe('reset button', () => { + const renderForm = (props?: { preventResetValuesOnReset?: boolean; resetBtn?: boolean }) => { + render( +
+ ); + return screen.getByLabelText('Name'); + }; + + // The button is identified by its aria-label, so the query does not depend on the resolved + // translation for the visible text. + const getResetButton = () => screen.getByRole('button', { name: 'Reset' }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('should not render the reset button unless resetBtn is set', () => { + renderForm(); + expect(screen.queryByRole('button', { name: 'Reset' })).not.toBeInTheDocument(); + }); + + it('should render the reset button when resetBtn is set', () => { + renderForm({ resetBtn: true }); + expect(getResetButton()).toBeInTheDocument(); + }); + + it('should clear the values when the reset button is clicked', async () => { + const name = renderForm({ resetBtn: true }); + await userEvent.type(name, 'Winston'); + expect(name.value).toBe('Winston'); + await userEvent.click(getResetButton()); + expect(name.value).toBe(''); + }); + + it('should not submit the form when the reset button is clicked', async () => { + const name = renderForm({ resetBtn: true }); + await userEvent.type(name, 'Winston'); + await userEvent.click(getResetButton()); + expect(onSubmit).not.toHaveBeenCalled(); + }); + + it('should clear the errors when the reset button is clicked', async () => { + const name = renderForm({ resetBtn: true }); + await userEvent.type(name, 'ab'); + fireEvent.submit(screen.getByTestId(testid)); + await waitFor(() => + expect(screen.getAllByTestId('error-message-text').map((e) => e.innerHTML)).toMatchObject(['Too short']) + ); + await userEvent.click(getResetButton()); + expect(screen.queryAllByTestId('error-message-text')).toHaveLength(0); + }); + + it('should keep the values, but still clear the errors, when preventResetValuesOnReset is set', async () => { + const name = renderForm({ preventResetValuesOnReset: true, resetBtn: true }); + await userEvent.type(name, 'ab'); + fireEvent.submit(screen.getByTestId(testid)); + await waitFor(() => + expect(screen.getAllByTestId('error-message-text').map((e) => e.innerHTML)).toMatchObject(['Too short']) + ); + await userEvent.click(getResetButton()); + expect(screen.queryAllByTestId('error-message-text')).toHaveLength(0); + expect(name.value).toBe('ab'); + }); + + it('should clear the values after a successful submit, even without the reset button', async () => { + const name = renderForm(); + await userEvent.type(name, 'Winston'); + fireEvent.submit(screen.getByTestId(testid)); + await waitFor(() => expect(onSubmit).toHaveBeenCalledOnce()); + await waitFor(() => expect(name.value).toBe('')); + }); + + it('should keep the values after a successful submit when preventResetValuesOnReset is set', async () => { + const name = renderForm({ preventResetValuesOnReset: true }); + await userEvent.type(name, 'Winston'); + fireEvent.submit(screen.getByTestId(testid)); + await waitFor(() => expect(onSubmit).toHaveBeenCalledOnce()); + expect(name.value).toBe('Winston'); + }); + }); });