From 864117752893d2c9fed0e5c6bdfa614935120c0d Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Thu, 13 May 2021 07:36:55 +0800 Subject: [PATCH] Set up tests and components The tests for each component has been set up. The way on writing tests have been patterned from https://kentcdodds.com/blog/common-mistakes-with-react-testing-library. In addition, the requirements document has been modified to use a consistent formatting which can be translated into code. --- REQUIREMENTS.md | 22 +++--- packages/app-web/jest.config.js | 3 +- packages/app-web/jest.setup.ts | 1 + packages/app-web/package.json | 1 + .../forms/ActionButton/index.test.tsx | 19 ++--- .../molecules/forms/TextArea/index.test.tsx | 16 ++-- .../molecules/forms/TextInput/index.test.tsx | 16 ++-- .../molecules/navigation/Link/index.test.tsx | 15 ++++ .../forms/CreateRingtone/index.test.tsx | 33 ++++++++ .../organisms/forms/CreateRingtone/index.tsx | 23 ++++-- .../organisms/forms/Omnisearch/index.test.tsx | 27 +++++++ .../organisms/forms/Omnisearch/index.tsx | 38 +++++++++ .../templates/CreateRingtone/index.tsx | 20 +++++ packages/app-web/src/utils/api/fetch.ts | 62 +++++++++++++++ packages/app-web/tsconfig.test.json | 15 ++-- packages/app-web/yarn.lock | 79 ++++++++++++++++++- 16 files changed, 329 insertions(+), 61 deletions(-) create mode 100644 packages/app-web/jest.setup.ts create mode 100644 packages/app-web/src/components/molecules/navigation/Link/index.test.tsx create mode 100644 packages/app-web/src/components/organisms/forms/CreateRingtone/index.test.tsx create mode 100644 packages/app-web/src/components/organisms/forms/Omnisearch/index.test.tsx create mode 100644 packages/app-web/src/components/organisms/forms/Omnisearch/index.tsx create mode 100644 packages/app-web/src/utils/api/fetch.ts diff --git a/REQUIREMENTS.md b/REQUIREMENTS.md index 67a378e..948a6d0 100644 --- a/REQUIREMENTS.md +++ b/REQUIREMENTS.md @@ -1,30 +1,26 @@ # Requirements - As a client, I want to log in to the service. - - [ ] In the front-end, the client requests login by providing a username and a password to the back-end. + - [ ] In the front-end, the client provides a username, and a password to request login to the back-end. - [ ] In the back-end, the server processes the login request from the front-end. - As a client, I want to log out from the service. - [ ] In the front-end, the client requests logout to the backend. - [ ] In the back-end, the server processes the logout request from the front-end. -- As a client, I want to search for available ringtones. - - [ ] In the front-end, the client requests ringtones by providing a search keyword to the back-end. - - [ ] In the back-end, the server retrieves the ringtones whose name matches the search keyword provided by the - front-end. - As a client, I want to download a ringtone. - - [ ] In the front-end, the client requests the data of a ringtone from the back-end. + - [ ] In the front-end, the client provides a ringtone ID to request a ringtone from the back-end. - [ ] In the back-end, the server sends the ringtone data to the front-end. -- As a client, I want to search for composers. - - [ ] In the front-end, the client requests composers by providing a search keyword to the back-end. - - [ ] In the back-end, the server retrieves the composers whose name matches the search keyword provided by the - front-end. +- As a client, I want to search for composers and ringtones. + - [ ] In the front-end, the client requests provides a search keyword to request for composers and ringtones from the back-end. + - [ ] In the back-end, the server retrieves the composers and ringtones whose name matches the search keyword provided + by the front-end. - As a composer, I want to create a ringtone. - [ ] In the front-end, the client inputs ringtone data to the view. - [ ] In the front-end, the client sends the ringtone data to the back-end. - [ ] In the back-end, the server stores the ringtone. - As a composer, I want to update a ringtone. - - [ ] In the front-end, the client modifies the ringtone data loaded on the view. + - [ ] In the front-end, the client modifies the ringtone data retrieved from the back-end and loaded on the view. - [ ] In the front-end, the client sends the ringtone data to the back-end. - [ ] In the back-end, the server stores the ringtone. - As a composer, I want to delete a ringtone. - - [ ] In the front-end, the client requests deletion of a ringtone to the back-end. - - [ ] In the back-end, the server deletes the ringtone. + - [ ] In the front-end, the client provides a ringtone ID to request a ringtone's deletion to the back-end. + - [ ] In the back-end, the server deletes the ringtone if its ID matches the one provided by the front-end. diff --git a/packages/app-web/jest.config.js b/packages/app-web/jest.config.js index cc0c90b..19aa368 100644 --- a/packages/app-web/jest.config.js +++ b/packages/app-web/jest.config.js @@ -10,5 +10,6 @@ module.exports = { 'src/components/**/*.{jsx,tsx}', 'src/modules/**/*.{js,ts}', 'src/utils/**/*.{js,ts}', - ] + ], + setupFilesAfterEnv: ['/jest.setup.ts'] }; diff --git a/packages/app-web/jest.setup.ts b/packages/app-web/jest.setup.ts new file mode 100644 index 0000000..c44951a --- /dev/null +++ b/packages/app-web/jest.setup.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom' diff --git a/packages/app-web/package.json b/packages/app-web/package.json index f805939..4620dcf 100644 --- a/packages/app-web/package.json +++ b/packages/app-web/package.json @@ -18,6 +18,7 @@ "styled-components": "^5.3.0" }, "devDependencies": { + "@testing-library/jest-dom": "^5.12.0", "@testing-library/react": "^11.2.6", "@types/jest": "^26.0.23", "@types/node": "^15.0.2", diff --git a/packages/app-web/src/components/molecules/forms/ActionButton/index.test.tsx b/packages/app-web/src/components/molecules/forms/ActionButton/index.test.tsx index 993556e..6105ea3 100644 --- a/packages/app-web/src/components/molecules/forms/ActionButton/index.test.tsx +++ b/packages/app-web/src/components/molecules/forms/ActionButton/index.test.tsx @@ -1,22 +1,19 @@ -import {cleanup, render} from '@testing-library/react' +import {render, screen} from '@testing-library/react' import ActionButton from '.' describe('button component for triggering actions', () => { - afterEach(() => { - cleanup() - }) - it('should render a button element with a no-op action', () => { - const result = render() - const input = result.queryByRole('button') - expect(input).not.toBeNull() + render() + expect(screen.getByRole('button')).toBeInTheDocument() }) describe.each(['button', 'reset', 'submit'] as const)('on %p action', (type) => { + beforeEach(() => { + render() + }) + it('should render a button element with a submit action', () => { - const result = render() - const input = result.queryByRole('button') as HTMLButtonElement - expect(input.type).toBe(type) + expect(screen.getByRole('button')).toHaveAttribute('type', type) }) }) }) diff --git a/packages/app-web/src/components/molecules/forms/TextArea/index.test.tsx b/packages/app-web/src/components/molecules/forms/TextArea/index.test.tsx index 90a0e85..730979c 100644 --- a/packages/app-web/src/components/molecules/forms/TextArea/index.test.tsx +++ b/packages/app-web/src/components/molecules/forms/TextArea/index.test.tsx @@ -1,21 +1,15 @@ -import {render, cleanup} from '@testing-library/react' +import {render, screen} from '@testing-library/react' import TextInput from '.' describe('single-line text input component', () => { - afterEach(() => { - cleanup() - }) - it('should contain a text input element', () => { - const result = render() - const input = result.queryByRole('textbox') - expect(input).not.toBeNull() + render() + expect(screen.getByRole('textbox')).toBeInTheDocument() }) it('should acquire a descriptive label', () => { const label = 'foo' - const result = render() - const input = result.queryByLabelText(label) - expect(input).not.toBeNull() + render() + expect(screen.getByRole('textbox', { name: label, })).toBeInTheDocument() }) }) diff --git a/packages/app-web/src/components/molecules/forms/TextInput/index.test.tsx b/packages/app-web/src/components/molecules/forms/TextInput/index.test.tsx index 90a0e85..0eafa65 100644 --- a/packages/app-web/src/components/molecules/forms/TextInput/index.test.tsx +++ b/packages/app-web/src/components/molecules/forms/TextInput/index.test.tsx @@ -1,21 +1,15 @@ -import {render, cleanup} from '@testing-library/react' +import {render, screen} from '@testing-library/react' import TextInput from '.' describe('single-line text input component', () => { - afterEach(() => { - cleanup() - }) - it('should contain a text input element', () => { - const result = render() - const input = result.queryByRole('textbox') - expect(input).not.toBeNull() + render() + expect(screen.getByRole('textbox')).toBeInTheDocument() }) it('should acquire a descriptive label', () => { const label = 'foo' - const result = render() - const input = result.queryByLabelText(label) - expect(input).not.toBeNull() + render() + expect(screen.getByLabelText(label)).toBeInTheDocument() }) }) diff --git a/packages/app-web/src/components/molecules/navigation/Link/index.test.tsx b/packages/app-web/src/components/molecules/navigation/Link/index.test.tsx new file mode 100644 index 0000000..c21fa40 --- /dev/null +++ b/packages/app-web/src/components/molecules/navigation/Link/index.test.tsx @@ -0,0 +1,15 @@ +import { render, screen } from '@testing-library/react' +import Link from '.' + +describe('link component', () => { + it('should render an anchor element', () => { + render( + + ) + expect(screen.getByRole('link')).toBeInTheDocument() + }) +}) diff --git a/packages/app-web/src/components/organisms/forms/CreateRingtone/index.test.tsx b/packages/app-web/src/components/organisms/forms/CreateRingtone/index.test.tsx new file mode 100644 index 0000000..23b6de3 --- /dev/null +++ b/packages/app-web/src/components/organisms/forms/CreateRingtone/index.test.tsx @@ -0,0 +1,33 @@ +import {render, screen} from '@testing-library/react' +import CreateRingtoneForm from '.' + +describe('form for creating ringtones', () => { + beforeEach(() => { + render( + + ) + }) + + it('should render a form', () => { + expect(screen.getByRole('form', { name: 'Create Ringtone' })).toBeInTheDocument() + }) + + it('should render a textbox for the ringtone name', () => { + expect(screen.getByRole('textbox', { name: 'Name' })).toBeInTheDocument() + }) + + it('should render a textbox for the ringtone data', () => { + expect(screen.getByRole('textbox', { name: 'Data' })).toBeInTheDocument() + }) + + it('should render a button for submitting the ringtone data', () => { + expect(screen.getByRole('button', { name: 'Post' })).toBeInTheDocument() + }) +}) diff --git a/packages/app-web/src/components/organisms/forms/CreateRingtone/index.tsx b/packages/app-web/src/components/organisms/forms/CreateRingtone/index.tsx index d151173..75e1ae6 100644 --- a/packages/app-web/src/components/organisms/forms/CreateRingtone/index.tsx +++ b/packages/app-web/src/components/organisms/forms/CreateRingtone/index.tsx @@ -10,25 +10,38 @@ const Form = styled('form')({ }) type Props = { - onSubmit?: FormEventHandler + onSubmit?: FormEventHandler, + action?: string, + labels: Record, } const CreateRingtoneForm: FC = ({ onSubmit, + action, + labels, }) => { return (
- -