From d99f926a8df84bc78e743bf2af888df0cdf365b1 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 15:14:29 +0200 Subject: [PATCH 01/27] added useQuery and useMutation hooks t CategoryDropdown page --- .../category-dropdown/CategoryDropdown.tsx | 62 ++++++++++++------- src/services/resource-service.ts | 15 +++++ .../CategoryDropdown.spec.jsx | 24 ++++--- 3 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 9a1647fcbb..f50a40573c 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -4,7 +4,6 @@ import Box from '@mui/material/Box' import Divider from '@mui/material/Divider' import AddIcon from '@mui/icons-material/Add' -import useAxios from '~/hooks/use-axios' import { useModalContext } from '~/context/modal-context' import { useAppDispatch } from '~/hooks/use-redux' import { ResourceService } from '~/services/resource-service' @@ -27,6 +26,8 @@ import { } from '~/containers/category-dropdown/CategoryDropdown.constants' import { openAlert } from '~/redux/features/snackbarSlice' import { getErrorKey } from '~/utils/get-error-key' +import useQuery from '~/hooks/use-query' +import useMutation from '~/hooks/use-mutation' interface CategoryDropdownInterface { category: string | null @@ -44,20 +45,25 @@ const CategoryDropdown = ({ const dispatch = useAppDispatch() const { openModal, closeModal } = useModalContext() - const handleResponseError = (error?: ErrorResponse) => { - dispatch( - openAlert({ - severity: snackbarVariants.error, - message: getErrorKey(error) - }) - ) - } + const handleResponseError = useCallback( + (error?: ErrorResponse) => { + dispatch( + openAlert({ + severity: snackbarVariants.error, + message: getErrorKey(error) + }) + ) + }, + [dispatch] + ) - const { response: allCategoriesNames, fetchData: fetchAllCategoriesNames } = - useAxios({ - service: ResourceService.getResourcesCategoriesNames, - defaultResponse: [], - fetchOnMount: true + const { data: allCategoriesNames, refetch: fetchAllCategoriesNames } = + useQuery({ + queryKey: ['categoriesNames'], + queryFn: ResourceService.getResourcesCategoriesName, + options: { + initialData: [] + } }) const onCreateCategory = () => { @@ -65,16 +71,23 @@ const CategoryDropdown = ({ component: ( item.name)} /> ) }) } + const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => + new Promise((resolve, reject) => { + handleCreateCategory(params, { + onSuccess: () => resolve(), + onError: (error) => reject(error) + }) + }) const createCategory = useCallback( - (params?: CreateCategoriesParams) => - ResourceService.createResourceCategory(params), + async (params?: CreateCategoriesParams): Promise => + await ResourceService.createCategory(params), [] ) @@ -99,14 +112,15 @@ const CategoryDropdown = ({ [dispatch, fetchAllCategoriesNames] ) - const { fetchData: handleCreateCategory } = useAxios({ - service: createCategory, - defaultResponse: null, - fetchOnMount: false, - onResponse: onResponseCategory, - onResponseError: handleResponseError + const { mutate: handleCreateCategory } = useMutation({ + mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + onSuccess: async (response) => { + await onResponseCategory(response) + }, + onError: (error: ErrorResponse) => { + handleResponseError(error) + } }) - const optionsList = ( props: HTMLAttributes, option: string, diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index 9f1bec1b7d..5e7ccb3daa 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -145,10 +145,25 @@ export const ResourceService = { getResourcesCategoriesNames: (): Promise< AxiosResponse > => axiosClient.get(URLs.resources.resourcesCategories.getNames), + getResourcesCategoriesName: () => { + return baseService.request({ + method: 'GET', + url: URLs.resources.resourcesCategories.getNames + }) + }, createResourceCategory: async ( params?: CreateCategoriesParams ): Promise> => await axiosClient.post(URLs.resources.resourcesCategories.post, params), + createCategory: async ( + params?: CreateCategoriesParams + ): Promise => { + return await baseService.request({ + method: 'POST', + url: URLs.resources.resourcesCategories.post, + data: params || {} + }) + }, deleteResourceCategory: async (id: string): Promise => await axiosClient.delete( createUrlPath(URLs.resources.resourcesCategories.delete, id) diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 5d5dbc5912..a8a2b70eb1 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,26 +1,31 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' import { URLs } from '~/constants/request' - +import { baseService } from '~/services/base-service' +import useQuery from '~/hooks/use-query' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' const categoriesNamesMock = [ { _id: '650c27618a9fbf234b8bb4cf', name: 'New category in resources!' }, { _id: '650c27618a9fbf234b8bb4cd', name: 'Category 1' } ] - +vi.mock('~/hooks/use-query', () => ({ + __esModule: true, + default: vi.fn(), +})) describe('CategoryDropdown test', () => { - mockAxiosClient - .onGet(URLs.resources.resourcesCategories.getNames) - .reply(200, categoriesNamesMock) - - beforeEach(async () => { - await waitFor(() => { - renderWithProviders() + beforeEach(() => { + useQuery.mockReturnValue({ + data: categoriesNamesMock, + refetch: vi.fn(), }) }) + afterEach(() => { + vi.clearAllMocks() + }) it('should choose the category from options list', async () => { + renderWithProviders() const autocomplete = screen.getByRole('combobox') expect(autocomplete).toBeInTheDocument() @@ -47,6 +52,7 @@ describe('CategoryDropdown test', () => { }) it('should click on "add button" in options list', async () => { + renderWithProviders() const autocomplete = screen.getByRole('combobox') fireEvent.click(autocomplete) From 1200f8f1e8f174fe1b4ccdba8b793a59dea63a6e Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 17:14:52 +0200 Subject: [PATCH 02/27] changed occurrence files that also have service functions from CategoryDropdown --- .../app-button-menu/AppButtonMenu.tsx | 16 +++---- .../category-dropdown/CategoryDropdown.tsx | 2 +- .../add-resource-modal/AddResourceModal.tsx | 2 +- .../CategoriesContainer.tsx | 42 ++++++++++++------- .../ResourcesToolbarDrawer.tsx | 2 +- src/services/resource-service.ts | 4 -- src/types/services/types/services.types.ts | 9 ++-- .../app-button-menu/AppButtonMenu.spec.jsx | 9 +++- .../CategoryDropdown.spec.jsx | 4 +- 9 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/components/app-button-menu/AppButtonMenu.tsx b/src/components/app-button-menu/AppButtonMenu.tsx index 33dcea5319..55f3a2b975 100644 --- a/src/components/app-button-menu/AppButtonMenu.tsx +++ b/src/components/app-button-menu/AppButtonMenu.tsx @@ -10,25 +10,24 @@ import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline' import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown' import CircleIcon from '@mui/icons-material/Circle' -import useAxios from '~/hooks/use-axios' +import useQuery from '~/hooks/use-query' import useMenu from '~/hooks/use-menu' import Loader from '~/components/loader/Loader' import AppButton from '~/components/app-button/AppButton' import AppMenuButton from '~/components/app-menu-button/AppMenuButton' import AppSelectButton from '~/components/app-select-button/AppSelectButton' -import { defaultResponses } from '~/constants' import { spliceSx } from '~/utils/helper-functions' import { styles } from '~/components/app-button-menu/AppButtonMenu.styles' import { ButtonVariantEnum, CategoryNameInterface, - ServiceFunction + ServiceFunctionNew } from '~/types' interface AppButtonMenuProps extends Omit { title: string - service: ServiceFunction + service: ServiceFunctionNew selectedItems: string[] setSelectedItems: (value: string[]) => void position?: PopoverOrigin['horizontal'] @@ -65,9 +64,12 @@ const AppButtonMenu = >({ setSelectedItems([]) } - const { loading, response } = useAxios({ - service, - defaultResponse: defaultResponses.array + const { data: response, isLoading: loading } = useQuery({ + queryKey: [title], + queryFn: () => service(), + options: { + initialData: [] + } }) const filteredItems = useMemo(() => { diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index f50a40573c..35cc4c1ce9 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -87,7 +87,7 @@ const CategoryDropdown = ({ }) const createCategory = useCallback( async (params?: CreateCategoriesParams): Promise => - await ResourceService.createCategory(params), + await ResourceService.createResourceCategory(params), [] ) diff --git a/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx b/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx index 64305de746..c04272bb51 100644 --- a/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx +++ b/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx @@ -89,7 +89,7 @@ const AddResourceModal = ({ /> selectedItems={selectedItems} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={setSelectedItems} showNoneProperty title={t('myResourcesPage.categories.category')} diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index ca398f515f..19a28c8d24 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -32,8 +32,7 @@ import { GetResourcesCategoriesParams, ErrorResponse, ResourcesTabsEnum, - CreateCategoriesParams, - CategoryNameInterface + CreateCategoriesParams } from '~/types' import { adjustColumns, getScreenBasedLimit } from '~/utils/helper-functions' @@ -41,6 +40,8 @@ import { styles } from '~/containers/my-resources/categories-container/Categorie import { useAppDispatch } from '~/hooks/use-redux' import { openAlert } from '~/redux/features/snackbarSlice' import { getErrorKey } from '~/utils/get-error-key' +import useMutation from '~/hooks/use-mutation' +import useQuery from '~/hooks/use-query' const CategoriesContainer = () => { const { t } = useTranslation() @@ -118,12 +119,13 @@ const CategoriesContainer = () => { onResponseError }) - const { response: allCategoriesNames, fetchData: fetchAllCategoriesNames } = - useAxios({ - service: ResourceService.getResourcesCategoriesNames, - defaultResponse: [], - onResponseError, - fetchOnMount: true + const { data: allCategoriesNames, refetch: fetchAllCategoriesNames } = + useQuery({ + queryKey: ['categoriesNames'], + queryFn: ResourceService.getResourcesCategoriesName, + options: { + initialData: [] + } }) const onCategoryUpdate = useCallback(async () => { @@ -138,14 +140,22 @@ const CategoriesContainer = () => { [fetchData, fetchAllCategoriesNames, onResponse] ) - const { fetchData: handleCreateCategory } = useAxios({ - service: createCategory, - defaultResponse: null, - fetchOnMount: false, - onResponseError, - onResponse: onCategoryCreate + const { mutate: handleCreateCategory } = useMutation({ + mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + onSuccess: async (response) => { + await onCategoryCreate(response) + }, + onError: (error: ErrorResponse) => { + onResponseError(error) + } }) - + const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => + new Promise((resolve, reject) => { + handleCreateCategory(params, { + onSuccess: () => resolve(), + onError: (error) => reject(error) + }) + }) const existingCategoriesNames = allCategoriesNames?.map((item) => item.name) const onAdd = () => { @@ -153,7 +163,7 @@ const CategoriesContainer = () => { component: ( ) diff --git a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx index 652200c37d..8256f53c76 100644 --- a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx +++ b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx @@ -85,7 +85,7 @@ const ResourcesToolBarDrawer: FC = ({ customSx={styles.filter} selectedItems={data.categories} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={onCategoryChange} showNoneProperty slotProps={{ paper: styles.filterPaper(isMobile) }} diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index 5e7ccb3daa..7bff875c08 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -153,10 +153,6 @@ export const ResourceService = { }, createResourceCategory: async ( params?: CreateCategoriesParams - ): Promise> => - await axiosClient.post(URLs.resources.resourcesCategories.post, params), - createCategory: async ( - params?: CreateCategoriesParams ): Promise => { return await baseService.request({ method: 'POST', diff --git a/src/types/services/types/services.types.ts b/src/types/services/types/services.types.ts index e8074ec326..278dbc2ef1 100644 --- a/src/types/services/types/services.types.ts +++ b/src/types/services/types/services.types.ts @@ -18,9 +18,12 @@ export type ServiceFunction = ( params: Params extends undefined ? undefined : Params ) => Promise> -export type ServiceFunctionNew = ( - params: Params extends undefined ? undefined : Params -) => Promise +export type ServiceFunctionNew< + Response, + Params = undefined +> = Params extends undefined + ? () => Promise + : (params: Params) => Promise export interface AxiosResponseError extends AxiosError { config: InternalAxiosRequestConfig & { _isRetry: boolean } diff --git a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx index eeb157acd3..19044ea394 100644 --- a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx +++ b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx @@ -1,5 +1,6 @@ import { render, screen, fireEvent } from '@testing-library/react' import AppButtonMenu from '~/components/app-button-menu/AppButtonMenu' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' vi.mock('simplebar-react', () => { return { @@ -20,11 +21,15 @@ vi.mock('react-i18next', () => ({ } }) })) - +const queryClient = new QueryClient() beforeEach(() => { const selectedItems = [] - render() + render( + + + +) }) describe('AppButtonMenu', () => { diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index a8a2b70eb1..6221c55774 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,7 +1,5 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' -import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' -import { URLs } from '~/constants/request' -import { baseService } from '~/services/base-service' +import { renderWithProviders } from '~tests/test-utils' import useQuery from '~/hooks/use-query' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' From 7ca925a5d486000ab766054c4fe2e1a29e8825b8 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 18:08:36 +0200 Subject: [PATCH 03/27] fixed tests --- .../AddResourceWithInput.tsx | 2 +- .../ResourcesToolbarDrawer.tsx | 4 +-- .../CategoryDropdown.spec.jsx | 25 +++++++------------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx b/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx index 9f321315b8..feb6411990 100644 --- a/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx +++ b/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx @@ -87,7 +87,7 @@ const AddResourceWithInput: FC = ({ }} position={PositionEnum.Right} selectedItems={selectedItems} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={setItems} showNoneProperty title={t('myResourcesPage.categories.category')} diff --git a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx index 8256f53c76..26681ab9c6 100644 --- a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx +++ b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx @@ -58,7 +58,7 @@ const ResourcesToolBarDrawer: FC = ({ handleNonInputValueChange('sortBy', value) const onApplyFilters = () => { - setCategories(data.categories) + setCategories(data.categories || []) setSearch(data.name) onRequestSort(data.sortBy) closeDrawer() @@ -84,7 +84,7 @@ const ResourcesToolBarDrawer: FC = ({ customSx={styles.filter} - selectedItems={data.categories} + selectedItems={data.categories || []} service={ResourceService.getResourcesCategoriesName} setSelectedItems={onCategoryChange} showNoneProperty diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 6221c55774..36aab6e410 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,29 +1,23 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' -import { renderWithProviders } from '~tests/test-utils' -import useQuery from '~/hooks/use-query' +import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' +import { URLs } from '~/constants/request' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' const categoriesNamesMock = [ { _id: '650c27618a9fbf234b8bb4cf', name: 'New category in resources!' }, { _id: '650c27618a9fbf234b8bb4cd', name: 'Category 1' } ] -vi.mock('~/hooks/use-query', () => ({ - __esModule: true, - default: vi.fn(), -})) describe('CategoryDropdown test', () => { - beforeEach(() => { - useQuery.mockReturnValue({ - data: categoriesNamesMock, - refetch: vi.fn(), - }) - }) + mockAxiosClient + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, categoriesNamesMock) - afterEach(() => { - vi.clearAllMocks() + beforeEach(async () => { + await waitFor(() => { + renderWithProviders() + }) }) it('should choose the category from options list', async () => { - renderWithProviders() const autocomplete = screen.getByRole('combobox') expect(autocomplete).toBeInTheDocument() @@ -50,7 +44,6 @@ describe('CategoryDropdown test', () => { }) it('should click on "add button" in options list', async () => { - renderWithProviders() const autocomplete = screen.getByRole('combobox') fireEvent.click(autocomplete) From 4bd61beb1d16919936e9a3b149974ef2c873cba4 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 15:14:29 +0200 Subject: [PATCH 04/27] added useQuery and useMutation hooks t CategoryDropdown page --- .../category-dropdown/CategoryDropdown.tsx | 62 ++++++++++++------- src/services/resource-service.ts | 15 +++++ .../CategoryDropdown.spec.jsx | 24 ++++--- 3 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 9a1647fcbb..f50a40573c 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -4,7 +4,6 @@ import Box from '@mui/material/Box' import Divider from '@mui/material/Divider' import AddIcon from '@mui/icons-material/Add' -import useAxios from '~/hooks/use-axios' import { useModalContext } from '~/context/modal-context' import { useAppDispatch } from '~/hooks/use-redux' import { ResourceService } from '~/services/resource-service' @@ -27,6 +26,8 @@ import { } from '~/containers/category-dropdown/CategoryDropdown.constants' import { openAlert } from '~/redux/features/snackbarSlice' import { getErrorKey } from '~/utils/get-error-key' +import useQuery from '~/hooks/use-query' +import useMutation from '~/hooks/use-mutation' interface CategoryDropdownInterface { category: string | null @@ -44,20 +45,25 @@ const CategoryDropdown = ({ const dispatch = useAppDispatch() const { openModal, closeModal } = useModalContext() - const handleResponseError = (error?: ErrorResponse) => { - dispatch( - openAlert({ - severity: snackbarVariants.error, - message: getErrorKey(error) - }) - ) - } + const handleResponseError = useCallback( + (error?: ErrorResponse) => { + dispatch( + openAlert({ + severity: snackbarVariants.error, + message: getErrorKey(error) + }) + ) + }, + [dispatch] + ) - const { response: allCategoriesNames, fetchData: fetchAllCategoriesNames } = - useAxios({ - service: ResourceService.getResourcesCategoriesNames, - defaultResponse: [], - fetchOnMount: true + const { data: allCategoriesNames, refetch: fetchAllCategoriesNames } = + useQuery({ + queryKey: ['categoriesNames'], + queryFn: ResourceService.getResourcesCategoriesName, + options: { + initialData: [] + } }) const onCreateCategory = () => { @@ -65,16 +71,23 @@ const CategoryDropdown = ({ component: ( item.name)} /> ) }) } + const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => + new Promise((resolve, reject) => { + handleCreateCategory(params, { + onSuccess: () => resolve(), + onError: (error) => reject(error) + }) + }) const createCategory = useCallback( - (params?: CreateCategoriesParams) => - ResourceService.createResourceCategory(params), + async (params?: CreateCategoriesParams): Promise => + await ResourceService.createCategory(params), [] ) @@ -99,14 +112,15 @@ const CategoryDropdown = ({ [dispatch, fetchAllCategoriesNames] ) - const { fetchData: handleCreateCategory } = useAxios({ - service: createCategory, - defaultResponse: null, - fetchOnMount: false, - onResponse: onResponseCategory, - onResponseError: handleResponseError + const { mutate: handleCreateCategory } = useMutation({ + mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + onSuccess: async (response) => { + await onResponseCategory(response) + }, + onError: (error: ErrorResponse) => { + handleResponseError(error) + } }) - const optionsList = ( props: HTMLAttributes, option: string, diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index ad1d0ed653..70cf45e815 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -158,10 +158,25 @@ export const ResourceService = { getResourcesCategoriesNames: (): Promise< AxiosResponse > => axiosClient.get(URLs.resources.resourcesCategories.getNames), + getResourcesCategoriesName: () => { + return baseService.request({ + method: 'GET', + url: URLs.resources.resourcesCategories.getNames + }) + }, createResourceCategory: async ( params?: CreateCategoriesParams ): Promise> => await axiosClient.post(URLs.resources.resourcesCategories.post, params), + createCategory: async ( + params?: CreateCategoriesParams + ): Promise => { + return await baseService.request({ + method: 'POST', + url: URLs.resources.resourcesCategories.post, + data: params || {} + }) + }, deleteResourceCategory: async (id: string): Promise => await axiosClient.delete( createUrlPath(URLs.resources.resourcesCategories.delete, id) diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 5d5dbc5912..a8a2b70eb1 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,26 +1,31 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' import { URLs } from '~/constants/request' - +import { baseService } from '~/services/base-service' +import useQuery from '~/hooks/use-query' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' const categoriesNamesMock = [ { _id: '650c27618a9fbf234b8bb4cf', name: 'New category in resources!' }, { _id: '650c27618a9fbf234b8bb4cd', name: 'Category 1' } ] - +vi.mock('~/hooks/use-query', () => ({ + __esModule: true, + default: vi.fn(), +})) describe('CategoryDropdown test', () => { - mockAxiosClient - .onGet(URLs.resources.resourcesCategories.getNames) - .reply(200, categoriesNamesMock) - - beforeEach(async () => { - await waitFor(() => { - renderWithProviders() + beforeEach(() => { + useQuery.mockReturnValue({ + data: categoriesNamesMock, + refetch: vi.fn(), }) }) + afterEach(() => { + vi.clearAllMocks() + }) it('should choose the category from options list', async () => { + renderWithProviders() const autocomplete = screen.getByRole('combobox') expect(autocomplete).toBeInTheDocument() @@ -47,6 +52,7 @@ describe('CategoryDropdown test', () => { }) it('should click on "add button" in options list', async () => { + renderWithProviders() const autocomplete = screen.getByRole('combobox') fireEvent.click(autocomplete) From 784aac3c64da837740f2856202efa0aa1c104ba3 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 17:14:52 +0200 Subject: [PATCH 05/27] changed occurrence files that also have service functions from CategoryDropdown --- .../app-button-menu/AppButtonMenu.tsx | 16 +++---- .../category-dropdown/CategoryDropdown.tsx | 2 +- .../add-resource-modal/AddResourceModal.tsx | 2 +- .../CategoriesContainer.tsx | 42 ++++++++++++------- .../ResourcesToolbarDrawer.tsx | 2 +- src/services/resource-service.ts | 4 -- src/types/services/types/services.types.ts | 9 ++-- .../app-button-menu/AppButtonMenu.spec.jsx | 9 +++- .../CategoryDropdown.spec.jsx | 4 +- 9 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/components/app-button-menu/AppButtonMenu.tsx b/src/components/app-button-menu/AppButtonMenu.tsx index 33dcea5319..55f3a2b975 100644 --- a/src/components/app-button-menu/AppButtonMenu.tsx +++ b/src/components/app-button-menu/AppButtonMenu.tsx @@ -10,25 +10,24 @@ import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline' import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown' import CircleIcon from '@mui/icons-material/Circle' -import useAxios from '~/hooks/use-axios' +import useQuery from '~/hooks/use-query' import useMenu from '~/hooks/use-menu' import Loader from '~/components/loader/Loader' import AppButton from '~/components/app-button/AppButton' import AppMenuButton from '~/components/app-menu-button/AppMenuButton' import AppSelectButton from '~/components/app-select-button/AppSelectButton' -import { defaultResponses } from '~/constants' import { spliceSx } from '~/utils/helper-functions' import { styles } from '~/components/app-button-menu/AppButtonMenu.styles' import { ButtonVariantEnum, CategoryNameInterface, - ServiceFunction + ServiceFunctionNew } from '~/types' interface AppButtonMenuProps extends Omit { title: string - service: ServiceFunction + service: ServiceFunctionNew selectedItems: string[] setSelectedItems: (value: string[]) => void position?: PopoverOrigin['horizontal'] @@ -65,9 +64,12 @@ const AppButtonMenu = >({ setSelectedItems([]) } - const { loading, response } = useAxios({ - service, - defaultResponse: defaultResponses.array + const { data: response, isLoading: loading } = useQuery({ + queryKey: [title], + queryFn: () => service(), + options: { + initialData: [] + } }) const filteredItems = useMemo(() => { diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index f50a40573c..35cc4c1ce9 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -87,7 +87,7 @@ const CategoryDropdown = ({ }) const createCategory = useCallback( async (params?: CreateCategoriesParams): Promise => - await ResourceService.createCategory(params), + await ResourceService.createResourceCategory(params), [] ) diff --git a/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx b/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx index 64305de746..c04272bb51 100644 --- a/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx +++ b/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx @@ -89,7 +89,7 @@ const AddResourceModal = ({ /> selectedItems={selectedItems} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={setSelectedItems} showNoneProperty title={t('myResourcesPage.categories.category')} diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index ca398f515f..19a28c8d24 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -32,8 +32,7 @@ import { GetResourcesCategoriesParams, ErrorResponse, ResourcesTabsEnum, - CreateCategoriesParams, - CategoryNameInterface + CreateCategoriesParams } from '~/types' import { adjustColumns, getScreenBasedLimit } from '~/utils/helper-functions' @@ -41,6 +40,8 @@ import { styles } from '~/containers/my-resources/categories-container/Categorie import { useAppDispatch } from '~/hooks/use-redux' import { openAlert } from '~/redux/features/snackbarSlice' import { getErrorKey } from '~/utils/get-error-key' +import useMutation from '~/hooks/use-mutation' +import useQuery from '~/hooks/use-query' const CategoriesContainer = () => { const { t } = useTranslation() @@ -118,12 +119,13 @@ const CategoriesContainer = () => { onResponseError }) - const { response: allCategoriesNames, fetchData: fetchAllCategoriesNames } = - useAxios({ - service: ResourceService.getResourcesCategoriesNames, - defaultResponse: [], - onResponseError, - fetchOnMount: true + const { data: allCategoriesNames, refetch: fetchAllCategoriesNames } = + useQuery({ + queryKey: ['categoriesNames'], + queryFn: ResourceService.getResourcesCategoriesName, + options: { + initialData: [] + } }) const onCategoryUpdate = useCallback(async () => { @@ -138,14 +140,22 @@ const CategoriesContainer = () => { [fetchData, fetchAllCategoriesNames, onResponse] ) - const { fetchData: handleCreateCategory } = useAxios({ - service: createCategory, - defaultResponse: null, - fetchOnMount: false, - onResponseError, - onResponse: onCategoryCreate + const { mutate: handleCreateCategory } = useMutation({ + mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + onSuccess: async (response) => { + await onCategoryCreate(response) + }, + onError: (error: ErrorResponse) => { + onResponseError(error) + } }) - + const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => + new Promise((resolve, reject) => { + handleCreateCategory(params, { + onSuccess: () => resolve(), + onError: (error) => reject(error) + }) + }) const existingCategoriesNames = allCategoriesNames?.map((item) => item.name) const onAdd = () => { @@ -153,7 +163,7 @@ const CategoriesContainer = () => { component: ( ) diff --git a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx index 652200c37d..8256f53c76 100644 --- a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx +++ b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx @@ -85,7 +85,7 @@ const ResourcesToolBarDrawer: FC = ({ customSx={styles.filter} selectedItems={data.categories} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={onCategoryChange} showNoneProperty slotProps={{ paper: styles.filterPaper(isMobile) }} diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index 70cf45e815..cc5878bec9 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -166,10 +166,6 @@ export const ResourceService = { }, createResourceCategory: async ( params?: CreateCategoriesParams - ): Promise> => - await axiosClient.post(URLs.resources.resourcesCategories.post, params), - createCategory: async ( - params?: CreateCategoriesParams ): Promise => { return await baseService.request({ method: 'POST', diff --git a/src/types/services/types/services.types.ts b/src/types/services/types/services.types.ts index e8074ec326..278dbc2ef1 100644 --- a/src/types/services/types/services.types.ts +++ b/src/types/services/types/services.types.ts @@ -18,9 +18,12 @@ export type ServiceFunction = ( params: Params extends undefined ? undefined : Params ) => Promise> -export type ServiceFunctionNew = ( - params: Params extends undefined ? undefined : Params -) => Promise +export type ServiceFunctionNew< + Response, + Params = undefined +> = Params extends undefined + ? () => Promise + : (params: Params) => Promise export interface AxiosResponseError extends AxiosError { config: InternalAxiosRequestConfig & { _isRetry: boolean } diff --git a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx index eeb157acd3..19044ea394 100644 --- a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx +++ b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx @@ -1,5 +1,6 @@ import { render, screen, fireEvent } from '@testing-library/react' import AppButtonMenu from '~/components/app-button-menu/AppButtonMenu' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' vi.mock('simplebar-react', () => { return { @@ -20,11 +21,15 @@ vi.mock('react-i18next', () => ({ } }) })) - +const queryClient = new QueryClient() beforeEach(() => { const selectedItems = [] - render() + render( + + + +) }) describe('AppButtonMenu', () => { diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index a8a2b70eb1..6221c55774 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,7 +1,5 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' -import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' -import { URLs } from '~/constants/request' -import { baseService } from '~/services/base-service' +import { renderWithProviders } from '~tests/test-utils' import useQuery from '~/hooks/use-query' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' From 3ac02d5dae4be69ae09c1f928dc0d8c81fbf9ee1 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 18:08:36 +0200 Subject: [PATCH 06/27] fixed tests --- .../AddResourceWithInput.tsx | 2 +- .../ResourcesToolbarDrawer.tsx | 4 +-- .../CategoryDropdown.spec.jsx | 25 +++++++------------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx b/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx index 9f321315b8..feb6411990 100644 --- a/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx +++ b/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx @@ -87,7 +87,7 @@ const AddResourceWithInput: FC = ({ }} position={PositionEnum.Right} selectedItems={selectedItems} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={setItems} showNoneProperty title={t('myResourcesPage.categories.category')} diff --git a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx index 8256f53c76..26681ab9c6 100644 --- a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx +++ b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx @@ -58,7 +58,7 @@ const ResourcesToolBarDrawer: FC = ({ handleNonInputValueChange('sortBy', value) const onApplyFilters = () => { - setCategories(data.categories) + setCategories(data.categories || []) setSearch(data.name) onRequestSort(data.sortBy) closeDrawer() @@ -84,7 +84,7 @@ const ResourcesToolBarDrawer: FC = ({ customSx={styles.filter} - selectedItems={data.categories} + selectedItems={data.categories || []} service={ResourceService.getResourcesCategoriesName} setSelectedItems={onCategoryChange} showNoneProperty diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 6221c55774..36aab6e410 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,29 +1,23 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' -import { renderWithProviders } from '~tests/test-utils' -import useQuery from '~/hooks/use-query' +import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' +import { URLs } from '~/constants/request' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' const categoriesNamesMock = [ { _id: '650c27618a9fbf234b8bb4cf', name: 'New category in resources!' }, { _id: '650c27618a9fbf234b8bb4cd', name: 'Category 1' } ] -vi.mock('~/hooks/use-query', () => ({ - __esModule: true, - default: vi.fn(), -})) describe('CategoryDropdown test', () => { - beforeEach(() => { - useQuery.mockReturnValue({ - data: categoriesNamesMock, - refetch: vi.fn(), - }) - }) + mockAxiosClient + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, categoriesNamesMock) - afterEach(() => { - vi.clearAllMocks() + beforeEach(async () => { + await waitFor(() => { + renderWithProviders() + }) }) it('should choose the category from options list', async () => { - renderWithProviders() const autocomplete = screen.getByRole('combobox') expect(autocomplete).toBeInTheDocument() @@ -50,7 +44,6 @@ describe('CategoryDropdown test', () => { }) it('should click on "add button" in options list', async () => { - renderWithProviders() const autocomplete = screen.getByRole('combobox') fireEvent.click(autocomplete) From 03a1784661ad9aa725aa393ac7dff11b834e0294 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 19:12:28 +0200 Subject: [PATCH 07/27] added more tests --- tests/unit/services/resource-service.spec.jsx | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/unit/services/resource-service.spec.jsx b/tests/unit/services/resource-service.spec.jsx index 1420d5cf0c..350fc7c96a 100644 --- a/tests/unit/services/resource-service.spec.jsx +++ b/tests/unit/services/resource-service.spec.jsx @@ -24,4 +24,33 @@ describe('resourseService tests', () => { URLs.resources.lessons.patch.replace(':id', lessonId) ) }) + it('should get resource categories names', async () => { + const mockResponse = [ + { _id: '1', name: 'Category 1' }, + { _id: '2', name: 'Category 2' } + ] + + mockAxiosClient + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, mockResponse) + + const response = await ResourceService.getResourcesCategoriesName() + + expect(mockAxiosClient.history.get[0].url).toBe(URLs.resources.resourcesCategories.getNames) + expect(response).toEqual(mockResponse) + }) + it('should create a resource category', async () => { + const mockResponse = { _id: '3', name: 'New Category' } + const params = { name: 'New Category' } + + mockAxiosClient + .onPost(URLs.resources.resourcesCategories.post) + .reply(200, mockResponse) + + const response = await ResourceService.createResourceCategory(params) + + expect(mockAxiosClient.history.post[0].url).toBe(URLs.resources.resourcesCategories.post) + expect(mockAxiosClient.history.post[0].data).toBe(JSON.stringify(params)) + expect(response).toEqual(mockResponse) + }) }) From ad1607f5995b2a3fe497ed8aad093b377fd12b7e Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 16 Jan 2025 11:18:14 +0200 Subject: [PATCH 08/27] removed promise from callback --- src/containers/category-dropdown/CategoryDropdown.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 35cc4c1ce9..3358b68d1c 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -86,8 +86,8 @@ const CategoryDropdown = ({ }) }) const createCategory = useCallback( - async (params?: CreateCategoriesParams): Promise => - await ResourceService.createResourceCategory(params), + (params?: CreateCategoriesParams) => + ResourceService.createResourceCategory(params), [] ) From cb9c08cbbf9780d0212f85b2fbd8fb1477fc434a Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 16 Jan 2025 12:24:15 +0200 Subject: [PATCH 09/27] fixed service in mutation and fixed tests --- .../category-dropdown/CategoryDropdown.tsx | 18 ++-------------- .../AddCategoriesModal.tsx | 6 +++--- .../CategoriesContainer.tsx | 21 ++++--------------- .../app-button-menu/AppButtonMenu.spec.jsx | 11 +++------- 4 files changed, 12 insertions(+), 44 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 3358b68d1c..7f32e60d04 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -15,7 +15,6 @@ import { Categories, CategoryNameInterface, ComponentEnum, - CreateCategoriesParams, ErrorResponse } from '~/types' import { styles } from '~/containers/category-dropdown/CategoryDropdown.styles' @@ -71,26 +70,13 @@ const CategoryDropdown = ({ component: ( item.name)} /> ) }) } - const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => - new Promise((resolve, reject) => { - handleCreateCategory(params, { - onSuccess: () => resolve(), - onError: (error) => reject(error) - }) - }) - const createCategory = useCallback( - (params?: CreateCategoriesParams) => - ResourceService.createResourceCategory(params), - [] - ) - const onResponseCategory = useCallback( async (response: Categories | null) => { const categoryName = response ? response.name : '' @@ -113,7 +99,7 @@ const CategoryDropdown = ({ ) const { mutate: handleCreateCategory } = useMutation({ - mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + mutationFn: ResourceService.createResourceCategory, onSuccess: async (response) => { await onResponseCategory(response) }, diff --git a/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx b/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx index ffb25c9071..cc1370bd8c 100644 --- a/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx +++ b/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx @@ -21,7 +21,7 @@ import { interface AddCategoriesModalProps { closeModal: () => void - createCategories: (params?: CreateCategoriesParams) => Promise + createCategories: (params: CreateCategoriesParams) => void existingCategoriesNames: string[] } @@ -37,9 +37,9 @@ const AddCategoriesModal: FC = ({ useForm({ initialValues: initialValues, validations: validations(existingCategoriesNames), - onSubmit: async () => { + onSubmit: () => { setLoading(true) - await createCategories({ name: data.name.trim() }) + createCategories({ name: data.name.trim() }) setLoading(false) closeModal() } diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index 19a28c8d24..75d4b4fd1d 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -31,8 +31,7 @@ import { ItemsWithCount, GetResourcesCategoriesParams, ErrorResponse, - ResourcesTabsEnum, - CreateCategoriesParams + ResourcesTabsEnum } from '~/types' import { adjustColumns, getScreenBasedLimit } from '~/utils/helper-functions' @@ -99,12 +98,6 @@ const CategoriesContainer = () => { [page, itemsPerPage, sort, searchTitle] ) - const createCategory = useCallback( - (params?: CreateCategoriesParams) => - ResourceService.createResourceCategory(params), - [] - ) - const deleteCategory = useCallback( (id?: string) => ResourceService.deleteResourceCategory(id ?? ''), [] @@ -141,7 +134,8 @@ const CategoriesContainer = () => { ) const { mutate: handleCreateCategory } = useMutation({ - mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + // mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + mutationFn: ResourceService.createResourceCategory, onSuccess: async (response) => { await onCategoryCreate(response) }, @@ -149,13 +143,6 @@ const CategoriesContainer = () => { onResponseError(error) } }) - const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => - new Promise((resolve, reject) => { - handleCreateCategory(params, { - onSuccess: () => resolve(), - onError: (error) => reject(error) - }) - }) const existingCategoriesNames = allCategoriesNames?.map((item) => item.name) const onAdd = () => { @@ -163,7 +150,7 @@ const CategoriesContainer = () => { component: ( ) diff --git a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx index 19044ea394..dfde209f3d 100644 --- a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx +++ b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx @@ -1,6 +1,6 @@ -import { render, screen, fireEvent } from '@testing-library/react' +import { screen, fireEvent } from '@testing-library/react' import AppButtonMenu from '~/components/app-button-menu/AppButtonMenu' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { renderWithProviders } from '~tests/test-utils' vi.mock('simplebar-react', () => { return { @@ -21,15 +21,10 @@ vi.mock('react-i18next', () => ({ } }) })) -const queryClient = new QueryClient() beforeEach(() => { const selectedItems = [] - render( - - - -) + renderWithProviders() }) describe('AppButtonMenu', () => { From e58937b9d89b79445560dac36de0a2cd01631c74 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 16 Jan 2025 13:47:31 +0200 Subject: [PATCH 10/27] fixed tests --- .../CreateOrEditLessonWithId.spec.jsx | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/tests/unit/pages/create-or-edit-lesson/CreateOrEditLessonWithId.spec.jsx b/tests/unit/pages/create-or-edit-lesson/CreateOrEditLessonWithId.spec.jsx index d1811249bf..b18a095551 100644 --- a/tests/unit/pages/create-or-edit-lesson/CreateOrEditLessonWithId.spec.jsx +++ b/tests/unit/pages/create-or-edit-lesson/CreateOrEditLessonWithId.spec.jsx @@ -1,11 +1,11 @@ -import { waitFor } from '@testing-library/react' +import { screen } from '@testing-library/react' import { vi } from 'vitest' import CreateOrEditLesson from '~/pages/create-or-edit-lesson/CreateOrEditLesson' import { ResourceService } from '~/services/resource-service' import { baseService } from '~/services/base-service' -import { renderWithProviders } from '~tests/test-utils' - +import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' +import { URLs } from '~/constants/request' const mockParams = { id: 'id' } @@ -25,25 +25,30 @@ vi.mock('react-router-dom', async () => ({ describe('CreateOrEditLesson with id', () => { beforeAll(() => { - vi.spyOn(baseService, 'request').mockImplementation((config) => { - if (config.method === 'PATCH') { - return Promise.resolve() - } - if (config.method === 'GET') { - return Promise.resolve({ data: mockLesson }) - } - return Promise.reject(new Error('Unexpected request')) - }) + mockAxiosClient + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, []) + + mockAxiosClient + .onGet(URLs.resources.lessons.getById.replace(':id', mockParams.id)) + .reply(200, mockLesson) + + mockAxiosClient + .onPatch(URLs.resources.lessons.patch.replace(':id', mockParams.id)) + .reply(204) }) beforeEach(async () => { await renderWithProviders() }) - it('should call ResourceService.getLesson with the correct id when loading the lesson', async () => { - const getLessonSpy = vi.spyOn(ResourceService, 'getLesson') - await waitFor(() => renderWithProviders()) + it('should display the lesson title and description when the lesson is loaded', async () => { + const lessonTitle = await screen.findByDisplayValue(mockLesson.title) + const lessonDescription = await screen.findByDisplayValue( + mockLesson.description + ) - expect(getLessonSpy).toHaveBeenCalledWith('id') + expect(lessonTitle).toBeInTheDocument() + expect(lessonDescription).toBeInTheDocument() }) }) From 9351e300e593bdd0b42e8f3e8b91b220ff302d31 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 15:14:29 +0200 Subject: [PATCH 11/27] added useQuery and useMutation hooks t CategoryDropdown page --- .../category-dropdown/CategoryDropdown.tsx | 62 ++++++++++++------- src/services/resource-service.ts | 15 +++++ .../CategoryDropdown.spec.jsx | 24 ++++--- 3 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 9a1647fcbb..f50a40573c 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -4,7 +4,6 @@ import Box from '@mui/material/Box' import Divider from '@mui/material/Divider' import AddIcon from '@mui/icons-material/Add' -import useAxios from '~/hooks/use-axios' import { useModalContext } from '~/context/modal-context' import { useAppDispatch } from '~/hooks/use-redux' import { ResourceService } from '~/services/resource-service' @@ -27,6 +26,8 @@ import { } from '~/containers/category-dropdown/CategoryDropdown.constants' import { openAlert } from '~/redux/features/snackbarSlice' import { getErrorKey } from '~/utils/get-error-key' +import useQuery from '~/hooks/use-query' +import useMutation from '~/hooks/use-mutation' interface CategoryDropdownInterface { category: string | null @@ -44,20 +45,25 @@ const CategoryDropdown = ({ const dispatch = useAppDispatch() const { openModal, closeModal } = useModalContext() - const handleResponseError = (error?: ErrorResponse) => { - dispatch( - openAlert({ - severity: snackbarVariants.error, - message: getErrorKey(error) - }) - ) - } + const handleResponseError = useCallback( + (error?: ErrorResponse) => { + dispatch( + openAlert({ + severity: snackbarVariants.error, + message: getErrorKey(error) + }) + ) + }, + [dispatch] + ) - const { response: allCategoriesNames, fetchData: fetchAllCategoriesNames } = - useAxios({ - service: ResourceService.getResourcesCategoriesNames, - defaultResponse: [], - fetchOnMount: true + const { data: allCategoriesNames, refetch: fetchAllCategoriesNames } = + useQuery({ + queryKey: ['categoriesNames'], + queryFn: ResourceService.getResourcesCategoriesName, + options: { + initialData: [] + } }) const onCreateCategory = () => { @@ -65,16 +71,23 @@ const CategoryDropdown = ({ component: ( item.name)} /> ) }) } + const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => + new Promise((resolve, reject) => { + handleCreateCategory(params, { + onSuccess: () => resolve(), + onError: (error) => reject(error) + }) + }) const createCategory = useCallback( - (params?: CreateCategoriesParams) => - ResourceService.createResourceCategory(params), + async (params?: CreateCategoriesParams): Promise => + await ResourceService.createCategory(params), [] ) @@ -99,14 +112,15 @@ const CategoryDropdown = ({ [dispatch, fetchAllCategoriesNames] ) - const { fetchData: handleCreateCategory } = useAxios({ - service: createCategory, - defaultResponse: null, - fetchOnMount: false, - onResponse: onResponseCategory, - onResponseError: handleResponseError + const { mutate: handleCreateCategory } = useMutation({ + mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + onSuccess: async (response) => { + await onResponseCategory(response) + }, + onError: (error: ErrorResponse) => { + handleResponseError(error) + } }) - const optionsList = ( props: HTMLAttributes, option: string, diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index ad1d0ed653..70cf45e815 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -158,10 +158,25 @@ export const ResourceService = { getResourcesCategoriesNames: (): Promise< AxiosResponse > => axiosClient.get(URLs.resources.resourcesCategories.getNames), + getResourcesCategoriesName: () => { + return baseService.request({ + method: 'GET', + url: URLs.resources.resourcesCategories.getNames + }) + }, createResourceCategory: async ( params?: CreateCategoriesParams ): Promise> => await axiosClient.post(URLs.resources.resourcesCategories.post, params), + createCategory: async ( + params?: CreateCategoriesParams + ): Promise => { + return await baseService.request({ + method: 'POST', + url: URLs.resources.resourcesCategories.post, + data: params || {} + }) + }, deleteResourceCategory: async (id: string): Promise => await axiosClient.delete( createUrlPath(URLs.resources.resourcesCategories.delete, id) diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 5d5dbc5912..a8a2b70eb1 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,26 +1,31 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' import { URLs } from '~/constants/request' - +import { baseService } from '~/services/base-service' +import useQuery from '~/hooks/use-query' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' const categoriesNamesMock = [ { _id: '650c27618a9fbf234b8bb4cf', name: 'New category in resources!' }, { _id: '650c27618a9fbf234b8bb4cd', name: 'Category 1' } ] - +vi.mock('~/hooks/use-query', () => ({ + __esModule: true, + default: vi.fn(), +})) describe('CategoryDropdown test', () => { - mockAxiosClient - .onGet(URLs.resources.resourcesCategories.getNames) - .reply(200, categoriesNamesMock) - - beforeEach(async () => { - await waitFor(() => { - renderWithProviders() + beforeEach(() => { + useQuery.mockReturnValue({ + data: categoriesNamesMock, + refetch: vi.fn(), }) }) + afterEach(() => { + vi.clearAllMocks() + }) it('should choose the category from options list', async () => { + renderWithProviders() const autocomplete = screen.getByRole('combobox') expect(autocomplete).toBeInTheDocument() @@ -47,6 +52,7 @@ describe('CategoryDropdown test', () => { }) it('should click on "add button" in options list', async () => { + renderWithProviders() const autocomplete = screen.getByRole('combobox') fireEvent.click(autocomplete) From 6460ec55fa4da04d68ecf46c27870ed8baec4e75 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 17:14:52 +0200 Subject: [PATCH 12/27] changed occurrence files that also have service functions from CategoryDropdown --- .../app-button-menu/AppButtonMenu.tsx | 16 +++---- .../category-dropdown/CategoryDropdown.tsx | 2 +- .../add-resource-modal/AddResourceModal.tsx | 2 +- .../CategoriesContainer.tsx | 42 ++++++++++++------- .../ResourcesToolbarDrawer.tsx | 2 +- src/services/resource-service.ts | 4 -- src/types/services/types/services.types.ts | 9 ++-- .../app-button-menu/AppButtonMenu.spec.jsx | 9 +++- .../CategoryDropdown.spec.jsx | 4 +- 9 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/components/app-button-menu/AppButtonMenu.tsx b/src/components/app-button-menu/AppButtonMenu.tsx index 33dcea5319..55f3a2b975 100644 --- a/src/components/app-button-menu/AppButtonMenu.tsx +++ b/src/components/app-button-menu/AppButtonMenu.tsx @@ -10,25 +10,24 @@ import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline' import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown' import CircleIcon from '@mui/icons-material/Circle' -import useAxios from '~/hooks/use-axios' +import useQuery from '~/hooks/use-query' import useMenu from '~/hooks/use-menu' import Loader from '~/components/loader/Loader' import AppButton from '~/components/app-button/AppButton' import AppMenuButton from '~/components/app-menu-button/AppMenuButton' import AppSelectButton from '~/components/app-select-button/AppSelectButton' -import { defaultResponses } from '~/constants' import { spliceSx } from '~/utils/helper-functions' import { styles } from '~/components/app-button-menu/AppButtonMenu.styles' import { ButtonVariantEnum, CategoryNameInterface, - ServiceFunction + ServiceFunctionNew } from '~/types' interface AppButtonMenuProps extends Omit { title: string - service: ServiceFunction + service: ServiceFunctionNew selectedItems: string[] setSelectedItems: (value: string[]) => void position?: PopoverOrigin['horizontal'] @@ -65,9 +64,12 @@ const AppButtonMenu = >({ setSelectedItems([]) } - const { loading, response } = useAxios({ - service, - defaultResponse: defaultResponses.array + const { data: response, isLoading: loading } = useQuery({ + queryKey: [title], + queryFn: () => service(), + options: { + initialData: [] + } }) const filteredItems = useMemo(() => { diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index f50a40573c..35cc4c1ce9 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -87,7 +87,7 @@ const CategoryDropdown = ({ }) const createCategory = useCallback( async (params?: CreateCategoriesParams): Promise => - await ResourceService.createCategory(params), + await ResourceService.createResourceCategory(params), [] ) diff --git a/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx b/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx index 64305de746..c04272bb51 100644 --- a/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx +++ b/src/containers/my-resources/add-resource-modal/AddResourceModal.tsx @@ -89,7 +89,7 @@ const AddResourceModal = ({ /> selectedItems={selectedItems} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={setSelectedItems} showNoneProperty title={t('myResourcesPage.categories.category')} diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index ca398f515f..19a28c8d24 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -32,8 +32,7 @@ import { GetResourcesCategoriesParams, ErrorResponse, ResourcesTabsEnum, - CreateCategoriesParams, - CategoryNameInterface + CreateCategoriesParams } from '~/types' import { adjustColumns, getScreenBasedLimit } from '~/utils/helper-functions' @@ -41,6 +40,8 @@ import { styles } from '~/containers/my-resources/categories-container/Categorie import { useAppDispatch } from '~/hooks/use-redux' import { openAlert } from '~/redux/features/snackbarSlice' import { getErrorKey } from '~/utils/get-error-key' +import useMutation from '~/hooks/use-mutation' +import useQuery from '~/hooks/use-query' const CategoriesContainer = () => { const { t } = useTranslation() @@ -118,12 +119,13 @@ const CategoriesContainer = () => { onResponseError }) - const { response: allCategoriesNames, fetchData: fetchAllCategoriesNames } = - useAxios({ - service: ResourceService.getResourcesCategoriesNames, - defaultResponse: [], - onResponseError, - fetchOnMount: true + const { data: allCategoriesNames, refetch: fetchAllCategoriesNames } = + useQuery({ + queryKey: ['categoriesNames'], + queryFn: ResourceService.getResourcesCategoriesName, + options: { + initialData: [] + } }) const onCategoryUpdate = useCallback(async () => { @@ -138,14 +140,22 @@ const CategoriesContainer = () => { [fetchData, fetchAllCategoriesNames, onResponse] ) - const { fetchData: handleCreateCategory } = useAxios({ - service: createCategory, - defaultResponse: null, - fetchOnMount: false, - onResponseError, - onResponse: onCategoryCreate + const { mutate: handleCreateCategory } = useMutation({ + mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + onSuccess: async (response) => { + await onCategoryCreate(response) + }, + onError: (error: ErrorResponse) => { + onResponseError(error) + } }) - + const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => + new Promise((resolve, reject) => { + handleCreateCategory(params, { + onSuccess: () => resolve(), + onError: (error) => reject(error) + }) + }) const existingCategoriesNames = allCategoriesNames?.map((item) => item.name) const onAdd = () => { @@ -153,7 +163,7 @@ const CategoriesContainer = () => { component: ( ) diff --git a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx index 652200c37d..8256f53c76 100644 --- a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx +++ b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx @@ -85,7 +85,7 @@ const ResourcesToolBarDrawer: FC = ({ customSx={styles.filter} selectedItems={data.categories} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={onCategoryChange} showNoneProperty slotProps={{ paper: styles.filterPaper(isMobile) }} diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index 70cf45e815..cc5878bec9 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -166,10 +166,6 @@ export const ResourceService = { }, createResourceCategory: async ( params?: CreateCategoriesParams - ): Promise> => - await axiosClient.post(URLs.resources.resourcesCategories.post, params), - createCategory: async ( - params?: CreateCategoriesParams ): Promise => { return await baseService.request({ method: 'POST', diff --git a/src/types/services/types/services.types.ts b/src/types/services/types/services.types.ts index e8074ec326..278dbc2ef1 100644 --- a/src/types/services/types/services.types.ts +++ b/src/types/services/types/services.types.ts @@ -18,9 +18,12 @@ export type ServiceFunction = ( params: Params extends undefined ? undefined : Params ) => Promise> -export type ServiceFunctionNew = ( - params: Params extends undefined ? undefined : Params -) => Promise +export type ServiceFunctionNew< + Response, + Params = undefined +> = Params extends undefined + ? () => Promise + : (params: Params) => Promise export interface AxiosResponseError extends AxiosError { config: InternalAxiosRequestConfig & { _isRetry: boolean } diff --git a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx index eeb157acd3..19044ea394 100644 --- a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx +++ b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx @@ -1,5 +1,6 @@ import { render, screen, fireEvent } from '@testing-library/react' import AppButtonMenu from '~/components/app-button-menu/AppButtonMenu' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' vi.mock('simplebar-react', () => { return { @@ -20,11 +21,15 @@ vi.mock('react-i18next', () => ({ } }) })) - +const queryClient = new QueryClient() beforeEach(() => { const selectedItems = [] - render() + render( + + + +) }) describe('AppButtonMenu', () => { diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index a8a2b70eb1..6221c55774 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,7 +1,5 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' -import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' -import { URLs } from '~/constants/request' -import { baseService } from '~/services/base-service' +import { renderWithProviders } from '~tests/test-utils' import useQuery from '~/hooks/use-query' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' From 57bcecbc025544dbf6567d556127d443e2be035a Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 18:08:36 +0200 Subject: [PATCH 13/27] fixed tests --- .../AddResourceWithInput.tsx | 2 +- .../ResourcesToolbarDrawer.tsx | 4 +-- .../CategoryDropdown.spec.jsx | 25 +++++++------------ 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx b/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx index 9f321315b8..feb6411990 100644 --- a/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx +++ b/src/containers/my-resources/add-resource-with-input/AddResourceWithInput.tsx @@ -87,7 +87,7 @@ const AddResourceWithInput: FC = ({ }} position={PositionEnum.Right} selectedItems={selectedItems} - service={ResourceService.getResourcesCategoriesNames} + service={ResourceService.getResourcesCategoriesName} setSelectedItems={setItems} showNoneProperty title={t('myResourcesPage.categories.category')} diff --git a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx index 8256f53c76..26681ab9c6 100644 --- a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx +++ b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx @@ -58,7 +58,7 @@ const ResourcesToolBarDrawer: FC = ({ handleNonInputValueChange('sortBy', value) const onApplyFilters = () => { - setCategories(data.categories) + setCategories(data.categories || []) setSearch(data.name) onRequestSort(data.sortBy) closeDrawer() @@ -84,7 +84,7 @@ const ResourcesToolBarDrawer: FC = ({ customSx={styles.filter} - selectedItems={data.categories} + selectedItems={data.categories || []} service={ResourceService.getResourcesCategoriesName} setSelectedItems={onCategoryChange} showNoneProperty diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 6221c55774..36aab6e410 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,29 +1,23 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' -import { renderWithProviders } from '~tests/test-utils' -import useQuery from '~/hooks/use-query' +import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' +import { URLs } from '~/constants/request' import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' const categoriesNamesMock = [ { _id: '650c27618a9fbf234b8bb4cf', name: 'New category in resources!' }, { _id: '650c27618a9fbf234b8bb4cd', name: 'Category 1' } ] -vi.mock('~/hooks/use-query', () => ({ - __esModule: true, - default: vi.fn(), -})) describe('CategoryDropdown test', () => { - beforeEach(() => { - useQuery.mockReturnValue({ - data: categoriesNamesMock, - refetch: vi.fn(), - }) - }) + mockAxiosClient + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, categoriesNamesMock) - afterEach(() => { - vi.clearAllMocks() + beforeEach(async () => { + await waitFor(() => { + renderWithProviders() + }) }) it('should choose the category from options list', async () => { - renderWithProviders() const autocomplete = screen.getByRole('combobox') expect(autocomplete).toBeInTheDocument() @@ -50,7 +44,6 @@ describe('CategoryDropdown test', () => { }) it('should click on "add button" in options list', async () => { - renderWithProviders() const autocomplete = screen.getByRole('combobox') fireEvent.click(autocomplete) From 10f21a4b1d144f69a4f505e0100c2769d952aa2e Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 15:14:29 +0200 Subject: [PATCH 14/27] added useQuery and useMutation hooks t CategoryDropdown page --- .../category-dropdown/CategoryDropdown.tsx | 18 ++---------------- .../AddCategoriesModal.tsx | 6 +++--- .../CategoryDropdown.spec.jsx | 8 ++++++-- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 35cc4c1ce9..7f32e60d04 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -15,7 +15,6 @@ import { Categories, CategoryNameInterface, ComponentEnum, - CreateCategoriesParams, ErrorResponse } from '~/types' import { styles } from '~/containers/category-dropdown/CategoryDropdown.styles' @@ -71,26 +70,13 @@ const CategoryDropdown = ({ component: ( item.name)} /> ) }) } - const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => - new Promise((resolve, reject) => { - handleCreateCategory(params, { - onSuccess: () => resolve(), - onError: (error) => reject(error) - }) - }) - const createCategory = useCallback( - async (params?: CreateCategoriesParams): Promise => - await ResourceService.createResourceCategory(params), - [] - ) - const onResponseCategory = useCallback( async (response: Categories | null) => { const categoryName = response ? response.name : '' @@ -113,7 +99,7 @@ const CategoryDropdown = ({ ) const { mutate: handleCreateCategory } = useMutation({ - mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + mutationFn: ResourceService.createResourceCategory, onSuccess: async (response) => { await onResponseCategory(response) }, diff --git a/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx b/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx index ffb25c9071..eff555dbd6 100644 --- a/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx +++ b/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx @@ -21,7 +21,7 @@ import { interface AddCategoriesModalProps { closeModal: () => void - createCategories: (params?: CreateCategoriesParams) => Promise + createCategories: (params?: CreateCategoriesParams) => void existingCategoriesNames: string[] } @@ -37,9 +37,9 @@ const AddCategoriesModal: FC = ({ useForm({ initialValues: initialValues, validations: validations(existingCategoriesNames), - onSubmit: async () => { + onSubmit: () => { setLoading(true) - await createCategories({ name: data.name.trim() }) + createCategories({ name: data.name.trim() }) setLoading(false) closeModal() } diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 36aab6e410..8f7d30d7f9 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,16 +1,18 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' import { URLs } from '~/constants/request' + import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' const categoriesNamesMock = [ { _id: '650c27618a9fbf234b8bb4cf', name: 'New category in resources!' }, { _id: '650c27618a9fbf234b8bb4cd', name: 'Category 1' } ] + describe('CategoryDropdown test', () => { mockAxiosClient - .onGet(URLs.resources.resourcesCategories.getNames) - .reply(200, categoriesNamesMock) + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, categoriesNamesMock) beforeEach(async () => { await waitFor(() => { @@ -18,6 +20,7 @@ describe('CategoryDropdown test', () => { }) }) it('should choose the category from options list', async () => { + renderWithProviders() const autocomplete = screen.getByRole('combobox') expect(autocomplete).toBeInTheDocument() @@ -44,6 +47,7 @@ describe('CategoryDropdown test', () => { }) it('should click on "add button" in options list', async () => { + renderWithProviders() const autocomplete = screen.getByRole('combobox') fireEvent.click(autocomplete) From cb10ace3cb7abd4fbea89482d0394babfc64066b Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 17:14:52 +0200 Subject: [PATCH 15/27] changed occurrence files that also have service functions from CategoryDropdown --- .../category-dropdown/CategoryDropdown.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 7f32e60d04..0ba4cf67a7 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -15,6 +15,7 @@ import { Categories, CategoryNameInterface, ComponentEnum, + CreateCategoriesParams, ErrorResponse } from '~/types' import { styles } from '~/containers/category-dropdown/CategoryDropdown.styles' @@ -77,6 +78,19 @@ const CategoryDropdown = ({ }) } + const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => + new Promise((resolve, reject) => { + handleCreateCategory(params, { + onSuccess: () => resolve(), + onError: (error) => reject(error) + }) + }) + const createCategory = useCallback( + async (params?: CreateCategoriesParams): Promise => + await ResourceService.createResourceCategory(params), + [] + ) + const onResponseCategory = useCallback( async (response: Categories | null) => { const categoryName = response ? response.name : '' From 253f3e3be413e7c4ec23caca74b7c9eab77751f4 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 15 Jan 2025 19:12:28 +0200 Subject: [PATCH 16/27] added more tests --- tests/unit/services/resource-service.spec.jsx | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/unit/services/resource-service.spec.jsx b/tests/unit/services/resource-service.spec.jsx index 1420d5cf0c..350fc7c96a 100644 --- a/tests/unit/services/resource-service.spec.jsx +++ b/tests/unit/services/resource-service.spec.jsx @@ -24,4 +24,33 @@ describe('resourseService tests', () => { URLs.resources.lessons.patch.replace(':id', lessonId) ) }) + it('should get resource categories names', async () => { + const mockResponse = [ + { _id: '1', name: 'Category 1' }, + { _id: '2', name: 'Category 2' } + ] + + mockAxiosClient + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, mockResponse) + + const response = await ResourceService.getResourcesCategoriesName() + + expect(mockAxiosClient.history.get[0].url).toBe(URLs.resources.resourcesCategories.getNames) + expect(response).toEqual(mockResponse) + }) + it('should create a resource category', async () => { + const mockResponse = { _id: '3', name: 'New Category' } + const params = { name: 'New Category' } + + mockAxiosClient + .onPost(URLs.resources.resourcesCategories.post) + .reply(200, mockResponse) + + const response = await ResourceService.createResourceCategory(params) + + expect(mockAxiosClient.history.post[0].url).toBe(URLs.resources.resourcesCategories.post) + expect(mockAxiosClient.history.post[0].data).toBe(JSON.stringify(params)) + expect(response).toEqual(mockResponse) + }) }) From fdae645cb9706b587283521a360a09e8929c20d9 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 16 Jan 2025 11:18:14 +0200 Subject: [PATCH 17/27] removed promise from callback --- src/containers/category-dropdown/CategoryDropdown.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 0ba4cf67a7..dae12cc2fb 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -86,8 +86,8 @@ const CategoryDropdown = ({ }) }) const createCategory = useCallback( - async (params?: CreateCategoriesParams): Promise => - await ResourceService.createResourceCategory(params), + (params?: CreateCategoriesParams) => + ResourceService.createResourceCategory(params), [] ) From b8e44a62f0ce9d7b5f0a627f7ae0953450aee394 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 16 Jan 2025 12:24:15 +0200 Subject: [PATCH 18/27] fixed service in mutation and fixed tests --- .../category-dropdown/CategoryDropdown.tsx | 14 ------------- .../AddCategoriesModal.tsx | 2 +- .../CategoriesContainer.tsx | 21 ++++--------------- .../app-button-menu/AppButtonMenu.spec.jsx | 11 +++------- 4 files changed, 8 insertions(+), 40 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index dae12cc2fb..7f32e60d04 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -15,7 +15,6 @@ import { Categories, CategoryNameInterface, ComponentEnum, - CreateCategoriesParams, ErrorResponse } from '~/types' import { styles } from '~/containers/category-dropdown/CategoryDropdown.styles' @@ -78,19 +77,6 @@ const CategoryDropdown = ({ }) } - const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => - new Promise((resolve, reject) => { - handleCreateCategory(params, { - onSuccess: () => resolve(), - onError: (error) => reject(error) - }) - }) - const createCategory = useCallback( - (params?: CreateCategoriesParams) => - ResourceService.createResourceCategory(params), - [] - ) - const onResponseCategory = useCallback( async (response: Categories | null) => { const categoryName = response ? response.name : '' diff --git a/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx b/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx index eff555dbd6..cc1370bd8c 100644 --- a/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx +++ b/src/containers/my-resources/add-categories-modal/AddCategoriesModal.tsx @@ -21,7 +21,7 @@ import { interface AddCategoriesModalProps { closeModal: () => void - createCategories: (params?: CreateCategoriesParams) => void + createCategories: (params: CreateCategoriesParams) => void existingCategoriesNames: string[] } diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index 19a28c8d24..75d4b4fd1d 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -31,8 +31,7 @@ import { ItemsWithCount, GetResourcesCategoriesParams, ErrorResponse, - ResourcesTabsEnum, - CreateCategoriesParams + ResourcesTabsEnum } from '~/types' import { adjustColumns, getScreenBasedLimit } from '~/utils/helper-functions' @@ -99,12 +98,6 @@ const CategoriesContainer = () => { [page, itemsPerPage, sort, searchTitle] ) - const createCategory = useCallback( - (params?: CreateCategoriesParams) => - ResourceService.createResourceCategory(params), - [] - ) - const deleteCategory = useCallback( (id?: string) => ResourceService.deleteResourceCategory(id ?? ''), [] @@ -141,7 +134,8 @@ const CategoriesContainer = () => { ) const { mutate: handleCreateCategory } = useMutation({ - mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + // mutationFn: (params?: CreateCategoriesParams) => createCategory(params), + mutationFn: ResourceService.createResourceCategory, onSuccess: async (response) => { await onCategoryCreate(response) }, @@ -149,13 +143,6 @@ const CategoriesContainer = () => { onResponseError(error) } }) - const handleCreateCategoryPromise = async (params?: CreateCategoriesParams) => - new Promise((resolve, reject) => { - handleCreateCategory(params, { - onSuccess: () => resolve(), - onError: (error) => reject(error) - }) - }) const existingCategoriesNames = allCategoriesNames?.map((item) => item.name) const onAdd = () => { @@ -163,7 +150,7 @@ const CategoriesContainer = () => { component: ( ) diff --git a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx index 19044ea394..dfde209f3d 100644 --- a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx +++ b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx @@ -1,6 +1,6 @@ -import { render, screen, fireEvent } from '@testing-library/react' +import { screen, fireEvent } from '@testing-library/react' import AppButtonMenu from '~/components/app-button-menu/AppButtonMenu' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { renderWithProviders } from '~tests/test-utils' vi.mock('simplebar-react', () => { return { @@ -21,15 +21,10 @@ vi.mock('react-i18next', () => ({ } }) })) -const queryClient = new QueryClient() beforeEach(() => { const selectedItems = [] - render( - - - -) + renderWithProviders() }) describe('AppButtonMenu', () => { From 7eb39d205b86221e051eaa4ca89eae3d6894e7f5 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Thu, 16 Jan 2025 13:47:31 +0200 Subject: [PATCH 19/27] fixed tests --- .../CreateOrEditLessonWithId.spec.jsx | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/tests/unit/pages/create-or-edit-lesson/CreateOrEditLessonWithId.spec.jsx b/tests/unit/pages/create-or-edit-lesson/CreateOrEditLessonWithId.spec.jsx index d1811249bf..b18a095551 100644 --- a/tests/unit/pages/create-or-edit-lesson/CreateOrEditLessonWithId.spec.jsx +++ b/tests/unit/pages/create-or-edit-lesson/CreateOrEditLessonWithId.spec.jsx @@ -1,11 +1,11 @@ -import { waitFor } from '@testing-library/react' +import { screen } from '@testing-library/react' import { vi } from 'vitest' import CreateOrEditLesson from '~/pages/create-or-edit-lesson/CreateOrEditLesson' import { ResourceService } from '~/services/resource-service' import { baseService } from '~/services/base-service' -import { renderWithProviders } from '~tests/test-utils' - +import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' +import { URLs } from '~/constants/request' const mockParams = { id: 'id' } @@ -25,25 +25,30 @@ vi.mock('react-router-dom', async () => ({ describe('CreateOrEditLesson with id', () => { beforeAll(() => { - vi.spyOn(baseService, 'request').mockImplementation((config) => { - if (config.method === 'PATCH') { - return Promise.resolve() - } - if (config.method === 'GET') { - return Promise.resolve({ data: mockLesson }) - } - return Promise.reject(new Error('Unexpected request')) - }) + mockAxiosClient + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, []) + + mockAxiosClient + .onGet(URLs.resources.lessons.getById.replace(':id', mockParams.id)) + .reply(200, mockLesson) + + mockAxiosClient + .onPatch(URLs.resources.lessons.patch.replace(':id', mockParams.id)) + .reply(204) }) beforeEach(async () => { await renderWithProviders() }) - it('should call ResourceService.getLesson with the correct id when loading the lesson', async () => { - const getLessonSpy = vi.spyOn(ResourceService, 'getLesson') - await waitFor(() => renderWithProviders()) + it('should display the lesson title and description when the lesson is loaded', async () => { + const lessonTitle = await screen.findByDisplayValue(mockLesson.title) + const lessonDescription = await screen.findByDisplayValue( + mockLesson.description + ) - expect(getLessonSpy).toHaveBeenCalledWith('id') + expect(lessonTitle).toBeInTheDocument() + expect(lessonDescription).toBeInTheDocument() }) }) From d5bddb4c999872ffc6318740ff3a6bd6d862b518 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Fri, 17 Jan 2025 13:37:51 +0200 Subject: [PATCH 20/27] fixed tests after rebase --- .../categories-container/CategoriesContainer.tsx | 1 - .../category-dropdown/CategoryDropdown.spec.jsx | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index 75d4b4fd1d..3fcc634662 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -134,7 +134,6 @@ const CategoriesContainer = () => { ) const { mutate: handleCreateCategory } = useMutation({ - // mutationFn: (params?: CreateCategoriesParams) => createCategory(params), mutationFn: ResourceService.createResourceCategory, onSuccess: async (response) => { await onCategoryCreate(response) diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 1b6bafb752..3837cc520e 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -1,24 +1,26 @@ import { fireEvent, screen, waitFor } from '@testing-library/react' import { renderWithProviders, mockAxiosClient } from '~tests/test-utils' import { URLs } from '~/constants/request' + import CategoryDropdown from '~/containers/category-dropdown/CategoryDropdown' const categoriesNamesMock = [ { _id: '650c27618a9fbf234b8bb4cf', name: 'New category in resources!' }, { _id: '650c27618a9fbf234b8bb4cd', name: 'Category 1' } ] + describe('CategoryDropdown test', () => { mockAxiosClient - .onGet(URLs.resources.resourcesCategories.getNames) - .reply(200, categoriesNamesMock) + .onGet(URLs.resources.resourcesCategories.getNames) + .reply(200, categoriesNamesMock) beforeEach(async () => { await waitFor(() => { renderWithProviders() }) }) + it('should choose the category from options list', async () => { - renderWithProviders() const autocomplete = screen.getByRole('combobox') expect(autocomplete).toBeInTheDocument() @@ -45,7 +47,6 @@ describe('CategoryDropdown test', () => { }) it('should click on "add button" in options list', async () => { - renderWithProviders() const autocomplete = screen.getByRole('combobox') fireEvent.click(autocomplete) @@ -65,4 +66,4 @@ describe('CategoryDropdown test', () => { expect(newCategory).toBeInTheDocument() }) }) -}) +}) \ No newline at end of file From ae221b9c675671ab429103fae68b3fad7f5565d6 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Fri, 17 Jan 2025 15:59:05 +0200 Subject: [PATCH 21/27] fixed comments --- .../app-button-menu/AppButtonMenu.tsx | 10 +++---- .../category-dropdown/CategoryDropdown.tsx | 28 +++++++------------ .../CategoriesContainer.tsx | 15 +++------- .../ResourcesToolbarDrawer.tsx | 4 +-- src/services/resource-service.ts | 4 +-- .../app-button-menu/AppButtonMenu.spec.jsx | 10 ------- 6 files changed, 22 insertions(+), 49 deletions(-) diff --git a/src/components/app-button-menu/AppButtonMenu.tsx b/src/components/app-button-menu/AppButtonMenu.tsx index 55f3a2b975..55f59dc67d 100644 --- a/src/components/app-button-menu/AppButtonMenu.tsx +++ b/src/components/app-button-menu/AppButtonMenu.tsx @@ -64,15 +64,13 @@ const AppButtonMenu = >({ setSelectedItems([]) } - const { data: response, isLoading: loading } = useQuery({ + const { data: response, isLoading } = useQuery({ queryKey: [title], - queryFn: () => service(), - options: { - initialData: [] - } + queryFn: service }) const filteredItems = useMemo(() => { + if (!response) return [] const noneItem = { _id: 'null', [valueField as string]: 'No category' @@ -117,7 +115,7 @@ const AppButtonMenu = >({ ) - const itemsLoad = !response.length && loading + const itemsLoad = !response?.length && isLoading const chosenFiltersText = selectedNames.length ? selectedNames.join(', ') : t('cooperationsPage.tabs.all') diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 7f32e60d04..56a0f4e9fb 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -56,14 +56,10 @@ const CategoryDropdown = ({ [dispatch] ) - const { data: allCategoriesNames, refetch: fetchAllCategoriesNames } = - useQuery({ - queryKey: ['categoriesNames'], - queryFn: ResourceService.getResourcesCategoriesName, - options: { - initialData: [] - } - }) + const { data: allCategoriesNames = [] } = useQuery({ + queryKey: ['categoriesNames'], + queryFn: ResourceService.getResourcesCategoriesName + }) const onCreateCategory = () => { openModal({ @@ -78,7 +74,7 @@ const CategoryDropdown = ({ } const onResponseCategory = useCallback( - async (response: Categories | null) => { + (response: Categories | null) => { const categoryName = response ? response.name : '' dispatch( @@ -92,21 +88,17 @@ const CategoryDropdown = ({ } }) ) - - await fetchAllCategoriesNames() }, - [dispatch, fetchAllCategoriesNames] + [dispatch] ) const { mutate: handleCreateCategory } = useMutation({ + queryKey: ['categoriesNames'], mutationFn: ResourceService.createResourceCategory, - onSuccess: async (response) => { - await onResponseCategory(response) - }, - onError: (error: ErrorResponse) => { - handleResponseError(error) - } + onSuccess: onResponseCategory, + onError: handleResponseError }) + const optionsList = ( props: HTMLAttributes, option: string, diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index 3fcc634662..79a69117c2 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -112,13 +112,10 @@ const CategoriesContainer = () => { onResponseError }) - const { data: allCategoriesNames, refetch: fetchAllCategoriesNames } = + const { data: allCategoriesNames = [], refetch: fetchAllCategoriesNames } = useQuery({ queryKey: ['categoriesNames'], - queryFn: ResourceService.getResourcesCategoriesName, - options: { - initialData: [] - } + queryFn: ResourceService.getResourcesCategoriesName }) const onCategoryUpdate = useCallback(async () => { @@ -135,12 +132,8 @@ const CategoriesContainer = () => { const { mutate: handleCreateCategory } = useMutation({ mutationFn: ResourceService.createResourceCategory, - onSuccess: async (response) => { - await onCategoryCreate(response) - }, - onError: (error: ErrorResponse) => { - onResponseError(error) - } + onSuccess: onCategoryCreate, + onError: onResponseError }) const existingCategoriesNames = allCategoriesNames?.map((item) => item.name) diff --git a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx index 26681ab9c6..5b6159e6ed 100644 --- a/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx +++ b/src/containers/my-resources/resources-toolbar-drawer/ResourcesToolbarDrawer.tsx @@ -58,7 +58,7 @@ const ResourcesToolBarDrawer: FC = ({ handleNonInputValueChange('sortBy', value) const onApplyFilters = () => { - setCategories(data.categories || []) + setCategories(data.categories ?? []) setSearch(data.name) onRequestSort(data.sortBy) closeDrawer() @@ -84,7 +84,7 @@ const ResourcesToolBarDrawer: FC = ({ customSx={styles.filter} - selectedItems={data.categories || []} + selectedItems={data.categories ?? []} service={ResourceService.getResourcesCategoriesName} setSelectedItems={onCategoryChange} showNoneProperty diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index cc5878bec9..f4ec17c075 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -165,12 +165,12 @@ export const ResourceService = { }) }, createResourceCategory: async ( - params?: CreateCategoriesParams + params: CreateCategoriesParams ): Promise => { return await baseService.request({ method: 'POST', url: URLs.resources.resourcesCategories.post, - data: params || {} + data: params }) }, deleteResourceCategory: async (id: string): Promise => diff --git a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx index dfde209f3d..cc7293ebcb 100644 --- a/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx +++ b/tests/unit/components/app-button-menu/AppButtonMenu.spec.jsx @@ -33,16 +33,6 @@ describe('AppButtonMenu', () => { expect(buttonEl).toBeInTheDocument() }) - - it('renders no items message after clicking if there are no selected items', () => { - const buttonEl = screen.getByRole('button') - - fireEvent.click(buttonEl) - - const el = screen.getByText('No items found') - - expect(el).toBeInTheDocument() - }) it('input field should be in the component after clicking on a button', () => { const buttonEl = screen.getByRole('button') From 9c345d0e56684dffe4827ae454744415d24a534e Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Fri, 17 Jan 2025 18:54:54 +0200 Subject: [PATCH 22/27] fixed comments --- src/components/app-button-menu/AppButtonMenu.tsx | 6 ++++-- src/containers/category-dropdown/CategoryDropdown.tsx | 4 ++-- .../categories-container/CategoriesContainer.tsx | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/app-button-menu/AppButtonMenu.tsx b/src/components/app-button-menu/AppButtonMenu.tsx index 55f59dc67d..f6fc94bd08 100644 --- a/src/components/app-button-menu/AppButtonMenu.tsx +++ b/src/components/app-button-menu/AppButtonMenu.tsx @@ -70,7 +70,9 @@ const AppButtonMenu = >({ }) const filteredItems = useMemo(() => { - if (!response) return [] + if (!response) { + return [] + } const noneItem = { _id: 'null', [valueField as string]: 'No category' @@ -115,7 +117,7 @@ const AppButtonMenu = >({ ) - const itemsLoad = !response?.length && isLoading + const itemsLoad = !response || isLoading const chosenFiltersText = selectedNames.length ? selectedNames.join(', ') : t('cooperationsPage.tabs.all') diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 56a0f4e9fb..9537889696 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -6,6 +6,8 @@ import AddIcon from '@mui/icons-material/Add' import { useModalContext } from '~/context/modal-context' import { useAppDispatch } from '~/hooks/use-redux' +import useQuery from '~/hooks/use-query' +import useMutation from '~/hooks/use-mutation' import { ResourceService } from '~/services/resource-service' import AddCategoriesModal from '~/containers/my-resources/add-categories-modal/AddCategoriesModal' import DropdownButton from '~/components/dropdown-add-btn/DropdownButton' @@ -25,8 +27,6 @@ import { } from '~/containers/category-dropdown/CategoryDropdown.constants' import { openAlert } from '~/redux/features/snackbarSlice' import { getErrorKey } from '~/utils/get-error-key' -import useQuery from '~/hooks/use-query' -import useMutation from '~/hooks/use-mutation' interface CategoryDropdownInterface { category: string | null diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index 79a69117c2..1da9d11f7c 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -13,6 +13,8 @@ import { } from '~/services/resource-service' import MyResourcesTable from '~/containers/my-resources/my-resources-table/MyResourcesTable' import useAxios from '~/hooks/use-axios' +import useMutation from '~/hooks/use-mutation' +import useQuery from '~/hooks/use-query' import useSort from '~/hooks/table/use-sort' import useBreakpoints from '~/hooks/use-breakpoints' import usePagination from '~/hooks/table/use-pagination' @@ -39,8 +41,6 @@ import { styles } from '~/containers/my-resources/categories-container/Categorie import { useAppDispatch } from '~/hooks/use-redux' import { openAlert } from '~/redux/features/snackbarSlice' import { getErrorKey } from '~/utils/get-error-key' -import useMutation from '~/hooks/use-mutation' -import useQuery from '~/hooks/use-query' const CategoriesContainer = () => { const { t } = useTranslation() From 385c3c52bc5cb1830bf1f9acdbeeae2c1aad73ee Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 22 Jan 2025 17:55:19 +0200 Subject: [PATCH 23/27] fixed comments --- .../category-dropdown/CategoryDropdown.tsx | 12 ++++-------- .../category-dropdown/CategoryDropdown.spec.jsx | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 9537889696..02671b4712 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -13,12 +13,9 @@ import AddCategoriesModal from '~/containers/my-resources/add-categories-modal/A import DropdownButton from '~/components/dropdown-add-btn/DropdownButton' import { snackbarVariants } from '~/constants' -import { - Categories, - CategoryNameInterface, - ComponentEnum, - ErrorResponse -} from '~/types' +import { Categories, CategoryNameInterface, ComponentEnum } from '~/types' +import { getErrorKey } from '~/utils/get-error-key' +import { ResponseError } from '~/exceptions' import { styles } from '~/containers/category-dropdown/CategoryDropdown.styles' import AppAutoComplete from '~/components/app-auto-complete/AppAutoComplete' import { @@ -26,7 +23,6 @@ import { isOptionEqualToValue } from '~/containers/category-dropdown/CategoryDropdown.constants' import { openAlert } from '~/redux/features/snackbarSlice' -import { getErrorKey } from '~/utils/get-error-key' interface CategoryDropdownInterface { category: string | null @@ -45,7 +41,7 @@ const CategoryDropdown = ({ const { openModal, closeModal } = useModalContext() const handleResponseError = useCallback( - (error?: ErrorResponse) => { + (error?: ResponseError) => { dispatch( openAlert({ severity: snackbarVariants.error, diff --git a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx index 3837cc520e..5d5dbc5912 100644 --- a/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx +++ b/tests/unit/containers/category-dropdown/CategoryDropdown.spec.jsx @@ -66,4 +66,4 @@ describe('CategoryDropdown test', () => { expect(newCategory).toBeInTheDocument() }) }) -}) \ No newline at end of file +}) From d064c9e8f51d676dc32d8215c247054e5f545997 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 22 Jan 2025 18:07:11 +0200 Subject: [PATCH 24/27] fixed tests --- tests/unit/services/resource-service.spec.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/services/resource-service.spec.jsx b/tests/unit/services/resource-service.spec.jsx index a5fcd61992..08525d3648 100644 --- a/tests/unit/services/resource-service.spec.jsx +++ b/tests/unit/services/resource-service.spec.jsx @@ -89,4 +89,5 @@ describe('resourseService tests', () => { expect(mockAxiosClient.history.post[0].url).toBe(URLs.resources.resourcesCategories.post) expect(mockAxiosClient.history.post[0].data).toBe(JSON.stringify(params)) expect(response).toEqual(mockResponse) + }) }) From b94ee3fdbd8d25146bdc14f89a60408fac4190b7 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Fri, 24 Jan 2025 12:44:30 +0200 Subject: [PATCH 25/27] fixed comments --- src/components/app-button-menu/AppButtonMenu.tsx | 7 +------ src/containers/category-dropdown/CategoryDropdown.tsx | 2 +- src/services/resource-service.ts | 4 ++-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/components/app-button-menu/AppButtonMenu.tsx b/src/components/app-button-menu/AppButtonMenu.tsx index 89ab9bbae6..f78ef669de 100644 --- a/src/components/app-button-menu/AppButtonMenu.tsx +++ b/src/components/app-button-menu/AppButtonMenu.tsx @@ -19,12 +19,7 @@ import Button from '~scss-components/button/Button' import { spliceSx } from '~/utils/helper-functions' import { styles } from '~/components/app-button-menu/AppButtonMenu.styles' -import { CategoryNameInterface, ServiceFunction } from '~/types' -import { - ButtonVariantEnum, - CategoryNameInterface, - ServiceFunctionNew -} from '~/types' +import { CategoryNameInterface, ServiceFunctionNew } from '~/types' interface AppButtonMenuProps extends Omit { title: string diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 02671b4712..747d43213f 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -41,7 +41,7 @@ const CategoryDropdown = ({ const { openModal, closeModal } = useModalContext() const handleResponseError = useCallback( - (error?: ResponseError) => { + (error: ResponseError) => { dispatch( openAlert({ severity: snackbarVariants.error, diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index 53ebee8fc7..8ac632fab2 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -173,10 +173,10 @@ export const ResourceService = { url: URLs.resources.resourcesCategories.getNames }) }, - createResourceCategory: async ( + createResourceCategory: ( params: CreateCategoriesParams ): Promise => { - return await baseService.request({ + return baseService.request({ method: 'POST', url: URLs.resources.resourcesCategories.post, data: params From 7a8256e614a2703e4716cf0d8c276d0fad616a0c Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 29 Jan 2025 19:30:04 +0200 Subject: [PATCH 26/27] fixed comments --- src/components/app-button-menu/AppButtonMenu.tsx | 2 +- src/containers/category-dropdown/CategoryDropdown.tsx | 10 +++++++--- .../categories-container/CategoriesContainer.tsx | 2 +- src/services/resource-service.ts | 4 +--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/app-button-menu/AppButtonMenu.tsx b/src/components/app-button-menu/AppButtonMenu.tsx index f78ef669de..616e5d30ee 100644 --- a/src/components/app-button-menu/AppButtonMenu.tsx +++ b/src/components/app-button-menu/AppButtonMenu.tsx @@ -61,7 +61,7 @@ const AppButtonMenu = >({ } const { data: response, isLoading } = useQuery({ - queryKey: [title], + queryKey: ['app-button-menu', title], queryFn: service }) diff --git a/src/containers/category-dropdown/CategoryDropdown.tsx b/src/containers/category-dropdown/CategoryDropdown.tsx index 747d43213f..5f8bfd661a 100644 --- a/src/containers/category-dropdown/CategoryDropdown.tsx +++ b/src/containers/category-dropdown/CategoryDropdown.tsx @@ -13,9 +13,13 @@ import AddCategoriesModal from '~/containers/my-resources/add-categories-modal/A import DropdownButton from '~/components/dropdown-add-btn/DropdownButton' import { snackbarVariants } from '~/constants' -import { Categories, CategoryNameInterface, ComponentEnum } from '~/types' +import { + type Categories, + type CategoryNameInterface, + ComponentEnum +} from '~/types' import { getErrorKey } from '~/utils/get-error-key' -import { ResponseError } from '~/exceptions' +import { type ResponseError } from '~/exceptions' import { styles } from '~/containers/category-dropdown/CategoryDropdown.styles' import AppAutoComplete from '~/components/app-auto-complete/AppAutoComplete' import { @@ -70,7 +74,7 @@ const CategoryDropdown = ({ } const onResponseCategory = useCallback( - (response: Categories | null) => { + (response: Categories) => { const categoryName = response ? response.name : '' dispatch( diff --git a/src/containers/my-resources/categories-container/CategoriesContainer.tsx b/src/containers/my-resources/categories-container/CategoriesContainer.tsx index 2c58b6f8ca..488b7268d2 100644 --- a/src/containers/my-resources/categories-container/CategoriesContainer.tsx +++ b/src/containers/my-resources/categories-container/CategoriesContainer.tsx @@ -123,7 +123,7 @@ const CategoriesContainer = () => { }, [fetchData, fetchAllCategoriesNames]) const onCategoryCreate = useCallback( - async (response: Categories | null) => { + async (response: Categories) => { onResponse(response) await Promise.all([fetchData(), fetchAllCategoriesNames()]) }, diff --git a/src/services/resource-service.ts b/src/services/resource-service.ts index 8ac632fab2..d8e15bbadf 100644 --- a/src/services/resource-service.ts +++ b/src/services/resource-service.ts @@ -173,9 +173,7 @@ export const ResourceService = { url: URLs.resources.resourcesCategories.getNames }) }, - createResourceCategory: ( - params: CreateCategoriesParams - ): Promise => { + createResourceCategory: (params: CreateCategoriesParams) => { return baseService.request({ method: 'POST', url: URLs.resources.resourcesCategories.post, From d3dd349a12db8febc74de0f587fb64f5be16c8c0 Mon Sep 17 00:00:00 2001 From: Zhayvoronok Kateryna <1gayv425@gmail.com> Date: Wed, 29 Jan 2025 20:46:38 +0200 Subject: [PATCH 27/27] added type to import --- src/components/app-button-menu/AppButtonMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/app-button-menu/AppButtonMenu.tsx b/src/components/app-button-menu/AppButtonMenu.tsx index 616e5d30ee..d33cbc20e4 100644 --- a/src/components/app-button-menu/AppButtonMenu.tsx +++ b/src/components/app-button-menu/AppButtonMenu.tsx @@ -19,7 +19,7 @@ import Button from '~scss-components/button/Button' import { spliceSx } from '~/utils/helper-functions' import { styles } from '~/components/app-button-menu/AppButtonMenu.styles' -import { CategoryNameInterface, ServiceFunctionNew } from '~/types' +import { CategoryNameInterface, type ServiceFunctionNew } from '~/types' interface AppButtonMenuProps extends Omit { title: string