From c4a561c333f6f82678efcffef5ce3ed0f8e322f4 Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Sat, 4 Nov 2023 17:14:25 +0100
Subject: refactor(components): rewrite ContactForm component

* remove `Notice` props to handle it directly inside the form
* replace `sendMail` prop with `onSubmit` prop
* use `useForm` hook to handle fields
---
 .../forms/contact-form/contact-form.test.tsx       | 173 +++++++++++++++++----
 1 file changed, 142 insertions(+), 31 deletions(-)

(limited to 'src/components/organisms/forms/contact-form/contact-form.test.tsx')

diff --git a/src/components/organisms/forms/contact-form/contact-form.test.tsx b/src/components/organisms/forms/contact-form/contact-form.test.tsx
index 0e2685e..b68146f 100644
--- a/src/components/organisms/forms/contact-form/contact-form.test.tsx
+++ b/src/components/organisms/forms/contact-form/contact-form.test.tsx
@@ -1,53 +1,164 @@
 import { describe, expect, it } from '@jest/globals';
+import { userEvent } from '@testing-library/user-event';
 import { render, screen as rtlScreen } from '../../../../../tests/utils';
-import { ContactForm } from './contact-form';
-
-const props = {
-  sendMail: async () => {
-    /** Do nothing. */
-  },
-};
+import { ContactForm, type ContactFormData } from './contact-form';
 
 describe('ContactForm', () => {
-  it('renders a contact form', () => {
-    render(<ContactForm {...props} />);
-    expect(
-      rtlScreen.getByRole('form', { name: 'Contact form' })
-    ).toBeInTheDocument();
-  });
+  const user = userEvent.setup();
+
+  it('renders the form fields with a submit button', () => {
+    const label = 'Contact form';
+    render(<ContactForm aria-label={label} />);
 
-  it('renders a name field', () => {
-    render(<ContactForm {...props} />);
+    expect(rtlScreen.getByRole('form')).toHaveAccessibleName(label);
     expect(
       rtlScreen.getByRole('textbox', { name: /^Name:/ })
     ).toBeInTheDocument();
-  });
-
-  it('renders an email field', () => {
-    render(<ContactForm {...props} />);
     expect(
       rtlScreen.getByRole('textbox', { name: /^Email:/ })
     ).toBeInTheDocument();
-  });
-
-  it('renders an object field', () => {
-    render(<ContactForm {...props} />);
     expect(
       rtlScreen.getByRole('textbox', { name: /^Object:/ })
     ).toBeInTheDocument();
-  });
-
-  it('renders a message field', () => {
-    render(<ContactForm {...props} />);
     expect(
       rtlScreen.getByRole('textbox', { name: /^Message:/ })
     ).toBeInTheDocument();
-  });
-
-  it('renders a submit button', () => {
-    render(<ContactForm {...props} />);
     expect(
       rtlScreen.getByRole('button', { name: /^Send/ })
     ).toBeInTheDocument();
   });
+
+  /* eslint-disable max-statements */
+  it('can submit the form', async () => {
+    const onSubmit = jest.fn((_data: ContactFormData) => undefined);
+    const values: ContactFormData = {
+      email: 'Camryn.Hegmann23@gmail.com',
+      message: 'Nulla eveniet tempora aliquid.',
+      name: 'Erick82',
+      object: 'sequi nobis unde',
+    };
+
+    render(<ContactForm onSubmit={onSubmit} />);
+
+    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+    expect.assertions(3);
+
+    expect(onSubmit).not.toHaveBeenCalled();
+
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Name:/ }),
+      values.name
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Email:/ }),
+      values.email
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Object:/ }),
+      values.object
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Message:/ }),
+      values.message
+    );
+    await user.click(rtlScreen.getByRole('button', { name: /^Send/ }));
+
+    expect(onSubmit).toHaveBeenCalledTimes(1);
+    expect(onSubmit).toHaveBeenCalledWith(values);
+  });
+  /* eslint-enable max-statements */
+
+  /* eslint-disable max-statements */
+  it('can submit the form and inform user on success', async () => {
+    const successMsg = 'Mail has been sent.';
+    const onSubmit = jest.fn((_data: ContactFormData) => {
+      return {
+        messages: { success: successMsg },
+        validator: () => true,
+      };
+    });
+    const values: ContactFormData = {
+      email: 'Camryn.Hegmann23@gmail.com',
+      message: 'Nulla eveniet tempora aliquid.',
+      name: 'Erick82',
+      object: 'sequi nobis unde',
+    };
+
+    render(<ContactForm onSubmit={onSubmit} />);
+
+    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+    expect.assertions(4);
+
+    expect(onSubmit).not.toHaveBeenCalled();
+
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Name:/ }),
+      values.name
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Email:/ }),
+      values.email
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Object:/ }),
+      values.object
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Message:/ }),
+      values.message
+    );
+    await user.click(rtlScreen.getByRole('button', { name: /^Send/ }));
+
+    expect(onSubmit).toHaveBeenCalledTimes(1);
+    expect(onSubmit).toHaveBeenCalledWith(values);
+    expect(rtlScreen.getByText(successMsg)).toBeInTheDocument();
+  });
+  /* eslint-enable max-statements */
+
+  /* eslint-disable max-statements */
+  it('can abort submit and inform user on failure', async () => {
+    const errorMsg = 'An error occurred.';
+    const onSubmit = jest.fn((_data: ContactFormData) => {
+      return {
+        messages: { error: errorMsg },
+        validator: () => false,
+      };
+    });
+    const values: ContactFormData = {
+      email: 'Camryn.Hegmann23@gmail.com',
+      message: 'Nulla eveniet tempora aliquid.',
+      name: 'Erick82',
+      object: 'sequi nobis unde',
+    };
+
+    render(<ContactForm onSubmit={onSubmit} />);
+
+    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
+    expect.assertions(4);
+
+    expect(onSubmit).not.toHaveBeenCalled();
+
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Name:/ }),
+      values.name
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Email:/ }),
+      values.email
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Object:/ }),
+      values.object
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Message:/ }),
+      values.message
+    );
+    await user.click(rtlScreen.getByRole('button', { name: /^Send/ }));
+
+    expect(onSubmit).toHaveBeenCalledTimes(1);
+    expect(onSubmit).toHaveBeenCalledWith(values);
+    expect(rtlScreen.getByText(errorMsg)).toBeInTheDocument();
+  });
+  /* eslint-enable max-statements */
 });
-- 
cgit v1.2.3

