From 2771de88f40a5f4ed7480bd8614532dda72deeda Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Sat, 4 Nov 2023 19:26:16 +0100
Subject: refactor(components): rewrite CommentForm component

* remove `Notice` prop to handle it directly in the form
* replace `saveComment` prop with `onSubmit`
* use `useForm` hook to handle the form
---
 .../forms/comment-form/comment-form.test.tsx       | 164 +++++++++++++++++++--
 1 file changed, 149 insertions(+), 15 deletions(-)

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

diff --git a/src/components/organisms/forms/comment-form/comment-form.test.tsx b/src/components/organisms/forms/comment-form/comment-form.test.tsx
index 88a7de9..3578db9 100644
--- a/src/components/organisms/forms/comment-form/comment-form.test.tsx
+++ b/src/components/organisms/forms/comment-form/comment-form.test.tsx
@@ -1,24 +1,158 @@
 import { describe, expect, it } from '@jest/globals';
+import { userEvent } from '@testing-library/user-event';
 import { render, screen as rtlScreen } from '../../../../../tests/utils';
-import { CommentForm } from './comment-form';
-
-const saveComment = async () => {
-  /** Do nothing. */
-};
-const title = 'Cum voluptas voluptatibus';
+import { CommentForm, type CommentFormData } from './comment-form';
 
 describe('CommentForm', () => {
-  it('renders a form', () => {
-    render(<CommentForm saveComment={saveComment} />);
-    expect(rtlScreen.getByRole('form')).toBeInTheDocument();
-  });
+  const user = userEvent.setup();
 
-  it('renders an optional title', () => {
-    render(
-      <CommentForm saveComment={saveComment} title={title} titleLevel={2} />
-    );
+  it('renders the form fields with a submit button', () => {
+    const label = 'Comment form';
+    render(<CommentForm aria-label={label} />);
+
+    expect(rtlScreen.getByRole('form')).toHaveAccessibleName(label);
+    expect(
+      rtlScreen.getByRole('textbox', { name: /^Name:/ })
+    ).toBeInTheDocument();
+    expect(
+      rtlScreen.getByRole('textbox', { name: /^Email:/ })
+    ).toBeInTheDocument();
+    expect(
+      rtlScreen.getByRole('textbox', { name: /^Website:/ })
+    ).toBeInTheDocument();
+    expect(
+      rtlScreen.getByRole('textbox', { name: /^Comment:/ })
+    ).toBeInTheDocument();
     expect(
-      rtlScreen.getByRole('heading', { level: 2, name: title })
+      rtlScreen.getByRole('button', { name: /^Publish/ })
     ).toBeInTheDocument();
   });
+
+  /* eslint-disable max-statements */
+  it('can submit the form', async () => {
+    const onSubmit = jest.fn((_data: CommentFormData) => undefined);
+    const values = {
+      author: 'Brandon_West93',
+      comment: 'Ut aspernatur et aut et ab.',
+      email: 'Fannie_Connelly8@example.net',
+      website: 'https://example.com',
+    } satisfies CommentFormData;
+
+    render(<CommentForm 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.author
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Email:/ }),
+      values.email
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Website:/ }),
+      values.website
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Comment:/ }),
+      values.comment
+    );
+    await user.click(rtlScreen.getByRole('button', { name: /^Publish/ }));
+
+    expect(onSubmit).toHaveBeenCalledTimes(1);
+    expect(onSubmit).toHaveBeenCalledWith(values);
+  });
+  /* eslint-enable max-statements */
+
+  /* eslint-disable max-statements */
+  it('can submit and inform user on success', async () => {
+    const successMsg = 'Comment has been saved.';
+    const onSubmit = jest.fn((_data: CommentFormData) => {
+      return {
+        messages: { success: successMsg },
+        validator: () => true,
+      };
+    });
+    const values = {
+      author: 'Brandon_West93',
+      comment: 'Ut aspernatur et aut et ab.',
+      email: 'Fannie_Connelly8@example.net',
+      parentId: undefined,
+      website: '',
+    } satisfies CommentFormData;
+
+    render(<CommentForm 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.author
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Email:/ }),
+      values.email
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Comment:/ }),
+      values.comment
+    );
+    await user.click(rtlScreen.getByRole('button', { name: /^Publish/ }));
+
+    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 on error and inform user', async () => {
+    const errorMsg = 'Cannot save comment.';
+    const onSubmit = jest.fn((_data: CommentFormData) => {
+      return {
+        messages: { error: errorMsg },
+        validator: () => false,
+      };
+    });
+    const values = {
+      author: 'Brandon_West93',
+      comment: 'Ut aspernatur et aut et ab.',
+      email: 'Fannie_Connelly8@example.net',
+      parentId: undefined,
+      website: '',
+    } satisfies CommentFormData;
+
+    render(<CommentForm 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.author
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Email:/ }),
+      values.email
+    );
+    await user.type(
+      rtlScreen.getByRole('textbox', { name: /^Comment:/ }),
+      values.comment
+    );
+    await user.click(rtlScreen.getByRole('button', { name: /^Publish/ }));
+
+    expect(onSubmit).toHaveBeenCalledTimes(1);
+    expect(onSubmit).toHaveBeenCalledWith(values);
+    expect(rtlScreen.getByText(errorMsg)).toBeInTheDocument();
+  });
+  /* eslint-enable max-statements */
 });
-- 
cgit v1.2.3

