mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 13:38:51 +00:00
Add unit test
This commit is contained in:
@@ -16,6 +16,7 @@ exports[`AppLayout Should render correctly 1`] = `
|
||||
>
|
||||
<li>
|
||||
<button
|
||||
aria-label="Profile"
|
||||
className="sc-bdnyFh bxHnoO"
|
||||
iconStyle={
|
||||
{
|
||||
@@ -59,6 +60,7 @@ exports[`AppLayout Should render correctly 1`] = `
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
aria-label="Logout"
|
||||
className="sc-bdnyFh bxHnoO"
|
||||
disabled={false}
|
||||
iconStyle={
|
||||
|
||||
@@ -14,6 +14,7 @@ exports[`Header Should render correctly 1`] = `
|
||||
>
|
||||
<li>
|
||||
<button
|
||||
aria-label="Profile"
|
||||
className="sc-bdnyFh bxHnoO"
|
||||
iconStyle={
|
||||
{
|
||||
@@ -57,6 +58,7 @@ exports[`Header Should render correctly 1`] = `
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
aria-label="Logout"
|
||||
className="sc-bdnyFh bxHnoO"
|
||||
disabled={false}
|
||||
iconStyle={
|
||||
|
||||
@@ -6,6 +6,7 @@ exports[`HeaderMenu Should render correctly 1`] = `
|
||||
>
|
||||
<li>
|
||||
<button
|
||||
aria-label="Profile"
|
||||
className="sc-bdnyFh bxHnoO"
|
||||
iconStyle={
|
||||
{
|
||||
@@ -49,6 +50,7 @@ exports[`HeaderMenu Should render correctly 1`] = `
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
aria-label="Logout"
|
||||
className="sc-bdnyFh bxHnoO"
|
||||
disabled={false}
|
||||
iconStyle={
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Pagination Should render correctly 1`] = `
|
||||
{
|
||||
"asFragment": [Function],
|
||||
"baseElement": <body>
|
||||
<div>
|
||||
<div
|
||||
class="sc-bdnyFh kjuCvI"
|
||||
>
|
||||
<p>
|
||||
Showing
|
||||
1
|
||||
to
|
||||
5
|
||||
of
|
||||
<span>
|
||||
10
|
||||
</span>
|
||||
results
|
||||
</p>
|
||||
<div
|
||||
class="sc-gtsqUy gUbTlC"
|
||||
>
|
||||
<button
|
||||
class="sc-dlniIP kLAzMx"
|
||||
disabled=""
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
stroke="currentColor"
|
||||
stroke-width="0"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 0h24v24H0V0z"
|
||||
fill="none"
|
||||
/>
|
||||
<path
|
||||
d="M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<span>
|
||||
Previous
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="sc-dlniIP kLAzMx"
|
||||
>
|
||||
<span>
|
||||
Next
|
||||
</span>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
stroke="currentColor"
|
||||
stroke-width="0"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 0h24v24H0V0z"
|
||||
fill="none"
|
||||
/>
|
||||
<path
|
||||
d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>,
|
||||
"container": <div>
|
||||
<div
|
||||
class="sc-bdnyFh kjuCvI"
|
||||
>
|
||||
<p>
|
||||
Showing
|
||||
1
|
||||
to
|
||||
5
|
||||
of
|
||||
<span>
|
||||
10
|
||||
</span>
|
||||
results
|
||||
</p>
|
||||
<div
|
||||
class="sc-gtsqUy gUbTlC"
|
||||
>
|
||||
<button
|
||||
class="sc-dlniIP kLAzMx"
|
||||
disabled=""
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
stroke="currentColor"
|
||||
stroke-width="0"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 0h24v24H0V0z"
|
||||
fill="none"
|
||||
/>
|
||||
<path
|
||||
d="M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<span>
|
||||
Previous
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="sc-dlniIP kLAzMx"
|
||||
>
|
||||
<span>
|
||||
Next
|
||||
</span>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
stroke="currentColor"
|
||||
stroke-width="0"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 0h24v24H0V0z"
|
||||
fill="none"
|
||||
/>
|
||||
<path
|
||||
d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
"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],
|
||||
}
|
||||
`;
|
||||
@@ -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(
|
||||
<BrowserRouter>
|
||||
<Pagination count={count} />
|
||||
</BrowserRouter>
|
||||
);
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
// beforeEach(() => {
|
||||
// wrapper = render(
|
||||
// <BrowserRouter>
|
||||
// <Search setPlaceHolder={placeHolder} />
|
||||
// </BrowserRouter>
|
||||
// );
|
||||
// });
|
||||
|
||||
// test('Should render correctly', () => {
|
||||
// expect(wrapper).toMatchSnapshot();
|
||||
// });
|
||||
|
||||
test('Should add query to url after 1 second', async () => {
|
||||
const mockSearchParams = new URLSearchParams();
|
||||
(useSearchParams as jest.Mock).mockReturnValue([mockSearchParams, jest.fn()]);
|
||||
let wrapper: RenderResult | null = null;
|
||||
act(() => {
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = render(
|
||||
<BrowserRouter>
|
||||
<Search setPlaceHolder={'Search placeholder...'} />
|
||||
<Search setPlaceHolder="Search" />
|
||||
</BrowserRouter>
|
||||
);
|
||||
});
|
||||
|
||||
const searchField = await wrapper!.findByPlaceholderText(
|
||||
'Search placeholder...'
|
||||
);
|
||||
test('Should render correctly', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
})
|
||||
|
||||
act(() => {
|
||||
fireEvent.change(searchField, { target: { value: 'abc' } });
|
||||
});
|
||||
test('updates searchParams on input change', () => {
|
||||
const searchInput = wrapper!.getByPlaceholderText('Search');
|
||||
|
||||
// jest.advanceTimersByTime(1000);
|
||||
// Type into the search input
|
||||
fireEvent.change(searchInput, { target: { value: 'Search value' } });
|
||||
|
||||
// Expect searchParams to be updated
|
||||
expect(mockSearchParams.get('search')).toBe('Search value');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Search Should render correctly 1`] = `
|
||||
{
|
||||
"asFragment": [Function],
|
||||
"baseElement": <body>
|
||||
<div>
|
||||
<input
|
||||
class="sc-bdnyFh fkeDFp"
|
||||
placeholder="Search"
|
||||
/>
|
||||
</div>
|
||||
</body>,
|
||||
"container": <div>
|
||||
<input
|
||||
class="sc-bdnyFh fkeDFp"
|
||||
placeholder="Search"
|
||||
/>
|
||||
</div>,
|
||||
"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],
|
||||
}
|
||||
`;
|
||||
@@ -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,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user