diff --git a/packages/manager/apps/zimbra/.gitignore b/packages/manager/apps/zimbra/.gitignore new file mode 100644 index 000000000000..4ebc8aea50e0 --- /dev/null +++ b/packages/manager/apps/zimbra/.gitignore @@ -0,0 +1 @@ +coverage diff --git a/packages/manager/apps/zimbra/src/api/_mock_/account.ts b/packages/manager/apps/zimbra/src/api/_mock_/account.ts index 02cf6613e70a..c561f24e6cf1 100644 --- a/packages/manager/apps/zimbra/src/api/_mock_/account.ts +++ b/packages/manager/apps/zimbra/src/api/_mock_/account.ts @@ -1,82 +1,94 @@ import { AccountType } from '@/api/account'; import { ResourceStatus } from '@/api/api.type'; -export const accountMock: AccountType[] = [ - { - checksum: 'string', - currentState: { - contactInformation: { - city: 'string', - company: 'string', - country: 'string', - faxNumber: 'string', - mobileNumber: 'string', - office: 'string', - phoneNumber: 'string', - postcode: 'string', - profession: 'string', - service: 'string', - street: 'string', - }, - createdAt: '2024-07-09T13:27:12.775Z', - description: 'string', - detailedStatus: [ - { - details: 'string', - link: 'string', - status: 'BLOCKEDFORSPAM', - }, - ], - displayName: 'string', - domainId: '19097ad4-2870-4000-8bb0-470f414b0301', - email: 'string', - firstName: 'string', - hideInGal: false, - lastConnectionAt: '2024-07-09T13:27:12.775Z', - lastName: 'string', - offer: 'BUSINESS', - organizationId: '19097ad4-2870-4000-82b3-b71a147bc580', - organizationLabel: 'string', - quota: { - available: 0, - used: 0, - }, - updatedAt: '2024-07-09T13:27:12.775Z', +export const accountDetailMock: AccountType = { + checksum: 'string', + currentState: { + contactInformation: { + city: 'string', + company: 'string', + country: 'string', + faxNumber: 'string', + mobileNumber: 'string', + office: 'string', + phoneNumber: 'string', + postcode: 'string', + profession: 'string', + service: 'string', + street: 'string', }, - currentTasks: [ + createdAt: '2024-07-09T13:27:12.775Z', + description: 'string', + detailedStatus: [ { - id: '19097ad4-2870-4000-8bed-ecab3a061780', + details: 'string', link: 'string', - status: 'ERROR', - type: 'string', + status: 'BLOCKEDFORSPAM', }, ], - id: '19097ad4-2880-4000-8b03-9d110f0b8f80', - resourceStatus: ResourceStatus.CREATING, - targetSpec: { - contactInformation: { - city: 'string', - company: 'string', - country: 'string', - faxNumber: 'string', - mobileNumber: 'string', - office: 'string', - phoneNumber: 'string', - postcode: 'string', - profession: 'string', - service: 'string', - street: 'string', - }, - description: 'string', - displayName: 'string', - email: 'string', - firstName: 'string', - hideInGal: false, - lastName: 'string', - quota: { - available: 0, - used: 0, - }, + displayName: 'string', + domainId: '19097ad4-2870-4000-8bb0-470f414b0301', + email: 'string', + firstName: 'string', + hideInGal: false, + lastConnectionAt: '2024-07-09T13:27:12.775Z', + lastName: 'string', + offer: 'BUSINESS', + organizationId: '19097ad4-2870-4000-82b3-b71a147bc580', + organizationLabel: 'string', + quota: { + available: 0, + used: 0, + }, + updatedAt: '2024-07-09T13:27:12.775Z', + }, + currentTasks: [ + { + id: '19097ad4-2870-4000-8bed-ecab3a061780', + link: 'string', + status: 'ERROR', + type: 'string', }, + ], + id: '19097ad4-2880-4000-8b03-9d110f0b8f80', + resourceStatus: ResourceStatus.READY, + targetSpec: { + contactInformation: { + city: 'string', + company: 'string', + country: 'string', + faxNumber: 'string', + mobileNumber: 'string', + office: 'string', + phoneNumber: 'string', + postcode: 'string', + profession: 'string', + service: 'string', + street: 'string', + }, + description: 'string', + displayName: 'string', + email: 'string', + firstName: 'string', + hideInGal: false, + lastName: 'string', + quota: { + available: 0, + used: 0, + }, + }, +}; + +export const accountsMock: AccountType[] = [ + accountDetailMock, + { + ...accountDetailMock, + id: '19097ad4-2880-4444-8b03-9d110f0b8f80', + resourceStatus: ResourceStatus.CREATING, + }, + { + ...accountDetailMock, + id: '19097ad4-2880-5555-8b03-9d110f0b8f80', + resourceStatus: ResourceStatus.ERROR, }, ]; diff --git a/packages/manager/apps/zimbra/src/api/_mock_/domain.ts b/packages/manager/apps/zimbra/src/api/_mock_/domain.ts index 47a58b809970..23feb81d5869 100644 --- a/packages/manager/apps/zimbra/src/api/_mock_/domain.ts +++ b/packages/manager/apps/zimbra/src/api/_mock_/domain.ts @@ -1,44 +1,46 @@ import { DomainType } from '@/api/domain'; import { ResourceStatus } from '@/api/api.type'; -export const domainMock: DomainType[] = [ - { - id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', - resourceStatus: ResourceStatus.READY, - checksum: 'string', - targetSpec: { - organizationId: '00000000-0000-0000-0000-000000000000', - }, - currentState: { - organizationId: '00000000-0000-0000-0000-000000000000', - name: 'NormalDomain', - status: 'READY', - createdAt: '2024-04-12T12:27:47.213Z', - updatedAt: '2024-04-12T12:27:47.213Z', - organizationLabel: 'ToyStory', - cnameToCheck: '', - accountsStatistics: [ - { - offer: 'STARTER', - configuredAccountsCount: 0, - availableAccountsCount: 4, - }, - ], - expectedDNSConfig: { - mx: [], - ownership: { - cname: null, - }, - }, - }, - currentTasks: [ +export const domainDetailMock: DomainType = { + id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', + resourceStatus: ResourceStatus.READY, + checksum: 'string', + targetSpec: { + organizationId: '00000000-0000-0000-0000-000000000000', + }, + currentState: { + organizationId: '00000000-0000-0000-0000-000000000000', + name: 'NormalDomain', + status: 'READY', + createdAt: '2024-04-12T12:27:47.213Z', + updatedAt: '2024-04-12T12:27:47.213Z', + organizationLabel: 'ToyStory', + cnameToCheck: '', + accountsStatistics: [ { - id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', - type: 'string', - link: 'string', + offer: 'STARTER', + configuredAccountsCount: 0, + availableAccountsCount: 4, }, ], + expectedDNSConfig: { + mx: [], + ownership: { + cname: null, + }, + }, }, + currentTasks: [ + { + id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', + type: 'string', + link: 'string', + }, + ], +}; + +export const domainsMock: DomainType[] = [ + domainDetailMock, { id: '3fa91f64-0000-4562-b3fc-000000000000', resourceStatus: ResourceStatus.READY, diff --git a/packages/manager/apps/zimbra/src/api/_mock_/index.ts b/packages/manager/apps/zimbra/src/api/_mock_/index.ts index e89981b0b17a..39c0455f42f9 100644 --- a/packages/manager/apps/zimbra/src/api/_mock_/index.ts +++ b/packages/manager/apps/zimbra/src/api/_mock_/index.ts @@ -4,3 +4,4 @@ export * from './organization'; export * from './domain'; export * from './account'; export * from './alias'; +export * from './task'; diff --git a/packages/manager/apps/zimbra/src/api/_mock_/task.ts b/packages/manager/apps/zimbra/src/api/_mock_/task.ts new file mode 100644 index 000000000000..28dc4b356d9d --- /dev/null +++ b/packages/manager/apps/zimbra/src/api/_mock_/task.ts @@ -0,0 +1,21 @@ +export const taskDetailMock = { + createdAt: 'string', + errors: [{ message: 'string' }], + finishedAt: 'string', + id: '1', + link: 'string', + message: 'string', + progress: [{ name: 'string', status: 'string' }], + startedAt: 'string', + status: 'string', + type: 'string', + updatedAt: 'string', +}; + +export const taskMocks = [ + taskDetailMock, + { ...taskDetailMock, id: '2' }, + { ...taskDetailMock, id: '3' }, + { ...taskDetailMock, id: '4' }, + { ...taskDetailMock, id: '5' }, +]; diff --git a/packages/manager/apps/zimbra/src/components/Breadcrumb/Breadcrumb.tsx b/packages/manager/apps/zimbra/src/components/Breadcrumb/Breadcrumb.tsx index e4a6074561dd..86735b42281c 100644 --- a/packages/manager/apps/zimbra/src/components/Breadcrumb/Breadcrumb.tsx +++ b/packages/manager/apps/zimbra/src/components/Breadcrumb/Breadcrumb.tsx @@ -55,7 +55,13 @@ export const Breadcrumb: React.FC = ({ ...items, ].filter(Boolean); - return ; + return ( + + ); }; export default Breadcrumb; diff --git a/packages/manager/apps/zimbra/src/components/Breadcrumb/__test__/Breadcrumb.spec.tsx b/packages/manager/apps/zimbra/src/components/Breadcrumb/__test__/Breadcrumb.spec.tsx new file mode 100644 index 000000000000..ff3cf061bafd --- /dev/null +++ b/packages/manager/apps/zimbra/src/components/Breadcrumb/__test__/Breadcrumb.spec.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { describe, expect } from 'vitest'; +import { render } from '@/utils/test.provider'; +import Breadcrumb from '../Breadcrumb'; + +describe('Breadcrumb component', () => { + it('should render', async () => { + const { getByTestId } = render(); + const cmp = getByTestId('breadcrumb'); + expect(cmp).toBeInTheDocument(); + }); +}); diff --git a/packages/manager/apps/zimbra/src/components/ButtonTooltip/ButtonTooltip.tsx b/packages/manager/apps/zimbra/src/components/ButtonTooltip/ButtonTooltip.tsx index 6a1ba4cff121..8d990ec00662 100644 --- a/packages/manager/apps/zimbra/src/components/ButtonTooltip/ButtonTooltip.tsx +++ b/packages/manager/apps/zimbra/src/components/ButtonTooltip/ButtonTooltip.tsx @@ -52,6 +52,7 @@ const ButtonTooltip: React.FC = (props) => { variant={ODS_BUTTON_VARIANT.stroked} color={ODS_THEME_COLOR_INTENT.primary} onClick={(event) => handleTooltipToggle(event)} + data-testid="button-tooltip" circle > { + it('should render', async () => { + const { getByTestId } = render( + , + ); + const cmp = getByTestId('button-tooltip'); + expect(cmp).toBeInTheDocument(); + }); +}); diff --git a/packages/manager/apps/zimbra/src/components/Error/__test__/Error.spec.tsx b/packages/manager/apps/zimbra/src/components/Error/__test__/Error.spec.tsx new file mode 100644 index 000000000000..e78859751e50 --- /dev/null +++ b/packages/manager/apps/zimbra/src/components/Error/__test__/Error.spec.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { describe, expect, vi } from 'vitest'; +import { render } from '@/utils/test.provider'; +import ErrorBanner from '../Error'; + +vi.mock('@ovh-ux/manager-react-core-application', async (importActual) => { + return { + ...(await importActual< + typeof import('@ovh-ux/manager-react-core-application') + >()), + useShell: vi.fn(() => ({ + tracking: { + trackPage: vi.fn(), + }, + environment: { + getEnvironment: vi.fn(() => Promise.resolve({})), + }, + })), + }; +}); + +describe('Error component', () => { + it('should render', async () => { + const { getByText } = render( + , + ); + expect(getByText('test')).toBeInTheDocument(); + }); +}); diff --git a/packages/manager/apps/zimbra/src/components/Loading/Loading.tsx b/packages/manager/apps/zimbra/src/components/Loading/Loading.tsx index c7ed75ea9de6..303bc4571e2e 100644 --- a/packages/manager/apps/zimbra/src/components/Loading/Loading.tsx +++ b/packages/manager/apps/zimbra/src/components/Loading/Loading.tsx @@ -8,7 +8,7 @@ export default function Loading({ size = ODS_SPINNER_SIZE.md, }) { return ( -
+
); diff --git a/packages/manager/apps/zimbra/src/components/Modals/Modal.tsx b/packages/manager/apps/zimbra/src/components/Modals/Modal.tsx index fdef3a13af31..5d00408bb36b 100644 --- a/packages/manager/apps/zimbra/src/components/Modals/Modal.tsx +++ b/packages/manager/apps/zimbra/src/components/Modals/Modal.tsx @@ -1,11 +1,8 @@ import React from 'react'; -import { - OsdsButton, - OsdsModal, - OsdsSpinner, -} from '@ovhcloud/ods-components/react'; +import { OsdsButton, OsdsModal } from '@ovhcloud/ods-components/react'; import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; -import { ODS_BUTTON_VARIANT, ODS_SPINNER_MODE } from '@ovhcloud/ods-components'; +import { ODS_BUTTON_VARIANT } from '@ovhcloud/ods-components'; +import Loading from '@/components/Loading/Loading'; export interface ButtonType { testid?: string; @@ -47,14 +44,7 @@ const Modal: React.FC = ({ onOdsModalClose={onDismissible} > {!isLoading &&
{children}
} - {isLoading && ( -
- -
- )} + {isLoading && } {secondaryButton && ( > = ({ label, + testid, children, }) => ( -
+
{ + it('should display correctly', async () => { + const { getByTestId } = render(); + const cmp = getByTestId('breadcrumb'); + expect(cmp).toBeInTheDocument(); + }); +}); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useAccount.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useAccount.spec.tsx index 8a4822cede78..b1a3e80dcea1 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useAccount.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useAccount.spec.tsx @@ -1,40 +1,23 @@ -import { describe, expect, vi } from 'vitest'; +import { describe, expect } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; -import { platformMock, accountMock } from '@/api/_mock_'; -import { useAccount } from '../useAccount'; +import { accountDetailMock } from '@/api/_mock_'; +import { useAccount } from '@/hooks'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - }; -}); - -vi.mock('@/api/account/api', () => { - const apiZimbraPlatformAccountDetail = vi.fn(() => - Promise.resolve(accountMock[0]), - ); - return { - getZimbraPlatformAccountDetail: apiZimbraPlatformAccountDetail, - }; -}); - describe('useAccount', () => { it('should return the detail of an account', async () => { const { result } = renderHook( - () => useAccount({ accountId: accountMock[0].id }), + () => useAccount({ accountId: accountDetailMock.id }), { wrapper, }, ); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); - expect(result.current.data).toEqual(accountMock[0]); + expect(result.current.data).toEqual(accountDetailMock); }); }); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useAccountList.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useAccountList.spec.tsx index e2296765af7e..62dae1ef4e4b 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useAccountList.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useAccountList.spec.tsx @@ -1,39 +1,18 @@ -import { describe, expect, vi } from 'vitest'; +import { describe, expect } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; -import { platformMock, accountMock } from '@/api/_mock_'; -import { useAccountList } from '../useAccountList'; +import { accountsMock } from '@/api/_mock_'; +import { useAccountList } from '@/hooks'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - }; -}); - -vi.mock('@/api/account/api', () => { - const apiZimbraPlatformAccount = vi.fn(() => Promise.resolve(accountMock)); - return { - getZimbraPlatformAccounts: apiZimbraPlatformAccount, - }; -}); - -vi.mock('react-router-dom', () => { - return { - useSearchParams: vi.fn(() => [new URLSearchParams()]), - }; -}); - describe('useAccountList', () => { it('should return a list of accounts', async () => { const { result } = renderHook(() => useAccountList(), { wrapper }); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); - expect(result.current.data).toEqual(accountMock); + expect(result.current.data).toEqual(accountsMock); }); }); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useDomain.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useDomain.spec.tsx index f024c6b8f2a3..38eaa0171ba9 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useDomain.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useDomain.spec.tsx @@ -1,37 +1,20 @@ -import { describe, expect, vi } from 'vitest'; +import { describe, expect } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; -import { platformMock, domainMock } from '@/api/_mock_'; +import { domainDetailMock } from '@/api/_mock_'; import { useDomain } from '../useDomain'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - }; -}); - -vi.mock('@/api/domain/api', () => { - const apiGetDomainDetail = (_platformId: string, id: string) => - Promise.resolve(domainMock.find((domain) => domain.id === id)); - return { - getZimbraPlatformDomainDetail: apiGetDomainDetail, - }; -}); - describe('useDomain', () => { it('should return the detail of a domain', async () => { - const domain = domainMock[0]; - const { result } = renderHook(() => useDomain(domain.id), { + const { result } = renderHook(() => useDomain(domainDetailMock.id), { wrapper, }); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); - expect(result.current.data).toEqual(domain); + expect(result.current.data).toEqual(domainDetailMock); }); }); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useDomains.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useDomains.spec.tsx index 346d06c73ca4..ca3909535cb8 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useDomains.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useDomains.spec.tsx @@ -1,36 +1,18 @@ -import { describe, expect, vi } from 'vitest'; +import { describe, expect } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; -import { platformMock, organizationDetailMock, domainMock } from '@/api/_mock_'; +import { domainsMock } from '@/api/_mock_'; import { useDomains } from '../useDomains'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useOrganization: vi.fn(() => ({ - data: organizationDetailMock, - })), - }; -}); - -vi.mock('@/api/domain/api', () => { - const apiGetDomains = vi.fn(() => Promise.resolve(domainMock)); - return { - getZimbraPlatformDomains: apiGetDomains, - }; -}); - describe('useDomains', () => { it('should return a domain list', async () => { const { result } = renderHook(() => useDomains(), { wrapper }); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); - expect(result.current.data).toEqual(domainMock); + expect(result.current.data).toEqual(domainsMock); }); }); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useGenerateUrl.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useGenerateUrl.spec.tsx index 83c031fdb940..91037092772f 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useGenerateUrl.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useGenerateUrl.spec.tsx @@ -4,16 +4,9 @@ import { renderHook } from '@testing-library/react'; import { useGenerateUrl } from '../useGenerateUrl'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/hooks', () => { - return { - useOrganization: vi.fn(() => ({ data: undefined })), - }; -}); - vi.mock('react-router-dom', async (importOriginal) => { - const actual: any = await importOriginal(); return { - ...actual, + ...(await importOriginal()), useHref: vi.fn( (text) => `#/00000000-0000-0000-0000-000000000001/organizations/${text.slice(2)}`, diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useMailingList.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useMailingList.spec.tsx index 397e5edf9d1b..6db2172b95bd 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useMailingList.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useMailingList.spec.tsx @@ -1,40 +1,23 @@ -import { describe, expect, vi } from 'vitest'; +import { describe, expect } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; -import { platformMock, mailingListsMock } from '@/api/_mock_'; -import { useMailingList } from '../useMailingList'; +import { mailingListDetailMock } from '@/api/_mock_'; +import { useMailingList } from '@/hooks'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - }; -}); - -vi.mock('@/api/mailinglist/api', () => { - const apiGetMailingListDetail = (_platformId: string, id: string) => - Promise.resolve(mailingListsMock.find((ml) => ml.id === id)); - return { - getZimbraPlatformMailingListDetails: apiGetMailingListDetail, - }; -}); - describe('useMailingList', () => { it('should return a mailinglist detail', async () => { - const mailingList = mailingListsMock[0]; const { result } = renderHook( - () => useMailingList({ mailingListId: mailingList.id }), + () => useMailingList({ mailingListId: mailingListDetailMock.id }), { wrapper, }, ); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); - expect(result.current.data).toEqual(mailingList); + expect(result.current.data).toEqual(mailingListDetailMock); }); }); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useMailingLists.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useMailingLists.spec.tsx index 13673c78ebc4..137bc4a4b4bc 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useMailingLists.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useMailingLists.spec.tsx @@ -1,37 +1,16 @@ -import { describe, expect, vi } from 'vitest'; +import { describe, expect } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; -import { platformMock, mailingListsMock } from '@/api/_mock_'; -import { useMailingLists } from '../useMailingLists'; +import { mailingListsMock } from '@/api/_mock_'; +import { useMailingLists } from '@/hooks'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - }; -}); - -vi.mock('@/api/mailinglist/api', () => { - const apiGetMailingLists = vi.fn(() => Promise.resolve(mailingListsMock)); - return { - getZimbraPlatformMailingLists: apiGetMailingLists, - }; -}); - -vi.mock('react-router-dom', () => { - return { - useSearchParams: vi.fn(() => [new URLSearchParams()]), - }; -}); - describe('useMailingLists', () => { it('should return mailing lists', async () => { const { result } = renderHook(() => useMailingLists(), { wrapper }); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); expect(result.current.data).toEqual(mailingListsMock); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useOrganization.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useOrganization.spec.tsx index fa333e09ffc6..84f54edcb124 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useOrganization.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useOrganization.spec.tsx @@ -1,55 +1,24 @@ import { describe, expect, vi } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; -import { platformMock, organizationDetailMock } from '@/api/_mock_'; +import { useSearchParams } from 'react-router-dom'; +import { organizationDetailMock } from '@/api/_mock_'; import { useOrganization } from '../useOrganization'; import { wrapper } from '@/utils/test.provider'; -const useLocationMock: { - pathname: string; - search: string; - hash: string; - state: string | null; - key: string; -} = { - pathname: '/00000000-0000-0000-0000-000000000001', - search: '?organizationId=1903b491-4d10-4000-8b70-f474d1abe601', - hash: '', - state: null, - key: 'naq3ecco', -}; - -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - }; -}); - -vi.mock('@/api/organization/api', () => { - const apiOrganizationDetail = vi.fn(() => - Promise.resolve(organizationDetailMock), - ); - return { - getZimbraPlatformOrganizationDetails: apiOrganizationDetail, - }; -}); - -vi.mock('react-router-dom', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useLocation: () => useLocationMock, - }; -}); - describe('useOrganization', () => { it('should return detail of organization in params url', async () => { + vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + organizationId: organizationDetailMock.id, + }), + vi.fn(), + ]); + const { result } = renderHook(() => useOrganization(), { wrapper }); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); expect(result.current.data).toEqual(organizationDetailMock); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useOrganizationsList.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useOrganizationsList.spec.tsx index 710f7a0f8a65..27f0ad9865b0 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/useOrganizationsList.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useOrganizationsList.spec.tsx @@ -1,31 +1,16 @@ -import { describe, expect, vi } from 'vitest'; +import { describe, expect } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; -import { platformMock, organizationListMock } from '@/api/_mock_'; +import { organizationListMock } from '@/api/_mock_'; import { useOrganizationList } from '../useOrganizationsList'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - }; -}); - -vi.mock('@/api/organization/api', () => { - const apiOrganization = vi.fn(() => Promise.resolve(organizationListMock)); - return { - getZimbraPlatformOrganization: apiOrganization, - }; -}); - describe('useOrganizationsList', () => { it('should return a list of organization', async () => { const { result } = renderHook(() => useOrganizationList(), { wrapper }); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); expect(result.current.data).toEqual(organizationListMock); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useOverridePage.spec.ts b/packages/manager/apps/zimbra/src/hooks/__test__/useOverridePage.spec.ts new file mode 100644 index 000000000000..5224a5c59f6a --- /dev/null +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useOverridePage.spec.ts @@ -0,0 +1,25 @@ +import { describe, expect, vi } from 'vitest'; +import { useMatches } from 'react-router-dom'; +import { useOverridePage } from '../useOverridePage'; +import '@testing-library/jest-dom'; + +describe('useOverridePage', () => { + it('should return false', async () => { + vi.mocked(useMatches).mockReturnValue([]); + expect(useOverridePage()).toBeFalsy(); + }); + + it('should return false', async () => { + vi.mocked(useMatches).mockReturnValue([ + { handle: { isOverridePage: false } }, + ] as never); + expect(useOverridePage()).toBeFalsy(); + }); + + it('should return false', async () => { + vi.mocked(useMatches).mockReturnValue([ + { handle: { isOverridePage: true } }, + ] as never); + expect(useOverridePage()).toBeTruthy(); + }); +}); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/usePlatform.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/usePlatform.spec.tsx index 2a5d562d4fb6..3da9f64c20e0 100644 --- a/packages/manager/apps/zimbra/src/hooks/__test__/usePlatform.spec.tsx +++ b/packages/manager/apps/zimbra/src/hooks/__test__/usePlatform.spec.tsx @@ -1,23 +1,16 @@ -import { describe, expect, vi } from 'vitest'; +import { describe, expect } from 'vitest'; import '@testing-library/jest-dom'; import { renderHook, waitFor } from '@testing-library/react'; import { usePlatform } from '../usePlatform'; import { platformMock } from '@/api/_mock_'; import { wrapper } from '@/utils/test.provider'; -vi.mock('@/api/platform/api', () => { - const mock = vi.fn(() => Promise.resolve(platformMock)); - return { - getZimbraPlatformList: mock, - }; -}); - describe('usePlatform', () => { it('should return the first element of the platform list', async () => { const { result } = renderHook(() => usePlatform(), { wrapper }); await waitFor(() => { - expect(result.current.isLoading).toBe(false); + expect(result.current.isSuccess).toBe(true); }); expect(result.current.data).toEqual(platformMock[0]); diff --git a/packages/manager/apps/zimbra/src/hooks/__test__/useTasks.spec.tsx b/packages/manager/apps/zimbra/src/hooks/__test__/useTasks.spec.tsx new file mode 100644 index 000000000000..83aa4405c0be --- /dev/null +++ b/packages/manager/apps/zimbra/src/hooks/__test__/useTasks.spec.tsx @@ -0,0 +1,18 @@ +import { describe, expect } from 'vitest'; +import '@testing-library/jest-dom'; +import { renderHook, waitFor } from '@testing-library/react'; +import { taskMocks } from '@/api/_mock_'; +import { useTasks } from '../useTasks'; +import { wrapper } from '@/utils/test.provider'; + +describe('useTasks', () => { + it('should return a list of tasks', async () => { + const { result } = renderHook(() => useTasks(), { wrapper }); + + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + }); + + expect(result.current.data).toEqual(taskMocks); + }); +}); diff --git a/packages/manager/apps/zimbra/src/hooks/index.ts b/packages/manager/apps/zimbra/src/hooks/index.ts index c8eed2e96310..f42c7fc916e6 100644 --- a/packages/manager/apps/zimbra/src/hooks/index.ts +++ b/packages/manager/apps/zimbra/src/hooks/index.ts @@ -10,4 +10,5 @@ export * from './useOrganizationsList'; export * from './useOverridePage'; export * from './usePlatform'; export * from './useAccount'; +export * from './useTasks'; export * from './types'; diff --git a/packages/manager/apps/zimbra/src/hooks/useDomain.ts b/packages/manager/apps/zimbra/src/hooks/useDomain.ts index 36c598a43209..b94ffe06f7b5 100644 --- a/packages/manager/apps/zimbra/src/hooks/useDomain.ts +++ b/packages/manager/apps/zimbra/src/hooks/useDomain.ts @@ -9,17 +9,10 @@ import { export const useDomain = (domainId: string, noCache?: boolean) => { const { platformId } = usePlatform(); - const { data, isLoading, isError, error } = useQuery({ + return useQuery({ queryKey: getZimbraPlatformDomainQueryKey(platformId, domainId), queryFn: () => getZimbraPlatformDomainDetail(platformId, domainId), enabled: !!platformId && !!domainId, gcTime: noCache ? 0 : 5000, }); - - return { - isLoading, - isError, - error, - data, - }; }; diff --git a/packages/manager/apps/zimbra/src/hooks/useOrganization.ts b/packages/manager/apps/zimbra/src/hooks/useOrganization.ts index a6039151df06..fb2e487c6483 100644 --- a/packages/manager/apps/zimbra/src/hooks/useOrganization.ts +++ b/packages/manager/apps/zimbra/src/hooks/useOrganization.ts @@ -1,5 +1,5 @@ import { useQuery } from '@tanstack/react-query'; -import { useLocation } from 'react-router-dom'; +import { useSearchParams } from 'react-router-dom'; import { usePlatform } from '@/hooks'; import { getZimbraPlatformOrganizationDetails, @@ -8,9 +8,8 @@ import { export const useOrganization = (organizationId?: string, noCache?: boolean) => { const { platformId } = usePlatform(); - const location = useLocation(); - const params = new URLSearchParams(location.search); - const selectedOrganizationId = params.get('organizationId'); + const [searchParams] = useSearchParams(); + const selectedOrganizationId = searchParams.get('organizationId'); return useQuery({ queryKey: getZimbraPlatformOrganizationDetailsQueryKey( platformId, diff --git a/packages/manager/apps/zimbra/src/hooks/usePlatform.ts b/packages/manager/apps/zimbra/src/hooks/usePlatform.ts index f8acb8200df1..3237789e8359 100644 --- a/packages/manager/apps/zimbra/src/hooks/usePlatform.ts +++ b/packages/manager/apps/zimbra/src/hooks/usePlatform.ts @@ -5,12 +5,13 @@ import { } from '@/api/platform'; export const usePlatform = () => { - const { data, isLoading, isError, error } = useQuery({ + const { data, isLoading, isError, error, ...rest } = useQuery({ queryKey: [getZimbraPlatformListQueryKey], queryFn: () => getZimbraPlatformList(), }); return { + ...rest, isLoading, isError, error, diff --git a/packages/manager/apps/zimbra/src/hooks/useTasks.ts b/packages/manager/apps/zimbra/src/hooks/useTasks.ts new file mode 100644 index 000000000000..debfc478f1ce --- /dev/null +++ b/packages/manager/apps/zimbra/src/hooks/useTasks.ts @@ -0,0 +1,29 @@ +import { + useQuery, + UseQueryOptions, + UseQueryResult, +} from '@tanstack/react-query'; +import { usePlatform, useOrganization } from '@/hooks'; +import { + getZimbraPlatformTask, + getZimbraPlatformTaskQueryKey, + TaskType, +} from '@/api/task'; + +type UseTasksParams = Omit; + +export const useTasks = (options: UseTasksParams = {}) => { + const { platformId } = usePlatform(); + const { data: organization } = useOrganization(); + + return useQuery({ + ...options, + queryKey: getZimbraPlatformTaskQueryKey(platformId, organization?.id), + queryFn: () => getZimbraPlatformTask(platformId, organization?.id), + enabled: (query) => + (typeof options.enabled === 'function' + ? options.enabled(query) + : typeof options.enabled !== 'boolean' || options.enabled) && + !!platformId, + }) as UseQueryResult; +}; diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/AutoReplies/AutoReplies.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/AutoReplies/AutoReplies.tsx index 3afde6ba7b99..582551816a16 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/AutoReplies/AutoReplies.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/AutoReplies/AutoReplies.tsx @@ -85,7 +85,7 @@ export function AutoReplies() { const { t } = useTranslation('autoReplies'); return ( -
+
{ - const actual: any = await importOriginal(); - return { - ...actual, - usePlatform: vi.fn(() => ({ - platformUrn: platformMock[0].iam.urn, - })), - useGenerateUrl: vi.fn( - () => '#/00000000-0000-0000-0000-000000000001/auto_replies', - ), - }; -}); - -afterEach(() => { - vi.clearAllMocks(); -}); describe('Redirections page', () => { it('should display page correctly', () => { const { getByTestId } = render(); - const button = getByTestId('header-until'); + const wrapper = getByTestId('autoreplies'); - expect(button).toHaveTextContent('zimbra_auto_replies_until'); + expect(wrapper).toBeVisible(); }); }); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/ModalDeleteDomain.component.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/ModalDeleteDomain.component.tsx index e6c8dba1a2f8..22f055e55abd 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/ModalDeleteDomain.component.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/ModalDeleteDomain.component.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { useSearchParams, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { @@ -28,21 +28,15 @@ export default function ModalDeleteDomain() { const deleteDomainId = searchParams.get('deleteDomainId'); const { platformId } = usePlatform(); - const { data, isLoading } = useAccountList({ + const { data: accounts, isLoading } = useAccountList({ domainId: deleteDomainId, }); const { addError, addSuccess } = useNotifications(); - const [hasEmailAccount, setHasEmailAccount] = useState(false); - const goBackUrl = useGenerateUrl('..', 'path'); const onClose = () => navigate(goBackUrl); - useEffect(() => { - setHasEmailAccount(data?.length > 0); - }, [isLoading]); - const { mutate: deleteDomain, isPending: isSending } = useMutation({ mutationFn: (domainId: string) => { return deleteZimbraPlatformDomain(platformId, domainId); @@ -85,7 +79,7 @@ export default function ModalDeleteDomain() { }); const handleDeleteClick = () => { - deleteDomain(deleteDomainId); + deleteDomain(deleteDomainId as string); }; return ( @@ -98,7 +92,7 @@ export default function ModalDeleteDomain() { primaryButton={{ label: t('zimbra_domain_delete'), action: handleDeleteClick, - disabled: hasEmailAccount || isSending, + disabled: accounts?.length > 0 || isSending || !deleteDomainId, testid: 'delete-btn', }} > @@ -111,7 +105,7 @@ export default function ModalDeleteDomain() { > {t('zimbra_domain_delete_modal_content')} - {hasEmailAccount && ( + {accounts?.length > 0 && ( { - const actual: any = await importOriginal(); - return { - ...actual, - usePlatform: vi.fn(() => ({ - platformUrn: platformMock[0].iam.urn, - })), - }; -}); +import { domainDetailMock } from '@/api/_mock_'; describe('Domains datagrid action menu', () => { it('we have good number of item with good content', () => { const { container } = render( - , + , ); expect(container.querySelectorAll('osds-menu-item').length).toBe(2); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/AddDomains.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/AddDomains.spec.tsx index 945402a1074b..39937caf2311 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/AddDomains.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/AddDomains.spec.tsx @@ -1,53 +1,9 @@ import React from 'react'; -import { vi, describe, expect, it, afterEach } from 'vitest'; +import { describe, expect, it } from 'vitest'; import { act } from 'react-dom/test-utils'; import { render, fireEvent, screen, waitFor } from '@/utils/test.provider'; import AddDomain from '../AddDomain.page'; import addDomainTranslation from '@/public/translations/domains/addDomain/Messages_fr_FR.json'; -import { platformMock, organizationListMock, domainZone } from '@/api/_mock_'; -import '@testing-library/jest-dom'; -import 'element-internals-polyfill'; - -vi.mock('@/hooks', () => ({ - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useOrganization: vi.fn(() => ({ - data: null, - isLoading: false, - })), - useOrganizationList: vi.fn(() => ({ - data: organizationListMock, - isLoading: false, - })), - useOverridePage: vi.fn(() => true), - useGenerateUrl: vi.fn(() => null), -})); - -vi.mock('@tanstack/react-query', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useQuery: vi.fn(() => ({ - data: domainZone, - isLoading: false, - })), - }; -}); - -vi.mock('@ovh-ux/manager-react-shell-client', () => ({ - ShellContext: React.createContext({ - environment: { - getUser: () => ({ - ovhSubsidiary: 'FR', - }), - }, - }), -})); - -afterEach(() => { - vi.restoreAllMocks(); -}); describe('Add Domain page', () => { const clickSelectOrganization = async (selectOrganization) => { diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/Domains.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/Domains.spec.tsx index 987836bc0eeb..82d33670cf90 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/Domains.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/Domains.spec.tsx @@ -1,51 +1,23 @@ import React from 'react'; import { vi, describe, expect } from 'vitest'; import Domains from '../Domains'; -import { render } from '@/utils/test.provider'; +import { render, waitFor } from '@/utils/test.provider'; import domainTranslation from '@/public/translations/domains/Messages_fr_FR.json'; -import { domainMock, platformMock, organizationListMock } from '@/api/_mock_'; +import { useGenerateUrl } from '@/hooks'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - platformUrn: platformMock[0].iam.urn, - })), - useDomains: vi.fn(() => ({ - data: domainMock, - })), - useOrganizationList: vi.fn(() => ({ - data: organizationListMock, - isLoading: false, - })), - useGenerateUrl: vi.fn( - () => '#/00000000-0000-0000-0000-000000000001/domains/add?', - ), - useOverridePage: vi.fn(() => false), - }; -}); - -vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - Notifications: vi.fn().mockReturnValue(
Notifications
), - Datagrid: vi.fn().mockReturnValue(
Datagrid
), - }; -}); - -afterEach(() => { - vi.clearAllMocks(); -}); +const addUrl = '#/00000000-0000-0000-0000-000000000001/domains/add?'; describe('Domains page', () => { - it('Page should display correctly', () => { + it('Page should display correctly', async () => { + vi.mocked(useGenerateUrl).mockReturnValue(addUrl); const { getByTestId } = render(); + + await waitFor(() => { + expect(getByTestId('add-domain-btn')).toBeInTheDocument(); + }); + const button = getByTestId('add-domain-btn'); - expect(button).toHaveAttribute( - 'href', - '#/00000000-0000-0000-0000-000000000001/domains/add?', - ); + expect(button).toHaveAttribute('href', addUrl); expect(button).toHaveTextContent( domainTranslation.zimbra_domains_add_domain_title, ); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalDeleteDomain.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalDeleteDomain.spec.tsx index daf3d9347ac5..5de97329e3d2 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalDeleteDomain.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalDeleteDomain.spec.tsx @@ -2,50 +2,19 @@ import React from 'react'; import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; -import { render } from '@/utils/test.provider'; -import { platformMock, accountMock } from '@/api/_mock_'; +import { useSearchParams } from 'react-router-dom'; +import { render, waitFor } from '@/utils/test.provider'; import ModalDeleteDomain from '../ModalDeleteDomain.component'; import domainsDeleteTranslation from '@/public/translations/domains/delete/Messages_fr_FR.json'; +import { getZimbraPlatformAccounts } from '@/api/account'; +import { domainDetailMock } from '@/api/_mock_'; -const { useAccountListMock } = vi.hoisted(() => ({ - useAccountListMock: vi.fn(() => ({ - data: accountMock, - isLoading: false, - })), -})); - -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - useAccountList: useAccountListMock, - }; -}); - -vi.mock('react-router-dom', () => ({ - useNavigate: vi.fn(), - MemoryRouter: vi.fn(() => ), - useSearchParams: vi.fn(() => [ - new URLSearchParams({ - deleteDomainId: '3fa85f64-5717-4562-b3fc-2c963f66afa6', - }), - ]), -})); - -vi.mock('@ovh-ux/manager-react-components', () => { - return { - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - }; -}); - -afterEach(() => { - vi.restoreAllMocks(); -}); +vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + deleteDomainId: domainDetailMock.id, + }), + vi.fn(), +]); describe('Domains delete modal', () => { it('check if it is displayed', () => { @@ -57,20 +26,25 @@ describe('Domains delete modal', () => { ); }); - it('if have email use the domain', () => { - const { getByTestId } = render(); + it('if have email use the domain', async () => { + const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); + expect(getByTestId('banner-message')).toBeVisible(); expect(getByTestId('delete-btn')).toBeDisabled(); }); - it('if there is not email use the domain', () => { - useAccountListMock.mockImplementation( - vi.fn(() => ({ - data: [], - isLoading: false, - })), - ); + it('if there is not email use the domain', async () => { + vi.mocked(getZimbraPlatformAccounts).mockReturnValue([]); const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); + expect(queryByTestId('banner-message')).toBeNull(); expect(getByTestId('delete-btn')).not.toBeDisabled(); }); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalEditDomain.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalEditDomain.spec.tsx index d600896a4de2..9fd7bcea584f 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalEditDomain.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalEditDomain.spec.tsx @@ -3,50 +3,18 @@ import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; import { act } from 'react-dom/test-utils'; -import { fireEvent, render } from '@/utils/test.provider'; -import { platformMock, domainMock, organizationListMock } from '@/api/_mock_'; +import { useSearchParams } from 'react-router-dom'; +import { fireEvent, render, waitFor } from '@/utils/test.provider'; +import { domainDetailMock } from '@/api/_mock_'; import ModalEditDomain from '../ModalEditDomain.component'; import domainsEditTranslation from '@/public/translations/domains/edit/Messages_fr_FR.json'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - useDomain: vi.fn(() => ({ - data: domainMock[0], - isLoading: false, - })), - useOrganizationList: vi.fn(() => ({ - data: organizationListMock, - isLoading: false, - })), - }; -}); - -vi.mock('react-router-dom', () => ({ - useNavigate: vi.fn(), - MemoryRouter: vi.fn(() => ), - useSearchParams: vi.fn(() => [ - new URLSearchParams({ - editDomainId: '3fa85f64-5717-4562-b3fc-2c963f66afa6', - }), - ]), -})); - -vi.mock('@ovh-ux/manager-react-components', () => { - return { - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - }; -}); - -afterEach(() => { - vi.restoreAllMocks(); -}); +vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + editDomainId: domainDetailMock.id, + }), + vi.fn(), +]); describe('Domains edit modal', () => { it('check if it is displayed', () => { @@ -58,10 +26,17 @@ describe('Domains edit modal', () => { ); }); - it('check if disabled input have the domain name', () => { + it('check if disabled input have the domain name', async () => { const { getByTestId } = render(); - const modal = getByTestId('input-domain'); - expect(modal).toHaveProperty('value', domainMock[0].currentState.name); + + await waitFor(() => { + expect(getByTestId('input-domain')).toBeInTheDocument(); + }); + + expect(getByTestId('input-domain')).toHaveProperty( + 'value', + domainDetailMock.currentState.name, + ); }); it('check the status of confirm cta', () => { diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalsDiagnosticDNSRecord.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalsDiagnosticDNSRecord.spec.tsx index 0cab11c2eb59..20983bcbd6b8 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalsDiagnosticDNSRecord.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Domains/__test__/ModalsDiagnosticDNSRecord.spec.tsx @@ -2,63 +2,19 @@ import React from 'react'; import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; +import { useSearchParams } from 'react-router-dom'; import { render } from '@/utils/test.provider'; import { DnsRecordType } from '@/utils'; -import { platformMock, domainMock } from '@/api/_mock_'; -import { DomainType } from '@/api/domain'; +import { domainDetailMock } from '@/api/_mock_'; import ModalDiagnosticDnsRecord from '../ModalDiagnosticDnsRecord.component'; import domainDiagnosticTranslation from '@/public/translations/domains/diagnostic/Messages_fr_FR.json'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - useDomain: (id: string) => ({ - data: domainMock.find((domain: DomainType) => id === domain.id), - isLoading: false, - }), - }; -}); - -vi.mock('react-router-dom', async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - useNavigate: vi.fn(), - useSearchParams: vi.fn(() => [ - new URLSearchParams({ - domainId: domainMock[0].id, - }), - ]), - }; -}); - -vi.mock('@ovh-ux/manager-react-shell-client', () => ({ - ShellContext: React.createContext({ - environment: { - getUser: () => ({ - ovhSubsidiary: 'FR', - }), - }, +vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + domainId: domainDetailMock.id, }), -})); - -vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - }; -}); - -afterEach(() => { - vi.restoreAllMocks(); -}); + vi.fn(), +]); describe('Domain diagnostic modalc ', () => { it('should display diagnostic modal', () => { @@ -70,7 +26,9 @@ describe('Domain diagnostic modalc ', () => { 'headline', domainDiagnosticTranslation.zimbra_domain_modal_diagnostic_srv_title, ); - expect(getByTestId('diagnostic-srv-modal-secondary-btn')).toBeEnabled(); + expect( + getByTestId('diagnostic-srv-modal-secondary-btn'), + ).toBeInTheDocument(); }); }); @@ -84,7 +42,9 @@ describe('Domain diagnostic modal MX', () => { 'headline', domainDiagnosticTranslation.zimbra_domain_modal_diagnostic_mx_title, ); - expect(getByTestId('diagnostic-mx-modal-secondary-btn')).toBeEnabled(); + expect( + getByTestId('diagnostic-mx-modal-secondary-btn'), + ).toBeInTheDocument(); }); }); @@ -98,6 +58,8 @@ describe('Domain diagnostic modal SPF', () => { 'headline', domainDiagnosticTranslation.zimbra_domain_modal_diagnostic_spf_title, ); - expect(getByTestId('diagnostic-spf-modal-secondary-btn')).toBeEnabled(); + expect( + getByTestId('diagnostic-spf-modal-secondary-btn'), + ).toBeInTheDocument(); }); }); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ActionButtonEmail.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ActionButtonEmail.spec.tsx index e4657891a128..2603e46f2e70 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ActionButtonEmail.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ActionButtonEmail.spec.tsx @@ -1,24 +1,14 @@ import React from 'react'; -import { vi, describe, expect } from 'vitest'; +import { describe, expect } from 'vitest'; import ActionButtonEmail from '../ActionButtonEmail.component'; import { render } from '@/utils/test.provider'; import accountTranslation from '@/public/translations/accounts/Messages_fr_FR.json'; -import { accountMock, platformMock } from '@/api/_mock_'; - -vi.mock('@/hooks', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - usePlatform: vi.fn(() => ({ - platformUrn: platformMock[0].iam.urn, - })), - }; -}); +import { accountsMock } from '@/api/_mock_'; describe('EmailAccounts datagrid action menu', () => { it('we have good number of item with good content', () => { const { container } = render( - , + , ); expect(container.querySelectorAll('osds-menu-item').length).toBe(2); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/AddAndEditEmailAccount.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/AddAndEditEmailAccount.spec.tsx index 5c5624447b82..466ad24b3c7a 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/AddAndEditEmailAccount.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/AddAndEditEmailAccount.spec.tsx @@ -3,135 +3,68 @@ import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; import { act } from 'react-dom/test-utils'; -import { fireEvent, render } from '@/utils/test.provider'; -import { accountMock, domainMock, platformMock } from '@/api/_mock_'; +import { Location, useLocation, useSearchParams } from 'react-router-dom'; +import { fireEvent, render, waitFor } from '@/utils/test.provider'; +import { accountDetailMock } from '@/api/_mock_'; import AddAndEditEmailAccount from '../AddAndEditEmailAccount.page'; import emailAccountAddAndEditTranslation from '@/public/translations/accounts/addAndEdit/Messages_fr_FR.json'; import emailAccountAliasTranslation from '@/public/translations/accounts/alias/Messages_fr_FR.json'; import redirectionsTranslation from '@/public/translations/redirections/Messages_fr_FR.json'; -const { useSearchParamsMock } = vi.hoisted(() => ({ - useSearchParamsMock: vi.fn(() => [new URLSearchParams()]), -})); - -const { useLocationMock } = vi.hoisted(() => ({ - useLocationMock: vi.fn(() => ({ - pathname: '/00000000-0000-0000-0000-000000000001/email_accounts/add', - search: '', - })), -})); - -const { useAccountMock } = vi.hoisted(() => ({ - useAccountMock: vi.fn(() => ({ - data: null, - isLoading: false, - })), -})); - -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - platformUrn: platformMock[0].iam.urn, - })), - useGenerateUrl: vi.fn(), - useDomains: vi.fn(() => ({ - data: domainMock, - isLoading: false, - })), - useOrganization: vi.fn(() => ({ - data: null, - isLoading: false, - })), - useAccount: useAccountMock, - }; -}); +describe('email account add and edit page', () => { + it('if there is not editEmailAccountId params', async () => { + vi.mocked(useLocation).mockReturnValue({ + pathname: '/00000000-0000-0000-0000-000000000001/email_accounts/settings', + } as Location); -vi.mock('react-router-dom', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useNavigate: vi.fn(), - useLocation: useLocationMock, - useResolvedPath: vi.fn(() => '/:serviceName/email_accounts'), - useSearchParams: useSearchParamsMock, - }; -}); + vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams(), + vi.fn(), + ]); -vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - Datagrid: vi.fn().mockReturnValue(
Datagrid
), - }; -}); + const { getByTestId, queryByTestId } = render(); -afterEach(() => { - vi.restoreAllMocks(); -}); + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); -describe('email account add and edit page', () => { - it('if there is not editEmailAccountId params', () => { - useAccountMock.mockImplementation( - vi.fn(() => ({ - data: null, - isLoading: false, - })), - ); - const { getByTestId } = render(); expect(getByTestId('page-title')).toHaveTextContent( emailAccountAddAndEditTranslation.zimbra_account_add_title, ); }); - it('if there is editEmailAccountId params', () => { - useAccountMock.mockImplementation( - vi.fn(() => ({ - data: accountMock[0], - isLoading: false, - })), - ); - useLocationMock.mockImplementation( - vi.fn(() => ({ - pathname: - '/00000000-0000-0000-0000-000000000001/email_accounts/settings?editEmailAccountId=19097ad4-2880-4000-8b03-9d110f0b8f80', - search: '', - })), - ); - useSearchParamsMock.mockImplementation( - vi.fn(() => [ - new URLSearchParams({ - editEmailAccountId: '19097ad4-2880-4000-8b03-9d110f0b8f80', - }), - ]), - ); - const { getByTestId } = render(); + it('if there is editEmailAccountId params', async () => { + vi.mocked(useLocation).mockReturnValue({ + pathname: '/00000000-0000-0000-0000-000000000001/email_accounts/settings', + search: `?editEmailAccountId=${accountDetailMock}`, + } as Location); + + vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + editEmailAccountId: accountDetailMock.id, + }), + vi.fn(), + ]); + + const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); + expect(getByTestId('page-title')).toHaveTextContent( emailAccountAddAndEditTranslation.zimbra_account_edit_title.replace( '{{ account }}', - accountMock[0].currentState?.email, + accountDetailMock.currentState?.email, ), ); }); it('test alias tabs page', () => { - useSearchParamsMock.mockImplementation( - vi.fn(() => [ - new URLSearchParams({ - editEmailAccountId: '19097ad4-2880-4000-8b03-9d110f0b8f80', - }), - ]), - ); - useLocationMock.mockImplementation( - vi.fn(() => ({ - pathname: '/00000000-0000-0000-0000-000000000001/email_accounts/alias', - search: '', - })), - ); + vi.mocked(useLocation).mockReturnValue({ + pathname: '/00000000-0000-0000-0000-000000000001/email_accounts/alias', + } as Location); + const { getByText } = render(); expect( @@ -140,20 +73,11 @@ describe('email account add and edit page', () => { }); it('should display redirection tab page', () => { - useSearchParamsMock.mockImplementation( - vi.fn(() => [ - new URLSearchParams({ - editEmailAccountId: '19097ad4-2880-4000-8b03-9d110f0b8f80', - }), - ]), - ); - useLocationMock.mockImplementation( - vi.fn(() => ({ - pathname: - '/00000000-0000-0000-0000-000000000001/email_accounts/redirections', - search: '', - })), - ); + vi.mocked(useLocation).mockReturnValue({ + pathname: + '/00000000-0000-0000-0000-000000000001/email_accounts/redirections', + } as Location); + const { getByText } = render(); expect( @@ -162,20 +86,11 @@ describe('email account add and edit page', () => { }); it('check validity form', () => { - useLocationMock.mockImplementation( - vi.fn(() => ({ - pathname: - '/00000000-0000-0000-0000-000000000001/email_accounts/settings?editEmailAccountId=19097ad4-2880-4000-8b03-9d110f0b8f80', - search: '', - })), - ); - useSearchParamsMock.mockImplementation( - vi.fn(() => [ - new URLSearchParams({ - editEmailAccountId: '19097ad4-2880-4000-8b03-9d110f0b8f80', - }), - ]), - ); + vi.mocked(useLocation).mockReturnValue({ + pathname: '/00000000-0000-0000-0000-000000000001/email_accounts/settings', + search: `?editEmailAccountId=${accountDetailMock}`, + } as Location); + const { getByTestId } = render(); const button = getByTestId('confirm-btn'); @@ -186,6 +101,7 @@ describe('email account add and edit page', () => { expect(button).not.toBeEnabled(); act(() => { + fireEvent.change(inputAccount, { target: { value: '' } }); inputAccount.odsInputBlur.emit({ name: 'account', value: '' }); }); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/EmailAccount.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/EmailAccount.spec.tsx index 722e53600cf1..8bbf3178c9cc 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/EmailAccount.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/EmailAccount.spec.tsx @@ -1,52 +1,23 @@ import React from 'react'; import { vi, describe, expect } from 'vitest'; import EmailAccounts from '../EmailAccounts'; -import { render } from '@/utils/test.provider'; +import { render, waitFor } from '@/utils/test.provider'; import accountTranslation from '@/public/translations/accounts/Messages_fr_FR.json'; -import { accountMock, platformMock, domainMock } from '@/api/_mock_'; +import { useGenerateUrl } from '@/hooks'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - platformUrn: platformMock[0].iam.urn, - })), - useAccountList: vi.fn(() => ({ - data: accountMock, - isLoading: false, - })), - useDomains: vi.fn(() => ({ - data: domainMock, - isLoading: false, - })), - useGenerateUrl: vi.fn( - () => '#/00000000-0000-0000-0000-000000000001/email_accounts/add?', - ), - useOverridePage: vi.fn(() => false), - }; -}); - -vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - Notifications: vi.fn().mockReturnValue(
Notifications
), - Datagrid: vi.fn().mockReturnValue(
Datagrid
), - }; -}); - -afterEach(() => { - vi.clearAllMocks(); -}); +const addUrl = '#/00000000-0000-0000-0000-000000000001/email_accounts/add?'; describe('EmailAccounts page', () => { - it('Page should display correctly', () => { + it('Page should display correctly', async () => { + vi.mocked(useGenerateUrl).mockReturnValue(addUrl); const { getByTestId } = render(); + + await waitFor(() => { + expect(getByTestId('add-account-btn')).toBeInTheDocument(); + }); + const button = getByTestId('add-account-btn'); - expect(button).toHaveAttribute( - 'href', - '#/00000000-0000-0000-0000-000000000001/email_accounts/add?', - ); + expect(button).toHaveAttribute('href', addUrl); expect(button).toHaveTextContent( accountTranslation.zimbra_account_account_add, ); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalAddAlias.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalAddAlias.spec.tsx index be4e27c09886..c96ab9b94446 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalAddAlias.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalAddAlias.spec.tsx @@ -3,78 +3,47 @@ import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; import { act } from 'react-dom/test-utils'; -import { fireEvent, render, screen } from '@/utils/test.provider'; -import { accountMock, domainMock, platformMock } from '@/api/_mock_'; +import { useResolvedPath, useSearchParams } from 'react-router-dom'; +import { fireEvent, render, screen, waitFor } from '@/utils/test.provider'; +import { accountDetailMock } from '@/api/_mock_'; import ModalAddAlias from '../ModalAddAlias.component'; import emailAccountAliasAddTranslation from '@/public/translations/accounts/alias/add/Messages_fr_FR.json'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - useDomains: vi.fn(() => ({ - data: domainMock, - isLoading: false, - })), - useOrganization: vi.fn(() => ({ - data: null, - isLoading: false, - })), - useAccount: vi.fn(() => ({ - data: accountMock[0], - isLoading: false, - })), - }; +vi.mocked(useResolvedPath).mockReturnValue({ + pathname: '/:serviceName/email_accounts/alias/add', + search: '', + hash: '', }); -vi.mock('react-router-dom', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useNavigate: vi.fn(), - useLocation: vi.fn(() => ({ - pathname: `/00000000-0000-0000-0000-000000000001/email_accounts/alias/add?editEmailAccountId=${accountMock[0].id}`, - search: '', - })), - useResolvedPath: vi.fn(() => '/:serviceName/email_accounts/alias/add'), - useSearchParams: vi.fn(() => [ - new URLSearchParams({ - editEmailAccountId: '19097ad4-2880-4000-8b03-9d110f0b8f80', - }), - ]), - }; -}); +vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + editEmailAccountId: accountDetailMock.id, + }), + vi.fn(), +]); -vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - }; -}); +describe('add alias modal', () => { + it('if modal are displayed', async () => { + const { queryByTestId } = render(); -afterEach(() => { - vi.restoreAllMocks(); -}); + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); -describe('add alias modal', () => { - it('if modal are displayed', () => { - render(); screen.getByText( emailAccountAliasAddTranslation.zimbra_account_alias_add_description.replace( '{{ account }}', - accountMock[0].currentState?.email, + accountDetailMock.currentState?.email, ), ); }); - it('check validity form', () => { - const { getByTestId } = render(); + it('check validity form', async () => { + const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); const button = getByTestId('confirm-btn'); const inputAccount = getByTestId('input-alias'); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalDeleteAlias.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalDeleteAlias.spec.tsx index 335a1aeaeac9..8b65bbdca65b 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalDeleteAlias.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalDeleteAlias.spec.tsx @@ -2,39 +2,19 @@ import React from 'react'; import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; +import { useSearchParams } from 'react-router-dom'; import { render } from '@/utils/test.provider'; -import { platformMock, aliasMock, accountMock } from '@/api/_mock_'; +import { aliasMock, accountsMock } from '@/api/_mock_'; import ModalDeleteAlias from '../ModalDeleteAlias.component'; import accountAliasDeleteTranslation from '@/public/translations/accounts/alias/delete/Messages_fr_FR.json'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - }; -}); - -vi.mock('react-router-dom', () => ({ - useNavigate: vi.fn(), - MemoryRouter: vi.fn(() => ), - useSearchParams: vi.fn(() => [ - new URLSearchParams({ - editEmailAccountId: accountMock[0].id, - deleteAliasId: aliasMock[0].id, - }), - ]), -})); - -vi.mock('@ovh-ux/manager-react-components', () => { - return { - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - }; -}); +vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + editEmailAccountId: accountsMock[0].id, + deleteAliasId: aliasMock[0].id, + }), + vi.fn(), +]); describe('Alias delete modal', () => { it('check if it is displayed', () => { diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalDeleteEmailAccount.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalDeleteEmailAccount.spec.tsx index 5803a93db4b0..fce1443728c4 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalDeleteEmailAccount.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/EmailAccounts/__test__/ModalDeleteEmailAccount.spec.tsx @@ -2,42 +2,19 @@ import React from 'react'; import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; -import { fireEvent, render } from '@/utils/test.provider'; -import { platformMock, accountMock } from '@/api/_mock_'; +import { useSearchParams } from 'react-router-dom'; +import { fireEvent, render, act } from '@/utils/test.provider'; +import { domainDetailMock } from '@/api/_mock_'; import ModalDeleteEmailAccount from '../ModalDeleteEmailAccount.component'; import accountsDeleteTranslation from '@/public/translations/accounts/delete/Messages_fr_FR.json'; +import { deleteZimbraPlatformAccount } from '@/api/account'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - useAccount: vi.fn(() => ({ - data: accountMock[0], - isLoading: false, - })), - }; -}); - -vi.mock('react-router-dom', () => ({ - useNavigate: vi.fn(), - MemoryRouter: vi.fn(() => ), - useSearchParams: vi.fn(() => [ - new URLSearchParams({ - deleteDomainId: '3fa85f64-5717-4562-b3fc-2c963f66afa6', - }), - ]), -})); - -vi.mock('@ovh-ux/manager-react-components', () => { - return { - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - }; -}); +vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + deleteDomainId: domainDetailMock.id, + }), + vi.fn(), +]); describe('Domains delete modal', () => { it('check if it is displayed', () => { @@ -48,10 +25,19 @@ describe('Domains delete modal', () => { ); }); - it('check transition from step 1 to step 2', () => { + it('check transition from step 1 to step 2 and delete', async () => { const { getByTestId } = render(); expect(getByTestId('text-step-1')).toBeVisible(); - fireEvent.click(getByTestId('primary-btn')); + await act(() => { + fireEvent.click(getByTestId('primary-btn')); + }); + expect(getByTestId('text-step-2')).toBeVisible(); + + await act(() => { + fireEvent.click(getByTestId('primary-btn')); + }); + + expect(deleteZimbraPlatformAccount).toHaveBeenCalledOnce(); }); }); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/GeneralInformation.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/GeneralInformation.tsx index 11044727408e..6bed7266cb09 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/GeneralInformation.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/GeneralInformation.tsx @@ -43,6 +43,7 @@ function GeneralInformation() { {t('zimbra_dashboard_tile_status_title')} {organisation && ( @@ -85,6 +86,7 @@ function GeneralInformation() { > {platformUrn && ( diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/OngoingTasks.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/OngoingTasks.tsx index c83408e450c5..a4453594821b 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/OngoingTasks.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/OngoingTasks.tsx @@ -1,32 +1,21 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useQuery } from '@tanstack/react-query'; import { OsdsIcon, OsdsLink } from '@ovhcloud/ods-components/react'; import { ODS_ICON_NAME, ODS_ICON_SIZE } from '@ovhcloud/ods-components'; -import { - getZimbraPlatformTask, - getZimbraPlatformTaskQueryKey, -} from '@/api/task'; -import { useOrganization, usePlatform } from '@/hooks'; +import { useTasks } from '@/hooks'; export const OngoingTasks: React.FC = () => { const { t } = useTranslation('dashboard'); const [loadMore, setLoadMore] = useState(false); const [tasksDiplayed, setTasksDiplayed] = useState([]); - const { data: organisation } = useOrganization(); - const { platformId } = usePlatform(); - const { data } = useQuery({ - queryKey: getZimbraPlatformTaskQueryKey(platformId, organisation?.id), - queryFn: () => getZimbraPlatformTask(platformId, organisation?.id), - enabled: !!platformId, - }); + const { data } = useTasks(); useEffect(() => { setTasksDiplayed(loadMore ? data : data?.slice(0, 5)); }, [loadMore, data]); return ( -
+
{tasksDiplayed?.map((task) => ( {`${task.type} ${task.message}`} ))} diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/__test__/GeneralInformation.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/__test__/GeneralInformation.spec.tsx new file mode 100644 index 000000000000..66cb3ca408e3 --- /dev/null +++ b/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/__test__/GeneralInformation.spec.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { describe, expect, vi } from 'vitest'; +import { useSearchParams } from 'react-router-dom'; +import GeneralInformation from '../GeneralInformation'; +import { render } from '@/utils/test.provider'; +import dashboardTranslation from '@/public/translations/dashboard/Messages_fr_FR.json'; +import { organizationDetailMock } from '@/api/_mock_'; + +describe('General Informations page', () => { + it('should display page correctly', async () => { + const { findByText, getByTestId, queryByTestId } = render( + , + ); + + const title = await findByText( + dashboardTranslation.zimbra_dashboard_tile_status_title, + ); + const serviceStatus = queryByTestId('tileblock-orga'); + const accounts = getByTestId('platform-accounts'); + + expect(title).toBeVisible(); + expect(serviceStatus).toBeNull(); + expect(accounts).toBeInTheDocument(); + }); + + it('should display organization status', async () => { + vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + organizationId: organizationDetailMock.id, + }), + vi.fn(), + ]); + + const { findByText, getByTestId } = render(); + + const title = await findByText( + dashboardTranslation.zimbra_dashboard_tile_status_title, + ); + + const serviceStatus = getByTestId('tileblock-orga'); + + expect(title).toBeVisible(); + expect(serviceStatus).toBeInTheDocument(); + }); +}); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/__test__/OngoingTasks.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/__test__/OngoingTasks.spec.tsx new file mode 100644 index 000000000000..7d6537d0642a --- /dev/null +++ b/packages/manager/apps/zimbra/src/pages/dashboard/GeneralInformation/__test__/OngoingTasks.spec.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { describe, expect } from 'vitest'; +import { OngoingTasks } from '../OngoingTasks'; +import { render } from '@/utils/test.provider'; + +describe('OngoingTasks component', () => { + it('should display component correctly', async () => { + const { getByTestId } = render(); + + const wrap = getByTestId('ongoingtasks'); + + expect(wrap).toBeVisible(); + }); +}); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/ActionButtonMailingList.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/ActionButtonMailingList.spec.tsx index 9fda6112ba7c..84747c77cb71 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/ActionButtonMailingList.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/ActionButtonMailingList.spec.tsx @@ -3,14 +3,14 @@ import { describe, expect } from 'vitest'; import ActionButtonMailingList from '../ActionButtonMailingList.component'; import { render } from '@/utils/test.provider'; import mailingListsTranslation from '@/public/translations/mailinglists/Messages_fr_FR.json'; -import { mailingListsMock } from '@/api/_mock_'; +import { mailingListDetailMock } from '@/api/_mock_'; import { getMailingListItem } from '../MailingLists'; describe('MailingLists datagrid action menu', () => { it('should display 4 actions buttons', () => { const { container } = render( , ); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/AddAndEditMailingList.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/AddAndEditMailingList.spec.tsx index 1e4be4bc210d..c76e01aa77ee 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/AddAndEditMailingList.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/AddAndEditMailingList.spec.tsx @@ -3,115 +3,34 @@ import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; import { act } from 'react-dom/test-utils'; -import { render } from '@/utils/test.provider'; -import { mailingListsMock, domainMock, platformMock } from '@/api/_mock_'; +import { useSearchParams } from 'react-router-dom'; +import { render, waitFor } from '@/utils/test.provider'; +import { mailingListsMock } from '@/api/_mock_'; import AddAndEditMailingList from '../AddAndEditMailingList.page'; import mailingListsAddAndEditTranslation from '@/public/translations/mailinglists/addAndEdit/Messages_fr_FR.json'; import { ModerationChoices, ReplyToChoices } from '@/api/mailinglist'; -const { useSearchParamsMock } = vi.hoisted(() => ({ - useSearchParamsMock: vi.fn(() => [new URLSearchParams()]), -})); - -const { useQueryMock } = vi.hoisted(() => ({ - useQueryMock: vi.fn(() => ({ - data: null, - isLoading: false, - })), -})); - -const { useLocationMock } = vi.hoisted(() => ({ - useLocationMock: vi.fn(() => ({ - pathname: '/00000000-0000-0000-0000-000000000001/mailing_lists/add', - search: '', - })), -})); - -const { useMailingListMock } = vi.hoisted(() => ({ - useMailingListMock: vi.fn(() => ({ - data: null, - isLoading: false, - })), -})); - -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - useDomains: vi.fn(() => ({ - data: domainMock, - isLoading: false, - })), - useOrganization: vi.fn(() => ({ - data: null, - isLoading: false, - })), - useMailingList: useMailingListMock, - }; -}); - -vi.mock('react-router-dom', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useNavigate: vi.fn(), - useLocation: useLocationMock, - useResolvedPath: vi.fn(() => '/:serviceName/mailing_lists'), - useSearchParams: useSearchParamsMock, - }; -}); - -vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - Datagrid: vi.fn().mockReturnValue(
Datagrid
), - }; -}); - -vi.mock('@tanstack/react-query', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useQuery: useQueryMock, - }; -}); - -afterEach(() => { - vi.restoreAllMocks(); -}); - describe('mailing lists add and edit page', () => { const editMailingListId = mailingListsMock[0].id; - it('should be in add mode if no editMailingListId param', () => { - useMailingListMock.mockImplementation( - vi.fn(() => ({ - data: null, - isLoading: false, - })), - ); - const { getByTestId } = render(); + it('should be in add mode if no editMailingListId param', async () => { + const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); + expect(getByTestId('page-title')).toHaveTextContent( mailingListsAddAndEditTranslation.zimbra_mailinglist_add_title, ); }); - it('should be add page and enable/disable button based on form validity', () => { - useLocationMock.mockImplementation( - vi.fn(() => ({ - pathname: `/00000000-0000-0000-0000-000000000001/mailing_lists/add`, - search: '', - })), - ); + it('should be add page and enable/disable button based on form validity', async () => { + const { getByTestId, queryByTestId } = render(); - const { getByTestId } = render(); + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); const button = getByTestId('confirm-btn'); const inputAccount = getByTestId('input-account'); @@ -164,28 +83,20 @@ describe('mailing lists add and edit page', () => { expect(button).not.toBeEnabled(); }); - it('should be in edit mode if editMailingListId param is present', () => { - useMailingListMock.mockImplementation( - vi.fn(() => ({ - data: mailingListsMock[0], - isLoading: false, - })), - ); + it('should be in edit mode if editMailingListId param is present', async () => { + vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + editMailingListId, + }), + vi.fn(), + ]); + + const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); - useLocationMock.mockImplementation( - vi.fn(() => ({ - pathname: `/00000000-0000-0000-0000-000000000001/mailing_lists/settings?editMailingListId=${editMailingListId}`, - search: '', - })), - ); - useSearchParamsMock.mockImplementation( - vi.fn(() => [ - new URLSearchParams({ - editMailingListId, - }), - ]), - ); - const { getByTestId } = render(); expect(getByTestId('page-title')).toHaveTextContent( mailingListsAddAndEditTranslation.zimbra_mailinglist_edit_title, ); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/MailingLists.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/MailingLists.spec.tsx index a55fbf844311..46d5f75ba830 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/MailingLists.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/MailingLists/__test__/MailingLists.spec.tsx @@ -1,47 +1,24 @@ import React from 'react'; import { vi, describe, expect } from 'vitest'; -import { render } from '@/utils/test.provider'; +import { render, waitFor } from '@/utils/test.provider'; import mailingListsTranslation from '@/public/translations/mailinglists/Messages_fr_FR.json'; -import { mailingListsMock, platformMock } from '@/api/_mock_'; import MailingLists from '../MailingLists'; +import { useGenerateUrl } from '@/hooks'; -vi.mock('@/hooks', () => { - return { - useOverridePage: vi.fn(() => false), - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - platformUrn: platformMock[0].iam.urn, - })), - useMailingLists: vi.fn(() => ({ - data: mailingListsMock, - })), - useGenerateUrl: vi.fn( - () => '#/00000000-0000-0000-0000-000000000001/mailing_lists/add', - ), - }; -}); +const addUrl = '#/00000000-0000-0000-0000-000000000001/mailing_lists/add'; -vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - Notifications: vi.fn().mockReturnValue(
Notifications
), - Datagrid: vi.fn().mockReturnValue(
Datagrid
), - }; -}); +describe('Mailing Lists page', () => { + it('should display add button correctly', async () => { + vi.mocked(useGenerateUrl).mockReturnValue(addUrl); -afterEach(() => { - vi.clearAllMocks(); -}); + const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); -describe('Mailing Lists page', () => { - it('should display add button correctly', () => { - const { getByTestId } = render(); const button = getByTestId('add-mailinglist-btn'); - expect(button).toHaveAttribute( - 'href', - '#/00000000-0000-0000-0000-000000000001/mailing_lists/add', - ); + expect(button).toHaveAttribute('href', addUrl); expect(button).toHaveTextContent( mailingListsTranslation.zimbra_mailinglists_datagrid_cta, ); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/ModalDeleteOrganization.component.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/ModalDeleteOrganization.component.tsx index e69d4101b752..35ea7f154346 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/ModalDeleteOrganization.component.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/ModalDeleteOrganization.component.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { useSearchParams, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { @@ -26,15 +26,13 @@ export default function ModalDeleteOrganization() { const { t } = useTranslation('organizations/delete'); const { platformId } = usePlatform(); const { addError, addSuccess } = useNotifications(); - const [hasDomain, setHasDomain] = useState(false); const navigate = useNavigate(); const onClose = () => navigate('..'); const { mutate: deleteOrganization, isPending: isSending } = useMutation({ - mutationFn: (organizationId: string) => { - return deleteZimbraPlatformOrganization(platformId, organizationId); - }, + mutationFn: (organizationId: string) => + deleteZimbraPlatformOrganization(platformId, organizationId), onSuccess: () => { addSuccess( { - setHasDomain(data?.length > 0); - }, [isLoading]); - return ( 0 || + isSending || + isLoading || + !deleteOrganizationId, }} > <> @@ -110,7 +108,7 @@ export default function ModalDeleteOrganization() { {t('zimbra_organization_delete_modal_content')} - {hasDomain && ( + {domains?.length > 0 && ( { - const actual: any = await importOriginal(); - return { - ...actual, - usePlatform: vi.fn(() => ({ - platformUrn: platformMock[0].iam.urn, - })), - }; -}); +import { organizationDetailMock } from '@/api/_mock_'; describe('Organizations datagrid action menu', () => { it('we have good number of item with good content', () => { const { container } = render( - , + , ); expect(container.querySelectorAll('osds-menu-item').length).toBe(2); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/ModalAddAndEditOrganization.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/ModalAddAndEditOrganization.spec.tsx index 5163a9a793fc..2f085a244cc4 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/ModalAddAndEditOrganization.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/ModalAddAndEditOrganization.spec.tsx @@ -2,47 +2,15 @@ import React from 'react'; import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; -import { act } from 'react-dom/test-utils'; -import { fireEvent, render } from '@/utils/test.provider'; -import { platformMock } from '@/api/_mock_'; +import { useSearchParams } from 'react-router-dom'; +import { fireEvent, render, act, waitFor } from '@/utils/test.provider'; import ModalAddAndEditOrganization from '../ModalAddAndEditOrganization.page'; import organizationsAddAndEditTranslation from '@/public/translations/organizations/addAndEdit/Messages_fr_FR.json'; - -const { useSearchParamsMock } = vi.hoisted(() => ({ - useSearchParamsMock: vi.fn(() => [new URLSearchParams()]), -})); - -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - useOrganization: vi.fn(() => ({ - data: null, - isLoading: false, - })), - }; -}); - -vi.mock('react-router-dom', () => ({ - useNavigate: vi.fn(), - MemoryRouter: vi.fn(() => ), - useSearchParams: useSearchParamsMock, -})); - -vi.mock('@ovh-ux/manager-react-components', () => { - return { - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - }; -}); - -afterEach(() => { - vi.restoreAllMocks(); -}); +import { organizationDetailMock } from '@/api/_mock_'; +import { + postZimbraPlatformOrganization, + putZimbraPlatformOrganization, +} from '@/api/organization'; describe('Organizations add and edit modal', () => { it('if i have not editOrganizationId params', () => { @@ -55,13 +23,13 @@ describe('Organizations add and edit modal', () => { }); it('if i have editOrganizationId params', () => { - useSearchParamsMock.mockImplementation( - vi.fn(() => [ - new URLSearchParams({ - editOrganizationId: '1903b491-4d10-4000-8b70-f474d1abe601', - }), - ]), - ); + vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + editOrganizationId: organizationDetailMock.id, + }), + vi.fn(), + ]); + const { getByTestId } = render(); const modal = getByTestId('modal'); expect(modal).toHaveProperty( @@ -70,8 +38,14 @@ describe('Organizations add and edit modal', () => { ); }); - it('check validity form', () => { - const { getByTestId } = render(); + it('check validity form', async () => { + const { getByTestId, queryByTestId } = render( + , + ); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); const button = getByTestId('confirm-btn'); const input1 = getByTestId('input-name'); @@ -79,8 +53,8 @@ describe('Organizations add and edit modal', () => { expect(getByTestId('confirm-btn')).not.toBeEnabled(); - act(() => { - input1.odsInputBlur.emit({ name: 'name', value: '' }); + await act(() => { + fireEvent.change(input1, { target: { value: '' } }); }); expect(input1).toHaveAttribute('color', 'error'); @@ -89,31 +63,20 @@ describe('Organizations add and edit modal', () => { organizationsAddAndEditTranslation.zimbra_organization_add_form_input_name_error, ); - act(() => { + await act(() => { fireEvent.change(input1, { target: { value: 'Name' } }); fireEvent.change(input2, { target: { value: 'Label' } }); - - // it seems we have to manually trigger the ods event - input1.odsValueChange.emit({ name: 'name', value: 'Name' }); - input2.odsValueChange.emit({ name: 'label', value: 'Label' }); }); expect(input1).toHaveAttribute('color', 'default'); expect(input2).toHaveAttribute('color', 'default'); expect(button).toBeEnabled(); - act(() => { + await act(() => { fireEvent.change(input1, { target: { value: 'Name' } }); fireEvent.change(input2, { target: { value: 'NoValidLabelWithMore12Digit' }, }); - - // it seems we have to manually trigger the ods event - input1.odsValueChange.emit({ name: 'name', value: 'Name' }); - input2.odsValueChange.emit({ - name: 'label', - value: 'NoValidLabelWithMore12Digit', - }); }); expect(input1).toHaveAttribute('color', 'default'); @@ -128,4 +91,76 @@ describe('Organizations add and edit modal', () => { expect(button).not.toBeEnabled(); }); + + it('should add a new organization', async () => { + vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({}), + vi.fn(), + ]); + const { getByTestId, queryByTestId } = render( + , + ); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); + + const button = getByTestId('confirm-btn'); + const input1 = getByTestId('input-name'); + const input2 = getByTestId('input-label'); + + expect(button).not.toBeEnabled(); + + await act(() => { + fireEvent.change(input1, { target: { value: 'Name' } }); + fireEvent.change(input2, { target: { value: 'Label' } }); + }); + + expect(input1).toHaveAttribute('color', 'default'); + expect(input2).toHaveAttribute('color', 'default'); + + expect(button).toBeEnabled(); + + await act(() => { + fireEvent.click(button); + }); + + expect(postZimbraPlatformOrganization).toHaveBeenCalledOnce(); + }); + + it('should add a new organization', async () => { + vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + editOrganizationId: organizationDetailMock.id, + }), + vi.fn(), + ]); + const { getByTestId, queryByTestId } = render( + , + ); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); + + const button = getByTestId('confirm-btn'); + const input1 = getByTestId('input-name'); + const input2 = getByTestId('input-label'); + + await act(() => { + fireEvent.change(input1, { target: { value: 'Name' } }); + fireEvent.change(input2, { target: { value: 'Label' } }); + }); + + expect(input1).toHaveAttribute('color', 'default'); + expect(input2).toHaveAttribute('color', 'default'); + + expect(button).toBeEnabled(); + + await act(() => { + fireEvent.click(button); + }); + + expect(putZimbraPlatformOrganization).toHaveBeenCalledOnce(); + }); }); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/ModalDeleteOrganization.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/ModalDeleteOrganization.spec.tsx index 93331084abe8..03e4911ff389 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/ModalDeleteOrganization.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/ModalDeleteOrganization.spec.tsx @@ -2,53 +2,23 @@ import React from 'react'; import 'element-internals-polyfill'; import '@testing-library/jest-dom'; import { vi, describe, expect } from 'vitest'; -import { render } from '@/utils/test.provider'; -import { platformMock, domainMock } from '@/api/_mock_'; +import { useSearchParams } from 'react-router-dom'; +import { render, waitFor, fireEvent, act } from '@/utils/test.provider'; import ModalDeleteOrganization from '../ModalDeleteOrganization.component'; import organizationsDeleteTranslation from '@/public/translations/organizations/delete/Messages_fr_FR.json'; +import { organizationDetailMock } from '@/api/_mock_'; +import { getZimbraPlatformDomains } from '@/api/domain'; +import { deleteZimbraPlatformOrganization } from '@/api/organization'; -const { useDomainsMock } = vi.hoisted(() => ({ - useDomainsMock: vi.fn(() => ({ - data: domainMock, - isLoading: false, - })), -})); - -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - })), - useGenerateUrl: vi.fn(), - useDomains: useDomainsMock, - }; -}); - -vi.mock('react-router-dom', () => ({ - useNavigate: vi.fn(), - MemoryRouter: vi.fn(() => ), - useSearchParams: vi.fn(() => [ - new URLSearchParams({ - deleteOrganizationId: '1903b491-4d10-4000-8b70-f474d1abe601', - }), - ]), -})); - -vi.mock('@ovh-ux/manager-react-components', () => { - return { - useNotifications: vi.fn(() => ({ - addError: () => vi.fn(), - addSuccess: () => vi.fn(), - })), - }; -}); - -afterEach(() => { - vi.restoreAllMocks(); -}); +vi.mocked(useSearchParams).mockReturnValue([ + new URLSearchParams({ + deleteOrganizationId: organizationDetailMock.id, + }), + vi.fn(), +]); describe('Organizations delete modal', () => { - it('check if it is displayed', () => { + it('should render modal', () => { const { getByTestId } = render(); const modal = getByTestId('modal'); expect(modal).toHaveProperty( @@ -57,21 +27,33 @@ describe('Organizations delete modal', () => { ); }); - it('if there is domain in organization', () => { - const { getByTestId } = render(); + it('should have button disabled if domains', async () => { + const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); + expect(getByTestId('banner-message')).toBeVisible(); expect(getByTestId('delete-btn')).toBeDisabled(); }); - it('if there is not domain in organization', () => { - useDomainsMock.mockImplementation( - vi.fn(() => ({ - data: [], - isLoading: false, - })), - ); + it('should delete org if no domains and clicked', async () => { + vi.mocked(getZimbraPlatformDomains).mockResolvedValue([]); + const { getByTestId, queryByTestId } = render(); + + await waitFor(() => { + expect(queryByTestId('spinner')).toBeNull(); + }); + expect(queryByTestId('banner-message')).toBeNull(); expect(getByTestId('delete-btn')).not.toBeDisabled(); + + await act(() => { + fireEvent.click(getByTestId('delete-btn')); + }); + + expect(deleteZimbraPlatformOrganization).toHaveBeenCalledOnce(); }); }); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/Organizations.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/Organizations.spec.tsx index ff86d96dc3ac..4f19e80f7006 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/Organizations.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Organizations/__test__/Organizations.spec.tsx @@ -1,46 +1,23 @@ import React from 'react'; import { vi, describe, expect } from 'vitest'; import Organizations from '../Organizations'; -import { render } from '@/utils/test.provider'; +import { render, waitFor } from '@/utils/test.provider'; import organizationsTranslation from '@/public/translations/organizations/Messages_fr_FR.json'; -import { organizationListMock, platformMock } from '@/api/_mock_'; +import { useGenerateUrl } from '@/hooks'; -vi.mock('@/hooks', () => { - return { - usePlatform: vi.fn(() => ({ - platformId: platformMock[0].id, - platformUrn: platformMock[0].iam.urn, - })), - useOrganizationList: vi.fn(() => ({ - data: organizationListMock, - })), - useGenerateUrl: vi.fn( - () => '#/00000000-0000-0000-0000-000000000001/organizations/add?', - ), - }; -}); - -vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - Notifications: vi.fn().mockReturnValue(
Notifications
), - Datagrid: vi.fn().mockReturnValue(
Datagrid
), - }; -}); - -afterEach(() => { - vi.clearAllMocks(); -}); +const addUrl = '#/00000000-0000-0000-0000-000000000001/organizations/add?'; describe('Organizations page', () => { - it('Page should display correctly', () => { + it('Page should display correctly', async () => { + vi.mocked(useGenerateUrl).mockReturnValue(addUrl); const { getByTestId } = render(); + + await waitFor(() => { + expect(getByTestId('add-organization-btn')).toBeInTheDocument(); + }); + const button = getByTestId('add-organization-btn'); - expect(button).toHaveAttribute( - 'href', - '#/00000000-0000-0000-0000-000000000001/organizations/add?', - ); + expect(button).toHaveAttribute('href', addUrl); expect(button).toHaveTextContent( organizationsTranslation.add_organisation_cta, ); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ActionButtonRedirections.component.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ActionButtonRedirections.component.spec.tsx index dc2e6765c53a..a33ad9b4e85a 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ActionButtonRedirections.component.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ActionButtonRedirections.component.spec.tsx @@ -1,22 +1,12 @@ import React from 'react'; -import { vi, describe, expect } from 'vitest'; +import { describe, expect } from 'vitest'; import ActionButtonRedirections from '../ActionButtonRedirections.component'; import { render } from '@/utils/test.provider'; -import { platformMock } from '@/api/_mock_'; import redirectionsTranslation from '@/public/translations/redirections/Messages_fr_FR.json'; - -vi.mock('@/hooks', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - usePlatform: vi.fn(() => ({ - platformUrn: platformMock[0].iam.urn, - })), - }; -}); +import { ResourceStatus } from '@/api/api.type'; describe('Redirections datagrid action menu', () => { - it('we have good number of item with good content', () => { + it('renders with menu enabled and 2 items', () => { const { container } = render( { from: 'testFrom', to: 'testTo', organization: 'TestOrganization', + status: ResourceStatus.READY, }} />, ); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ModalAddAndEditRedirections.page.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ModalAddAndEditRedirections.page.spec.tsx index e16fdb45e407..25b0339e4cbb 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ModalAddAndEditRedirections.page.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ModalAddAndEditRedirections.page.spec.tsx @@ -1,36 +1,13 @@ import React from 'react'; -import { vi, describe, expect, it, afterEach } from 'vitest'; +import { describe, expect, it } from 'vitest'; import { act } from 'react-dom/test-utils'; import ModalAddAndEditRedirections from '../ModalAddAndEditRedirections.page'; -import { render, fireEvent, screen } from '@/utils/test.provider'; - -vi.mock('@/hooks', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - useGenerateUrl: vi.fn(() => '#/redirections'), - }; -}); - -afterEach(() => { - vi.clearAllMocks(); -}); +import { render, fireEvent } from '@/utils/test.provider'; describe('ModalAddAndEditRedirections Component', () => { - it('should render correctly', () => { - render(); - - expect(screen.getByTestId('field-from')).toBeInTheDocument(); - expect(screen.getByTestId('field-to')).toBeInTheDocument(); - expect(screen.getByTestId('field-checkbox')).toBeInTheDocument(); - - const confirmButton = screen.getByTestId('confirm-btn'); - expect(confirmButton).toBeInTheDocument(); - expect(confirmButton).toBeDisabled(); - }); - - it('should enable the confirm button when form is valid', () => { + it('should render and enable the confirm button when form is valid', async () => { const { getByTestId } = render(); + const confirmButton = getByTestId('confirm-btn'); const checkbox = getByTestId('field-checkbox'); const inputAccount = getByTestId('input-account'); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ModalDeleteRedirections.component.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ModalDeleteRedirections.component.spec.tsx index cb25e887cc34..d2632980e680 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ModalDeleteRedirections.component.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/ModalDeleteRedirections.component.spec.tsx @@ -1,19 +1,8 @@ import React from 'react'; -import { vi, describe, expect, it, afterEach } from 'vitest'; +import { describe, expect, it } from 'vitest'; import ModalDeleteRedirections from '../ModalDeleteRedirections.component'; import { render, fireEvent, screen } from '@/utils/test.provider'; -vi.mock('@/hooks', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - }; -}); - -afterEach(() => { - vi.clearAllMocks(); -}); - describe('ModalDeleteRedirections Component', () => { it('should render correctly', () => { render(); diff --git a/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/Redirections.spec.tsx b/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/Redirections.spec.tsx index 7d897a83e9da..2e203dfa87d9 100644 --- a/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/Redirections.spec.tsx +++ b/packages/manager/apps/zimbra/src/pages/dashboard/Redirections/__test__/Redirections.spec.tsx @@ -1,34 +1,19 @@ import React from 'react'; -import { vi, describe, expect } from 'vitest'; +import { describe, expect } from 'vitest'; +import { waitFor } from '@testing-library/dom'; import Redirections from '../Redirections'; import { render } from '@/utils/test.provider'; -import { platformMock } from '@/api/_mock_'; import redirectionsTranslation from '@/public/translations/redirections/Messages_fr_FR.json'; -vi.mock('@/hooks', async (importOriginal) => { - const actual: any = await importOriginal(); - return { - ...actual, - usePlatform: vi.fn(() => ({ - platformUrn: platformMock[0].iam.urn, - })), - useGenerateUrl: vi.fn( - () => '#/00000000-0000-0000-0000-000000000001/redirections', - ), - }; -}); - -afterEach(() => { - vi.clearAllMocks(); -}); - describe('Redirections page', () => { - it('should display page correctly', () => { + it('should display page correctly', async () => { const { getByTestId } = render(); - const button = getByTestId('add-redirection-btn'); - expect(button).toHaveTextContent( - redirectionsTranslation.zimbra_redirections_cta, - ); + await waitFor(() => { + const button = getByTestId('add-redirection-btn'); + expect(button).toHaveTextContent( + redirectionsTranslation.zimbra_redirections_cta, + ); + }); }); }); diff --git a/packages/manager/apps/zimbra/src/pages/onboarding/__test__/index.spec.tsx b/packages/manager/apps/zimbra/src/pages/onboarding/__test__/index.spec.tsx new file mode 100644 index 000000000000..6990664020c8 --- /dev/null +++ b/packages/manager/apps/zimbra/src/pages/onboarding/__test__/index.spec.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { describe, expect, vi } from 'vitest'; +import Onboarding from '../index'; +import { render, act, fireEvent } from '@/utils/test.provider'; +import onboardingTranslation from '@/public/translations/onboarding/Messages_fr_FR.json'; + +describe('Onboarding page', () => { + it('should display page correctly', async () => { + const { findByText } = render(); + + const title = await findByText(onboardingTranslation.title); + expect(title).toBeVisible(); + }); + + it('should call window open on click', async () => { + const { findByText } = render(); + + const spy = vi.spyOn(window, 'open'); + + const button = await findByText(onboardingTranslation.orderButtonLabel); + + await act(() => { + fireEvent.click(button); + }); + + expect(spy).toHaveBeenCalledOnce(); + }); +}); diff --git a/packages/manager/apps/zimbra/src/utils/test.provider.tsx b/packages/manager/apps/zimbra/src/utils/test.provider.tsx index 9a48b501ea15..7a662f72d0e8 100644 --- a/packages/manager/apps/zimbra/src/utils/test.provider.tsx +++ b/packages/manager/apps/zimbra/src/utils/test.provider.tsx @@ -3,7 +3,11 @@ import i18n from 'i18next'; import React, { ComponentType } from 'react'; import { I18nextProvider, initReactI18next } from 'react-i18next'; import { MemoryRouter } from 'react-router-dom'; -import { QueryClientProvider } from '@tanstack/react-query'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { + ShellContext, + ShellContextType, +} from '@ovh-ux/manager-react-shell-client'; import dashboardTranslation from '@/public/translations/dashboard/Messages_fr_FR.json'; import organizationsTranslation from '@/public/translations/organizations/Messages_fr_FR.json'; import organizationsAddAndEditTranslation from '@/public/translations/organizations/addAndEdit/Messages_fr_FR.json'; @@ -24,7 +28,7 @@ import mailingListsAddAndEditTranslation from '@/public/translations/mailinglist import redirectionsTranslation from '@/public/translations/redirections/Messages_fr_FR.json'; import redirectionsAddAndEditTranslation from '@/public/translations/redirections/addAndEdit/Messages_fr_FR.json'; import redirectionsDeleteTranslation from '@/public/translations/redirections/delete/Messages_fr_FR.json'; -import queryClient from '@/queryClient'; +import onboardingTranslation from '@/public/translations/onboarding/Messages_fr_FR.json'; import '@testing-library/jest-dom'; import 'element-internals-polyfill'; @@ -53,14 +57,37 @@ i18n.use(initReactI18next).init({ redirections: redirectionsTranslation, 'redirections/addAndEdit': redirectionsAddAndEditTranslation, 'redirections/delete': redirectionsDeleteTranslation, + onboarding: onboardingTranslation, }, }, ns: ['dashboard'], }); +export const getShellContext = () => { + return { + environment: { + getUser: () => ({ + ovhSubsidiary: 'FR', + }), + }, + } as ShellContextType; +}; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, +}); + export const wrapper = ({ children }: { children: React.ReactNode }) => { return ( - {children} + + + {children} + + ); }; @@ -71,9 +98,11 @@ export const wrapperWithI18n = ({ }) => { return ( - - {children} - + + + {children} + + ); }; @@ -85,5 +114,4 @@ const customRender = ( render(ui, { wrapper: wrapperWithI18n as ComponentType, ...options }); export * from '@testing-library/react'; - export { customRender as render }; diff --git a/packages/manager/apps/zimbra/src/utils/test.setup.tsx b/packages/manager/apps/zimbra/src/utils/test.setup.tsx new file mode 100644 index 000000000000..833b4e879fbf --- /dev/null +++ b/packages/manager/apps/zimbra/src/utils/test.setup.tsx @@ -0,0 +1,176 @@ +import { vi } from 'vitest'; +import { + accountsMock, + domainsMock, + mailingListsMock, + organizationListMock, + platformMock, + taskMocks, +} from '@/api/_mock_'; +import { AccountType } from '../api/account'; +import { DomainType } from '../api/domain/type'; +import { aliasMock, domainZone } from '../api/_mock_'; + +const mocksAxios = vi.hoisted(() => ({ + get: vi.fn(), + post: vi.fn(), + put: vi.fn(), + delete: vi.fn(), +})); + +vi.mock('axios', async (importActual) => { + const actual = await importActual(); + + const mockAxios = { + default: { + ...actual.default, + get: mocksAxios.get, + post: mocksAxios.post, + put: mocksAxios.put, + delete: mocksAxios.delete, + create: vi.fn(() => ({ + ...actual.default.create(), + get: mocksAxios.get, + post: mocksAxios.post, + put: mocksAxios.put, + delete: mocksAxios.delete, + })), + }, + }; + + return mockAxios; +}); + +vi.mock('@/hooks', async (importActual) => { + return { + ...(await importActual()), + useGenerateUrl: vi.fn(), + }; +}); + +vi.mock('@/api/account', async (importActual) => { + return { + ...(await importActual()), + getZimbraPlatformAccountDetail: vi.fn((_platformId, accountId) => { + return Promise.resolve( + accountsMock.find((acc: AccountType) => acc.id === accountId), + ); + }), + getZimbraPlatformAccounts: vi.fn(() => { + return Promise.resolve(accountsMock); + }), + deleteZimbraPlatformAccount: vi.fn(() => { + return Promise.resolve(); + }), + }; +}); + +vi.mock('@/api/domain', async (importActual) => { + return { + ...(await importActual()), + getZimbraPlatformDomainDetail: vi.fn((_platformId, domainId) => { + return Promise.resolve( + domainsMock.find((dom: DomainType) => dom.id === domainId), + ); + }), + getZimbraPlatformDomains: vi.fn(() => { + return Promise.resolve(domainsMock); + }), + getDomainsZoneList: vi.fn(() => { + return Promise.resolve(domainZone); + }), + }; +}); + +vi.mock('@/api/alias', async (importActual) => { + return { + ...(await importActual()), + getZimbraPlatformAliasDetail: vi.fn((_platformId, aliasId) => { + return Promise.resolve(aliasMock.find((alias) => alias.id === aliasId)); + }), + getZimbraPlatformAlias: vi.fn(() => { + return Promise.resolve(aliasMock); + }), + }; +}); + +vi.mock('@/api/mailinglist', async (importActual) => { + return { + ...(await importActual()), + getZimbraPlatformMailingListDetails: vi.fn((_platformId, mlId) => { + return Promise.resolve(mailingListsMock.find((ml) => ml.id === mlId)); + }), + getZimbraPlatformMailingLists: vi.fn(() => { + return Promise.resolve(mailingListsMock); + }), + }; +}); + +vi.mock('@/api/organization', async (importActual) => { + return { + ...(await importActual()), + getZimbraPlatformOrganizationDetails: vi.fn((_platformId, orgId) => { + return Promise.resolve( + organizationListMock.find((org) => org.id === orgId), + ); + }), + getZimbraPlatformOrganization: vi.fn(() => { + return Promise.resolve(organizationListMock); + }), + postZimbraPlatformOrganization: vi.fn(() => { + return Promise.resolve(); + }), + putZimbraPlatformOrganization: vi.fn(() => { + return Promise.resolve(); + }), + deleteZimbraPlatformOrganization: vi.fn(() => { + return Promise.resolve(); + }), + }; +}); + +vi.mock('@/api/platform', async (importActual) => { + return { + ...(await importActual()), + getZimbraPlatformList: vi.fn(() => { + return Promise.resolve(platformMock); + }), + }; +}); + +vi.mock('@/api/task', async (importActual) => { + return { + ...(await importActual()), + getZimbraPlatformTask: vi.fn(() => { + return Promise.resolve(taskMocks); + }), + }; +}); + +vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => { + return { + ...(await importOriginal< + typeof import('@ovh-ux/manager-react-components') + >()), + }; +}); + +vi.mock('react-router-dom', async (importActual) => { + return { + ...(await importActual()), + useLocation: vi.fn(() => ({ + pathname: '', + search: '', + })), + useResolvedPath: vi.fn(() => ({ + pathname: '', + })), + useNavigate: vi.fn(() => vi.fn), + useSearchParams: vi.fn(() => [new URLSearchParams(), vi.fn()]), + useMatches: vi.fn(() => []), + }; +}); + +afterEach(() => { + vi.clearAllMocks(); +}); diff --git a/packages/manager/apps/zimbra/vitest.config.js b/packages/manager/apps/zimbra/vitest.config.js index ce6b3faa5017..6352fd8efafb 100644 --- a/packages/manager/apps/zimbra/vitest.config.js +++ b/packages/manager/apps/zimbra/vitest.config.js @@ -1,5 +1,5 @@ import path from 'path'; -import { defineConfig } from 'vite'; +import { defineConfig, coverageConfigDefaults } from 'vitest/config'; import react from '@vitejs/plugin-react'; // https://vitejs.dev/config/ @@ -14,18 +14,18 @@ export default defineConfig({ 'src/configInterface.ts', 'src/api', 'src/zimbra.config.ts', - 'src/__tests__', 'src/vite-*.ts', 'src/App.tsx', - 'src/hooks/__tests__', 'src/hooks/index.ts', 'src/hooks/types.ts', 'src/index.tsx', 'src/routes/routes.tsx', 'src/utils/index.ts', 'src/**/*constants.ts', + ...coverageConfigDefaults.exclude, ], }, + setupFiles: ['src/utils/test.setup.tsx'], }, resolve: { alias: { diff --git a/yarn.lock b/yarn.lock index 9bf66b480d54..4407348c30d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1762,20 +1762,13 @@ core-js-pure "^3.30.2" regenerator-runtime "^0.14.0" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.15", "@babel/runtime@^7.22.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@7.22.15", "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.15", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.8", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8" integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA== dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.23.2", "@babel/runtime@^7.23.8", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.0": - version "7.25.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.7.tgz#7ffb53c37a8f247c8c4d335e89cdf16a2e0d0fb6" - integrity sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w== - dependencies: - regenerator-runtime "^0.14.0" - "@babel/standalone@^7.17.11": version "7.24.4" resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.24.4.tgz#9461220fd641a92fff4be19b34fdb9d18e80d37d" @@ -6262,7 +6255,7 @@ "@babel/helper-module-imports" "^7.10.4" "@rollup/pluginutils" "^3.1.0" -"@rollup/plugin-commonjs@^11.0.2": +"@rollup/plugin-commonjs@11.0.2", "@rollup/plugin-commonjs@^11.0.2": version "11.0.2" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-11.0.2.tgz#837cc6950752327cb90177b608f0928a4e60b582" integrity sha512-MPYGZr0qdbV5zZj8/2AuomVpnRVXRU5XKXb3HVniwRoRCreGlf5kOE081isNWeiLIi6IYkwTX9zE0/c7V8g81g== @@ -8736,7 +8729,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@>=16", "@types/react@>=16.9.11", "@types/react@^18.0.0", "@types/react@^18.2.45", "@types/react@^18.2.55": +"@types/react@*", "@types/react@18.2.45", "@types/react@18.2.55", "@types/react@>=16", "@types/react@>=16.9.11", "@types/react@^18.0.0", "@types/react@^18.2.45", "@types/react@^18.2.55", "@types/react@^18.2.79", "@types/react@^18.3.3": version "18.2.55" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.55.tgz#38141821b7084404b5013742bc4ae08e44da7a67" integrity sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA== @@ -8745,23 +8738,6 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/react@18.2.45": - version "18.2.45" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.45.tgz#253f4fac288e7e751ab3dc542000fb687422c15c" - integrity sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/react@^18.2.79", "@types/react@^18.3.3": - version "18.3.11" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.11.tgz#9d530601ff843ee0d7030d4227ea4360236bd537" - integrity sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - "@types/resolve@0.0.8": version "0.0.8" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" @@ -9052,7 +9028,7 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@uirouter/angularjs@^1.0.22", "@uirouter/angularjs@^1.0.23": +"@uirouter/angularjs@1.0.23", "@uirouter/angularjs@^1.0.22", "@uirouter/angularjs@^1.0.23": version "1.0.23" resolved "https://registry.yarnpkg.com/@uirouter/angularjs/-/angularjs-1.0.23.tgz#aeec0f96b0c42187c5044ef244ba6ccb75a5d835" integrity sha512-r4hLSw7R3mwXGC5Sq7yxNlBK1sSzQUm/1MzigwwYRHoMO5uKcBPUhxFYx5U7kufP2Xl1165KeZvRsLCh0/Z1ng== @@ -11735,7 +11711,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -chart.js@^4.4.2: +chart.js@^4.4.2, chart.js@^4.4.3: version "4.4.4" resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.4.4.tgz#b682d2e7249f7a0cbb1b1d31c840266ae9db64b7" integrity sha512-emICKGBABnxhMjUjlYRR12PmOXhJ2eJjEHL2/dZlWjxRAZT1D8xplLFq5M0tMQK8ja+wBS/tuVEJB5C6r7VxJA== @@ -15742,16 +15718,11 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatpickr@^4.6.3, flatpickr@~4.6.3: +flatpickr@4.6.9, flatpickr@^4.6.3, flatpickr@~4.5.2, flatpickr@~4.6.3: version "4.6.9" resolved "https://registry.yarnpkg.com/flatpickr/-/flatpickr-4.6.9.tgz#9a13383e8a6814bda5d232eae3fcdccb97dc1499" integrity sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw== -flatpickr@~4.5.2: - version "4.5.7" - resolved "https://registry.yarnpkg.com/flatpickr/-/flatpickr-4.5.7.tgz#6efc0d93c65547aa77294205c67830ebabe3565c" - integrity sha512-JqPfihUc9A/j9QAsh6otoARmMyUauPE17vRBEG+ThJwbl8zAq4ssGpxlPK3wWM/i8EFxkHg9UuVo0ds7XluKxw== - flatted@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" @@ -16575,16 +16546,11 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -graphql@^16.3.0: +graphql@16.6.0, graphql@^16.3.0, graphql@^16.8.1: version "16.6.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== -graphql@^16.8.1: - version "16.9.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" - integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== - growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -20325,7 +20291,7 @@ locate-path@^7.1.0: dependencies: p-locate "^6.0.0" -lodash-es@^4.17.11, lodash-es@^4.17.15, lodash-es@^4.17.21: +lodash-es@4.17.21, lodash-es@^4.17.11, lodash-es@^4.17.15, lodash-es@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== @@ -20435,7 +20401,7 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.3.0, lodash@^4.7.0, lodash@~4.17.15: +lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.3.0, lodash@^4.7.0, lodash@~4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -25042,7 +25008,7 @@ rollup-plugin-peer-deps-external@^2.2.2: resolved "https://registry.yarnpkg.com/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.4.tgz#8a420bbfd6dccc30aeb68c9bf57011f2f109570d" integrity sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g== -rollup-plugin-sass@^1.12.16: +rollup-plugin-sass@1.12.16, rollup-plugin-sass@^1.12.16: version "1.12.16" resolved "https://registry.yarnpkg.com/rollup-plugin-sass/-/rollup-plugin-sass-1.12.16.tgz#46fe4c1f73bc08289e3fb4b418fa49525888ba1b" integrity sha512-hCX9v9/rkUQ+59ztH8BECSgPGcVSgI31TbsIaJtHdCtcUFoLxSXJDSNQhQnwJwX9FVXL3Uc15Zeti/K25Rwzjg== @@ -25331,16 +25297,7 @@ sass-loader@^13.2.2: dependencies: neo-async "^2.6.2" -sass@1.71.0: - version "1.71.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.71.0.tgz#b3085759b9b2ab503a977aecb7e91153bf941117" - integrity sha512-HKKIKf49Vkxlrav3F/w6qRuPcmImGVbIXJ2I3Kg0VMA+3Bav+8yE9G5XmP5lMj6nl4OlqbPftGAscNaNu28b8w== - dependencies: - chokidar ">=3.0.0 <4.0.0" - immutable "^4.0.0" - source-map-js ">=0.6.2 <2.0.0" - -sass@^1.56.0, sass@^1.7.2: +sass@1.56.1, sass@1.71.0, sass@^1.56.0, sass@^1.7.2: version "1.56.1" resolved "https://registry.yarnpkg.com/sass/-/sass-1.56.1.tgz#94d3910cd468fd075fa87f5bb17437a0b617d8a7" integrity sha512-VpEyKpyBPCxE7qGDtOcdJ6fFbcpOM+Emu7uZLxVrkX8KVU/Dp5UF7WLvzqRuUhB6mqqQt1xffLoG+AndxTZrCQ==