From 609b9abd52e02f2a53f5f3b57c5f75ba7fa7a017 Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Tue, 21 Nov 2023 17:45:27 +0700 Subject: [PATCH 01/11] Create function test helpers --- .../src/helpers/__tests__/helpers.test.ts | 9 ++++ .../src/helpers/__tests__/validators.test.ts | 44 +++++++++++++++++++ .../src/hooks/__tests__/rooms.test.tsx | 11 +++++ 3 files changed, 64 insertions(+) create mode 100644 hotel-management/src/helpers/__tests__/helpers.test.ts create mode 100644 hotel-management/src/helpers/__tests__/validators.test.ts create mode 100644 hotel-management/src/hooks/__tests__/rooms.test.tsx diff --git a/hotel-management/src/helpers/__tests__/helpers.test.ts b/hotel-management/src/helpers/__tests__/helpers.test.ts new file mode 100644 index 0000000..01ac7da --- /dev/null +++ b/hotel-management/src/helpers/__tests__/helpers.test.ts @@ -0,0 +1,9 @@ +import { formatCurrency } from '@helper/helper'; + +describe('Helpers function test', () => { + test('Format number to currency format', () => { + const result = formatCurrency(5000); + + expect(result).toEqual('$5,000.00'); + }); +}); diff --git a/hotel-management/src/helpers/__tests__/validators.test.ts b/hotel-management/src/helpers/__tests__/validators.test.ts new file mode 100644 index 0000000..611cf94 --- /dev/null +++ b/hotel-management/src/helpers/__tests__/validators.test.ts @@ -0,0 +1,44 @@ +import { REGEX } from '@constant/commons'; +import { isValidDiscount, isValidRegex, isValidString } from '@helper/validators'; + +describe('Check value is valid phone', () => { + test('Is valid phone', () => { + const result = isValidRegex(new RegExp(REGEX.PHONE), '0327212321'); + + expect(result).toEqual(true); + }); + + test('Is invalid phone', () => { + const result = isValidRegex(new RegExp(REGEX.PHONE), '0327212321Abc'); + + expect(result).toEqual(false); + }); +}); + +describe('Check value is valid discount', () => { + test('Is valid discount', () => { + const result = isValidDiscount(23); + + expect(result).toEqual(true); + }); + + test('Is invalid discount', () => { + const result = isValidDiscount(101); + + expect(result).toEqual(false); + }); +}); + +describe('Check value is valid string', () => { + test('Is valid string', () => { + const result = isValidString('Phan Huu Loi'); + + expect(result).toEqual(true); + }); + + test('Is valid string', () => { + const result = isValidString('Phan'); + + expect(result).toEqual(false); + }); +}); diff --git a/hotel-management/src/hooks/__tests__/rooms.test.tsx b/hotel-management/src/hooks/__tests__/rooms.test.tsx new file mode 100644 index 0000000..7782c75 --- /dev/null +++ b/hotel-management/src/hooks/__tests__/rooms.test.tsx @@ -0,0 +1,11 @@ +import { useRooms } from '@hook/rooms/useRooms'; +import { renderHook, waitFor } from '@testing-library/react'; + +describe('CRUD Room testing', () => { + test('Fetch room data', async () => { + const { result } = renderHook(() => useRooms()); + const { rooms } = result.current; + + await waitFor(() => expect(rooms?.length).toBeGreaterThan(0)) + }) +}) From d379262a7d1100e0c848411075597c0292333aeb Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Tue, 21 Nov 2023 21:10:49 +0700 Subject: [PATCH 02/11] Add room hook testing and update config test --- hotel-management/.gitignore | 3 +- hotel-management/jest.config.ts | 8 +- hotel-management/package.json | 1 + hotel-management/pnpm-lock.yaml | 11 +++ hotel-management/src/constants/config.ts | 4 +- .../src/hooks/__tests__/rooms.test.tsx | 83 +++++++++++++++++-- .../src/hooks/rooms/useCreateRoom.ts | 8 +- .../src/hooks/rooms/useDeleteRoom.ts | 8 +- hotel-management/src/hooks/rooms/useRooms.ts | 2 +- .../src/hooks/rooms/useUpdateRoom.ts | 8 +- hotel-management/vite.config.ts | 11 +-- 11 files changed, 125 insertions(+), 22 deletions(-) diff --git a/hotel-management/.gitignore b/hotel-management/.gitignore index 43c1272..6fc5f22 100644 --- a/hotel-management/.gitignore +++ b/hotel-management/.gitignore @@ -12,8 +12,7 @@ dist dist-ssr *.local .vscode - -src/db.json +.jest # Editor directories and files .vscode/* diff --git a/hotel-management/jest.config.ts b/hotel-management/jest.config.ts index 1b0d7a0..4f970e4 100644 --- a/hotel-management/jest.config.ts +++ b/hotel-management/jest.config.ts @@ -1,4 +1,7 @@ -export default { +import type { Config } from 'jest'; + +const config: Config = { + verbose: true, testEnvironment: 'jsdom', transform: { '^.+\\.tsx?$': 'ts-jest', @@ -17,4 +20,7 @@ export default { '@page/(.*)': ['/src/pages/$1'], }, setupFilesAfterEnv: ['/jest.setup.ts'], + setupFiles: ['/.jest/setEnvVar.ts'] }; + +export default config; diff --git a/hotel-management/package.json b/hotel-management/package.json index 07f3071..6a2920d 100644 --- a/hotel-management/package.json +++ b/hotel-management/package.json @@ -46,6 +46,7 @@ "ts-node": "^10.9.1", "typescript": "^5.0.2", "vite": "^4.4.5", + "vite-plugin-environment": "^1.1.3", "vite-tsconfig-paths": "^4.2.1" } } diff --git a/hotel-management/pnpm-lock.yaml b/hotel-management/pnpm-lock.yaml index 68ff571..6950453 100644 --- a/hotel-management/pnpm-lock.yaml +++ b/hotel-management/pnpm-lock.yaml @@ -106,6 +106,9 @@ devDependencies: vite: specifier: ^4.4.5 version: 4.4.11(@types/node@20.9.2) + vite-plugin-environment: + specifier: ^1.1.3 + version: 1.1.3(vite@4.4.11) vite-tsconfig-paths: specifier: ^4.2.1 version: 4.2.1(typescript@5.2.2)(vite@4.4.11) @@ -4580,6 +4583,14 @@ packages: convert-source-map: 2.0.0 dev: true + /vite-plugin-environment@1.1.3(vite@4.4.11): + resolution: {integrity: sha512-9LBhB0lx+2lXVBEWxFZC+WO7PKEyE/ykJ7EPWCq95NEcCpblxamTbs5Dm3DLBGzwODpJMEnzQywJU8fw6XGGGA==} + peerDependencies: + vite: '>= 2.7' + dependencies: + vite: 4.4.11(@types/node@20.9.2) + dev: true + /vite-tsconfig-paths@4.2.1(typescript@5.2.2)(vite@4.4.11): resolution: {integrity: sha512-GNUI6ZgPqT3oervkvzU+qtys83+75N/OuDaQl7HmOqFTb0pjZsuARrRipsyJhJ3enqV8beI1xhGbToR4o78nSQ==} peerDependencies: diff --git a/hotel-management/src/constants/config.ts b/hotel-management/src/constants/config.ts index f5c8e39..d4e2b57 100644 --- a/hotel-management/src/constants/config.ts +++ b/hotel-management/src/constants/config.ts @@ -1,6 +1,6 @@ const DEFAULT_SORT_BY = 'id'; const DEFAULT_ORDER_BY = 'asc'; -const supabaseUrl = 'https://pjqujsjzzdrlrgqbxepe.supabase.co' -const supabaseKey = import.meta.env.VITE_SUPABASE_KEY +const supabaseUrl = 'https://pjqujsjzzdrlrgqbxepe.supabase.co'; +const supabaseKey = process.env.VITE_SUPABASE_KEY; export { DEFAULT_SORT_BY, DEFAULT_ORDER_BY, supabaseKey, supabaseUrl }; diff --git a/hotel-management/src/hooks/__tests__/rooms.test.tsx b/hotel-management/src/hooks/__tests__/rooms.test.tsx index 7782c75..2081408 100644 --- a/hotel-management/src/hooks/__tests__/rooms.test.tsx +++ b/hotel-management/src/hooks/__tests__/rooms.test.tsx @@ -1,11 +1,84 @@ +import { useCreateRoom } from '@hook/rooms/useCreateRoom'; +import { useDeleteRoom } from '@hook/rooms/useDeleteRoom'; import { useRooms } from '@hook/rooms/useRooms'; +import { useUpdateRoom } from '@hook/rooms/useUpdateRoom'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook, waitFor } from '@testing-library/react'; +import { IRoom } from '@type/rooms'; +import { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { act } from 'react-test-renderer'; + +interface IWrapper { + children: ReactNode; +} + +const sampleData: IRoom = { + id: 999, + name: 'Room name test', + price: 9999, + status: true, +}; +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, +}); +const wrapper = ({ children }: IWrapper) => { + return ( + + {children} + + ); +}; describe('CRUD Room testing', () => { test('Fetch room data', async () => { - const { result } = renderHook(() => useRooms()); - const { rooms } = result.current; + const { result } = renderHook(() => useRooms(), { wrapper }); - await waitFor(() => expect(rooms?.length).toBeGreaterThan(0)) - }) -}) + await waitFor(() => + expect(result.current.rooms?.length).toBeGreaterThan(0) + ); + }); + + test('Create room', async () => { + const { result } = renderHook(() => useCreateRoom(), { wrapper }); + + act(() => { + const testMethod = async () => { + result.current.createRoom(sampleData); + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + }; + + testMethod(); + }); + }); + + test('Edit room', async () => { + const { result } = renderHook(() => useUpdateRoom(), { wrapper }); + + act(() => { + const testMethod = async () => { + result.current.updateRoom(sampleData); + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + }; + + testMethod(); + }); + }); + + test('Delete room', async () => { + const { result } = renderHook(() => useDeleteRoom(), { wrapper }); + + act(() => { + const testMethod = async () => { + result.current.deleteRoom(sampleData.id); + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + }; + + testMethod(); + }); + }); +}); diff --git a/hotel-management/src/hooks/rooms/useCreateRoom.ts b/hotel-management/src/hooks/rooms/useCreateRoom.ts index 7578bd6..3f9c06f 100644 --- a/hotel-management/src/hooks/rooms/useCreateRoom.ts +++ b/hotel-management/src/hooks/rooms/useCreateRoom.ts @@ -16,7 +16,11 @@ const useCreateRoom = () => { const queryClient = useQueryClient(); const { dispatch } = useUserRoomAvailable(); - const { mutate: createRoom, isPending: isCreating } = useMutation({ + const { + mutate: createRoom, + isPending: isCreating, + isSuccess, + } = useMutation({ mutationFn: createRoomFn, onSuccess: (room) => { toast.success(ADD_SUCCESS); @@ -31,7 +35,7 @@ const useCreateRoom = () => { onError: (err) => toast.error(err.message), }); - return { isCreating, createRoom }; + return { isCreating, createRoom, isSuccess }; }; export { useCreateRoom }; diff --git a/hotel-management/src/hooks/rooms/useDeleteRoom.ts b/hotel-management/src/hooks/rooms/useDeleteRoom.ts index 693d3d3..099d16b 100644 --- a/hotel-management/src/hooks/rooms/useDeleteRoom.ts +++ b/hotel-management/src/hooks/rooms/useDeleteRoom.ts @@ -14,7 +14,11 @@ import * as messages from '@constant/messages'; const useDeleteRoom = () => { const queryClient = useQueryClient(); - const { isPending: isDeleting, mutate: deleteRoom } = useMutation({ + const { + isPending: isDeleting, + mutate: deleteRoom, + isSuccess, + } = useMutation({ mutationFn: deleteRoomFn, onSuccess: () => { toast.success(messages.DELETE_SUCCESS); @@ -25,7 +29,7 @@ const useDeleteRoom = () => { onError: (err) => toast.error(err.message), }); - return { isDeleting, deleteRoom }; + return { isDeleting, deleteRoom, isSuccess }; }; export { useDeleteRoom }; diff --git a/hotel-management/src/hooks/rooms/useRooms.ts b/hotel-management/src/hooks/rooms/useRooms.ts index 84518dd..c7112a1 100644 --- a/hotel-management/src/hooks/rooms/useRooms.ts +++ b/hotel-management/src/hooks/rooms/useRooms.ts @@ -18,7 +18,7 @@ const useRooms = () => { const { isLoading, data: rooms, - error, + error } = useQuery({ queryKey: ['rooms', sortByValue, orderByValue, phoneSearch], queryFn: () => getAllRooms(sortByValue, orderByValue, phoneSearch), diff --git a/hotel-management/src/hooks/rooms/useUpdateRoom.ts b/hotel-management/src/hooks/rooms/useUpdateRoom.ts index 7b1bf15..798d416 100644 --- a/hotel-management/src/hooks/rooms/useUpdateRoom.ts +++ b/hotel-management/src/hooks/rooms/useUpdateRoom.ts @@ -16,7 +16,11 @@ const useUpdateRoom = () => { const queryClient = useQueryClient(); const { dispatch } = useUserRoomAvailable(); - const { mutate: updateRoom, isPending: isUpdating } = useMutation({ + const { + mutate: updateRoom, + isPending: isUpdating, + isSuccess, + } = useMutation({ mutationFn: updateRoomFn, onSuccess: (room) => { toast.success(UPDATE_SUCCESS); @@ -31,7 +35,7 @@ const useUpdateRoom = () => { onError: (err) => toast.error(err.message), }); - return { isUpdating, updateRoom }; + return { isUpdating, updateRoom, isSuccess }; }; export { useUpdateRoom }; diff --git a/hotel-management/vite.config.ts b/hotel-management/vite.config.ts index 3e8ce05..7072bdc 100644 --- a/hotel-management/vite.config.ts +++ b/hotel-management/vite.config.ts @@ -1,8 +1,9 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' -import tsconfigPaths from 'vite-tsconfig-paths' +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import tsconfigPaths from 'vite-tsconfig-paths'; +import EnvironmentPlugin from 'vite-plugin-environment'; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [react(), tsconfigPaths()], -}) + plugins: [react(), tsconfigPaths(), EnvironmentPlugin('all')], +}); From 603994faffbcee3586e32ebd48e1ae1dfe14cba2 Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Wed, 22 Nov 2023 17:40:32 +0700 Subject: [PATCH 03/11] Add useDebounce, useOutsideClick test --- hotel-management/.gitignore | 1 + hotel-management/jest.config.ts | 5 +- hotel-management/package.json | 6 +- hotel-management/pnpm-lock.yaml | 389 +++++++++++++++++- .../src/hooks/__tests__/rooms.test.tsx | 131 ++++-- .../src/hooks/__tests__/useDebounce.test.tsx | 47 +++ .../hooks/__tests__/useOutsideClick.test.tsx | 31 ++ .../src/hooks/__tests__/users.test.tsx | 70 ++++ .../src/hooks/rooms/useDeleteRoom.ts | 3 +- hotel-management/src/hooks/rooms/useRooms.ts | 12 +- .../src/hooks/rooms/useUpdateRoom.ts | 5 +- .../src/hooks/users/useCreateUser.ts | 8 +- .../src/hooks/users/useUpdateUser.ts | 8 +- 13 files changed, 655 insertions(+), 61 deletions(-) create mode 100644 hotel-management/src/hooks/__tests__/useDebounce.test.tsx create mode 100644 hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx create mode 100644 hotel-management/src/hooks/__tests__/users.test.tsx diff --git a/hotel-management/.gitignore b/hotel-management/.gitignore index 6fc5f22..ba9bc79 100644 --- a/hotel-management/.gitignore +++ b/hotel-management/.gitignore @@ -10,6 +10,7 @@ lerna-debug.log* node_modules dist dist-ssr +coverage *.local .vscode .jest diff --git a/hotel-management/jest.config.ts b/hotel-management/jest.config.ts index 4f970e4..24064df 100644 --- a/hotel-management/jest.config.ts +++ b/hotel-management/jest.config.ts @@ -20,7 +20,10 @@ const config: Config = { '@page/(.*)': ['/src/pages/$1'], }, setupFilesAfterEnv: ['/jest.setup.ts'], - setupFiles: ['/.jest/setEnvVar.ts'] + setupFiles: ['/.jest/setEnvVar.ts'], + testEnvironmentOptions: { + customExportConditions: [''], + }, }; export default config; diff --git a/hotel-management/package.json b/hotel-management/package.json index 6a2920d..a7bd98c 100644 --- a/hotel-management/package.json +++ b/hotel-management/package.json @@ -8,8 +8,11 @@ "build": "tsc && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", - "test": "jest" + "test": "jest --coverage" }, + "coverageReporters": [ + "html" + ], "dependencies": { "@emotion/is-prop-valid": "^1.2.1", "@supabase/supabase-js": "^2.38.4", @@ -42,6 +45,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "msw": "^2.0.8", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "typescript": "^5.0.2", diff --git a/hotel-management/pnpm-lock.yaml b/hotel-management/pnpm-lock.yaml index 6950453..f3a5113 100644 --- a/hotel-management/pnpm-lock.yaml +++ b/hotel-management/pnpm-lock.yaml @@ -94,6 +94,9 @@ devDependencies: jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 + msw: + specifier: ^2.0.8 + version: 2.0.8(typescript@5.2.2) ts-jest: specifier: ^29.1.1 version: 29.1.1(@babel/core@7.23.2)(jest@29.7.0)(typescript@5.2.2) @@ -488,6 +491,24 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true + /@bundled-es-modules/cookie@2.0.0: + resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==} + dependencies: + cookie: 0.5.0 + dev: true + + /@bundled-es-modules/js-levenshtein@2.0.1: + resolution: {integrity: sha512-DERMS3yfbAljKsQc0U2wcqGKUWpdFjwqWuoMugEJlqBnKO180/n+4SR/J8MRDt1AN48X1ovgoD9KrdVXcaa3Rg==} + dependencies: + js-levenshtein: 1.1.6 + dev: true + + /@bundled-es-modules/statuses@1.0.1: + resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} + dependencies: + statuses: 2.0.1 + dev: true + /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -1031,6 +1052,23 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@mswjs/cookies@1.1.0: + resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} + engines: {node: '>=18'} + dev: true + + /@mswjs/interceptors@0.25.12: + resolution: {integrity: sha512-a+zyoR01cPQeukSmaDEkE6aMwSjjfcT5ILzsyxmctEeCePnc2DMOd0X8Fn9bytq1IsAfMxJf/lu2aTfdivDbRg==} + engines: {node: '>=18'} + dependencies: + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.0 + strict-event-emitter: 0.5.1 + dev: true + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1052,6 +1090,21 @@ packages: fastq: 1.15.0 dev: true + /@open-draft/deferred-promise@2.2.0: + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + dev: true + + /@open-draft/logger@0.3.0: + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.0 + dev: true + + /@open-draft/until@2.1.0: + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + dev: true + /@remix-run/router@1.10.0: resolution: {integrity: sha512-Lm+fYpMfZoEucJ7cMxgt4dYt8jLfbpwRCzAjm9UgSLOkmlqo9gupxt6YX3DY0Fk155NT9l17d/ydi+964uS9Lw==} engines: {node: '>=14.0.0'} @@ -1270,6 +1323,10 @@ packages: '@babel/types': 7.23.0 dev: true + /@types/cookie@0.4.1: + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + dev: true + /@types/graceful-fs@4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} dependencies: @@ -1299,6 +1356,10 @@ packages: pretty-format: 29.7.0 dev: true + /@types/js-levenshtein@1.1.3: + resolution: {integrity: sha512-jd+Q+sD20Qfu9e2aEXogiO3vpOC1PYJOUdyN9gvs4Qrvkg4wF43L5OhqrPeokdv8TL0/mXoYfpkcoGZMNN2pkQ==} + dev: true + /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: @@ -1353,6 +1414,10 @@ packages: resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} dev: true + /@types/statuses@2.0.4: + resolution: {integrity: sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw==} + dev: true + /@types/stylis@4.2.2: resolution: {integrity: sha512-Rm17MsTpQQP5Jq4BF7CdrxJsDufoiL/q5IbJZYZmOZAJALyijgF7BzLgobXUqraNcQdqFYLYGeglDp6QzaxPpg==} dev: false @@ -1743,6 +1808,23 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -1785,6 +1867,13 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + /bufferutil@4.0.8: resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} engines: {node: '>=6.14.2'} @@ -1854,6 +1943,25 @@ packages: engines: {node: '>=10'} dev: true + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -1863,6 +1971,23 @@ packages: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} dev: true + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-spinners@2.9.1: + resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} + engines: {node: '>=6'} + dev: true + + /cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: true + /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1872,6 +1997,11 @@ packages: wrap-ansi: 7.0.0 dev: true + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + /co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -1917,6 +2047,11 @@ packages: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: true + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: true + /create-jest@29.7.0(@types/node@20.9.2)(ts-node@10.9.1): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2069,6 +2204,12 @@ packages: engines: {node: '>=0.10.0'} dev: true + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + /define-data-property@1.1.1: resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} engines: {node: '>= 0.4'} @@ -2414,6 +2555,15 @@ packages: type: 2.7.2 dev: false + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2449,6 +2599,13 @@ packages: bser: 2.1.1 dev: true + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2631,6 +2788,11 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /graphql@16.8.1: + resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + dev: true + /harmony-reflect@1.6.2: resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} dev: true @@ -2679,6 +2841,10 @@ packages: function-bind: 1.1.2 dev: true + /headers-polyfill@4.0.2: + resolution: {integrity: sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw==} + dev: true + /html-encoding-sniffer@3.0.0: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} @@ -2716,6 +2882,13 @@ packages: engines: {node: '>=10.17.0'} dev: true + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2730,6 +2903,10 @@ packages: harmony-reflect: 1.6.2 dev: true + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -2773,6 +2950,27 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true + /inquirer@8.2.6: + resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 6.2.0 + dev: true + /internal-slot@1.0.6: resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} engines: {node: '>= 0.4'} @@ -2808,6 +3006,13 @@ packages: has-bigints: 1.0.2 dev: true + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + /is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} @@ -2856,10 +3061,19 @@ packages: is-extglob: 2.1.1 dev: true + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} dev: true + /is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + dev: true + /is-number-object@1.0.7: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} @@ -2929,6 +3143,11 @@ packages: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} dev: false + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + /is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} dev: true @@ -3441,6 +3660,11 @@ packages: - ts-node dev: true + /js-levenshtein@1.1.6: + resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} + engines: {node: '>=0.10.0'} + dev: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3582,6 +3806,14 @@ packages: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: true + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -3676,6 +3908,45 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true + /msw@2.0.8(typescript@5.2.2): + resolution: {integrity: sha512-/5nQCotVka62lvubQ3tMfUS3TukyeBwvWyvAthcXvDlXGhkA/85HlEwZyFlJ3ZsPW45Ty+ao0S4oFvuM12R/kA==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + peerDependencies: + typescript: '>= 4.7.x <= 5.2.x' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@bundled-es-modules/cookie': 2.0.0 + '@bundled-es-modules/js-levenshtein': 2.0.1 + '@bundled-es-modules/statuses': 1.0.1 + '@mswjs/cookies': 1.1.0 + '@mswjs/interceptors': 0.25.12 + '@open-draft/until': 2.1.0 + '@types/cookie': 0.4.1 + '@types/js-levenshtein': 1.1.3 + '@types/statuses': 2.0.4 + chalk: 4.1.2 + chokidar: 3.5.3 + graphql: 16.8.1 + headers-polyfill: 4.0.2 + inquirer: 8.2.6 + is-node-process: 1.2.0 + js-levenshtein: 1.1.6 + outvariant: 1.4.0 + path-to-regexp: 6.2.1 + strict-event-emitter: 0.5.1 + type-fest: 2.19.0 + typescript: 5.2.2 + yargs: 17.7.2 + dev: true + + /mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: true + /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -3775,6 +4046,30 @@ packages: type-check: 0.4.0 dev: true + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.1 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /outvariant@1.4.0: + resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} + dev: true + /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -3850,6 +4145,10 @@ packages: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true + /path-to-regexp@6.2.1: + resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + dev: true + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -4041,6 +4340,22 @@ packages: dependencies: loose-envify: 1.4.0 + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + /redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -4102,6 +4417,14 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -4122,12 +4445,27 @@ packages: fsevents: 2.3.3 dev: true + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: true + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 dev: true + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + dependencies: + tslib: 2.6.2 + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true @@ -4240,6 +4578,11 @@ packages: escape-string-regexp: 2.0.0 dev: true + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: true + /stop-iteration-iterator@1.0.0: resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} engines: {node: '>= 0.4'} @@ -4247,6 +4590,10 @@ packages: internal-slot: 1.0.6 dev: true + /strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + dev: true + /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -4264,6 +4611,12 @@ packages: strip-ansi: 6.0.1 dev: true + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -4360,6 +4713,17 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: true @@ -4486,7 +4850,6 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: false /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} @@ -4510,6 +4873,11 @@ packages: engines: {node: '>=10'} dev: true + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: true + /type@1.2.0: resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} dev: false @@ -4570,6 +4938,10 @@ packages: node-gyp-build: 4.6.1 dev: false + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true @@ -4657,6 +5029,12 @@ packages: makeerror: 1.0.12 dev: true + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true + /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: false @@ -4745,6 +5123,15 @@ packages: isexe: 2.0.0 dev: true + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} diff --git a/hotel-management/src/hooks/__tests__/rooms.test.tsx b/hotel-management/src/hooks/__tests__/rooms.test.tsx index 2081408..5a8cb8b 100644 --- a/hotel-management/src/hooks/__tests__/rooms.test.tsx +++ b/hotel-management/src/hooks/__tests__/rooms.test.tsx @@ -1,24 +1,37 @@ -import { useCreateRoom } from '@hook/rooms/useCreateRoom'; -import { useDeleteRoom } from '@hook/rooms/useDeleteRoom'; import { useRooms } from '@hook/rooms/useRooms'; -import { useUpdateRoom } from '@hook/rooms/useUpdateRoom'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +// import { useCreateRoom } from '@hook/rooms/useCreateRoom'; +import { setupServer } from 'msw/node'; +import { http } from 'msw'; +import { + QueryCache, + QueryClient, + QueryClientProvider, +} from '@tanstack/react-query'; import { renderHook, waitFor } from '@testing-library/react'; -import { IRoom } from '@type/rooms'; +// import { IRoom } from '@type/rooms'; import { ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; -import { act } from 'react-test-renderer'; +import { supabaseUrl } from '@constant/config'; + +const mockUseRooms = jest.fn(useRooms); +// const mockUseCreateRoom = jest.fn(useCreateRoom); +// const mockUseUpdateRoom = useUpdateRoom; +// const mockUseDeleteRoom = useDeleteRoom; + +jest.mock('@hook/rooms/useRooms'); +jest.mock('@hook/rooms/useUpdateRoom'); +jest.mock('@hook/rooms/useDeleteRoom'); interface IWrapper { children: ReactNode; } -const sampleData: IRoom = { - id: 999, - name: 'Room name test', - price: 9999, - status: true, -}; +// const sampleData: IRoom = { +// id: 999, +// name: 'Room name test', +// price: 9999, +// status: true, +// }; const queryClient = new QueryClient({ defaultOptions: { queries: { @@ -26,6 +39,7 @@ const queryClient = new QueryClient({ }, }, }); +const queryCache = new QueryCache(); const wrapper = ({ children }: IWrapper) => { return ( @@ -34,51 +48,82 @@ const wrapper = ({ children }: IWrapper) => { ); }; +const server = setupServer( + http.post(supabaseUrl, async ({ request }) => { + const data = await request.formData(); + + console.log(data); + }) +); + +beforeAll(() => server.listen()); +afterEach(() => { + server.resetHandlers(); + queryCache.clear(); +}); +afterAll(() => server.close()); + describe('CRUD Room testing', () => { test('Fetch room data', async () => { - const { result } = renderHook(() => useRooms(), { wrapper }); + mockUseRooms.mockImplementation(() => ({ + rooms: [ + { + id: 1, + name: 'Nezumi', + price: 2500, + status: true, + }, + { + id: 2, + name: 'Loi Phan', + price: 8500, + status: false, + }, + ], + isLoading: false, + })); + const { result } = renderHook(() => mockUseRooms(), { wrapper }); await waitFor(() => expect(result.current.rooms?.length).toBeGreaterThan(0) ); }); - test('Create room', async () => { - const { result } = renderHook(() => useCreateRoom(), { wrapper }); + // test('Create room', async () => { + // const { result } = renderHook(() => useCreateRoom(), { wrapper }); - act(() => { - const testMethod = async () => { - result.current.createRoom(sampleData); - await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); - }; + // act(() => { + // result.current.createRoom(sampleData); + // }); - testMethod(); - }); - }); + // await waitFor(() => result.current.isSuccess); - test('Edit room', async () => { - const { result } = renderHook(() => useUpdateRoom(), { wrapper }); + // expect(result.current.isSuccess).toBeTruthy(); + // }); - act(() => { - const testMethod = async () => { - result.current.updateRoom(sampleData); - await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); - }; + // test('Edit room', async () => { + // const { result } = renderHook(() => useUpdateRoom(), { wrapper }); - testMethod(); - }); - }); + // act(() => { + // const testMethod = async () => { + // result.current.updateRoom(sampleData); + // await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + // }; - test('Delete room', async () => { - const { result } = renderHook(() => useDeleteRoom(), { wrapper }); + // testMethod(); + // }); + // }); - act(() => { - const testMethod = async () => { - result.current.deleteRoom(sampleData.id); - await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); - }; + // test('Delete room', async () => { + // const { result } = renderHook(() => useDeleteRoom(), { wrapper }); - testMethod(); - }); - }); + // act(() => { + // const testMethod = async () => { + // result.current.deleteRoom(sampleData.id); + // await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + // }; + + // testMethod(); + // }); + // }); }); diff --git a/hotel-management/src/hooks/__tests__/useDebounce.test.tsx b/hotel-management/src/hooks/__tests__/useDebounce.test.tsx new file mode 100644 index 0000000..ab6fdd6 --- /dev/null +++ b/hotel-management/src/hooks/__tests__/useDebounce.test.tsx @@ -0,0 +1,47 @@ +import { useDebounce } from '@hook/useDebounce'; +import { fireEvent, render } from '@testing-library/react'; +import { useState } from 'react'; +import { act } from 'react-test-renderer'; + +const TestComponent = ({ initialValue = 0 }: { initialValue?: number }) => { + const [value, setValue] = useState(initialValue); + const debouncedValue = useDebounce(value, 1000); + + return ( +
+ + {debouncedValue} + {value} +
+ ); +}; + +describe('useDebouncedValue', function () { + afterEach(() => { + jest.useRealTimers(); + }); + + test('Debounce value should not change before 1 second', () => { + jest.useFakeTimers(); + const { getByTestId, getByText } = render(); + const incrementButton = getByText('Increment'); + const debouncedValue = getByTestId('debouncedValue'); + const value = getByTestId('value'); + + const incrementAndPassTime = (passedTime: number) => { + act(() => { + fireEvent.click(incrementButton); + jest.advanceTimersByTime(passedTime); + }); + }; + incrementAndPassTime(999); + + expect(debouncedValue.textContent).toBe('0'); + expect(value.textContent).toBe('1'); + + incrementAndPassTime(1000); + + expect(debouncedValue.textContent).toBe('1'); + expect(value.textContent).toBe('2'); + }); +}); diff --git a/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx b/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx new file mode 100644 index 0000000..2f01194 --- /dev/null +++ b/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx @@ -0,0 +1,31 @@ +import { useOutsideClick } from '@hook/useOutsideClick'; +import { fireEvent, render, renderHook, screen } from '@testing-library/react'; + +describe('useOutsideClick testing', () => { + test('Call handler when click outside element', () => { + // Arrange + const handler = jest.fn(); + const ref = renderHook(() => useOutsideClick(handler)) + .result.current; + render(
); + + fireEvent.click(document); + + // Assert + expect(handler).toHaveBeenCalledTimes(1); + }); + + test('Not call handler when click outside element', () => { + // Arrange + const handler = jest.fn(); + const ref = renderHook(() => useOutsideClick(handler)) + .result.current; + render(
); + + // Act + fireEvent.click(screen.getByTestId('test-element')); + + // Assert + expect(handler).not.toHaveBeenCalled(); + }); +}); diff --git a/hotel-management/src/hooks/__tests__/users.test.tsx b/hotel-management/src/hooks/__tests__/users.test.tsx new file mode 100644 index 0000000..9ac0970 --- /dev/null +++ b/hotel-management/src/hooks/__tests__/users.test.tsx @@ -0,0 +1,70 @@ +// import { useCreateUser } from '@hook/users/useCreateUser'; +// import { useUpdateUser } from '@hook/users/useUpdateUser'; +// import { useUsers } from '@hook/users/useUsers'; +// import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +// import { renderHook, waitFor } from '@testing-library/react'; +// import { IUser } from '@type/users'; +// import { ReactNode } from 'react'; +// import { MemoryRouter } from 'react-router-dom'; +// import { act } from 'react-test-renderer'; + +// interface IWrapper { +// children: ReactNode; +// } + +// const sampleData: IUser = { +// id: 999, +// name: 'User name test', +// phone: '123456789', +// isBooked: true, +// }; +// const queryClient = new QueryClient({ +// defaultOptions: { +// queries: { +// retry: false, +// }, +// }, +// }); +// const wrapper = ({ children }: IWrapper) => { +// return ( +// +// {children} +// +// ); +// }; + +// describe('CRUD User testing', () => { +// test('Fetch user data', async () => { +// const { result } = renderHook(() => useUsers(), { wrapper }); + +// await waitFor(() => +// expect(result.current.users?.length).toBeGreaterThan(0) +// ); +// }); + +// test('Create user', async () => { +// const { result } = renderHook(() => useCreateUser(), { wrapper }); + +// act(() => { +// const testMethod = async () => { +// result.current.createUser(sampleData); +// await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); +// }; + +// testMethod(); +// }); +// }); + +// test('Update user', async () => { +// const { result } = renderHook(() => useUpdateUser(), { wrapper }); + +// act(() => { +// const testMethod = async () => { +// result.current.updateUser(sampleData); +// await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); +// }; + +// testMethod(); +// }); +// }); +// }); diff --git a/hotel-management/src/hooks/rooms/useDeleteRoom.ts b/hotel-management/src/hooks/rooms/useDeleteRoom.ts index 099d16b..2a99f5d 100644 --- a/hotel-management/src/hooks/rooms/useDeleteRoom.ts +++ b/hotel-management/src/hooks/rooms/useDeleteRoom.ts @@ -17,7 +17,6 @@ const useDeleteRoom = () => { const { isPending: isDeleting, mutate: deleteRoom, - isSuccess, } = useMutation({ mutationFn: deleteRoomFn, onSuccess: () => { @@ -29,7 +28,7 @@ const useDeleteRoom = () => { onError: (err) => toast.error(err.message), }); - return { isDeleting, deleteRoom, isSuccess }; + return { isDeleting, deleteRoom }; }; export { useDeleteRoom }; diff --git a/hotel-management/src/hooks/rooms/useRooms.ts b/hotel-management/src/hooks/rooms/useRooms.ts index c7112a1..f6ffc75 100644 --- a/hotel-management/src/hooks/rooms/useRooms.ts +++ b/hotel-management/src/hooks/rooms/useRooms.ts @@ -1,9 +1,9 @@ -import toast from "react-hot-toast"; -import { useQuery } from "@tanstack/react-query"; -import { useSearchParams } from "react-router-dom"; +import toast from 'react-hot-toast'; +import { useQuery } from '@tanstack/react-query'; +import { useSearchParams } from 'react-router-dom'; // Services -import { getAllRooms } from "@service/roomServices"; +import { getAllRooms } from '@service/roomServices'; /** * Fetch room from database @@ -13,12 +13,12 @@ const useRooms = () => { const [searchParams] = useSearchParams(); const sortByValue = searchParams.get('sortBy') || 'id'; const orderByValue = searchParams.get('orderBy') || 'asc'; - const phoneSearch = searchParams.get('search') || '' + const phoneSearch = searchParams.get('search') || ''; const { isLoading, data: rooms, - error + error, } = useQuery({ queryKey: ['rooms', sortByValue, orderByValue, phoneSearch], queryFn: () => getAllRooms(sortByValue, orderByValue, phoneSearch), diff --git a/hotel-management/src/hooks/rooms/useUpdateRoom.ts b/hotel-management/src/hooks/rooms/useUpdateRoom.ts index 798d416..f0b748d 100644 --- a/hotel-management/src/hooks/rooms/useUpdateRoom.ts +++ b/hotel-management/src/hooks/rooms/useUpdateRoom.ts @@ -18,8 +18,7 @@ const useUpdateRoom = () => { const { mutate: updateRoom, - isPending: isUpdating, - isSuccess, + isPending: isUpdating } = useMutation({ mutationFn: updateRoomFn, onSuccess: (room) => { @@ -35,7 +34,7 @@ const useUpdateRoom = () => { onError: (err) => toast.error(err.message), }); - return { isUpdating, updateRoom, isSuccess }; + return { isUpdating, updateRoom }; }; export { useUpdateRoom }; diff --git a/hotel-management/src/hooks/users/useCreateUser.ts b/hotel-management/src/hooks/users/useCreateUser.ts index 7d7c8e3..5da048c 100644 --- a/hotel-management/src/hooks/users/useCreateUser.ts +++ b/hotel-management/src/hooks/users/useCreateUser.ts @@ -16,7 +16,11 @@ const useCreateUser = () => { const queryClient = useQueryClient(); const { dispatch } = useUserRoomAvailable(); - const { mutate: createUser, isPending: isCreating } = useMutation({ + const { + mutate: createUser, + isPending: isCreating, + isSuccess, + } = useMutation({ mutationFn: createUserFn, onSuccess: (user) => { toast.success(ADD_SUCCESS); @@ -31,7 +35,7 @@ const useCreateUser = () => { onError: (err) => toast.error(err.message), }); - return { isCreating, createUser }; + return { isCreating, createUser, isSuccess }; }; export { useCreateUser }; diff --git a/hotel-management/src/hooks/users/useUpdateUser.ts b/hotel-management/src/hooks/users/useUpdateUser.ts index 6603c8d..496d587 100644 --- a/hotel-management/src/hooks/users/useUpdateUser.ts +++ b/hotel-management/src/hooks/users/useUpdateUser.ts @@ -16,7 +16,11 @@ const useUpdateUser = () => { const queryClient = useQueryClient(); const { dispatch } = useUserRoomAvailable(); - const { mutate: updateUser, isPending: isUpdating } = useMutation({ + const { + mutate: updateUser, + isPending: isUpdating, + isSuccess, + } = useMutation({ mutationFn: updateUserFn, onSuccess: (user) => { toast.success(UPDATE_SUCCESS); @@ -31,7 +35,7 @@ const useUpdateUser = () => { onError: (err) => toast.error(err.message), }); - return { isUpdating, updateUser }; + return { isUpdating, updateUser, isSuccess }; }; export { useUpdateUser }; From bc6f8675ff83d4a155cbc006b1789a22e3eaa82b Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Thu, 23 Nov 2023 10:06:41 +0700 Subject: [PATCH 04/11] Create test for add room function --- hotel-management/package.json | 1 - hotel-management/pnpm-lock.yaml | 389 +----------------- .../src/hooks/__tests__/rooms.test.tsx | 78 ++-- 3 files changed, 41 insertions(+), 427 deletions(-) diff --git a/hotel-management/package.json b/hotel-management/package.json index a7bd98c..57eddfc 100644 --- a/hotel-management/package.json +++ b/hotel-management/package.json @@ -45,7 +45,6 @@ "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", - "msw": "^2.0.8", "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "typescript": "^5.0.2", diff --git a/hotel-management/pnpm-lock.yaml b/hotel-management/pnpm-lock.yaml index f3a5113..6950453 100644 --- a/hotel-management/pnpm-lock.yaml +++ b/hotel-management/pnpm-lock.yaml @@ -94,9 +94,6 @@ devDependencies: jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 - msw: - specifier: ^2.0.8 - version: 2.0.8(typescript@5.2.2) ts-jest: specifier: ^29.1.1 version: 29.1.1(@babel/core@7.23.2)(jest@29.7.0)(typescript@5.2.2) @@ -491,24 +488,6 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true - /@bundled-es-modules/cookie@2.0.0: - resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==} - dependencies: - cookie: 0.5.0 - dev: true - - /@bundled-es-modules/js-levenshtein@2.0.1: - resolution: {integrity: sha512-DERMS3yfbAljKsQc0U2wcqGKUWpdFjwqWuoMugEJlqBnKO180/n+4SR/J8MRDt1AN48X1ovgoD9KrdVXcaa3Rg==} - dependencies: - js-levenshtein: 1.1.6 - dev: true - - /@bundled-es-modules/statuses@1.0.1: - resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} - dependencies: - statuses: 2.0.1 - dev: true - /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -1052,23 +1031,6 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true - /@mswjs/cookies@1.1.0: - resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} - engines: {node: '>=18'} - dev: true - - /@mswjs/interceptors@0.25.12: - resolution: {integrity: sha512-a+zyoR01cPQeukSmaDEkE6aMwSjjfcT5ILzsyxmctEeCePnc2DMOd0X8Fn9bytq1IsAfMxJf/lu2aTfdivDbRg==} - engines: {node: '>=18'} - dependencies: - '@open-draft/deferred-promise': 2.2.0 - '@open-draft/logger': 0.3.0 - '@open-draft/until': 2.1.0 - is-node-process: 1.2.0 - outvariant: 1.4.0 - strict-event-emitter: 0.5.1 - dev: true - /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1090,21 +1052,6 @@ packages: fastq: 1.15.0 dev: true - /@open-draft/deferred-promise@2.2.0: - resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} - dev: true - - /@open-draft/logger@0.3.0: - resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} - dependencies: - is-node-process: 1.2.0 - outvariant: 1.4.0 - dev: true - - /@open-draft/until@2.1.0: - resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - dev: true - /@remix-run/router@1.10.0: resolution: {integrity: sha512-Lm+fYpMfZoEucJ7cMxgt4dYt8jLfbpwRCzAjm9UgSLOkmlqo9gupxt6YX3DY0Fk155NT9l17d/ydi+964uS9Lw==} engines: {node: '>=14.0.0'} @@ -1323,10 +1270,6 @@ packages: '@babel/types': 7.23.0 dev: true - /@types/cookie@0.4.1: - resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} - dev: true - /@types/graceful-fs@4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} dependencies: @@ -1356,10 +1299,6 @@ packages: pretty-format: 29.7.0 dev: true - /@types/js-levenshtein@1.1.3: - resolution: {integrity: sha512-jd+Q+sD20Qfu9e2aEXogiO3vpOC1PYJOUdyN9gvs4Qrvkg4wF43L5OhqrPeokdv8TL0/mXoYfpkcoGZMNN2pkQ==} - dev: true - /@types/jsdom@20.0.1: resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} dependencies: @@ -1414,10 +1353,6 @@ packages: resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} dev: true - /@types/statuses@2.0.4: - resolution: {integrity: sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw==} - dev: true - /@types/stylis@4.2.2: resolution: {integrity: sha512-Rm17MsTpQQP5Jq4BF7CdrxJsDufoiL/q5IbJZYZmOZAJALyijgF7BzLgobXUqraNcQdqFYLYGeglDp6QzaxPpg==} dev: false @@ -1808,23 +1743,6 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true - - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: true - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: true - /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -1867,13 +1785,6 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - /bufferutil@4.0.8: resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} engines: {node: '>=6.14.2'} @@ -1943,25 +1854,6 @@ packages: engines: {node: '>=10'} dev: true - /chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - dev: true - - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -1971,23 +1863,6 @@ packages: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} dev: true - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: true - - /cli-spinners@2.9.1: - resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} - engines: {node: '>=6'} - dev: true - - /cli-width@3.0.0: - resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} - engines: {node: '>= 10'} - dev: true - /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1997,11 +1872,6 @@ packages: wrap-ansi: 7.0.0 dev: true - /clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - /co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -2047,11 +1917,6 @@ packages: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: true - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - dev: true - /create-jest@29.7.0(@types/node@20.9.2)(ts-node@10.9.1): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2204,12 +2069,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: true - /define-data-property@1.1.1: resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} engines: {node: '>= 0.4'} @@ -2555,15 +2414,6 @@ packages: type: 2.7.2 dev: false - /external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - dev: true - /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2599,13 +2449,6 @@ packages: bser: 2.1.1 dev: true - /figures@3.2.0: - resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} - engines: {node: '>=8'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2788,11 +2631,6 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true - /graphql@16.8.1: - resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} - engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - dev: true - /harmony-reflect@1.6.2: resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} dev: true @@ -2841,10 +2679,6 @@ packages: function-bind: 1.1.2 dev: true - /headers-polyfill@4.0.2: - resolution: {integrity: sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw==} - dev: true - /html-encoding-sniffer@3.0.0: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} @@ -2882,13 +2716,6 @@ packages: engines: {node: '>=10.17.0'} dev: true - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -2903,10 +2730,6 @@ packages: harmony-reflect: 1.6.2 dev: true - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true - /ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -2950,27 +2773,6 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true - /inquirer@8.2.6: - resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} - engines: {node: '>=12.0.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 6.2.0 - dev: true - /internal-slot@1.0.6: resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} engines: {node: '>= 0.4'} @@ -3006,13 +2808,6 @@ packages: has-bigints: 1.0.2 dev: true - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: true - /is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} @@ -3061,19 +2856,10 @@ packages: is-extglob: 2.1.1 dev: true - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: true - /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} dev: true - /is-node-process@1.2.0: - resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} - dev: true - /is-number-object@1.0.7: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} @@ -3143,11 +2929,6 @@ packages: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} dev: false - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true - /is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} dev: true @@ -3660,11 +3441,6 @@ packages: - ts-node dev: true - /js-levenshtein@1.1.6: - resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} - engines: {node: '>=0.10.0'} - dev: true - /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3806,14 +3582,6 @@ packages: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: true - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: true - /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -3908,45 +3676,6 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true - /msw@2.0.8(typescript@5.2.2): - resolution: {integrity: sha512-/5nQCotVka62lvubQ3tMfUS3TukyeBwvWyvAthcXvDlXGhkA/85HlEwZyFlJ3ZsPW45Ty+ao0S4oFvuM12R/kA==} - engines: {node: '>=18'} - hasBin: true - requiresBuild: true - peerDependencies: - typescript: '>= 4.7.x <= 5.2.x' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@bundled-es-modules/cookie': 2.0.0 - '@bundled-es-modules/js-levenshtein': 2.0.1 - '@bundled-es-modules/statuses': 1.0.1 - '@mswjs/cookies': 1.1.0 - '@mswjs/interceptors': 0.25.12 - '@open-draft/until': 2.1.0 - '@types/cookie': 0.4.1 - '@types/js-levenshtein': 1.1.3 - '@types/statuses': 2.0.4 - chalk: 4.1.2 - chokidar: 3.5.3 - graphql: 16.8.1 - headers-polyfill: 4.0.2 - inquirer: 8.2.6 - is-node-process: 1.2.0 - js-levenshtein: 1.1.6 - outvariant: 1.4.0 - path-to-regexp: 6.2.1 - strict-event-emitter: 0.5.1 - type-fest: 2.19.0 - typescript: 5.2.2 - yargs: 17.7.2 - dev: true - - /mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} - dev: true - /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -4046,30 +3775,6 @@ packages: type-check: 0.4.0 dev: true - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.1 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - - /outvariant@1.4.0: - resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} - dev: true - /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -4145,10 +3850,6 @@ packages: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true - /path-to-regexp@6.2.1: - resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} - dev: true - /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -4340,22 +4041,6 @@ packages: dependencies: loose-envify: 1.4.0 - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - /redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -4417,14 +4102,6 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -4445,27 +4122,12 @@ packages: fsevents: 2.3.3 dev: true - /run-async@2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} - dev: true - /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 dev: true - /rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - dependencies: - tslib: 2.6.2 - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true - /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true @@ -4578,11 +4240,6 @@ packages: escape-string-regexp: 2.0.0 dev: true - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true - /stop-iteration-iterator@1.0.0: resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} engines: {node: '>= 0.4'} @@ -4590,10 +4247,6 @@ packages: internal-slot: 1.0.6 dev: true - /strict-event-emitter@0.5.1: - resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} - dev: true - /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -4611,12 +4264,6 @@ packages: strip-ansi: 6.0.1 dev: true - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -4713,17 +4360,6 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true - - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: true @@ -4850,6 +4486,7 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: false /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} @@ -4873,11 +4510,6 @@ packages: engines: {node: '>=10'} dev: true - /type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - dev: true - /type@1.2.0: resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} dev: false @@ -4938,10 +4570,6 @@ packages: node-gyp-build: 4.6.1 dev: false - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true @@ -5029,12 +4657,6 @@ packages: makeerror: 1.0.12 dev: true - /wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: true - /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: false @@ -5123,15 +4745,6 @@ packages: isexe: 2.0.0 dev: true - /wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} diff --git a/hotel-management/src/hooks/__tests__/rooms.test.tsx b/hotel-management/src/hooks/__tests__/rooms.test.tsx index 5a8cb8b..de4af17 100644 --- a/hotel-management/src/hooks/__tests__/rooms.test.tsx +++ b/hotel-management/src/hooks/__tests__/rooms.test.tsx @@ -1,20 +1,16 @@ import { useRooms } from '@hook/rooms/useRooms'; -// import { useCreateRoom } from '@hook/rooms/useCreateRoom'; -import { setupServer } from 'msw/node'; -import { http } from 'msw'; +import { useCreateRoom } from '@hook/rooms/useCreateRoom'; import { - QueryCache, QueryClient, QueryClientProvider, } from '@tanstack/react-query'; -import { renderHook, waitFor } from '@testing-library/react'; -// import { IRoom } from '@type/rooms'; +import { act, renderHook, waitFor } from '@testing-library/react'; +import { IRoom } from '@type/rooms'; import { ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; -import { supabaseUrl } from '@constant/config'; const mockUseRooms = jest.fn(useRooms); -// const mockUseCreateRoom = jest.fn(useCreateRoom); +const mockUseCreateRoom = jest.fn(useCreateRoom); // const mockUseUpdateRoom = useUpdateRoom; // const mockUseDeleteRoom = useDeleteRoom; @@ -26,12 +22,12 @@ interface IWrapper { children: ReactNode; } -// const sampleData: IRoom = { -// id: 999, -// name: 'Room name test', -// price: 9999, -// status: true, -// }; +const sampleData: IRoom = { + id: 999, + name: 'Room name test', + price: 9999, + status: true, +}; const queryClient = new QueryClient({ defaultOptions: { queries: { @@ -39,7 +35,6 @@ const queryClient = new QueryClient({ }, }, }); -const queryCache = new QueryCache(); const wrapper = ({ children }: IWrapper) => { return ( @@ -48,21 +43,6 @@ const wrapper = ({ children }: IWrapper) => { ); }; -const server = setupServer( - http.post(supabaseUrl, async ({ request }) => { - const data = await request.formData(); - - console.log(data); - }) -); - -beforeAll(() => server.listen()); -afterEach(() => { - server.resetHandlers(); - queryCache.clear(); -}); -afterAll(() => server.close()); - describe('CRUD Room testing', () => { test('Fetch room data', async () => { mockUseRooms.mockImplementation(() => ({ @@ -89,17 +69,39 @@ describe('CRUD Room testing', () => { ); }); - // test('Create room', async () => { - // const { result } = renderHook(() => useCreateRoom(), { wrapper }); + test('Create room', async () => { + mockUseCreateRoom.mockImplementation(() => ({ + createRoom: () => {sampleData}, + isCreating: false, + isSuccess: true + })); + const { result } = renderHook(() => mockUseCreateRoom(), { wrapper }); - // act(() => { - // result.current.createRoom(sampleData); - // }); + act(() => { + result.current.createRoom(sampleData); + }); - // await waitFor(() => result.current.isSuccess); + await waitFor(() => result.current.isSuccess); - // expect(result.current.isSuccess).toBeTruthy(); - // }); + expect(result.current.isSuccess).toBeTruthy(); + }); + + test('Create failed room', async () => { + mockUseCreateRoom.mockImplementation(() => ({ + createRoom: () => {sampleData}, + isCreating: false, + isSuccess: false + })); + const { result } = renderHook(() => mockUseCreateRoom(), { wrapper }); + + act(() => { + result.current.createRoom(sampleData); + }); + + await waitFor(() => result.current.isSuccess); + + expect(result.current.isSuccess).toBeFalsy(); + }); // test('Edit room', async () => { // const { result } = renderHook(() => useUpdateRoom(), { wrapper }); From e3db60b2ddfea2fb67186e2af44df098236a67d6 Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Thu, 23 Nov 2023 17:45:26 +0700 Subject: [PATCH 05/11] Add test case for user, room hooks --- .../src/hooks/__tests__/rooms.test.tsx | 72 ++++----- .../src/hooks/__tests__/users.test.tsx | 151 +++++++++++------- .../src/hooks/rooms/useDeleteRoom.ts | 3 +- .../src/hooks/rooms/useUpdateRoom.ts | 7 +- 4 files changed, 128 insertions(+), 105 deletions(-) diff --git a/hotel-management/src/hooks/__tests__/rooms.test.tsx b/hotel-management/src/hooks/__tests__/rooms.test.tsx index de4af17..c70b563 100644 --- a/hotel-management/src/hooks/__tests__/rooms.test.tsx +++ b/hotel-management/src/hooks/__tests__/rooms.test.tsx @@ -8,16 +8,13 @@ import { act, renderHook, waitFor } from '@testing-library/react'; import { IRoom } from '@type/rooms'; import { ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; +import { useUpdateRoom } from '@hook/rooms/useUpdateRoom'; +import { useDeleteRoom } from '@hook/rooms/useDeleteRoom'; const mockUseRooms = jest.fn(useRooms); const mockUseCreateRoom = jest.fn(useCreateRoom); -// const mockUseUpdateRoom = useUpdateRoom; -// const mockUseDeleteRoom = useDeleteRoom; - -jest.mock('@hook/rooms/useRooms'); -jest.mock('@hook/rooms/useUpdateRoom'); -jest.mock('@hook/rooms/useDeleteRoom'); - +const mockUseUpdateRoom = jest.fn(useUpdateRoom); +const mockUseDeleteRoom = jest.fn(useDeleteRoom); interface IWrapper { children: ReactNode; } @@ -86,46 +83,39 @@ describe('CRUD Room testing', () => { expect(result.current.isSuccess).toBeTruthy(); }); - test('Create failed room', async () => { - mockUseCreateRoom.mockImplementation(() => ({ - createRoom: () => {sampleData}, - isCreating: false, - isSuccess: false + test('Edit room', async () => { + mockUseUpdateRoom.mockImplementation(() => ({ + updateRoom: () => {sampleData}, + isUpdating: false, + isSuccess: true })); - const { result } = renderHook(() => mockUseCreateRoom(), { wrapper }); + const { result } = renderHook(() => mockUseUpdateRoom(), { wrapper }); act(() => { - result.current.createRoom(sampleData); + const testMethod = async () => { + result.current.updateRoom(sampleData); + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + }; + + testMethod(); }); - - await waitFor(() => result.current.isSuccess); - - expect(result.current.isSuccess).toBeFalsy(); }); - // test('Edit room', async () => { - // const { result } = renderHook(() => useUpdateRoom(), { wrapper }); + test('Delete room', async () => { + mockUseDeleteRoom.mockImplementation(() => ({ + deleteRoom: () => {sampleData.id}, + isDeleting: false, + isSuccess: true + })); + const { result } = renderHook(() => mockUseDeleteRoom(), { wrapper }); - // act(() => { - // const testMethod = async () => { - // result.current.updateRoom(sampleData); - // await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); - // }; + act(() => { + const testMethod = async () => { + result.current.deleteRoom(sampleData.id); + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + }; - // testMethod(); - // }); - // }); - - // test('Delete room', async () => { - // const { result } = renderHook(() => useDeleteRoom(), { wrapper }); - - // act(() => { - // const testMethod = async () => { - // result.current.deleteRoom(sampleData.id); - // await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); - // }; - - // testMethod(); - // }); - // }); + testMethod(); + }); + }); }); diff --git a/hotel-management/src/hooks/__tests__/users.test.tsx b/hotel-management/src/hooks/__tests__/users.test.tsx index 9ac0970..5958f17 100644 --- a/hotel-management/src/hooks/__tests__/users.test.tsx +++ b/hotel-management/src/hooks/__tests__/users.test.tsx @@ -1,70 +1,101 @@ -// import { useCreateUser } from '@hook/users/useCreateUser'; -// import { useUpdateUser } from '@hook/users/useUpdateUser'; -// import { useUsers } from '@hook/users/useUsers'; -// import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -// import { renderHook, waitFor } from '@testing-library/react'; -// import { IUser } from '@type/users'; -// import { ReactNode } from 'react'; -// import { MemoryRouter } from 'react-router-dom'; -// import { act } from 'react-test-renderer'; +import { useCreateUser } from '@hook/users/useCreateUser'; +import { useUpdateUser } from '@hook/users/useUpdateUser'; +import { useUsers } from '@hook/users/useUsers'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { renderHook, waitFor } from '@testing-library/react'; +import { IUser } from '@type/users'; +import { ReactNode } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { act } from 'react-test-renderer'; -// interface IWrapper { -// children: ReactNode; -// } +const mockUseUsers = jest.fn(useUsers); +const mockUseCreateUser = jest.fn(useCreateUser); +const mockUseUpdateUser = jest.fn(useUpdateUser); -// const sampleData: IUser = { -// id: 999, -// name: 'User name test', -// phone: '123456789', -// isBooked: true, -// }; -// const queryClient = new QueryClient({ -// defaultOptions: { -// queries: { -// retry: false, -// }, -// }, -// }); -// const wrapper = ({ children }: IWrapper) => { -// return ( -// -// {children} -// -// ); -// }; +interface IWrapper { + children: ReactNode; +} -// describe('CRUD User testing', () => { -// test('Fetch user data', async () => { -// const { result } = renderHook(() => useUsers(), { wrapper }); +const sampleData: IUser = { + id: 999, + name: 'User name test', + phone: '123456789', + isBooked: true, +}; +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, +}); +const wrapper = ({ children }: IWrapper) => { + return ( + + {children} + + ); +}; -// await waitFor(() => -// expect(result.current.users?.length).toBeGreaterThan(0) -// ); -// }); +describe('CRUD User testing', () => { + test('Fetch user data', async () => { + mockUseUsers.mockImplementation(() => ({ + users: [ + { + id: 1, + name: 'Nezumi', + phone: '0123456678', + isBooked: true, + }, + { + id: 2, + name: 'Loi Phan', + phone: '0123456678', + isBooked: false, + }, + ], + isLoading: false, + })) + const { result } = renderHook(() => mockUseUsers(), { wrapper }); -// test('Create user', async () => { -// const { result } = renderHook(() => useCreateUser(), { wrapper }); + await waitFor(() => + expect(result.current.users?.length).toEqual(2) + ); + }); -// act(() => { -// const testMethod = async () => { -// result.current.createUser(sampleData); -// await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); -// }; + test('Create user', async () => { + mockUseCreateUser.mockImplementation(() => ({ + createUser: () => {sampleData}, + isCreating: false, + isSuccess: true, + })); + const { result } = renderHook(() => mockUseCreateUser(), { wrapper }); -// testMethod(); -// }); -// }); + act(() => { + const testMethod = async () => { + result.current.createUser(sampleData); + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + }; -// test('Update user', async () => { -// const { result } = renderHook(() => useUpdateUser(), { wrapper }); + testMethod(); + }); + }); -// act(() => { -// const testMethod = async () => { -// result.current.updateUser(sampleData); -// await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); -// }; + test('Update user', async () => { + mockUseUpdateUser.mockImplementation(() => ({ + updateUser: () => {sampleData}, + isUpdating: false, + isSuccess: true, + })); + const { result } = renderHook(() => mockUseUpdateUser(), { wrapper }); -// testMethod(); -// }); -// }); -// }); + act(() => { + const testMethod = async () => { + result.current.updateUser(sampleData); + await waitFor(() => expect(result.current.isSuccess).toBeTruthy()); + }; + + testMethod(); + }); + }); +}); diff --git a/hotel-management/src/hooks/rooms/useDeleteRoom.ts b/hotel-management/src/hooks/rooms/useDeleteRoom.ts index 2a99f5d..56d3aeb 100644 --- a/hotel-management/src/hooks/rooms/useDeleteRoom.ts +++ b/hotel-management/src/hooks/rooms/useDeleteRoom.ts @@ -17,6 +17,7 @@ const useDeleteRoom = () => { const { isPending: isDeleting, mutate: deleteRoom, + isSuccess } = useMutation({ mutationFn: deleteRoomFn, onSuccess: () => { @@ -28,7 +29,7 @@ const useDeleteRoom = () => { onError: (err) => toast.error(err.message), }); - return { isDeleting, deleteRoom }; + return { isDeleting, deleteRoom, isSuccess }; }; export { useDeleteRoom }; diff --git a/hotel-management/src/hooks/rooms/useUpdateRoom.ts b/hotel-management/src/hooks/rooms/useUpdateRoom.ts index f0b748d..cc0baf4 100644 --- a/hotel-management/src/hooks/rooms/useUpdateRoom.ts +++ b/hotel-management/src/hooks/rooms/useUpdateRoom.ts @@ -18,7 +18,8 @@ const useUpdateRoom = () => { const { mutate: updateRoom, - isPending: isUpdating + isPending: isUpdating, + isSuccess } = useMutation({ mutationFn: updateRoomFn, onSuccess: (room) => { @@ -26,7 +27,7 @@ const useUpdateRoom = () => { queryClient.invalidateQueries({ queryKey: ['rooms'] }); // Update name room in global state - dispatch!({ + dispatch?.({ type: 'updateRoomName', payload: [{ id: room.id, name: room.name }], }); @@ -34,7 +35,7 @@ const useUpdateRoom = () => { onError: (err) => toast.error(err.message), }); - return { isUpdating, updateRoom }; + return { isUpdating, updateRoom, isSuccess }; }; export { useUpdateRoom }; From 42fa1ad628275691867fc2940e3cec56d98f4400 Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Thu, 23 Nov 2023 22:11:29 +0700 Subject: [PATCH 06/11] Update test case for services --- .../services/__tests__/roomService.test.ts | 71 +++++++++++++++++++ .../services/__tests__/userService.test.ts | 54 ++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 hotel-management/src/services/__tests__/roomService.test.ts create mode 100644 hotel-management/src/services/__tests__/userService.test.ts diff --git a/hotel-management/src/services/__tests__/roomService.test.ts b/hotel-management/src/services/__tests__/roomService.test.ts new file mode 100644 index 0000000..f3cc3a5 --- /dev/null +++ b/hotel-management/src/services/__tests__/roomService.test.ts @@ -0,0 +1,71 @@ +import { waitFor } from '@testing-library/react'; + +// Services +import { + createRoom, + deleteRoom, + getAllRooms, + updateRoom, +} from '@service/roomServices'; + +// Types +import { IRoom } from '@type/rooms'; + +const mockGetAllRooms = jest.fn(getAllRooms); +const mockUpdateRoom = jest.fn(updateRoom); +const mockCreateRoom = jest.fn(createRoom); +const mockDeleteRoom = jest.fn(deleteRoom); + +const sampleData: IRoom = { + id: 999, + name: 'Room name test', + price: 9999, + status: true, +}; + +describe('CRUD Room testing', () => { + test('Fetch room data', async () => { + mockGetAllRooms.mockResolvedValue([ + { + id: 1, + name: 'Nezumi', + price: 2500, + status: true, + }, + { + id: 2, + name: 'Loi Phan', + price: 8500, + status: false, + }, + ]); + const result = await mockGetAllRooms('name', 'asc', ''); + + await waitFor(() => expect(result.length).toEqual(2)); + }); + + test('Create room', async () => { + mockCreateRoom.mockResolvedValue(sampleData); + + const result = await mockCreateRoom(sampleData); + + await waitFor(() => expect(result).toBeTruthy()); + }); + + test('Update room', async () => { + mockUpdateRoom.mockResolvedValue({ + id: 1, + name: 'Nezumi', + price: 2500, + status: true, + }); + const result = await mockUpdateRoom(sampleData); + + await waitFor(() => expect(result).toBeTruthy()); + }); + + test('Delete room', async () => { + mockDeleteRoom.mockImplementation(() => Promise.resolve()); + await mockDeleteRoom(1); + }); +}); diff --git a/hotel-management/src/services/__tests__/userService.test.ts b/hotel-management/src/services/__tests__/userService.test.ts new file mode 100644 index 0000000..3b56b26 --- /dev/null +++ b/hotel-management/src/services/__tests__/userService.test.ts @@ -0,0 +1,54 @@ +import { waitFor } from '@testing-library/react'; + +// Services +import { createUser, getAllUsers, updateUser } from '@service/userServices'; + +// Types +import { IUser } from '@type/users'; + +const mockGetAllUsers = jest.fn(getAllUsers); +const mockCreateUser = jest.fn(createUser); +const mockUpdateUser = jest.fn(updateUser); + +const sampleData: IUser = { + id: 999, + name: 'User name test', + phone: '123456789', + isBooked: true, +}; + +describe('CRUD User testing', () => { + test('Fetch user data', async () => { + mockGetAllUsers.mockResolvedValue([ + { + id: 1, + name: 'Nezumi', + phone: '0324422123', + isBooked: true, + }, + { + id: 2, + name: 'Loi Phan', + phone: '0324422145', + isBooked: false, + }, + ]); + const result = await mockGetAllUsers('name', 'asc', ''); + + await waitFor(() => expect(result.length).toEqual(2)); + }); + + test('Create user', async () => { + mockCreateUser.mockResolvedValue(sampleData); + const result = await mockCreateUser(sampleData); + + await waitFor(() => expect(result).toBeTruthy()); + }); + + test('Update user', async () => { + mockUpdateUser.mockResolvedValue(sampleData); + const result = await mockUpdateUser(sampleData); + + await waitFor(() => expect(result).toBeTruthy()); + }); +}); From ea1187291c49c5472605abd4fe620887147327b9 Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Mon, 27 Nov 2023 10:11:05 +0700 Subject: [PATCH 07/11] Format code style and update test case --- .../src/helpers/__tests__/helpers.test.ts | 5 ++- .../src/helpers/__tests__/validators.test.ts | 25 +++++++---- .../src/hooks/__tests__/rooms.test.tsx | 45 +++++++++++-------- .../src/hooks/__tests__/useDebounce.test.tsx | 18 ++++---- .../hooks/__tests__/useOutsideClick.test.tsx | 6 ++- .../src/hooks/__tests__/users.test.tsx | 34 ++++++++------ .../services/__tests__/roomService.test.ts | 10 ++--- .../services/__tests__/userService.test.ts | 12 ++--- 8 files changed, 89 insertions(+), 66 deletions(-) diff --git a/hotel-management/src/helpers/__tests__/helpers.test.ts b/hotel-management/src/helpers/__tests__/helpers.test.ts index 01ac7da..8e71b7f 100644 --- a/hotel-management/src/helpers/__tests__/helpers.test.ts +++ b/hotel-management/src/helpers/__tests__/helpers.test.ts @@ -1,7 +1,8 @@ +// Helpers import { formatCurrency } from '@helper/helper'; -describe('Helpers function test', () => { - test('Format number to currency format', () => { +describe('formatCurrency', () => { + test('Should format correctly', () => { const result = formatCurrency(5000); expect(result).toEqual('$5,000.00'); diff --git a/hotel-management/src/helpers/__tests__/validators.test.ts b/hotel-management/src/helpers/__tests__/validators.test.ts index 611cf94..f2e31d6 100644 --- a/hotel-management/src/helpers/__tests__/validators.test.ts +++ b/hotel-management/src/helpers/__tests__/validators.test.ts @@ -1,42 +1,49 @@ +// Constants import { REGEX } from '@constant/commons'; -import { isValidDiscount, isValidRegex, isValidString } from '@helper/validators'; -describe('Check value is valid phone', () => { - test('Is valid phone', () => { +// Helpers +import { + isValidDiscount, + isValidRegex, + isValidString, +} from '@helper/validators'; + +describe('isValidPhone', () => { + test('Should is valid phone', () => { const result = isValidRegex(new RegExp(REGEX.PHONE), '0327212321'); expect(result).toEqual(true); }); - test('Is invalid phone', () => { + test('Should is not valid phone', () => { const result = isValidRegex(new RegExp(REGEX.PHONE), '0327212321Abc'); expect(result).toEqual(false); }); }); -describe('Check value is valid discount', () => { - test('Is valid discount', () => { +describe('isValidDiscount', () => { + test('Should is valid discount', () => { const result = isValidDiscount(23); expect(result).toEqual(true); }); - test('Is invalid discount', () => { + test('Should is not valid discount', () => { const result = isValidDiscount(101); expect(result).toEqual(false); }); }); -describe('Check value is valid string', () => { +describe('Should is valid string', () => { test('Is valid string', () => { const result = isValidString('Phan Huu Loi'); expect(result).toEqual(true); }); - test('Is valid string', () => { + test('Should is not valid string', () => { const result = isValidString('Phan'); expect(result).toEqual(false); diff --git a/hotel-management/src/hooks/__tests__/rooms.test.tsx b/hotel-management/src/hooks/__tests__/rooms.test.tsx index c70b563..70b747b 100644 --- a/hotel-management/src/hooks/__tests__/rooms.test.tsx +++ b/hotel-management/src/hooks/__tests__/rooms.test.tsx @@ -1,16 +1,17 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { act, renderHook, waitFor } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; +import { ReactNode } from 'react'; + +// Hooks import { useRooms } from '@hook/rooms/useRooms'; import { useCreateRoom } from '@hook/rooms/useCreateRoom'; -import { - QueryClient, - QueryClientProvider, -} from '@tanstack/react-query'; -import { act, renderHook, waitFor } from '@testing-library/react'; -import { IRoom } from '@type/rooms'; -import { ReactNode } from 'react'; -import { MemoryRouter } from 'react-router-dom'; import { useUpdateRoom } from '@hook/rooms/useUpdateRoom'; import { useDeleteRoom } from '@hook/rooms/useDeleteRoom'; +// Types +import { IRoom } from '@type/rooms'; + const mockUseRooms = jest.fn(useRooms); const mockUseCreateRoom = jest.fn(useCreateRoom); const mockUseUpdateRoom = jest.fn(useUpdateRoom); @@ -40,8 +41,8 @@ const wrapper = ({ children }: IWrapper) => { ); }; -describe('CRUD Room testing', () => { - test('Fetch room data', async () => { +describe('Room hooks', () => { + test('Should fetch data correctly', async () => { mockUseRooms.mockImplementation(() => ({ rooms: [ { @@ -66,11 +67,13 @@ describe('CRUD Room testing', () => { ); }); - test('Create room', async () => { + test('Should create room correctly', async () => { mockUseCreateRoom.mockImplementation(() => ({ - createRoom: () => {sampleData}, + createRoom: () => { + sampleData; + }, isCreating: false, - isSuccess: true + isSuccess: true, })); const { result } = renderHook(() => mockUseCreateRoom(), { wrapper }); @@ -83,11 +86,13 @@ describe('CRUD Room testing', () => { expect(result.current.isSuccess).toBeTruthy(); }); - test('Edit room', async () => { + test('Should edit room correctly', async () => { mockUseUpdateRoom.mockImplementation(() => ({ - updateRoom: () => {sampleData}, + updateRoom: () => { + sampleData; + }, isUpdating: false, - isSuccess: true + isSuccess: true, })); const { result } = renderHook(() => mockUseUpdateRoom(), { wrapper }); @@ -101,11 +106,13 @@ describe('CRUD Room testing', () => { }); }); - test('Delete room', async () => { + test('Should delete room correctly', async () => { mockUseDeleteRoom.mockImplementation(() => ({ - deleteRoom: () => {sampleData.id}, + deleteRoom: () => { + sampleData.id; + }, isDeleting: false, - isSuccess: true + isSuccess: true, })); const { result } = renderHook(() => mockUseDeleteRoom(), { wrapper }); diff --git a/hotel-management/src/hooks/__tests__/useDebounce.test.tsx b/hotel-management/src/hooks/__tests__/useDebounce.test.tsx index ab6fdd6..4eca0c2 100644 --- a/hotel-management/src/hooks/__tests__/useDebounce.test.tsx +++ b/hotel-management/src/hooks/__tests__/useDebounce.test.tsx @@ -1,8 +1,12 @@ -import { useDebounce } from '@hook/useDebounce'; import { fireEvent, render } from '@testing-library/react'; import { useState } from 'react'; import { act } from 'react-test-renderer'; +// Hooks +import { useDebounce } from '@hook/useDebounce'; + +jest.useFakeTimers(); + const TestComponent = ({ initialValue = 0 }: { initialValue?: number }) => { const [value, setValue] = useState(initialValue); const debouncedValue = useDebounce(value, 1000); @@ -17,29 +21,25 @@ const TestComponent = ({ initialValue = 0 }: { initialValue?: number }) => { }; describe('useDebouncedValue', function () { - afterEach(() => { - jest.useRealTimers(); - }); - test('Debounce value should not change before 1 second', () => { - jest.useFakeTimers(); const { getByTestId, getByText } = render(); const incrementButton = getByText('Increment'); const debouncedValue = getByTestId('debouncedValue'); const value = getByTestId('value'); - const incrementAndPassTime = (passedTime: number) => { + const clickAndWaitTime = (passedTime: number) => { act(() => { fireEvent.click(incrementButton); jest.advanceTimersByTime(passedTime); }); }; - incrementAndPassTime(999); + + clickAndWaitTime(100); expect(debouncedValue.textContent).toBe('0'); expect(value.textContent).toBe('1'); - incrementAndPassTime(1000); + clickAndWaitTime(1000); expect(debouncedValue.textContent).toBe('1'); expect(value.textContent).toBe('2'); diff --git a/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx b/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx index 2f01194..0178a71 100644 --- a/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx +++ b/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx @@ -1,7 +1,9 @@ -import { useOutsideClick } from '@hook/useOutsideClick'; import { fireEvent, render, renderHook, screen } from '@testing-library/react'; -describe('useOutsideClick testing', () => { +// Hooks +import { useOutsideClick } from '@hook/useOutsideClick'; + +describe('useOutsideClick', () => { test('Call handler when click outside element', () => { // Arrange const handler = jest.fn(); diff --git a/hotel-management/src/hooks/__tests__/users.test.tsx b/hotel-management/src/hooks/__tests__/users.test.tsx index 5958f17..a61b101 100644 --- a/hotel-management/src/hooks/__tests__/users.test.tsx +++ b/hotel-management/src/hooks/__tests__/users.test.tsx @@ -1,13 +1,17 @@ -import { useCreateUser } from '@hook/users/useCreateUser'; -import { useUpdateUser } from '@hook/users/useUpdateUser'; -import { useUsers } from '@hook/users/useUsers'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { renderHook, waitFor } from '@testing-library/react'; -import { IUser } from '@type/users'; import { ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { act } from 'react-test-renderer'; +// Hooks +import { useCreateUser } from '@hook/users/useCreateUser'; +import { useUpdateUser } from '@hook/users/useUpdateUser'; +import { useUsers } from '@hook/users/useUsers'; + +// Types +import { IUser } from '@type/users'; + const mockUseUsers = jest.fn(useUsers); const mockUseCreateUser = jest.fn(useCreateUser); const mockUseUpdateUser = jest.fn(useUpdateUser); @@ -37,8 +41,8 @@ const wrapper = ({ children }: IWrapper) => { ); }; -describe('CRUD User testing', () => { - test('Fetch user data', async () => { +describe('Users hook', () => { + test('Should fetch user data correctly', async () => { mockUseUsers.mockImplementation(() => ({ users: [ { @@ -55,17 +59,17 @@ describe('CRUD User testing', () => { }, ], isLoading: false, - })) + })); const { result } = renderHook(() => mockUseUsers(), { wrapper }); - await waitFor(() => - expect(result.current.users?.length).toEqual(2) - ); + await waitFor(() => expect(result.current.users?.length).toEqual(2)); }); - test('Create user', async () => { + test('Should create user correctly', async () => { mockUseCreateUser.mockImplementation(() => ({ - createUser: () => {sampleData}, + createUser: () => { + sampleData; + }, isCreating: false, isSuccess: true, })); @@ -81,9 +85,11 @@ describe('CRUD User testing', () => { }); }); - test('Update user', async () => { + test('Should update user correctly', async () => { mockUseUpdateUser.mockImplementation(() => ({ - updateUser: () => {sampleData}, + updateUser: () => { + sampleData; + }, isUpdating: false, isSuccess: true, })); diff --git a/hotel-management/src/services/__tests__/roomService.test.ts b/hotel-management/src/services/__tests__/roomService.test.ts index f3cc3a5..6519042 100644 --- a/hotel-management/src/services/__tests__/roomService.test.ts +++ b/hotel-management/src/services/__tests__/roomService.test.ts @@ -23,8 +23,8 @@ const sampleData: IRoom = { status: true, }; -describe('CRUD Room testing', () => { - test('Fetch room data', async () => { +describe('Rooms service', () => { + test('Should fetch room correctly', async () => { mockGetAllRooms.mockResolvedValue([ { id: 1, @@ -44,7 +44,7 @@ describe('CRUD Room testing', () => { await waitFor(() => expect(result.length).toEqual(2)); }); - test('Create room', async () => { + test('Should create room correctly', async () => { mockCreateRoom.mockResolvedValue(sampleData); const result = await mockCreateRoom(sampleData); @@ -52,7 +52,7 @@ describe('CRUD Room testing', () => { await waitFor(() => expect(result).toBeTruthy()); }); - test('Update room', async () => { + test('Should update room correctly', async () => { mockUpdateRoom.mockResolvedValue({ id: 1, name: 'Nezumi', @@ -64,7 +64,7 @@ describe('CRUD Room testing', () => { await waitFor(() => expect(result).toBeTruthy()); }); - test('Delete room', async () => { + test('Should delete room correctly', async () => { mockDeleteRoom.mockImplementation(() => Promise.resolve()); await mockDeleteRoom(1); }); diff --git a/hotel-management/src/services/__tests__/userService.test.ts b/hotel-management/src/services/__tests__/userService.test.ts index 3b56b26..9bf2619 100644 --- a/hotel-management/src/services/__tests__/userService.test.ts +++ b/hotel-management/src/services/__tests__/userService.test.ts @@ -17,20 +17,20 @@ const sampleData: IUser = { isBooked: true, }; -describe('CRUD User testing', () => { - test('Fetch user data', async () => { +describe('User services', () => { + test('Should fetch user data correctly', async () => { mockGetAllUsers.mockResolvedValue([ { id: 1, name: 'Nezumi', phone: '0324422123', - isBooked: true, + isBooked: true, }, { id: 2, name: 'Loi Phan', phone: '0324422145', - isBooked: false, + isBooked: false, }, ]); const result = await mockGetAllUsers('name', 'asc', ''); @@ -38,14 +38,14 @@ describe('CRUD User testing', () => { await waitFor(() => expect(result.length).toEqual(2)); }); - test('Create user', async () => { + test('Should create user correctly', async () => { mockCreateUser.mockResolvedValue(sampleData); const result = await mockCreateUser(sampleData); await waitFor(() => expect(result).toBeTruthy()); }); - test('Update user', async () => { + test('Should update user correctly', async () => { mockUpdateUser.mockResolvedValue(sampleData); const result = await mockUpdateUser(sampleData); From ddf96492c9479479fb45e3d9b8a0a5b7b64160e2 Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Mon, 27 Nov 2023 17:44:05 +0700 Subject: [PATCH 08/11] Improve test case function --- .../src/components/Menus/Menus.test.tsx | 65 +++++--- .../Menus/__snapshots__/Menus.test.tsx.snap | 139 ++++++++++++++---- .../src/components/OrderBy/Order.test.tsx | 28 ---- .../src/components/OrderBy/OrderBy.test.tsx | 40 +++++ .../OrderBy/__snapshots__/Order.test.tsx.snap | 110 +++++++++++--- .../src/components/Search/Search.test.tsx | 26 +++- .../Search/__snapshots__/Search.test.tsx.snap | 73 ++++++++- hotel-management/src/constants/commons.ts | 2 +- .../src/helpers/__tests__/validators.test.ts | 65 ++++++-- .../services/__tests__/roomService.test.ts | 13 ++ 10 files changed, 440 insertions(+), 121 deletions(-) delete mode 100644 hotel-management/src/components/OrderBy/Order.test.tsx create mode 100644 hotel-management/src/components/OrderBy/OrderBy.test.tsx diff --git a/hotel-management/src/components/Menus/Menus.test.tsx b/hotel-management/src/components/Menus/Menus.test.tsx index 5e4039d..781e901 100644 --- a/hotel-management/src/components/Menus/Menus.test.tsx +++ b/hotel-management/src/components/Menus/Menus.test.tsx @@ -1,31 +1,60 @@ -import renderer from 'react-test-renderer'; - // Components import Menus from '.'; import { RiEditBoxFill, RiDeleteBin2Line } from 'react-icons/ri'; +import { RenderResult, fireEvent, render } from '@testing-library/react'; describe('Menus', () => { const id = '123'; const handleOnClick = jest.fn(); - const wrapper = renderer.create( - - - + let wrapper: RenderResult | null = null; - - }> - Edit - - }> - Delete - - - - - ); + beforeEach(() => { + wrapper = render( + + + - test('Should render correctly', () => { + + }> + Edit + + }> + Delete + + + + + ); + }); + + test('Should render correctly', async () => { expect(wrapper).toMatchSnapshot(); }); + + test('Should show context menu', async () => { + const btn = await wrapper!.findByRole('button'); + + fireEvent.click(btn); + + const editBtn = wrapper!.getByText('Edit'); + + expect(editBtn).toBeInTheDocument(); + + fireEvent.click(btn); + + expect(editBtn).not.toBeInTheDocument(); + }); + + test('HandleOnClick should work', async () => { + const btn = await wrapper!.findByRole('button'); + + fireEvent.click(btn); + + const editBtn = wrapper!.getByText('Edit'); + + fireEvent.click(editBtn); + + expect(handleOnClick).toHaveBeenCalled(); + }); }); diff --git a/hotel-management/src/components/Menus/__snapshots__/Menus.test.tsx.snap b/hotel-management/src/components/Menus/__snapshots__/Menus.test.tsx.snap index e6606ee..7dee797 100644 --- a/hotel-management/src/components/Menus/__snapshots__/Menus.test.tsx.snap +++ b/hotel-management/src/components/Menus/__snapshots__/Menus.test.tsx.snap @@ -1,35 +1,114 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Menus Should render correctly 1`] = ` -
- +
+ + , + "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/components/OrderBy/Order.test.tsx b/hotel-management/src/components/OrderBy/Order.test.tsx deleted file mode 100644 index e3e47a0..0000000 --- a/hotel-management/src/components/OrderBy/Order.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import renderer from 'react-test-renderer'; -import { BrowserRouter } from 'react-router-dom'; - -// Components -import Order from '.'; - -describe('Order', () => { - const options = [ - { - value: 'Value 1', - label: 'Option 1', - }, - { - value: 'Value 2', - label: 'Option 2', - }, - ]; - - const wrapper = renderer.create( - - - - ); - - test('Should render correctly', () => { - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/hotel-management/src/components/OrderBy/OrderBy.test.tsx b/hotel-management/src/components/OrderBy/OrderBy.test.tsx new file mode 100644 index 0000000..ed46741 --- /dev/null +++ b/hotel-management/src/components/OrderBy/OrderBy.test.tsx @@ -0,0 +1,40 @@ +import { RenderResult, fireEvent, render } from '@testing-library/react'; + +// Components +import OrderBy from '.'; + +jest.mock('react-router-dom'); + +describe('Order', () => { + const options = [ + { + value: 'value1', + label: 'Option 1', + }, + { + value: 'value2', + label: 'Option 2', + }, + ]; + + let wrapper: RenderResult | null = null; + + beforeEach(() => { + wrapper = render(); + }); + + test('Should render correctly', () => { + expect(wrapper).toMatchSnapshot(); + }); + + test('handleClick should work correctly', async () => { + const mockSearchParams = jest.fn(); + // useSearchParams.search = mockSearchParams; + // setSearchParams = jest.fn(); + + const nameButton = wrapper!.getByText('Name'); + fireEvent.click(nameButton); + + expect(mockSearchParams).toHaveBeenCalled(); + }); +}); diff --git a/hotel-management/src/components/OrderBy/__snapshots__/Order.test.tsx.snap b/hotel-management/src/components/OrderBy/__snapshots__/Order.test.tsx.snap index 915c1ab..a72f02d 100644 --- a/hotel-management/src/components/OrderBy/__snapshots__/Order.test.tsx.snap +++ b/hotel-management/src/components/OrderBy/__snapshots__/Order.test.tsx.snap @@ -1,24 +1,94 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Order 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/components/Search/Search.test.tsx b/hotel-management/src/components/Search/Search.test.tsx index 5068e51..e19db87 100644 --- a/hotel-management/src/components/Search/Search.test.tsx +++ b/hotel-management/src/components/Search/Search.test.tsx @@ -1,18 +1,32 @@ -import renderer from 'react-test-renderer'; import { BrowserRouter } from 'react-router-dom'; // Components import Search from '.'; +import { RenderResult, fireEvent, render } from '@testing-library/react'; + +jest.useFakeTimers(); describe('Search', () => { const placeHolder = 'Search placeholder...'; - const wrapper = renderer.create( - - - - ); + 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 () => { + const searchField = await wrapper!.findByPlaceholderText('Search placeholder...'); + + fireEvent.input(searchField, 'test'); + + jest.advanceTimersByTime(500); + }); }); diff --git a/hotel-management/src/components/Search/__snapshots__/Search.test.tsx.snap b/hotel-management/src/components/Search/__snapshots__/Search.test.tsx.snap index a0f238e..366b3b6 100644 --- a/hotel-management/src/components/Search/__snapshots__/Search.test.tsx.snap +++ b/hotel-management/src/components/Search/__snapshots__/Search.test.tsx.snap @@ -1,9 +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/constants/commons.ts b/hotel-management/src/constants/commons.ts index 9e62af2..1d99359 100644 --- a/hotel-management/src/constants/commons.ts +++ b/hotel-management/src/constants/commons.ts @@ -51,7 +51,7 @@ const FORM = { }; const REGEX = { - PHONE: /(84|0[3|5|7|8|9])+([0-9]{8})\b/g, + PHONE: /(0[3|5|7|8|9])+([0-9]{8})\b/g, NAME: /^[a-zA-Z]{2,}(?: [a-zA-Z]+){0,2}$/gm, NUMBER: /^[0-9]*$/, }; diff --git a/hotel-management/src/helpers/__tests__/validators.test.ts b/hotel-management/src/helpers/__tests__/validators.test.ts index f2e31d6..61d6b94 100644 --- a/hotel-management/src/helpers/__tests__/validators.test.ts +++ b/hotel-management/src/helpers/__tests__/validators.test.ts @@ -9,43 +9,82 @@ import { } from '@helper/validators'; describe('isValidPhone', () => { - test('Should is valid phone', () => { - const result = isValidRegex(new RegExp(REGEX.PHONE), '0327212321'); + const isValidPhone = (phone: string) => + isValidRegex(new RegExp(REGEX.PHONE), phone); - expect(result).toEqual(true); + test('Should is valid phone', () => { + const case_1 = isValidPhone('0321123212'); + const case_2 = isValidPhone('0533245422'); + const case_3 = isValidPhone('0723342321'); + const case_4 = isValidPhone('0823654321'); + const case_5 = isValidPhone('0943212343'); + + expect(case_1).toBeTruthy(); + expect(case_2).toBeTruthy(); + expect(case_3).toBeTruthy(); + expect(case_4).toBeTruthy(); + expect(case_5).toBeTruthy(); }); test('Should is not valid phone', () => { - const result = isValidRegex(new RegExp(REGEX.PHONE), '0327212321Abc'); + const case_1 = isValidPhone('0327212321Abc'); + const case_2 = isValidPhone('0021432123'); + const case_3 = isValidPhone('@325542321'); + const case_4 = isValidPhone('A321443232'); + const case_5 = isValidPhone('ValidPhone'); + const case_6 = isValidPhone('000'); - expect(result).toEqual(false); + expect(case_1).toBeFalsy(); + expect(case_2).toBeFalsy(); + expect(case_3).toBeFalsy(); + expect(case_4).toBeFalsy(); + expect(case_5).toBeFalsy(); + expect(case_6).toBeFalsy(); }); }); describe('isValidDiscount', () => { test('Should is valid discount', () => { - const result = isValidDiscount(23); + const case_1 = isValidDiscount(99.99); + const case_2 = isValidDiscount(50); + const case_3 = isValidDiscount(0); + const case_4 = isValidDiscount(100); - expect(result).toEqual(true); + expect(case_1).toBeTruthy(); + expect(case_2).toBeTruthy(); + expect(case_3).toBeTruthy(); + expect(case_4).toBeTruthy(); }); test('Should is not valid discount', () => { - const result = isValidDiscount(101); + const case_1 = isValidDiscount(-1); + const case_2 = isValidDiscount(-0.99); + const case_3 = isValidDiscount(101); - expect(result).toEqual(false); + expect(case_1).toBeFalsy(); + expect(case_2).toBeFalsy(); + expect(case_3).toBeFalsy(); }); }); describe('Should is valid string', () => { test('Is valid string', () => { - const result = isValidString('Phan Huu Loi'); + const case_1 = isValidString('Phan Huu Loi'); + const case_2 = isValidString('Nezumi'); - expect(result).toEqual(true); + expect(case_1).toBeTruthy(); + expect(case_2).toBeTruthy(); }); test('Should is not valid string', () => { - const result = isValidString('Phan'); + const case_1 = isValidString('Le'); + const case_2 = isValidString('1tét'); + const case_3 = isValidString('@!'); + const case_4 = isValidString(' '); - expect(result).toEqual(false); + expect(case_1).toBeFalsy(); + expect(case_2).toBeFalsy(); + expect(case_3).toBeFalsy(); + expect(case_4).toBeFalsy(); }); }); diff --git a/hotel-management/src/services/__tests__/roomService.test.ts b/hotel-management/src/services/__tests__/roomService.test.ts index 6519042..a348130 100644 --- a/hotel-management/src/services/__tests__/roomService.test.ts +++ b/hotel-management/src/services/__tests__/roomService.test.ts @@ -10,6 +10,7 @@ import { // Types import { IRoom } from '@type/rooms'; +import supabase from '@service/supabaseService'; const mockGetAllRooms = jest.fn(getAllRooms); const mockUpdateRoom = jest.fn(updateRoom); @@ -44,6 +45,18 @@ describe('Rooms service', () => { await waitFor(() => expect(result.length).toEqual(2)); }); + test('Can not fetch data', async () => { + jest.spyOn(supabase.from('rooms').select(), 'single').mockRejectedValue(() => { + return { + error: 'Error' + } + }) + + await mockGetAllRooms('name', 'asc', ''); + + expect(mockGetAllRooms).toThrow(); + }); + test('Should create room correctly', async () => { mockCreateRoom.mockResolvedValue(sampleData); From 7bb83f74c8422497f848b1b43b0835d8477feddd Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Tue, 28 Nov 2023 17:49:22 +0700 Subject: [PATCH 09/11] Update test case for sortBy, select, orderBy component --- hotel-management/package.json | 3 +- .../src/__snapshots__/App.test.tsx.snap | 1156 +++++++++++++++++ .../src/components/OrderBy/OrderBy.test.tsx | 32 +- ...er.test.tsx.snap => OrderBy.test.tsx.snap} | 0 .../src/components/Search/Search.test.tsx | 67 +- .../Select/__snapshots__/Select.test.tsx.snap | 2 + .../src/components/Select/index.tsx | 2 +- .../src/components/SortBy/SortBy.test.tsx | 45 +- .../SortBy/__snapshots__/SortBy.test.tsx.snap | 111 +- .../userRoomAvailableContext.test.tsx | 40 + .../pages/Room/__tests__/RoomForm.test.tsx | 22 - .../src/pages/Room/__tests__/RoomRow.test.tsx | 28 - .../pages/Room/__tests__/RoomTable.test.tsx | 22 - .../__snapshots__/RoomForm.test.tsx.snap | 67 - .../__snapshots__/RoomRow.test.tsx.snap | 53 - .../__snapshots__/RoomTable.test.tsx.snap | 63 - .../__snapshots__/index.test.tsx.snap | 84 -- .../src/pages/Room/__tests__/index.test.tsx | 22 - .../__snapshots__/UserTable.test.tsx.snap | 3 + .../__snapshots__/index.test.tsx.snap | 3 + 20 files changed, 1412 insertions(+), 413 deletions(-) create mode 100644 hotel-management/src/__snapshots__/App.test.tsx.snap rename hotel-management/src/components/OrderBy/__snapshots__/{Order.test.tsx.snap => OrderBy.test.tsx.snap} (100%) create mode 100644 hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx delete mode 100644 hotel-management/src/pages/Room/__tests__/RoomForm.test.tsx delete mode 100644 hotel-management/src/pages/Room/__tests__/RoomRow.test.tsx delete mode 100644 hotel-management/src/pages/Room/__tests__/RoomTable.test.tsx delete mode 100644 hotel-management/src/pages/Room/__tests__/__snapshots__/RoomForm.test.tsx.snap delete mode 100644 hotel-management/src/pages/Room/__tests__/__snapshots__/RoomRow.test.tsx.snap delete mode 100644 hotel-management/src/pages/Room/__tests__/__snapshots__/RoomTable.test.tsx.snap delete mode 100644 hotel-management/src/pages/Room/__tests__/__snapshots__/index.test.tsx.snap delete mode 100644 hotel-management/src/pages/Room/__tests__/index.test.tsx diff --git a/hotel-management/package.json b/hotel-management/package.json index 57eddfc..d13cb38 100644 --- a/hotel-management/package.json +++ b/hotel-management/package.json @@ -8,7 +8,8 @@ "build": "tsc && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", - "test": "jest --coverage" + "test-ci": "jest --coverage", + "test": "jest --runTestsByPath" }, "coverageReporters": [ "html" diff --git a/hotel-management/src/__snapshots__/App.test.tsx.snap b/hotel-management/src/__snapshots__/App.test.tsx.snap new file mode 100644 index 0000000..9314d15 --- /dev/null +++ b/hotel-management/src/__snapshots__/App.test.tsx.snap @@ -0,0 +1,1156 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`App Render with data 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+
+

+ Hi, + Admin + ! +

+
    +
  • + +
  • +
  • + +
  • +
+
+ +
+
+

+ This page currently still develop. Please try again later! +

+
+
+
+
+
+ , + "container":
+
+
+

+ Hi, + Admin + ! +

+
    +
  • + +
  • +
  • + +
  • +
+
+ +
+
+

+ This page currently still develop. Please try again later! +

+
+
+
+
+
, + "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], +} +`; + +exports[`App Should init room, user data 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+
+

+ Hi, + Admin + ! +

+
    +
  • + +
  • +
  • + +
  • +
+
+ +
+
+

+ This page currently still develop. Please try again later! +

+
+
+
+
+
+ , + "container":
+
+
+

+ Hi, + Admin + ! +

+
    +
  • + +
  • +
  • + +
  • +
+
+ +
+
+

+ This page currently still develop. Please try again later! +

+
+
+
+
+
, + "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], +} +`; + +exports[`App Should render correctly 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+
+

+ Hi, + Admin + ! +

+
    +
  • + +
  • +
  • + +
  • +
+
+ +
+
+

+ This page currently still develop. Please try again later! +

+
+
+
+
+
+ , + "container":
+
+
+

+ Hi, + Admin + ! +

+
    +
  • + +
  • +
  • + +
  • +
+
+ +
+
+

+ This page currently still develop. Please try again later! +

+
+
+
+
+
, + "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/OrderBy/OrderBy.test.tsx b/hotel-management/src/components/OrderBy/OrderBy.test.tsx index ed46741..4b31ef3 100644 --- a/hotel-management/src/components/OrderBy/OrderBy.test.tsx +++ b/hotel-management/src/components/OrderBy/OrderBy.test.tsx @@ -1,9 +1,25 @@ +import { useState } from 'react'; import { RenderResult, fireEvent, render } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; // Components import OrderBy from '.'; -jest.mock('react-router-dom'); +let mockSearchParam = ''; + +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)); + }, + ]; + }, +})); describe('Order', () => { const options = [ @@ -20,7 +36,11 @@ describe('Order', () => { let wrapper: RenderResult | null = null; beforeEach(() => { - wrapper = render(); + wrapper = render( + + + + ); }); test('Should render correctly', () => { @@ -28,13 +48,9 @@ describe('Order', () => { }); test('handleClick should work correctly', async () => { - const mockSearchParams = jest.fn(); - // useSearchParams.search = mockSearchParams; - // setSearchParams = jest.fn(); - - const nameButton = wrapper!.getByText('Name'); + const nameButton = wrapper!.getByText('Option 2'); fireEvent.click(nameButton); - expect(mockSearchParams).toHaveBeenCalled(); + expect(mockSearchParam.toString()).toEqual('orderBy=value2'); }); }); diff --git a/hotel-management/src/components/OrderBy/__snapshots__/Order.test.tsx.snap b/hotel-management/src/components/OrderBy/__snapshots__/OrderBy.test.tsx.snap similarity index 100% rename from hotel-management/src/components/OrderBy/__snapshots__/Order.test.tsx.snap rename to hotel-management/src/components/OrderBy/__snapshots__/OrderBy.test.tsx.snap diff --git a/hotel-management/src/components/Search/Search.test.tsx b/hotel-management/src/components/Search/Search.test.tsx index e19db87..fd3fb05 100644 --- a/hotel-management/src/components/Search/Search.test.tsx +++ b/hotel-management/src/components/Search/Search.test.tsx @@ -1,32 +1,67 @@ import { BrowserRouter } from 'react-router-dom'; +import { useState } from 'react'; // Components import Search from '.'; -import { RenderResult, fireEvent, render } from '@testing-library/react'; +import { + RenderResult, + fireEvent, + render, + act, +} 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)); + }, + ]; + }, +})); describe('Search', () => { - const placeHolder = 'Search placeholder...'; - let wrapper: RenderResult | null = null; + // const placeHolder = 'Search placeholder...'; + // let wrapper: RenderResult | null = null; - beforeEach(() => { - wrapper = render( - - - - ); - }) + // beforeEach(() => { + // wrapper = render( + // + // + // + // ); + // }); - test('Should render correctly', () => { - expect(wrapper).toMatchSnapshot(); - }); + // test('Should render correctly', () => { + // expect(wrapper).toMatchSnapshot(); + // }); test('Should add query to url after 1 second', async () => { - const searchField = await wrapper!.findByPlaceholderText('Search placeholder...'); + let wrapper: RenderResult | null = null; + act(() => { + wrapper = render( + + + + ); + }); - fireEvent.input(searchField, 'test'); + const searchField = await wrapper!.findByPlaceholderText( + 'Search placeholder...' + ); - jest.advanceTimersByTime(500); + act(() => { + fireEvent.change(searchField, { target: { value: 'abc' } }); + }); + + // jest.advanceTimersByTime(1000); }); }); + \ No newline at end of file diff --git a/hotel-management/src/components/Select/__snapshots__/Select.test.tsx.snap b/hotel-management/src/components/Select/__snapshots__/Select.test.tsx.snap index bf1a8d0..cc869d6 100644 --- a/hotel-management/src/components/Select/__snapshots__/Select.test.tsx.snap +++ b/hotel-management/src/components/Select/__snapshots__/Select.test.tsx.snap @@ -8,11 +8,13 @@ exports[`Select Should render correctly 1`] = ` value="Temp value" > ))} diff --git a/hotel-management/src/components/SortBy/SortBy.test.tsx b/hotel-management/src/components/SortBy/SortBy.test.tsx index 9df9124..28b6454 100644 --- a/hotel-management/src/components/SortBy/SortBy.test.tsx +++ b/hotel-management/src/components/SortBy/SortBy.test.tsx @@ -1,27 +1,54 @@ -import renderer from 'react-test-renderer'; import { BrowserRouter } from 'react-router-dom'; - +import { useState } from 'react'; +import { render, fireEvent, RenderResult } from '@testing-library/react'; // Components import SortBy from '.'; +let mockSearchParam = ''; +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)); + }, + ]; + }, +})); + describe('SortBy', () => { const options = [ { label: 'Option 1', - value: 'Value 1', + value: 'Value1', }, { label: 'Option 2', - value: 'Value 2', + value: 'Value2', }, ]; - const wrapper = renderer.create( - - - - ); + let wrapper: RenderResult | null = null; + + beforeEach(() => { + wrapper = render( + + + + ); + }); test('Should render correctly', () => { expect(wrapper).toMatchSnapshot(); }); + + test('handleClick should work correctly', () => { + const select = wrapper!.getByLabelText('Sort') as HTMLSelectElement; + + fireEvent.change(select, { target: { value: 'Value2' } }); + + expect(mockSearchParam.toString()).toEqual('sortBy=Value2'); + }); }); diff --git a/hotel-management/src/components/SortBy/__snapshots__/SortBy.test.tsx.snap b/hotel-management/src/components/SortBy/__snapshots__/SortBy.test.tsx.snap index a93cc33..9638f02 100644 --- a/hotel-management/src/components/SortBy/__snapshots__/SortBy.test.tsx.snap +++ b/hotel-management/src/components/SortBy/__snapshots__/SortBy.test.tsx.snap @@ -1,21 +1,98 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`SortBy 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 new file mode 100644 index 0000000..5cf3bda --- /dev/null +++ b/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx @@ -0,0 +1,40 @@ +import { render, act } from '@testing-library/react'; +import * as userServices from '@service/userServices'; +import * as roomServices from '@service/roomServices'; +import App from '../../App'; + +jest.mock('@service/userServices'); +jest.mock('@service/roomServices'); + +describe('App', () => { + test('Should init room, user data', async () => { + const mockGetUserNotBooked = jest.spyOn(userServices, 'getUserNotBooked'); + const mockGetRoomAvailable = jest.spyOn(roomServices, 'getRoomsAvailable'); + + mockGetUserNotBooked.mockResolvedValue([ + { + id: 1, + name: 'Nezumi', + }, + { + id: 2, + name: 'Loi Phan', + }, + ]); + + mockGetRoomAvailable.mockResolvedValue([ + { + id: 1, + name: 'Room 1', + }, + { + id: 2, + name: 'Room 2', + }, + ]); + + await act(async () => { + render(); + }); + }); +}); diff --git a/hotel-management/src/pages/Room/__tests__/RoomForm.test.tsx b/hotel-management/src/pages/Room/__tests__/RoomForm.test.tsx deleted file mode 100644 index c63a486..0000000 --- a/hotel-management/src/pages/Room/__tests__/RoomForm.test.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { BrowserRouter } from 'react-router-dom'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import renderer from 'react-test-renderer'; - -// Components -import RoomForm from '../RoomForm'; - -describe('RoomForm', () => { - const queryClient = new QueryClient(); - - const wrapper = renderer.create( - - - - - - ); - - test('Should render correctly', () => { - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/hotel-management/src/pages/Room/__tests__/RoomRow.test.tsx b/hotel-management/src/pages/Room/__tests__/RoomRow.test.tsx deleted file mode 100644 index e8aa24e..0000000 --- a/hotel-management/src/pages/Room/__tests__/RoomRow.test.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import renderer from 'react-test-renderer'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; - -// Types -import { IRoom } from '@type/rooms'; - -// Components -import RoomRow from '../RoomRow'; - -describe('RoomRow', () => { - const tempRoom: IRoom = { - id: 1, - name: 'Temp Room', - price: 250, - status: true, - }; - const queryClient = new QueryClient(); - - const wrapper = renderer.create( - - - - ); - - test('Should render correctly', () => { - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/hotel-management/src/pages/Room/__tests__/RoomTable.test.tsx b/hotel-management/src/pages/Room/__tests__/RoomTable.test.tsx deleted file mode 100644 index 13a76c1..0000000 --- a/hotel-management/src/pages/Room/__tests__/RoomTable.test.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import renderer from 'react-test-renderer'; -import { BrowserRouter } from 'react-router-dom'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; - -// Components -import RoomTable from '../RoomTable'; - -describe('RoomTable', () => { - const queryClient = new QueryClient(); - - const wrapper = renderer.create( - - - - - - ); - - test('Should render correctly', () => { - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomForm.test.tsx.snap b/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomForm.test.tsx.snap deleted file mode 100644 index 9cc4c07..0000000 --- a/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomForm.test.tsx.snap +++ /dev/null @@ -1,67 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RoomForm Should render correctly 1`] = ` -
-
- -
- -
-
-
- -
- -
-
-
- - -
-
-`; diff --git a/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomRow.test.tsx.snap b/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomRow.test.tsx.snap deleted file mode 100644 index 228a2f7..0000000 --- a/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomRow.test.tsx.snap +++ /dev/null @@ -1,53 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RoomRow Should render correctly 1`] = ` -
-
- 1 -
-
- Temp Room -
-
- $250.00 -
-
- Unavailable -
-
-
- -
-
-
-`; diff --git a/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomTable.test.tsx.snap b/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomTable.test.tsx.snap deleted file mode 100644 index 86243e4..0000000 --- a/hotel-management/src/pages/Room/__tests__/__snapshots__/RoomTable.test.tsx.snap +++ /dev/null @@ -1,63 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RoomTable Should render correctly 1`] = ` -
-
-
- - -
- - -
-
-
-`; diff --git a/hotel-management/src/pages/Room/__tests__/__snapshots__/index.test.tsx.snap b/hotel-management/src/pages/Room/__tests__/__snapshots__/index.test.tsx.snap deleted file mode 100644 index 6fb4c8d..0000000 --- a/hotel-management/src/pages/Room/__tests__/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,84 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Room Should render correctly 1`] = ` -
-
-

- List Room -

- -
-
-
-
- - -
- - -
-
-
-
-`; diff --git a/hotel-management/src/pages/Room/__tests__/index.test.tsx b/hotel-management/src/pages/Room/__tests__/index.test.tsx deleted file mode 100644 index 64fba84..0000000 --- a/hotel-management/src/pages/Room/__tests__/index.test.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import Room from '..'; -import { BrowserRouter } from 'react-router-dom'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; - -// Components -import renderer from 'react-test-renderer'; - -describe('Room', () => { - const queryClient = new QueryClient(); - - const wrapper = renderer.create( - - - - - - ); - - test('Should render correctly', () => { - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/hotel-management/src/pages/User/__tests__/__snapshots__/UserTable.test.tsx.snap b/hotel-management/src/pages/User/__tests__/__snapshots__/UserTable.test.tsx.snap index faf6c5b..3dc67b9 100644 --- a/hotel-management/src/pages/User/__tests__/__snapshots__/UserTable.test.tsx.snap +++ b/hotel-management/src/pages/User/__tests__/__snapshots__/UserTable.test.tsx.snap @@ -35,16 +35,19 @@ exports[`UserTable Should render correctly 1`] = ` value="" >