From f8b6f8db2829e8cdc56f4134de4e246739553d8c Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 6 Apr 2022 10:10:21 -0400 Subject: [PATCH 1/5] Add tests for Search --- ...moji-test.js => autosuggest_emoji.test.js} | 0 app/soapbox/components/account.tsx | 2 +- app/soapbox/components/autosuggest_input.js | 1 + .../components/__tests__/search.test.tsx | 28 +++++++++++++++++++ app/soapbox/jest/test-setup.ts | 3 ++ 5 files changed, 33 insertions(+), 1 deletion(-) rename app/soapbox/components/__tests__/{autosuggest_emoji-test.js => autosuggest_emoji.test.js} (100%) create mode 100644 app/soapbox/features/compose/components/__tests__/search.test.tsx diff --git a/app/soapbox/components/__tests__/autosuggest_emoji-test.js b/app/soapbox/components/__tests__/autosuggest_emoji.test.js similarity index 100% rename from app/soapbox/components/__tests__/autosuggest_emoji-test.js rename to app/soapbox/components/__tests__/autosuggest_emoji.test.js diff --git a/app/soapbox/components/account.tsx b/app/soapbox/components/account.tsx index 21178d5e4..3288127a1 100644 --- a/app/soapbox/components/account.tsx +++ b/app/soapbox/components/account.tsx @@ -125,7 +125,7 @@ const Account = ({ const LinkEl: any = showProfileHoverCard ? Link : 'div'; return ( -
+
', () => { + it('successfully renders', async() => { + render(); + expect(screen.getByLabelText('Search')).toBeInTheDocument(); + }); + + it('handles onChange', async() => { + __stub(mock => { + mock.onGet('/api/v1/accounts/search').reply(200, [{ id: 1 }]); + }); + const user = userEvent.setup(); + + render(); + + await user.type(screen.getByLabelText('Search'), '@jus'); + + expect(screen.getByLabelText('Search')).toHaveValue('@jus'); + expect(screen.getByTestId('account')).toBeInTheDocument(); + }); +}); diff --git a/app/soapbox/jest/test-setup.ts b/app/soapbox/jest/test-setup.ts index b3100425c..82beb982a 100644 --- a/app/soapbox/jest/test-setup.ts +++ b/app/soapbox/jest/test-setup.ts @@ -8,3 +8,6 @@ afterEach(() => clearApiMocks()); // Mock external dependencies jest.mock('uuid', () => ({ v4: jest.fn(() => 1) })); + +const intersectionObserverMock = () => ({ observe: () => null, disconnect: () => null }); +window.IntersectionObserver = jest.fn().mockImplementation(intersectionObserverMock); From b6ce38122d79f1c43d04bc88711cf2ad94fbe5f3 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 7 Apr 2022 10:12:23 -0400 Subject: [PATCH 2/5] Add simple test for FormActions --- .../ui/form-actions/__tests__/form-actions.test.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 app/soapbox/components/ui/form-actions/__tests__/form-actions.test.tsx diff --git a/app/soapbox/components/ui/form-actions/__tests__/form-actions.test.tsx b/app/soapbox/components/ui/form-actions/__tests__/form-actions.test.tsx new file mode 100644 index 000000000..3c954ca69 --- /dev/null +++ b/app/soapbox/components/ui/form-actions/__tests__/form-actions.test.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +import { render, screen } from '../../../../jest/test-helpers'; +import FormActions from '../form-actions'; + +describe('', () => { + it('renders successfully', () => { + render(
child
); + + expect(screen.getByTestId('child')).toBeInTheDocument(); + }); +}); From 4f1cf84d3924f337f0a8c03fa2a4d134bea2a1e7 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 7 Apr 2022 11:01:38 -0400 Subject: [PATCH 3/5] Add tests for Modal --- .../components/ui/icon-button/icon-button.tsx | 1 + .../ui/modal/__tests__/modal.test.tsx | 138 ++++++++++++++++++ app/soapbox/components/ui/modal/modal.tsx | 6 +- 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 app/soapbox/components/ui/modal/__tests__/modal.test.tsx diff --git a/app/soapbox/components/ui/icon-button/icon-button.tsx b/app/soapbox/components/ui/icon-button/icon-button.tsx index 291b0b4f8..10d08fc80 100644 --- a/app/soapbox/components/ui/icon-button/icon-button.tsx +++ b/app/soapbox/components/ui/icon-button/icon-button.tsx @@ -22,6 +22,7 @@ const IconButton = React.forwardRef((props: IIconButton, ref: React.ForwardedRef 'bg-white dark:bg-transparent': !transparent, }, className)} {...filteredProps} + data-testid='icon-button' > diff --git a/app/soapbox/components/ui/modal/__tests__/modal.test.tsx b/app/soapbox/components/ui/modal/__tests__/modal.test.tsx new file mode 100644 index 000000000..3894a4604 --- /dev/null +++ b/app/soapbox/components/ui/modal/__tests__/modal.test.tsx @@ -0,0 +1,138 @@ +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import { render, screen } from '../../../../jest/test-helpers'; +import Modal from '../modal'; + +describe('', () => { + it('renders', () => { + render(); + expect(screen.getByTestId('modal')).toBeInTheDocument(); + }); + + it('renders children', () => { + render(
); + expect(screen.getByTestId('child')).toBeInTheDocument(); + }); + + it('focuses the primary action', () => { + render( + null} + confirmationText='Click me' + />, + ); + + expect(screen.getByRole('button')).toHaveFocus(); + }); + + describe('onClose prop', () => { + it('renders the Icon to close the modal', async() => { + const mockFn = jest.fn(); + const user = userEvent.setup(); + + render(); + expect(screen.getByTestId('icon-button')).toBeInTheDocument(); + + expect(mockFn).not.toBeCalled(); + await user.click(screen.getByTestId('icon-button')); + expect(mockFn).toBeCalled(); + }); + + it('does not render the Icon to close the modal', () => { + render(); + expect(screen.queryAllByTestId('icon-button')).toHaveLength(0); + }); + }); + + describe('confirmationAction prop', () => { + it('renders the confirmation button', async() => { + const mockFn = jest.fn(); + const user = userEvent.setup(); + + render( + , + ); + + expect(mockFn).not.toBeCalled(); + await user.click(screen.getByRole('button')); + expect(mockFn).toBeCalled(); + }); + + it('does not render the actions to', () => { + render(); + expect(screen.queryAllByTestId('modal-actions')).toHaveLength(0); + }); + + describe('with secondaryAction', () => { + it('renders the secondary button', async() => { + const confirmationAction = jest.fn(); + const secondaryAction = jest.fn(); + const user = userEvent.setup(); + + render( + , + ); + + await user.click(screen.getByText(/secondary/i)); + expect(secondaryAction).toBeCalled(); + expect(confirmationAction).not.toBeCalled(); + }); + + it('does not render the secondary action', () => { + render( + null} + confirmationText='Click me' + />, + ); + expect(screen.queryAllByRole('button')).toHaveLength(1); + }); + }); + + describe('with cancelAction', () => { + it('renders the cancel button', async() => { + const confirmationAction = jest.fn(); + const cancelAction = jest.fn(); + const user = userEvent.setup(); + + render( + , + ); + + await user.click(screen.getByText(/cancel/i)); + expect(cancelAction).toBeCalled(); + expect(confirmationAction).not.toBeCalled(); + }); + + it('does not render the cancel action', () => { + render( + null} + confirmationText='Click me' + />, + ); + expect(screen.queryAllByRole('button')).toHaveLength(1); + }); + }); + }); +}); diff --git a/app/soapbox/components/ui/modal/modal.tsx b/app/soapbox/components/ui/modal/modal.tsx index d6d23ce92..efe580c23 100644 --- a/app/soapbox/components/ui/modal/modal.tsx +++ b/app/soapbox/components/ui/modal/modal.tsx @@ -17,7 +17,7 @@ interface IModal { confirmationDisabled?: boolean, confirmationText?: string, confirmationTheme?: 'danger', - onClose: () => void, + onClose?: () => void, secondaryAction?: () => void, secondaryText?: string, title: string | React.ReactNode, @@ -46,7 +46,7 @@ const Modal: React.FC = ({ }, [buttonRef]); return ( -
+
@@ -71,7 +71,7 @@ const Modal: React.FC = ({
{confirmationAction && ( -
+
{cancelAction && (