From 349b5ba996c0edfbe376dc630a12d9720a595b63 Mon Sep 17 00:00:00 2001 From: Thibault Barske Date: Fri, 18 Oct 2024 14:49:51 +0200 Subject: [PATCH] feat(hycu): add hycu dashboard ref: MANAGER-14499 Signed-off-by: Thibault Barske --- .../update-name-modal.spec.tsx.snap | 3 +- .../src/hooks/services/services.type.ts | 24 +- packages/manager/apps/hycu/.gitignore | 1 + packages/manager/apps/hycu/package.json | 8 +- .../dashboard/Messages_fr_FR.json | 7 - .../translations/hycu/Messages_fr_FR.json | 6 +- .../hycu/dashboard/Messages_fr_FR.json | 25 ++ .../hycu/listing/Messages_fr_FR.json | 4 - .../components/Loading/Loading.component.tsx | 1 + .../manager/apps/hycu/src/data/api/hycu.ts | 15 +- .../apps/hycu/src/hooks/api/license.ts | 15 ++ .../hooks/shell/useNavigationGetUrl.spec.tsx | 44 ++++ .../src/hooks/shell/useNavigationGetUrl.ts | 21 ++ packages/manager/apps/hycu/src/mocks/index.ts | 1 + .../src/mocks/licenseHycu/licenseHycu.data.ts | 2 +- .../hycu/src/mocks/licenseHycu/licenseHycu.ts | 22 +- .../serviceLicenseHycu.data.ts | 95 +++++++ .../serviceLicenseHycu/serviceLicenseHycu.ts | 25 ++ .../pages/dashboard/Dashboard.page.spec.tsx | 31 +++ .../src/pages/dashboard/Dashboard.page.tsx | 39 ++- .../BillingInformationsTile.spec.tsx | 32 +++ .../BillingInformationsTile.tsx | 128 ++++++++++ .../DashboardGeneralInformation.page.tsx | 20 +- .../GeneralInformationsTile.spec.tsx | 99 +++++++ .../GeneralInformationsTile.tsx | 150 +++++++++++ .../ShortcutsTile/ShortcutsTile.spec.tsx | 65 +++++ .../ShortcutsTile/ShortcutsTile.tsx | 65 +++++ .../hycu/src/pages/dashboard/tab2/index.tsx | 7 - .../hycu/src/pages/listing/Listing.page.tsx | 10 +- .../hycu/src/pages/listing/Listing.spec.tsx | 6 +- .../manager/apps/hycu/src/routes/routes.tsx | 11 - .../apps/hycu/src/utils/statusColor.ts | 1 + .../apps/hycu/src/utils/tests/TestApp.tsx | 4 +- .../apps/hycu/src/utils/tests/init.i18n.ts | 31 ++- .../hycu/src/utils/tests/renderTestApp.tsx | 37 ++- packages/manager/apps/hycu/vitest.config.js | 3 + yarn.lock | 241 ++++++++++++++---- 37 files changed, 1143 insertions(+), 156 deletions(-) delete mode 100644 packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_FR.json create mode 100644 packages/manager/apps/hycu/public/translations/hycu/dashboard/Messages_fr_FR.json create mode 100644 packages/manager/apps/hycu/src/hooks/api/license.ts create mode 100644 packages/manager/apps/hycu/src/hooks/shell/useNavigationGetUrl.spec.tsx create mode 100644 packages/manager/apps/hycu/src/hooks/shell/useNavigationGetUrl.ts create mode 100644 packages/manager/apps/hycu/src/mocks/serviceLicenseHycu/serviceLicenseHycu.data.ts create mode 100644 packages/manager/apps/hycu/src/mocks/serviceLicenseHycu/serviceLicenseHycu.ts create mode 100644 packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.spec.tsx create mode 100644 packages/manager/apps/hycu/src/pages/dashboard/general-information/BillingInformations/BillingInformationsTile.spec.tsx create mode 100644 packages/manager/apps/hycu/src/pages/dashboard/general-information/BillingInformations/BillingInformationsTile.tsx create mode 100644 packages/manager/apps/hycu/src/pages/dashboard/general-information/GeneralInformationsTiles/GeneralInformationsTile.spec.tsx create mode 100644 packages/manager/apps/hycu/src/pages/dashboard/general-information/GeneralInformationsTiles/GeneralInformationsTile.tsx create mode 100644 packages/manager/apps/hycu/src/pages/dashboard/general-information/ShortcutsTile/ShortcutsTile.spec.tsx create mode 100644 packages/manager/apps/hycu/src/pages/dashboard/general-information/ShortcutsTile/ShortcutsTile.tsx delete mode 100644 packages/manager/apps/hycu/src/pages/dashboard/tab2/index.tsx diff --git a/packages/manager-react-components/src/components/templates/update-name-modal/__snapshots__/update-name-modal.spec.tsx.snap b/packages/manager-react-components/src/components/templates/update-name-modal/__snapshots__/update-name-modal.spec.tsx.snap index e160c5981bb3..b4744bff035f 100644 --- a/packages/manager-react-components/src/components/templates/update-name-modal/__snapshots__/update-name-modal.spec.tsx.snap +++ b/packages/manager-react-components/src/components/templates/update-name-modal/__snapshots__/update-name-modal.spec.tsx.snap @@ -32,6 +32,7 @@ exports[`Update Name Modal component renders loading modal 1`] = ` aria-disabled="true" aria-label="update-input" disabled="true" + error="true" internals-disabled="" type="text" /> @@ -40,7 +41,7 @@ exports[`Update Name Modal component renders loading modal 1`] = ` > diff --git a/packages/manager-react-components/src/hooks/services/services.type.ts b/packages/manager-react-components/src/hooks/services/services.type.ts index 9b3f00f70a03..270b613c1d80 100644 --- a/packages/manager-react-components/src/hooks/services/services.type.ts +++ b/packages/manager-react-components/src/hooks/services/services.type.ts @@ -55,6 +55,21 @@ export type ResourceStatus = | 'toDelete' | 'toSuspend'; +export type Renew = { + current: CurrentRenew; + capacities: RenewCapacities; +}; + +export type CurrentRenew = { + mode: RenewMode | null; + nextDate: string | null; + period: string; +}; + +export type RenewCapacities = { + mode: RenewMode[]; +}; + export type ServiceDetails = { billing: { engagement: { @@ -115,14 +130,7 @@ export type ServiceDetails = { pricingMode: string; pricingType: PricingType; }; - }; - renew: { - capacities: { mode: RenewMode[] }; - current: { - mode: RenewMode | null; - nextDate: string | null; - period: string; - }; + renew: Renew; }; customer: { contacts: CustomerContact[]; diff --git a/packages/manager/apps/hycu/.gitignore b/packages/manager/apps/hycu/.gitignore index e06831cfdeb4..0b4d91f6ad34 100644 --- a/packages/manager/apps/hycu/.gitignore +++ b/packages/manager/apps/hycu/.gitignore @@ -1,2 +1,3 @@ e2e/reports e2e/coverage +coverage diff --git a/packages/manager/apps/hycu/package.json b/packages/manager/apps/hycu/package.json index 6c027e737c9e..cdc635374f38 100644 --- a/packages/manager/apps/hycu/package.json +++ b/packages/manager/apps/hycu/package.json @@ -16,7 +16,8 @@ "start": "lerna exec --stream --scope='@ovh-ux/manager-hycu-app' --include-dependencies -- npm run build --if-present", "start:dev": "lerna exec --stream --scope='@ovh-ux/manager-hycu-app' --include-dependencies -- npm run dev --if-present", "start:watch": "lerna exec --stream --parallel --scope='@ovh-ux/manager-hycu-app' --include-dependencies -- npm run dev:watch --if-present", - "test": "vitest run" + "test": "vitest run", + "test:coverage": "vitest run --coverage" }, "dependencies": { "@ovh-ux/manager-config": "*", @@ -46,17 +47,20 @@ "devDependencies": { "@cucumber/cucumber": "^10.3.1", "@ovh-ux/manager-vite-config": "*", + "@ovh-ux/url-builder": "^1.2.0", "@testing-library/jest-dom": "^6.5.0", "@testing-library/react": "^16.0.1", + "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.5.2", "@types/jest": "^29.5.13", "@vitejs/plugin-react": "^4.3.2", + "@vitest/coverage-v8": "^2.1.3", "element-internals-polyfill": "^1.3.12", "eslint-plugin-prettier": "^5.2.1", "msw": "2.1.7", "typescript": "^5.1.6", "vite": "^5.2.13", - "vitest": "^2.1.2" + "vitest": "^2.1.3" }, "regions": [ "CA", diff --git a/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_FR.json deleted file mode 100644 index f42a27b3366a..000000000000 --- a/packages/manager/apps/hycu/public/translations/dashboard/Messages_fr_FR.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "title": "Dashboard page", - "error_service": "No services info", - "general_informations": "Informations générales", - "tab2": "Tab 2", - "back_link": "Retour à la liste" -} diff --git a/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_FR.json index 36d8b913e6d9..a9a3a8b8dee5 100644 --- a/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_FR.json +++ b/packages/manager/apps/hycu/public/translations/hycu/Messages_fr_FR.json @@ -2,5 +2,9 @@ "hycu_crumb": "HYCU", "tabs_2": "Tabs 2", "hycu_description": "Simplifiez vos sauvegardes, plans de reprise après sinistre et migrations de votre infrastructure Nutanix. Ce service vous propose différents packs de licences HYCU Hybrid Cloud pour protéger vos charges de travail Nutanix.", - "hycu_cloud_vm_pack_unknown": "Pack inconnu" + "hycu_cloud_vm_pack_unknown": "Pack inconnu", + "hycu_status_activated": "Active", + "hycu_status_toActivate": "À activer", + "hycu_status_pending": "En cours d'activation", + "hycu_status_error": "Erreur d'activation" } diff --git a/packages/manager/apps/hycu/public/translations/hycu/dashboard/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/hycu/dashboard/Messages_fr_FR.json new file mode 100644 index 000000000000..4f6227f18791 --- /dev/null +++ b/packages/manager/apps/hycu/public/translations/hycu/dashboard/Messages_fr_FR.json @@ -0,0 +1,25 @@ +{ + "hycu_dashboard_generals_informations_title": "Informations générales", + "hycu_dashboard_label_name": "Nom", + "hycu_dashboard_label_status": "Statut", + "hycu_dashboard_label_pack_type": "Type de pack", + "hycu_dashboard_label_controller_id": "Controller ID", + "hycu_dashboard_label_license_key": "Clé de licence", + "hycu_dashboard_shortcuts_title": "Raccourcis", + "hycu_dashboard_link_activate": "Activer la licence", + "hycu_dashboard_link_reactivate": "Regénérer la licence", + "hycu_dashboard_link_terminated": "Résilier la licence", + "hycu_dashboard_link_change_pack_type": "Modifier le type de pack", + "hycu_dashboard_field_label_contacts": "Contacts", + "hycu_dashboard_contact_type_administrator": "Administrateur", + "hycu_dashboard_contact_type_technical": "Technique", + "hycu_dashboard_contact_type_billing": "Facturation", + "hycu_dashboard_action_billing_terminate": "Résilier", + "hycu_dashboard_field_label_manage_contacts": "Gérer les contacts", + "hycu_dashboard_label_renew": "Renouvellement automatique", + "hycu_dashboard_subscription_title": "Abonnement", + "hycu_dashboard_field_label_date_creation": "Date de création", + "hycu_dashboard_download_license_file": "Télécharger la license", + "hycu_dashboard_back_link": "Retour à la liste", + "hycu_dashboard_wait_for_activation": "En attente d'activation" +} diff --git a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_FR.json b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_FR.json index ea668aab4db9..0a8af73eb2b5 100644 --- a/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_FR.json +++ b/packages/manager/apps/hycu/public/translations/hycu/listing/Messages_fr_FR.json @@ -1,8 +1,4 @@ { - "hycu_status_activated": "Active", - "hycu_status_toActivate": "À activer", - "hycu_status_pending": "En cours d'activation", - "hycu_status_error": "Erreur d'activation", "hycu_cloud_vm_pack_unknown": "Pack inconnu", "hycu_name": "Nom", "hycu_controller_id": "Controller ID", diff --git a/packages/manager/apps/hycu/src/components/Loading/Loading.component.tsx b/packages/manager/apps/hycu/src/components/Loading/Loading.component.tsx index bb74a4fa8e15..8623d319f92b 100644 --- a/packages/manager/apps/hycu/src/components/Loading/Loading.component.tsx +++ b/packages/manager/apps/hycu/src/components/Loading/Loading.component.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { OsdsSpinner } from '@ovhcloud/ods-components/react'; +/* v8 ignore start */ export default function Loading() { return (
diff --git a/packages/manager/apps/hycu/src/data/api/hycu.ts b/packages/manager/apps/hycu/src/data/api/hycu.ts index 7068dc242d81..b7ebf0617df5 100644 --- a/packages/manager/apps/hycu/src/data/api/hycu.ts +++ b/packages/manager/apps/hycu/src/data/api/hycu.ts @@ -1,8 +1,10 @@ +import { AxiosResponse } from 'axios'; import { fetchIcebergV6, apiClient } from '@ovh-ux/manager-core-api'; +import { IHycuDetails } from '@/type/hycu.details.interface'; export type GetlicenseHycuListParams = { /** Filter resources on IAM tags */ - iamTags: any; + iamTags: string; }; export const getlicenseHycuListQueryKey = ['get/license/hycu']; @@ -10,7 +12,7 @@ export const getlicenseHycuListQueryKey = ['get/license/hycu']; /** * Manage HYCU licenses : Get list of owned HYCU licenses */ -export const getlicenseHycuList = async ( +export const getlicenseHycuList = ( params: GetlicenseHycuListParams, ): Promise => apiClient.v6.get('/license/hycu', { data: params }); @@ -19,16 +21,13 @@ export type GetlicenseHycuServiceParams = { serviceName?: string; }; -export const getlicenseHycuServiceQueryKey = ( - params: GetlicenseHycuServiceParams, -) => [`get/license/hycu/${params.serviceName}`]; - /** * Manage HYCU licenses : Get HYCU license info */ -export const getlicenseHycuService = async ( +export const getlicenseHycuService = ( params: GetlicenseHycuServiceParams, -): Promise => apiClient.v6.get(`/license/hycu/${params.serviceName}`); +): Promise> => + apiClient.v6.get(`/license/hycu/${params.serviceName}`); /** * Get listing with iceberg V6 diff --git a/packages/manager/apps/hycu/src/hooks/api/license.ts b/packages/manager/apps/hycu/src/hooks/api/license.ts new file mode 100644 index 000000000000..3c7854b22c14 --- /dev/null +++ b/packages/manager/apps/hycu/src/hooks/api/license.ts @@ -0,0 +1,15 @@ +import { AxiosResponse } from 'axios'; +import { DefinedInitialDataOptions, useQuery } from '@tanstack/react-query'; +import { getlicenseHycuService } from '@/data/api/hycu'; +import { IHycuDetails } from '@/type/hycu.details.interface'; + +export const useDetailsLicenseHYCU = ( + serviceName: string, + options?: DefinedInitialDataOptions>, +) => { + return useQuery({ + queryKey: ['license/hycu', 'get', serviceName], + queryFn: () => getlicenseHycuService({ serviceName }), + ...(options ?? {}), + }); +}; diff --git a/packages/manager/apps/hycu/src/hooks/shell/useNavigationGetUrl.spec.tsx b/packages/manager/apps/hycu/src/hooks/shell/useNavigationGetUrl.spec.tsx new file mode 100644 index 000000000000..58b23531d6a1 --- /dev/null +++ b/packages/manager/apps/hycu/src/hooks/shell/useNavigationGetUrl.spec.tsx @@ -0,0 +1,44 @@ +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; +import { vitest } from 'vitest'; +import { ParamValueType } from '@ovh-ux/url-builder'; +import React, { PropsWithChildren, useState } from 'react'; +import { renderHook, waitFor } from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { useNavigationGetUrl } from './useNavigationGetUrl'; + +const mockGetURL = vitest.fn(); + +const wrapper = ({ children }: PropsWithChildren) => { + const [queryClient] = useState(new QueryClient()); + const [mockContextValue] = useState({ + shell: { navigation: { getURL: mockGetURL } }, + }); + return ( + + {children} + + ); +}; + +describe('useNavigationGetUrl', () => { + it('should call navigation.getURL with correct linkParams', async () => { + const linkParams: [string, string, Record] = [ + 'param1', + 'param2', + { key: 'value' }, + ]; + mockGetURL.mockResolvedValue('mockedUrl'); + + const { result } = renderHook( + () => useNavigationGetUrl(linkParams, { retry: false }), + { + wrapper, + }, + ); + + await waitFor(() => result.current.isSuccess); + + await waitFor(() => expect(mockGetURL).toHaveBeenCalledWith(...linkParams)); + expect(result.current.data).toBe('mockedUrl'); + }); +}); diff --git a/packages/manager/apps/hycu/src/hooks/shell/useNavigationGetUrl.ts b/packages/manager/apps/hycu/src/hooks/shell/useNavigationGetUrl.ts new file mode 100644 index 000000000000..77cf71a49b0e --- /dev/null +++ b/packages/manager/apps/hycu/src/hooks/shell/useNavigationGetUrl.ts @@ -0,0 +1,21 @@ +import { ParamValueType } from '@ovh-ux/url-builder'; +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; +import { DefinedInitialDataOptions, useQuery } from '@tanstack/react-query'; +import { useContext } from 'react'; + +export const useNavigationGetUrl = ( + linkParams: [string, string, Record], + options?: Partial>, +) => { + const { + shell: { navigation }, + } = useContext(ShellContext); + + return useQuery({ + queryKey: ['shell', 'getUrl', linkParams], + queryFn: () => navigation.getURL(...linkParams), + refetchOnReconnect: false, + refetchOnWindowFocus: false, + ...(options ?? {}), + }); +}; diff --git a/packages/manager/apps/hycu/src/mocks/index.ts b/packages/manager/apps/hycu/src/mocks/index.ts index 202f88045626..1d92b2f2ffea 100644 --- a/packages/manager/apps/hycu/src/mocks/index.ts +++ b/packages/manager/apps/hycu/src/mocks/index.ts @@ -1 +1,2 @@ export * from './licenseHycu/licenseHycu'; +export * from './serviceLicenseHycu/serviceLicenseHycu'; diff --git a/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.data.ts b/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.data.ts index 260accd6ab47..998a3e14e3fb 100644 --- a/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.data.ts +++ b/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.data.ts @@ -21,7 +21,7 @@ export const licensesHycu: IHycuDetails[] = [ }, comment: '', serviceName: 'c1b7cb4f-6b63-45da-9a8a-f731f1a67b2c', - controllerId: '', + controllerId: 'test-id', licenseStatus: LicenseStatus.ACTIVATED, expirationDate: '0001-01-01T00:00:00Z', }, diff --git a/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.ts b/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.ts index 664d5fb4e95f..9d12981a842b 100644 --- a/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.ts +++ b/packages/manager/apps/hycu/src/mocks/licenseHycu/licenseHycu.ts @@ -1,14 +1,17 @@ +import { LicenseStatus } from '@/type/hycu.details.interface'; import { Handler } from '../../../../../../../playwright-helpers'; import { licensesHycu } from './licenseHycu.data'; export type GetLicenseHycuMocksParams = { isGetLicenseHycuKo?: boolean; nbLicenseHycu?: number; + licenseStatus?: LicenseStatus; }; export const getLicenseHycuMocks = ({ isGetLicenseHycuKo, nbLicenseHycu = Number.POSITIVE_INFINITY, + licenseStatus = LicenseStatus.TO_ACTIVATE, }: GetLicenseHycuMocksParams): Handler[] => { return [ { @@ -17,7 +20,24 @@ export const getLicenseHycuMocks = ({ ? { message: 'Backup error', } - : licensesHycu.slice(0, nbLicenseHycu), + : licensesHycu + .slice(0, nbLicenseHycu) + .map((license) => ({ ...license, licenseStatus })), + status: isGetLicenseHycuKo ? 500 : 200, + api: 'v6', + }, + { + url: 'license/hycu/:serviceName', + response: isGetLicenseHycuKo + ? { + message: 'Backup error', + } + : { + ...licensesHycu[0], + licenseStatus, + controllerId: + licenseStatus !== LicenseStatus.TO_ACTIVATE ? 'test-id' : '', + }, status: isGetLicenseHycuKo ? 500 : 200, api: 'v6', }, diff --git a/packages/manager/apps/hycu/src/mocks/serviceLicenseHycu/serviceLicenseHycu.data.ts b/packages/manager/apps/hycu/src/mocks/serviceLicenseHycu/serviceLicenseHycu.data.ts new file mode 100644 index 000000000000..40aa4f70141d --- /dev/null +++ b/packages/manager/apps/hycu/src/mocks/serviceLicenseHycu/serviceLicenseHycu.data.ts @@ -0,0 +1,95 @@ +import { CurrencyCode, ServiceDetails } from '@ovh-ux/manager-react-components'; + +export const licensesHycuService: ServiceDetails = { + route: { + path: '/license/hycu/{serviceName}', + url: '/license/hycu/425802fa-fb70-4b2a-9d5b-ec4de86bb40c', + vars: [ + { + key: 'serviceName', + value: '425802fa-fb70-4b2a-9d5b-ec4de86bb40c', + }, + ], + }, + billing: { + nextBillingDate: '2024-11-03T15:24:23Z', + expirationDate: '2024-11-03T15:24:23Z', + plan: { + code: 'hycu-vms-pack-25', + invoiceName: 'HYCU Hybrid Cloud - 25 VMs', + }, + pricing: { + capacities: 'renew', + description: 'rental for 1 month', + interval: 1, + duration: 'P1M', + minimumQuantity: 1, + maximumQuantity: null, + minimumRepeat: 1, + maximumRepeat: null, + price: { + currencyCode: CurrencyCode.EUR, + text: '157.50 €', + value: 157.5, + priceInUcents: 0, + }, + priceInUcents: 15750000000, + pricingMode: 'default', + pricingType: 'rental', + engagementConfiguration: null, + }, + group: null, + lifecycle: { + current: { + pendingActions: [], + terminationDate: null, + creationDate: '2024-10-03T15:24:23Z', + state: 'active', + }, + capacities: { + actions: ['earlyRenewal', 'terminateAtExpirationDate'], + }, + }, + renew: { + current: { + mode: 'automatic', + nextDate: '2024-11-03T15:24:23Z', + period: 'P1M', + }, + capacities: { + mode: ['automatic', 'manual'], + }, + }, + engagement: null, + engagementRequest: null, + }, + resource: { + displayName: '425802fa-fb70-4b2a-9d5b-ec4de86bb40c', + name: '425802fa-fb70-4b2a-9d5b-ec4de86bb40c', + state: 'active', + product: { + name: 'hycu-cloud-vm-pack-25', + description: 'HYCU Hybrid Cloud - 25 VMs', + }, + resellingProvider: null, + }, + serviceId: 128622602, + parentServiceId: null, + customer: { + contacts: [ + { + customerCode: 'ls148374-ovh', + type: 'administrator', + }, + { + customerCode: 'ls148374-ovh', + type: 'technical', + }, + { + customerCode: 'ls148374-ovh', + type: 'billing', + }, + ], + }, + tags: [], +}; diff --git a/packages/manager/apps/hycu/src/mocks/serviceLicenseHycu/serviceLicenseHycu.ts b/packages/manager/apps/hycu/src/mocks/serviceLicenseHycu/serviceLicenseHycu.ts new file mode 100644 index 000000000000..8168d84c5468 --- /dev/null +++ b/packages/manager/apps/hycu/src/mocks/serviceLicenseHycu/serviceLicenseHycu.ts @@ -0,0 +1,25 @@ +import { LicenseStatus } from '@/type/hycu.details.interface'; +import { Handler } from '../../../../../../../playwright-helpers'; +import { licensesHycuService } from './serviceLicenseHycu.data'; + +export type GetServiceLicenseHycuMocksParams = { + isGetServiceLicenseHycuKo?: boolean; + licenseStatus?: LicenseStatus; +}; + +export const getServiceLicenseHycuMocks = ({ + isGetServiceLicenseHycuKo, +}: GetServiceLicenseHycuMocksParams): Handler[] => { + return [ + { + url: 'services/:id', + response: isGetServiceLicenseHycuKo + ? { + message: 'Backup error', + } + : licensesHycuService, + status: isGetServiceLicenseHycuKo ? 500 : 200, + api: 'v6', + }, + ]; +}; diff --git a/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.spec.tsx b/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.spec.tsx new file mode 100644 index 000000000000..5bab4a2ccd8d --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.spec.tsx @@ -0,0 +1,31 @@ +import { screen, waitFor } from '@testing-library/react'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import '@testing-library/jest-dom'; + +describe('License Hycu Dashboard route test suite', () => { + it('should show informations of services', async () => { + await renderTestApp('/fake-id'); + + await waitFor( + () => + expect( + screen.getAllByText('425802fa-fb70-4b2a-9d5b-ec4de86bb40c')[0], + ).toBeVisible(), + { timeout: 30_000 }, + ); + + expect(screen.queryByAltText('OOPS')).not.toBeInTheDocument(); + }); + + it('should show error if api services fail', async () => { + await renderTestApp('/fake-id', { + getServicesKo: true, + isGetLicenseHycuKo: true, + isGetServiceLicenseHycuKo: true, + }); + + await waitFor(() => expect(screen.getByAltText('OOPS')).toBeVisible(), { + timeout: 30_000, + }); + }); +}); diff --git a/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.tsx b/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.tsx index 665a301e9a95..4f718e86902f 100644 --- a/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.tsx +++ b/packages/manager/apps/hycu/src/pages/dashboard/Dashboard.page.tsx @@ -5,8 +5,8 @@ import { NavLink, useLocation, useNavigate, - useParams, useResolvedPath, + useParams, } from 'react-router-dom'; import { OsdsTabs, @@ -14,9 +14,14 @@ import { OsdsTabBarItem, } from '@ovhcloud/ods-components/react'; -import { BaseLayout } from '@ovh-ux/manager-react-components'; +import { + BaseLayout, + useServiceDetails, +} from '@ovh-ux/manager-react-components'; import Breadcrumb from '@/components/Breadcrumb/Breadcrumb.component'; +import Errors from '@/components/Error/Error'; +import { urls } from '@/routes/routes.constant'; export type DashboardTabItemProps = { name: string; @@ -29,22 +34,22 @@ export type DashboardLayoutProps = { }; export default function DashboardPage() { + const { serviceName } = useParams(); const [panel, setActivePanel] = useState(''); const location = useLocation(); const navigate = useNavigate(); - const { t } = useTranslation('dashboard'); + const { t } = useTranslation('hycu/dashboard'); + + const { data: serviceDetails, error } = useServiceDetails({ + resourceName: serviceName, + }); const tabsList = [ { name: 'general_informations', - title: 'Informations générales', + title: t('hycu_dashboard_generals_informations_title'), to: useResolvedPath('').pathname, }, - { - name: 'Tab 2', - title: 'Tab 2', - to: useResolvedPath('Tab2').pathname, - }, ] as const; useEffect(() => { @@ -58,14 +63,26 @@ export default function DashboardPage() { }, [location.pathname]); const header = { - title: t('title'), + title: serviceDetails?.data.resource.displayName, + description: serviceName, }; + if (error) { + return ( + } header={header}> + + + ); + } + return ( } header={header} - description="Description du hycu" + backLinkLabel={t('hycu_dashboard_back_link')} + onClickReturn={() => { + navigate(urls.listing); + }} tabs={ diff --git a/packages/manager/apps/hycu/src/pages/dashboard/general-information/BillingInformations/BillingInformationsTile.spec.tsx b/packages/manager/apps/hycu/src/pages/dashboard/general-information/BillingInformations/BillingInformationsTile.spec.tsx new file mode 100644 index 000000000000..b5562fb9a1ac --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/general-information/BillingInformations/BillingInformationsTile.spec.tsx @@ -0,0 +1,32 @@ +import { screen, waitFor } from '@testing-library/react'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import '@testing-library/jest-dom'; +import { labels } from '@/utils/tests/init.i18n'; + +describe('License Hycu billing information tile for dashboard test suite', () => { + it('should show informations of services', async () => { + await renderTestApp('/fake-id'); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.dashboard.hycu_dashboard_subscription_title, + )[0], + ).toBeVisible(), + { timeout: 30_000 }, + ); + + expect( + screen.getByText(labels.dashboard.hycu_dashboard_label_renew), + ).toBeVisible(); + expect( + screen.getByText(labels.dashboard.hycu_dashboard_field_label_contacts), + ).toBeVisible(); + expect( + screen.getByText( + labels.dashboard.hycu_dashboard_field_label_date_creation, + ), + ).toBeVisible(); + }); +}); diff --git a/packages/manager/apps/hycu/src/pages/dashboard/general-information/BillingInformations/BillingInformationsTile.tsx b/packages/manager/apps/hycu/src/pages/dashboard/general-information/BillingInformations/BillingInformationsTile.tsx new file mode 100644 index 000000000000..cef4561d3014 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/general-information/BillingInformations/BillingInformationsTile.tsx @@ -0,0 +1,128 @@ +import { + DashboardTile, + DateFormat, + Description, + Renew, + useFormattedDate, + useServiceDetails, +} from '@ovh-ux/manager-react-components'; +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; +import { ODS_ICON_NAME, ODS_ICON_SIZE } from '@ovhcloud/ods-components'; +import { + OsdsIcon, + OsdsLink, + OsdsSkeleton, +} from '@ovhcloud/ods-components/react'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { useNavigationGetUrl } from '@/hooks/shell/useNavigationGetUrl'; + +const BillingInformationsTile = ({ serviceName }: { serviceName: string }) => { + const { t } = useTranslation('hycu/dashboard'); + + const { data: serviceDetails, isLoading } = useServiceDetails({ + resourceName: serviceName, + }); + + const renewDate = useFormattedDate({ + dateString: (serviceDetails?.data.billing.renew as Renew)?.current.nextDate, + format: DateFormat.display, + }); + + const creationDate = useFormattedDate({ + dateString: serviceDetails?.data.billing.lifecycle.current.creationDate, + format: DateFormat.display, + }); + + const { + data: contactUrl, + isLoading: isContactUrlLoading, + } = useNavigationGetUrl([ + 'dedicated', + '#/contacts/services', + { serviceName }, + ]); + + return ( + + ) : ( + {renewDate} + ), + }, + { + id: 'contact', + label: t('hycu_dashboard_field_label_contacts'), + value: ( +
+
+ {isLoading + ? Array.from({ length: 3 }).map((_, index) => ( + + )) + : serviceDetails?.data.customer.contacts.map((contact) => ( + {`${ + contact.customerCode + } ${t( + `hycu_dashboard_contact_type_${contact.type}`, + )}`} + ))} +
+ +
+ + {t('hycu_dashboard_field_label_manage_contacts')} + + + + +
+
+ ), + }, + { + id: 'date_creation', + label: t('hycu_dashboard_field_label_date_creation'), + value: isLoading ? ( + + ) : ( + {creationDate} + ), + }, + { + id: 'link_terminated', + value: ( + + {t('hycu_dashboard_link_terminated')} + + + + + ), + }, + ]} + >
+ ); +}; + +export default BillingInformationsTile; diff --git a/packages/manager/apps/hycu/src/pages/dashboard/general-information/DashboardGeneralInformation.page.tsx b/packages/manager/apps/hycu/src/pages/dashboard/general-information/DashboardGeneralInformation.page.tsx index a785e6d2ff0f..09627a1c37c2 100644 --- a/packages/manager/apps/hycu/src/pages/dashboard/general-information/DashboardGeneralInformation.page.tsx +++ b/packages/manager/apps/hycu/src/pages/dashboard/general-information/DashboardGeneralInformation.page.tsx @@ -1,7 +1,25 @@ import React from 'react'; +import { useParams } from 'react-router-dom'; +import BillingInformationsTile from './BillingInformations/BillingInformationsTile'; +import GeneralInformationsTile from './GeneralInformationsTiles/GeneralInformationsTile'; +import ShortcutsTile from './ShortcutsTile/ShortcutsTile'; function GeneralInfos() { - return
Information Générales Tab
; + const { serviceName } = useParams(); + + return ( +
+
+ +
+
+ +
+
+ +
+
+ ); } export default GeneralInfos; diff --git a/packages/manager/apps/hycu/src/pages/dashboard/general-information/GeneralInformationsTiles/GeneralInformationsTile.spec.tsx b/packages/manager/apps/hycu/src/pages/dashboard/general-information/GeneralInformationsTiles/GeneralInformationsTile.spec.tsx new file mode 100644 index 000000000000..850d04f7e0f6 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/general-information/GeneralInformationsTiles/GeneralInformationsTile.spec.tsx @@ -0,0 +1,99 @@ +import { screen, waitFor } from '@testing-library/react'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import '@testing-library/jest-dom'; +import { labels } from '@/utils/tests/init.i18n'; +import { LicenseStatus } from '@/type/hycu.details.interface'; + +describe('License Hycu general informations tile for dashboard test suite', () => { + it('should show informations of services', async () => { + await renderTestApp('/fake-id'); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.dashboard.hycu_dashboard_generals_informations_title, + )[1], + ).toBeVisible(), + { timeout: 30_000 }, + ); + + expect( + screen.getByText(labels.dashboard.hycu_dashboard_label_name), + ).toBeVisible(); + expect( + screen.getByText(labels.dashboard.hycu_dashboard_label_status), + ).toBeVisible(); + expect( + screen.getByText(labels.dashboard.hycu_dashboard_label_pack_type), + ).toBeVisible(); + expect( + screen.getByText(labels.dashboard.hycu_dashboard_label_controller_id), + ).toBeVisible(); + expect( + screen.getByText(labels.dashboard.hycu_dashboard_label_license_key), + ).toBeVisible(); + + expect( + screen.queryByText(labels.dashboard.hycu_dashboard_download_license_file), + ).not.toBeInTheDocument(); + }); + + it('should show download license button when license is activated', async () => { + await renderTestApp('/fake-id', { licenseStatus: LicenseStatus.ACTIVATED }); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.dashboard.hycu_dashboard_generals_informations_title, + )[1], + ).toBeVisible(), + { timeout: 30_000 }, + ); + + await waitFor( + () => + expect( + screen.getByText( + labels.dashboard.hycu_dashboard_download_license_file, + ), + ).toBeVisible(), + { timeout: 30_000 }, + ); + + expect( + screen.queryByText(labels.dashboard.hycu_dashboard_wait_for_activation), + ).not.toBeInTheDocument(); + }); + + it('should show wait for activation if license is not activated', async () => { + await renderTestApp('/fake-id', { + licenseStatus: LicenseStatus.TO_ACTIVATE, + }); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.dashboard.hycu_dashboard_generals_informations_title, + )[1], + ).toBeVisible(), + { timeout: 10_000 }, + ); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.dashboard.hycu_dashboard_wait_for_activation, + )[0], + ).toBeVisible(), + { timeout: 10_000 }, + ); + + expect( + screen.queryByText(labels.dashboard.hycu_dashboard_download_license_file), + ).not.toBeInTheDocument(); + }); +}); diff --git a/packages/manager/apps/hycu/src/pages/dashboard/general-information/GeneralInformationsTiles/GeneralInformationsTile.tsx b/packages/manager/apps/hycu/src/pages/dashboard/general-information/GeneralInformationsTiles/GeneralInformationsTile.tsx new file mode 100644 index 000000000000..b453d3984efa --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/general-information/GeneralInformationsTiles/GeneralInformationsTile.tsx @@ -0,0 +1,150 @@ +import { + DashboardTile, + Description, + useServiceDetails, +} from '@ovh-ux/manager-react-components'; +import { + OsdsChip, + OsdsIcon, + OsdsButton, + OsdsSkeleton, + OsdsLink, +} from '@ovhcloud/ods-components/react'; +import { + ODS_BUTTON_SIZE, + ODS_BUTTON_VARIANT, + ODS_CHIP_SIZE, + ODS_ICON_NAME, + ODS_ICON_SIZE, +} from '@ovhcloud/ods-components'; + +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; + +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { getStatusColor } from '@/utils/statusColor'; +import { useDetailsLicenseHYCU } from '@/hooks/api/license'; +import { LicenseStatus } from '@/type/hycu.details.interface'; + +const DownloadHycuLicense = ({ serviceName }: { serviceName: string }) => { + const { t } = useTranslation('hycu/dashboard'); + const { data: hycuDetail, isLoading } = useDetailsLicenseHYCU(serviceName); + + if (isLoading) return ; + if (LicenseStatus.ACTIVATED !== hycuDetail.data.licenseStatus) + return <>{t('hycu_dashboard_wait_for_activation')}; + return ( + + {t('hycu_dashboard_download_license_file')} + + + + + ); +}; + +const ControllerIdHycuLicense = ({ serviceName }: { serviceName: string }) => { + const { t } = useTranslation('hycu/dashboard'); + const { data: hycuDetail, isLoading } = useDetailsLicenseHYCU(serviceName); + + if (isLoading) return ; + if (!hycuDetail?.data.controllerId) + return <>{t('hycu_dashboard_wait_for_activation')}; + return {hycuDetail?.data.controllerId}; +}; + +const GeneralInformationsTile = ({ serviceName }: { serviceName: string }) => { + const { t: tCommon } = useTranslation('hycu'); + const { t } = useTranslation('hycu/dashboard'); + const { data: hycuDetail } = useDetailsLicenseHYCU(serviceName); + const { data: serviceDetails, isLoading } = useServiceDetails({ + resourceName: serviceName, + }); + + return ( + + ) : ( +
+ + {serviceDetails?.data.resource.displayName} + + + + + +
+ ), + }, + { + id: 'status', + label: t('hycu_dashboard_label_status'), + value: isLoading ? ( + + ) : ( + + {tCommon([ + `hycu_status_${hycuDetail?.data.licenseStatus}`, + 'hycu_status_error', + ])} + + ), + }, + { + id: 'pack_type', + label: t('hycu_dashboard_label_pack_type'), + value: isLoading ? ( + + ) : ( + + {serviceDetails?.data.resource.product.description} + + ), + }, + { + id: 'controller_id', + label: t('hycu_dashboard_label_controller_id'), + value: ControllerIdHycuLicense({ serviceName }), + }, + { + id: 'license_key', + label: t('hycu_dashboard_label_license_key'), + value: isLoading ? ( + + ) : ( + + ), + }, + ]} + >
+ ); +}; + +export default GeneralInformationsTile; diff --git a/packages/manager/apps/hycu/src/pages/dashboard/general-information/ShortcutsTile/ShortcutsTile.spec.tsx b/packages/manager/apps/hycu/src/pages/dashboard/general-information/ShortcutsTile/ShortcutsTile.spec.tsx new file mode 100644 index 000000000000..f28b5348f1be --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/general-information/ShortcutsTile/ShortcutsTile.spec.tsx @@ -0,0 +1,65 @@ +import '@testing-library/jest-dom'; +import { screen, waitFor } from '@testing-library/react'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import { labels } from '@/utils/tests/init.i18n'; +import { LicenseStatus } from '@/type/hycu.details.interface'; + +describe('License Hycu shortcuts tile for dashboard test suite', () => { + it('should show links of service to activate', async () => { + await renderTestApp('/fake-id', { + licenseStatus: LicenseStatus.TO_ACTIVATE, + }); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.dashboard.hycu_dashboard_shortcuts_title, + )[0], + ).toBeVisible(), + { timeout: 30_000 }, + ); + + await waitFor( + () => + expect( + screen.getByText(labels.dashboard.hycu_dashboard_link_activate), + ).toBeVisible(), + { timeout: 30_000 }, + ); + expect( + screen.queryByText(labels.dashboard.hycu_dashboard_link_change_pack_type), + ).not.toBeInTheDocument(); + }); + + it('should show links of services activated', async () => { + await renderTestApp('/fake-id', { licenseStatus: LicenseStatus.ACTIVATED }); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.dashboard.hycu_dashboard_shortcuts_title, + )[0], + ).toBeVisible(), + { timeout: 30_000 }, + ); + + await waitFor( + () => + expect( + screen.getByText(labels.dashboard.hycu_dashboard_link_reactivate), + ).toBeVisible(), + { timeout: 20_000 }, + ); + await waitFor( + () => + expect( + screen.getByText( + labels.dashboard.hycu_dashboard_link_change_pack_type, + ), + ).toBeVisible(), + { timeout: 20_000 }, + ); + }); +}); diff --git a/packages/manager/apps/hycu/src/pages/dashboard/general-information/ShortcutsTile/ShortcutsTile.tsx b/packages/manager/apps/hycu/src/pages/dashboard/general-information/ShortcutsTile/ShortcutsTile.tsx new file mode 100644 index 000000000000..1a54ba980ba0 --- /dev/null +++ b/packages/manager/apps/hycu/src/pages/dashboard/general-information/ShortcutsTile/ShortcutsTile.tsx @@ -0,0 +1,65 @@ +import { OsdsLink, OsdsIcon } from '@ovhcloud/ods-components/react'; +import { DashboardTile } from '@ovh-ux/manager-react-components'; + +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { ODS_ICON_NAME } from '@ovhcloud/ods-components'; +import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; +import { useDetailsLicenseHYCU } from '@/hooks/api/license'; +import { LicenseStatus } from '@/type/hycu.details.interface'; + +const ShortcutsItem = ({ + children, + ...rest +}: React.ComponentProps) => ( + +
+
{children}
+ +
+
+); + +const ShortcutsTile = ({ serviceName }: { serviceName: string }) => { + const { data: hycuDetail } = useDetailsLicenseHYCU(serviceName); + const { t } = useTranslation('hycu/dashboard'); + + const links = { + linkActivated: { + id: 'link_activated', + value: {t('hycu_dashboard_link_activate')}, + }, + linkReactivated: { + id: 'link_reactivated', + value: ( + {t('hycu_dashboard_link_reactivate')} + ), + }, + linkChangePackType: { + id: 'link_change_pack_type', + value: ( + + {t('hycu_dashboard_link_change_pack_type')} + + ), + }, + } as const; + + return ( + + ); +}; + +export default ShortcutsTile; diff --git a/packages/manager/apps/hycu/src/pages/dashboard/tab2/index.tsx b/packages/manager/apps/hycu/src/pages/dashboard/tab2/index.tsx deleted file mode 100644 index 9cb100623734..000000000000 --- a/packages/manager/apps/hycu/src/pages/dashboard/tab2/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -function Tab2() { - return
Tab 2
; -} - -export default Tab2; diff --git a/packages/manager/apps/hycu/src/pages/listing/Listing.page.tsx b/packages/manager/apps/hycu/src/pages/listing/Listing.page.tsx index 89ffb56d055f..b0e05416780f 100644 --- a/packages/manager/apps/hycu/src/pages/listing/Listing.page.tsx +++ b/packages/manager/apps/hycu/src/pages/listing/Listing.page.tsx @@ -37,12 +37,6 @@ import { usePackTypeLabel } from '@/hooks/service/usePackLabel'; import HycuActionMenu from './menu/HycuActionMenu.component'; import { getStatusColor } from '@/utils/statusColor'; -const dateFormat: Intl.DateTimeFormatOptions = { - day: '2-digit', - month: '2-digit', - year: 'numeric', -}; - /* ========= datagrid cells ========= */ const DatagridIdCell = (hycuDetail: IHycuDetails) => { const navigate = useNavigate(); @@ -65,11 +59,11 @@ const DatagridIdCell = (hycuDetail: IHycuDetails) => { }; const DatagridControllerIdCell = (hycuDetail: IHycuDetails) => { - return {hycuDetail.controllerId}; + return {hycuDetail.controllerId || '-'}; }; const DatagridStatusCell = (hycuDetail: IHycuDetails) => { - const { t } = useTranslation('hycu/listing'); + const { t } = useTranslation('hycu'); return ( diff --git a/packages/manager/apps/hycu/src/pages/listing/Listing.spec.tsx b/packages/manager/apps/hycu/src/pages/listing/Listing.spec.tsx index 396747dc0831..fc4739d31029 100644 --- a/packages/manager/apps/hycu/src/pages/listing/Listing.spec.tsx +++ b/packages/manager/apps/hycu/src/pages/listing/Listing.spec.tsx @@ -8,7 +8,7 @@ import HYCU_CONFIG from '@/hycu.config'; describe('License Hycu listing test suite', () => { it('should redirect to the onboarding page when the license hycu list is empty', async () => { - await renderTestApp({ nbLicenseHycu: 0 }); + await renderTestApp('/', { nbLicenseHycu: 0 }); expect(screen.getByText(HYCU_CONFIG.rootLabel)).toBeVisible(); expect( @@ -40,7 +40,9 @@ describe('License Hycu listing test suite', () => { await waitFor( () => expect( - screen.getByText(labels.dashboard.general_informations), + screen.getAllByText( + labels.dashboard.hycu_dashboard_generals_informations_title, + )[0], ).toBeVisible(), { timeout: 30_000 }, ); diff --git a/packages/manager/apps/hycu/src/routes/routes.tsx b/packages/manager/apps/hycu/src/routes/routes.tsx index 0fa1bc776da3..28fafd148573 100644 --- a/packages/manager/apps/hycu/src/routes/routes.tsx +++ b/packages/manager/apps/hycu/src/routes/routes.tsx @@ -51,17 +51,6 @@ export const Routes: any = [ }, }, }, - { - id: 'dashboard.tab2', - path: 'Tab2', - ...lazyRouteConfig(() => import('@/pages/dashboard/tab2')), - handle: { - tracking: { - pageName: 'tab2', - pageType: PageType.dashboard, - }, - }, - }, ], }, { diff --git a/packages/manager/apps/hycu/src/utils/statusColor.ts b/packages/manager/apps/hycu/src/utils/statusColor.ts index 1aedb85a5ad8..75efb753736a 100644 --- a/packages/manager/apps/hycu/src/utils/statusColor.ts +++ b/packages/manager/apps/hycu/src/utils/statusColor.ts @@ -1,6 +1,7 @@ import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming'; import { LicenseStatus } from '@/type/hycu.details.interface'; +/* v8 ignore start */ export const getStatusColor = ( licenseStatus: LicenseStatus, ): ODS_THEME_COLOR_INTENT => { diff --git a/packages/manager/apps/hycu/src/utils/tests/TestApp.tsx b/packages/manager/apps/hycu/src/utils/tests/TestApp.tsx index b016f4d6ec24..0ec94df2580f 100644 --- a/packages/manager/apps/hycu/src/utils/tests/TestApp.tsx +++ b/packages/manager/apps/hycu/src/utils/tests/TestApp.tsx @@ -3,9 +3,9 @@ import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; import { createMemoryRouter, RouterProvider } from 'react-router-dom'; import { Routes } from '../../routes/routes'; -export function TestApp() { +export function TestApp({ initialRoute = '/' }: { initialRoute: string }) { const router = createMemoryRouter(Routes, { - initialEntries: ['/'], + initialEntries: [initialRoute], initialIndex: 0, }); diff --git a/packages/manager/apps/hycu/src/utils/tests/init.i18n.ts b/packages/manager/apps/hycu/src/utils/tests/init.i18n.ts index 9af278be892c..6a1248a254ba 100644 --- a/packages/manager/apps/hycu/src/utils/tests/init.i18n.ts +++ b/packages/manager/apps/hycu/src/utils/tests/init.i18n.ts @@ -1,6 +1,7 @@ -import i18next, { i18n } from 'i18next'; +import i18next, { i18n, InitOptions } from 'i18next'; +import error from '@ovh-ux/manager-react-components/src/components/templates/error/translations/Messages_fr_FR.json'; import common from '../../../public/translations/hycu/Messages_fr_FR.json'; -import dashboard from '../../../public/translations/dashboard/Messages_fr_FR.json'; +import dashboard from '../../../public/translations/hycu/dashboard/Messages_fr_FR.json'; import listing from '../../../public/translations/hycu/listing/Messages_fr_FR.json'; import onboarding from '../../../public/translations/hycu/onboarding/Messages_fr_FR.json'; @@ -10,9 +11,10 @@ export const defaultAvailableLocales = [defaultLocale]; function addTranslations() { i18next .addResources(defaultLocale, 'hycu', common) - .addResources(defaultLocale, 'dashboard', dashboard) + .addResources(defaultLocale, 'hycu/dashboard', dashboard) .addResources(defaultLocale, 'hycu/listing', listing) .addResources(defaultLocale, 'hycu/onboarding', onboarding) + .addResources(defaultLocale, 'error', error) .use({ type: 'postProcessor', name: 'normalize', @@ -21,18 +23,20 @@ function addTranslations() { }); } +export const getTesti18nParams = (): InitOptions => ({ + lng: defaultLocale, + defaultNS: 'hycu', + ns: [], + supportedLngs: defaultAvailableLocales, + postProcess: 'normalize', + interpolation: { + escapeValue: false, + }, +}); + export const initTestI18n = () => new Promise((resolve) => { - i18next.init({ - lng: defaultLocale, - defaultNS: 'hycu', - ns: [], - supportedLngs: defaultAvailableLocales, - postProcess: 'normalize', - interpolation: { - escapeValue: false, - }, - }); + i18next.init(getTesti18nParams()); if (i18next.isInitialized) { addTranslations(); @@ -49,4 +53,5 @@ export const labels = { dashboard, listing, onboarding, + error, }; diff --git a/packages/manager/apps/hycu/src/utils/tests/renderTestApp.tsx b/packages/manager/apps/hycu/src/utils/tests/renderTestApp.tsx index fb0e6a88d311..fc96e1e3d01d 100644 --- a/packages/manager/apps/hycu/src/utils/tests/renderTestApp.tsx +++ b/packages/manager/apps/hycu/src/utils/tests/renderTestApp.tsx @@ -12,22 +12,33 @@ import { GetServicesMocksParams, } from '@ovh-ux/manager-react-components/src/hooks/services/mocks/services.mock'; import { TestApp } from './TestApp'; -import { initTestI18n } from './init.i18n'; +import { getTesti18nParams, initTestI18n } from './init.i18n'; import { toMswHandlers } from '../../../../../../../playwright-helpers'; import { getAuthenticationMocks } from '../../../../../../../playwright-helpers/mocks/auth'; -import { getLicenseHycuMocks, GetLicenseHycuMocksParams } from '@/mocks'; +import { + getLicenseHycuMocks, + GetLicenseHycuMocksParams, + getServiceLicenseHycuMocks, + GetServiceLicenseHycuMocksParams, +} from '@/mocks'; let context: ShellContextType; let i18nValue: i18n; export const renderTestApp = async ( - mockParams: GetServicesMocksParams & GetLicenseHycuMocksParams = {}, + initialRoute = '/', + mockParams: GetServicesMocksParams & + GetLicenseHycuMocksParams & + GetServicesMocksParams & + GetServicesMocksParams & + GetServiceLicenseHycuMocksParams = {}, ) => { global.server?.resetHandlers( ...toMswHandlers([ ...getAuthenticationMocks({ isAuthMocked: true }), - ...getServicesMocks(mockParams), ...getLicenseHycuMocks(mockParams), + ...getServiceLicenseHycuMocks(mockParams), + ...getServicesMocks(mockParams), ]), ); @@ -42,18 +53,20 @@ export const renderTestApp = async ( const result = render( - + , ); - await waitFor( - () => - expect( - screen.getAllByText('HYCU', { exact: false }).length, - ).toBeGreaterThan(0), - { timeout: 30000 }, - ); + if (!initialRoute || initialRoute === '/') { + await waitFor( + () => + expect( + screen.getAllByText('HYCU', { exact: false }).length, + ).toBeGreaterThan(0), + { timeout: 30000 }, + ); + } return result; }; diff --git a/packages/manager/apps/hycu/vitest.config.js b/packages/manager/apps/hycu/vitest.config.js index 5ad6ce3dccf7..9075895638be 100644 --- a/packages/manager/apps/hycu/vitest.config.js +++ b/packages/manager/apps/hycu/vitest.config.js @@ -10,8 +10,11 @@ export default defineConfig({ environment: 'jsdom', setupFiles: ['./src/setupTests.tsx'], coverage: { + provider: 'v8', + reporter: ['text'], include: ['src'], exclude: [ + 'src/mocks', 'src/App.tsx', 'src/index.tsx', 'src/tracking.constant.ts', diff --git a/yarn.lock b/yarn.lock index 9f2419d40475..e6d6ba8e2406 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,6 +938,13 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== +"@babel/parser@^7.25.4": + version "7.25.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.8.tgz#f6aaf38e80c36129460c1657c0762db584c9d5e2" + integrity sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ== + dependencies: + "@babel/types" "^7.25.8" + "@babel/parser@^7.25.7": version "7.25.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.7.tgz#99b927720f4ddbfeb8cd195a363ed4532f87c590" @@ -2086,6 +2093,15 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" +"@babel/types@^7.25.4", "@babel/types@^7.25.8": + version "7.25.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.8.tgz#5cf6037258e8a9bcad533f4979025140cb9993e1" + integrity sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg== + dependencies: + "@babel/helper-string-parser" "^7.25.7" + "@babel/helper-validator-identifier" "^7.25.7" + to-fast-properties "^2.0.0" + "@babel/types@^7.25.7": version "7.25.7" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.7.tgz#1b7725c1d3a59f328cb700ce704c46371e6eef9b" @@ -8524,6 +8540,14 @@ lodash "^4.17.21" redent "^3.0.0" +"@testing-library/react-hooks@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz#0924bbd5b55e0c0c0502d1754657ada66947ca12" + integrity sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g== + dependencies: + "@babel/runtime" "^7.12.5" + react-error-boundary "^3.1.0" + "@testing-library/react@14.0.0": version "14.0.0" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-14.0.0.tgz#59030392a6792450b9ab8e67aea5f3cc18d6347c" @@ -9661,6 +9685,24 @@ strip-literal "^2.0.0" test-exclude "^6.0.0" +"@vitest/coverage-v8@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz#22d519e5e56385ec126305492f5a3cfe5b44b14d" + integrity sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A== + dependencies: + "@ampproject/remapping" "^2.3.0" + "@bcoe/v8-coverage" "^0.2.3" + debug "^4.3.6" + istanbul-lib-coverage "^3.2.2" + istanbul-lib-report "^3.0.1" + istanbul-lib-source-maps "^5.0.6" + istanbul-reports "^3.1.7" + magic-string "^0.30.11" + magicast "^0.3.4" + std-env "^3.7.0" + test-exclude "^7.0.1" + tinyrainbow "^1.2.0" + "@vitest/expect@1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.3.1.tgz#d4c14b89c43a25fd400a6b941f51ba27fe0cb918" @@ -9698,22 +9740,22 @@ chai "^5.1.1" tinyrainbow "^1.2.0" -"@vitest/expect@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.2.tgz#e92fa284b8472548f72cacfe896020c64af6bf78" - integrity sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg== +"@vitest/expect@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.3.tgz#4b9a6fff22be4c4cd5d57e687cfda611b514b0ad" + integrity sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ== dependencies: - "@vitest/spy" "2.1.2" - "@vitest/utils" "2.1.2" + "@vitest/spy" "2.1.3" + "@vitest/utils" "2.1.3" chai "^5.1.1" tinyrainbow "^1.2.0" -"@vitest/mocker@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.2.tgz#08853a9d8d12afba284aebdf9b5ea26ddae5f20a" - integrity sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA== +"@vitest/mocker@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.3.tgz#a3593b426551be5715fa108faf04f8a9ddb0a9cc" + integrity sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ== dependencies: - "@vitest/spy" "^2.1.0-beta.1" + "@vitest/spy" "2.1.3" estree-walker "^3.0.3" magic-string "^0.30.11" @@ -9724,10 +9766,10 @@ dependencies: tinyrainbow "^1.2.0" -"@vitest/pretty-format@2.1.2", "@vitest/pretty-format@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.2.tgz#42882ea18c4cd40428e34f74bbac706a82465193" - integrity sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA== +"@vitest/pretty-format@2.1.3", "@vitest/pretty-format@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.3.tgz#48b9b03de75507d1d493df7beb48dc39a1946a3e" + integrity sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ== dependencies: tinyrainbow "^1.2.0" @@ -9757,12 +9799,12 @@ "@vitest/utils" "2.0.5" pathe "^1.1.2" -"@vitest/runner@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.2.tgz#14da1f5eac43fbd9a37d7cd72de102e8f785d727" - integrity sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw== +"@vitest/runner@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.3.tgz#20a6da112007dfd92969951df189c6da66c9dac4" + integrity sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ== dependencies: - "@vitest/utils" "2.1.2" + "@vitest/utils" "2.1.3" pathe "^1.1.2" "@vitest/snapshot@1.4.0": @@ -9792,12 +9834,12 @@ magic-string "^0.30.10" pathe "^1.1.2" -"@vitest/snapshot@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.2.tgz#e20bd794b33fdcd4bfe69138baac7bb890c4d51f" - integrity sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA== +"@vitest/snapshot@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.3.tgz#1b405a9c40a82563605b13fdc045217751069e58" + integrity sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg== dependencies: - "@vitest/pretty-format" "2.1.2" + "@vitest/pretty-format" "2.1.3" magic-string "^0.30.11" pathe "^1.1.2" @@ -9829,10 +9871,10 @@ dependencies: tinyspy "^3.0.0" -"@vitest/spy@2.1.2", "@vitest/spy@^2.1.0-beta.1": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.2.tgz#bccdeca597c8fc3777302889e8c98cec9264df44" - integrity sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A== +"@vitest/spy@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.3.tgz#2c8a457673094ec4c1ab7c50cb11c58e3624ada2" + integrity sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ== dependencies: tinyspy "^3.0.0" @@ -9889,12 +9931,12 @@ loupe "^3.1.1" tinyrainbow "^1.2.0" -"@vitest/utils@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.2.tgz#222ac35ba02493173e40581256eb7a62520fcdba" - integrity sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ== +"@vitest/utils@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.3.tgz#e52aa5745384091b151cbdf79bb5a3ad2bea88d2" + integrity sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA== dependencies: - "@vitest/pretty-format" "2.1.2" + "@vitest/pretty-format" "2.1.3" loupe "^3.1.1" tinyrainbow "^1.2.0" @@ -16824,6 +16866,18 @@ glob@^10.0.0, glob@^10.3.10: minipass "^7.0.4" path-scurry "^1.10.2" +glob@^10.4.1: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -18665,7 +18719,16 @@ istanbul-lib-source-maps@^5.0.4: debug "^4.1.1" istanbul-lib-coverage "^3.0.0" -istanbul-reports@^3.0.2, istanbul-reports@^3.1.3, istanbul-reports@^3.1.5, istanbul-reports@^3.1.6: +istanbul-lib-source-maps@^5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" + integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== + dependencies: + "@jridgewell/trace-mapping" "^0.3.23" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + +istanbul-reports@^3.0.2, istanbul-reports@^3.1.3, istanbul-reports@^3.1.5, istanbul-reports@^3.1.6, istanbul-reports@^3.1.7: version "3.1.7" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== @@ -18701,6 +18764,15 @@ jackspeak@^2.3.6: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jake@^10.8.5: version "10.8.7" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.7.tgz#63a32821177940c33f356e0ba44ff9d34e1c7d8f" @@ -20995,13 +21067,20 @@ magic-string@^0.30.0, magic-string@^0.30.1, magic-string@^0.30.5, magic-string@^ dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" -magic-string@^0.30.10, magic-string@^0.30.11: +magic-string@^0.30.10: version "0.30.11" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A== dependencies: "@jridgewell/sourcemap-codec" "^1.5.0" +magic-string@^0.30.11: + version "0.30.12" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.12.tgz#9eb11c9d072b9bcb4940a5b2c2e1a217e4ee1a60" + integrity sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + magicast@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.3.tgz#a15760f982deec9dabc5f314e318d7c6bddcb27b" @@ -21011,6 +21090,15 @@ magicast@^0.3.3: "@babel/types" "^7.23.6" source-map-js "^1.0.2" +magicast@^0.3.4: + version "0.3.5" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.5.tgz#8301c3c7d66704a0771eb1bad74274f0ec036739" + integrity sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ== + dependencies: + "@babel/parser" "^7.25.4" + "@babel/types" "^7.25.4" + source-map-js "^1.2.0" + majo@^0.6.2: version "0.6.3" resolved "https://registry.yarnpkg.com/majo/-/majo-0.6.3.tgz#ac8f35a64c644c87eaccddf940891f157a183846" @@ -21488,6 +21576,13 @@ minimatch@^9.0.1, minimatch@^9.0.3: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimatch@~3.0.3: version "3.0.8" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" @@ -21573,6 +21668,11 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== +minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + minisearch@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/minisearch/-/minisearch-6.3.0.tgz#985a2f1ca3c73c2d65af94f0616bfe57164b0b6b" @@ -22843,6 +22943,11 @@ p-waterfall@^2.1.1: dependencies: p-reduce "^2.0.0" +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + package-json@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" @@ -23121,6 +23226,14 @@ path-scurry@^1.10.2: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.10: version "0.1.10" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" @@ -24083,6 +24196,13 @@ react-element-to-jsx-string@^15.0.0: is-plain-object "5.0.0" react-is "18.1.0" +react-error-boundary@^3.1.0: + version "3.1.4" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0" + integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA== + dependencies: + "@babel/runtime" "^7.12.5" + react-hook-form@^7.47.0, react-hook-form@^7.50.1: version "7.51.2" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.51.2.tgz#79f7f72ee217c5114ff831012d1a7ec344096e7f" @@ -27209,6 +27329,15 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +test-exclude@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-7.0.1.tgz#20b3ba4906ac20994e275bbcafd68d510264c2a2" + integrity sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^10.4.1" + minimatch "^9.0.4" + text-extensions@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" @@ -27309,9 +27438,9 @@ tinybench@^2.8.0, tinybench@^2.9.0: integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== tinyexec@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.0.tgz#ed60cfce19c17799d4a241e06b31b0ec2bee69e6" - integrity sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg== + version "0.3.1" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.1.tgz#0ab0daf93b43e2c211212396bdb836b468c97c98" + integrity sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ== tinypool@^0.8.2: version "0.8.2" @@ -28685,10 +28814,10 @@ vite-node@2.0.5: tinyrainbow "^1.2.0" vite "^5.0.0" -vite-node@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.2.tgz#f5491a2b399959c9e2f3c4b70cb0cbaecf9be6d2" - integrity sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ== +vite-node@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.3.tgz#8291d31f91c69dc22fea7909f4394c2b3cc2e2d9" + integrity sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA== dependencies: cac "^6.7.14" debug "^4.3.6" @@ -28891,18 +29020,18 @@ vitest@^2.0.5: vite-node "2.0.5" why-is-node-running "^2.3.0" -vitest@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.2.tgz#f285fdde876749fddc0cb4d9748ae224443c1694" - integrity sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A== - dependencies: - "@vitest/expect" "2.1.2" - "@vitest/mocker" "2.1.2" - "@vitest/pretty-format" "^2.1.2" - "@vitest/runner" "2.1.2" - "@vitest/snapshot" "2.1.2" - "@vitest/spy" "2.1.2" - "@vitest/utils" "2.1.2" +vitest@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.3.tgz#dae1055dd328621b59fc6e594fd988fbf2e5370e" + integrity sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA== + dependencies: + "@vitest/expect" "2.1.3" + "@vitest/mocker" "2.1.3" + "@vitest/pretty-format" "^2.1.3" + "@vitest/runner" "2.1.3" + "@vitest/snapshot" "2.1.3" + "@vitest/spy" "2.1.3" + "@vitest/utils" "2.1.3" chai "^5.1.1" debug "^4.3.6" magic-string "^0.30.11" @@ -28913,7 +29042,7 @@ vitest@^2.1.2: tinypool "^1.0.0" tinyrainbow "^1.2.0" vite "^5.0.0" - vite-node "2.1.2" + vite-node "2.1.3" why-is-node-running "^2.3.0" void-elements@3.1.0: