From d53b869d65791bab29c05b3666d2bc227ac4068c Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Fri, 1 Dec 2023 17:45:13 +0700 Subject: [PATCH] Add unit test --- .../__snapshots__/AppLayout.test.tsx.snap | 2 + .../Header/__snapshots__/Header.test.tsx.snap | 2 + .../__snapshots__/HeaderMenu.test.tsx.snap | 2 + .../__snapshots__/index.test.tsx.snap | 202 ++++++++++++++++++ .../src/components/Pagination/index.test.tsx | 46 ++++ .../src/components/Search/Search.test.tsx | 79 +++---- .../Search/__snapshots__/Search.test.tsx.snap | 72 +++++++ .../userRoomAvailableContext.test.tsx | 34 ++- .../src/helpers/__tests__/helpers.test.ts | 10 +- .../src/helpers/__tests__/validators.test.ts | 21 ++ hotel-management/src/helpers/helper.ts | 10 - .../__tests__/useAccount.test.ts | 35 +++ 12 files changed, 450 insertions(+), 65 deletions(-) create mode 100644 hotel-management/src/components/Pagination/__snapshots__/index.test.tsx.snap create mode 100644 hotel-management/src/components/Pagination/index.test.tsx create mode 100644 hotel-management/src/components/Search/__snapshots__/Search.test.tsx.snap create mode 100644 hotel-management/src/hooks/authentication/__tests__/useAccount.test.ts diff --git a/hotel-management/src/components/AppLayout/__snapshots__/AppLayout.test.tsx.snap b/hotel-management/src/components/AppLayout/__snapshots__/AppLayout.test.tsx.snap index dc7ccf8..a1bf590 100644 --- a/hotel-management/src/components/AppLayout/__snapshots__/AppLayout.test.tsx.snap +++ b/hotel-management/src/components/AppLayout/__snapshots__/AppLayout.test.tsx.snap @@ -16,6 +16,7 @@ exports[`AppLayout Should render correctly 1`] = ` >
  • + + + + + , + "container":
    +
    +

    + Showing + 1 + to + 5 + of + + 10 + + results +

    +
    + + +
    +
    +
    , + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/hotel-management/src/components/Pagination/index.test.tsx b/hotel-management/src/components/Pagination/index.test.tsx new file mode 100644 index 0000000..be2dc33 --- /dev/null +++ b/hotel-management/src/components/Pagination/index.test.tsx @@ -0,0 +1,46 @@ +import { render, fireEvent, RenderResult } from '@testing-library/react'; +import Pagination from '.'; +import { BrowserRouter } from 'react-router-dom'; + +describe('Pagination', () => { + const count = 10; + let wrapper: RenderResult | null = null; + + jest.mock('react-router-dom', () => ({ + useSearchParams: jest.fn(() => [new URLSearchParams(), jest.fn()]), + })); + + beforeEach(() => { + wrapper = render( + + + + ); + }); + + test('Should render correctly', () => { + expect(wrapper).toMatchSnapshot(); + }); + + test('Next button should be disable when in the last page', () => { + fireEvent.click(wrapper!.getByText('Next')); + + expect(wrapper!.getByText('Next').closest('button')).toBeDisabled(); + }); + + test('Previous button should not be disable when move to second page', () => { + fireEvent.click(wrapper!.getByText('Next')); + + expect(wrapper!.getByText('Previous').closest('button')).not.toBeDisabled(); + }); + + test('Previous button should be disabled when go back to the first page', () => { + // Navigate to the second page + fireEvent.click(wrapper!.getByText('Next')); + + // Back to the first page + fireEvent.click(wrapper!.getByText('Previous')); + + expect(wrapper!.getByText('Previous').closest('button')).toBeDisabled(); + }); +}); diff --git a/hotel-management/src/components/Search/Search.test.tsx b/hotel-management/src/components/Search/Search.test.tsx index fd3fb05..dd66555 100644 --- a/hotel-management/src/components/Search/Search.test.tsx +++ b/hotel-management/src/components/Search/Search.test.tsx @@ -1,67 +1,42 @@ -import { BrowserRouter } from 'react-router-dom'; -import { useState } from 'react'; +import { BrowserRouter, useSearchParams } from 'react-router-dom'; // Components import Search from '.'; -import { - RenderResult, - fireEvent, - render, - act, -} from '@testing-library/react'; +import { RenderResult, fireEvent, render } from '@testing-library/react'; -let mockSearchParam = ''; - -jest.useFakeTimers(); jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), - useSearchParams: () => { - const [params, setParams] = useState(new URLSearchParams(mockSearchParam)); - return [ - params, - (newParams: string) => { - mockSearchParam = newParams; - setParams(new URLSearchParams(newParams)); - }, - ]; - }, + useSearchParams: jest.fn(), +})); + +jest.mock('@hook/useDebounce', () => ({ + useDebounce: jest.fn((value) => value), })); describe('Search', () => { - // const placeHolder = 'Search placeholder...'; - // let wrapper: RenderResult | null = null; + const mockSearchParams = new URLSearchParams(); + (useSearchParams as jest.Mock).mockReturnValue([mockSearchParams, jest.fn()]); + let wrapper: RenderResult | null = null; - // beforeEach(() => { - // wrapper = render( - // - // - // - // ); - // }); - - // test('Should render correctly', () => { - // expect(wrapper).toMatchSnapshot(); - // }); - - test('Should add query to url after 1 second', async () => { - let wrapper: RenderResult | null = null; - act(() => { - wrapper = render( - - - - ); - }); - - const searchField = await wrapper!.findByPlaceholderText( - 'Search placeholder...' + beforeEach(() => { + wrapper = render( + + + ); + }); - act(() => { - fireEvent.change(searchField, { target: { value: 'abc' } }); - }); + test('Should render correctly', () => { + expect(wrapper).toMatchSnapshot(); + }) - // jest.advanceTimersByTime(1000); + test('updates searchParams on input change', () => { + const searchInput = wrapper!.getByPlaceholderText('Search'); + + // Type into the search input + fireEvent.change(searchInput, { target: { value: 'Search value' } }); + + // Expect searchParams to be updated + expect(mockSearchParams.get('search')).toBe('Search value'); }); }); - \ No newline at end of file diff --git a/hotel-management/src/components/Search/__snapshots__/Search.test.tsx.snap b/hotel-management/src/components/Search/__snapshots__/Search.test.tsx.snap new file mode 100644 index 0000000..544f2a0 --- /dev/null +++ b/hotel-management/src/components/Search/__snapshots__/Search.test.tsx.snap @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Search Should render correctly 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
    + +
    + , + "container":
    + +
    , + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx b/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx index 672476c..1d19412 100644 --- a/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx +++ b/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx @@ -38,12 +38,14 @@ describe('userRoomAvailableContext', () => { { id: 1, name: 'Room 1', + status: true, }, ], usersAvailable: [ { id: 1, name: 'Nezumi', + isBooked: true, }, ], }; @@ -84,7 +86,8 @@ describe('userRoomAvailableContext', () => { expect(state.usersAvailable[0]).toEqual({ id: 1, - name: 'Update name' + name: 'Update name', + isBooked: true, }); }); @@ -123,7 +126,34 @@ describe('userRoomAvailableContext', () => { expect(state.roomsAvailable[0]).toEqual({ id: 1, - name: 'Update name' + name: 'Update name', + status: true, + }); + }); + + test('Should update room status correctly', async () => { + const state = reducer(initialState, { + type: 'updateStatusRoom', + payload: [{ id: 1, status: false }], + }); + + expect(state.roomsAvailable[0]).toEqual({ + id: 1, + name: 'Room 1', + status: false, + }); + }); + + test('Should update user status correctly', async () => { + const state = reducer(initialState, { + type: 'updateStatusUser', + payload: [{ id: 1, isBooked: false }], + }); + + expect(state.usersAvailable[0]).toEqual({ + id: 1, + name: 'Nezumi', + isBooked: false, }); }); }); diff --git a/hotel-management/src/helpers/__tests__/helpers.test.ts b/hotel-management/src/helpers/__tests__/helpers.test.ts index 8e71b7f..1594be5 100644 --- a/hotel-management/src/helpers/__tests__/helpers.test.ts +++ b/hotel-management/src/helpers/__tests__/helpers.test.ts @@ -1,5 +1,5 @@ // Helpers -import { formatCurrency } from '@helper/helper'; +import { formatCurrency, getDayDiff } from '@helper/helper'; describe('formatCurrency', () => { test('Should format correctly', () => { @@ -8,3 +8,11 @@ describe('formatCurrency', () => { expect(result).toEqual('$5,000.00'); }); }); + +describe('getDayDiff', () => { + test('Should calculate correctly', () => { + const result = getDayDiff(new Date('2023/11/30'), new Date('2023/12/01')); + + expect(result).toEqual(1); + }); +}); diff --git a/hotel-management/src/helpers/__tests__/validators.test.ts b/hotel-management/src/helpers/__tests__/validators.test.ts index 61d6b94..2d6be25 100644 --- a/hotel-management/src/helpers/__tests__/validators.test.ts +++ b/hotel-management/src/helpers/__tests__/validators.test.ts @@ -3,6 +3,7 @@ import { REGEX } from '@constant/commons'; // Helpers import { + compareTwoDates, isValidDiscount, isValidRegex, isValidString, @@ -88,3 +89,23 @@ describe('Should is valid string', () => { expect(case_4).toBeFalsy(); }); }); + +describe('Should compare two dates correctly', () => { + test('The start date should greater than end date', () => { + const result = compareTwoDates( + new Date('2023/12/05'), + new Date('2023/12/01') + ); + + expect(result).toBe(true); + }); + + test('The start date should fewer than end date', () => { + const result = compareTwoDates( + new Date('2023/12/01'), + new Date('2023/12/05') + ); + + expect(result).toBe(false); + }); +}); diff --git a/hotel-management/src/helpers/helper.ts b/hotel-management/src/helpers/helper.ts index dce6e83..0383c67 100644 --- a/hotel-management/src/helpers/helper.ts +++ b/hotel-management/src/helpers/helper.ts @@ -25,17 +25,7 @@ const getDayDiff = (startDate: Date, endDate: Date): number => { ); } -/** - * Convert from currency string to the number - * @param currency The currency string - * @returns The number - */ -const convertCurrencyToNumber = (currency: string) => { - return Number(currency.replace(/[^0-9.-]+/g,"")) -} - export { formatCurrency, getDayDiff, - convertCurrencyToNumber }; diff --git a/hotel-management/src/hooks/authentication/__tests__/useAccount.test.ts b/hotel-management/src/hooks/authentication/__tests__/useAccount.test.ts new file mode 100644 index 0000000..4ed1447 --- /dev/null +++ b/hotel-management/src/hooks/authentication/__tests__/useAccount.test.ts @@ -0,0 +1,35 @@ + +import { useQuery } from '@tanstack/react-query'; +import * as authenticationService from '@service/authenticationService'; +import { renderHook } from '@testing-library/react'; +import { User } from '@supabase/supabase-js'; +import { useAccount } from '../useAccount'; + +jest.mock('@tanstack/react-query'); + +describe('useAccount', () => { + it('Should return the value correctly', async () => { + const mockAccount: User = { + role: 'authenticated', + app_metadata: jest.fn(), + id: '1', + user_metadata: jest.fn(), + aud: '', + created_at: '' + }; + + (useQuery as jest.Mock).mockReturnValue({ + data: mockAccount, + isPending: false, + }); + + jest.spyOn(authenticationService, 'getCurrentAccount').mockResolvedValue(mockAccount); + + const { result } = renderHook(() => useAccount()); + + expect(result.current.isPending).toBe(false); + expect(result.current.account).toBe(mockAccount); + expect(result.current.isAuthenticated).toBe(true); + }); + +});