From 72f53d67dbd46191af66a1e089a81d6b1cbb67cc Mon Sep 17 00:00:00 2001 From: stif59100 Date: Thu, 30 Jan 2025 16:06:59 +0100 Subject: [PATCH] feat(web-office): add modal order users ref:MANAGER-16713 Signed-off-by: stif59100 --- packages/manager/apps/web-office/package.json | 12 +- .../users/order-users/Messages_fr_FR.json | 11 + .../web-office-365/Messages_fr_FR.json | 6 - .../web-office-365/error/Messages_fr_FR.json | 8 - .../apps/web-office/src/api/_mock_/index.ts | 1 + .../apps/web-office/src/api/_mock_/price.ts | 5 + .../apps/web-office/src/api/_mock_/user.ts | 2 + .../apps/web-office/src/api/api.type.ts | 10 + .../apps/web-office/src/api/order/api.ts | 1 - .../apps/web-office/src/api/order/type.ts | 5 + .../apps/web-office/src/api/price/api.ts | 12 + .../apps/web-office/src/api/price/index.ts | 2 + .../apps/web-office/src/api/price/key.ts | 7 + .../apps/web-office/src/api/users/api.ts | 22 +- .../apps/web-office/src/api/users/key.ts | 8 + .../web-office/src/pages/dashboard/index.tsx | 1 - .../users/ModalOrderLicenses.component.tsx | 1 + .../users/ModalOrderUsers.component.tsx | 272 +++++++++++++++++- .../src/pages/dashboard/users/Users.tsx | 42 ++- .../ModalOrderLicenses.component.spec.tsx | 8 - .../ModalOrderUsers.component.spec.tsx | 95 ++++++ .../dashboard/users/__test__/Users.spec.tsx | 4 +- .../web-office/src/utils/test.provider.tsx | 3 + .../apps/web-office/src/utils/test.setup.tsx | 15 +- .../manager/apps/web-office/tsconfig.json | 2 +- yarn.lock | 9 - 26 files changed, 502 insertions(+), 62 deletions(-) create mode 100644 packages/manager/apps/web-office/public/translations/dashboard/users/order-users/Messages_fr_FR.json delete mode 100644 packages/manager/apps/web-office/public/translations/web-office-365/Messages_fr_FR.json delete mode 100644 packages/manager/apps/web-office/public/translations/web-office-365/error/Messages_fr_FR.json create mode 100644 packages/manager/apps/web-office/src/api/_mock_/price.ts create mode 100644 packages/manager/apps/web-office/src/api/price/api.ts create mode 100644 packages/manager/apps/web-office/src/api/price/index.ts create mode 100644 packages/manager/apps/web-office/src/api/price/key.ts create mode 100644 packages/manager/apps/web-office/src/pages/dashboard/users/__test__/ModalOrderUsers.component.spec.tsx diff --git a/packages/manager/apps/web-office/package.json b/packages/manager/apps/web-office/package.json index b79e2a608188..bdad6d58623f 100644 --- a/packages/manager/apps/web-office/package.json +++ b/packages/manager/apps/web-office/package.json @@ -22,17 +22,17 @@ "dependencies": { "@hookform/resolvers": "^3.3.4", "@ovh-ux/manager-config": "^8.0.2", - "@ovh-ux/manager-core-api": "^0.9.0", + "@ovh-ux/manager-core-api": "^0.10.0", "@ovh-ux/manager-core-utils": "^0.3.0", - "@ovh-ux/manager-module-order": "^0.9.3", + "@ovh-ux/manager-module-order": "^0.9.4", "@ovh-ux/manager-react-components": "^2.7.1", - "@ovh-ux/manager-react-core-application": "^0.11.5", + "@ovh-ux/manager-react-core-application": "^0.11.6", "@ovh-ux/manager-react-shell-client": "^0.8.5", "@ovh-ux/manager-tailwind-config": "^0.2.1", "@ovh-ux/request-tagger": "^0.4.0", - "@ovh-ux/shell": "^4.1.2", - "@ovhcloud/ods-components": "^18.4.1", - "@ovhcloud/ods-themes": "^18.4.1", + "@ovh-ux/shell": "^4.1.3", + "@ovhcloud/ods-components": "^18.5.0", + "@ovhcloud/ods-themes": "^18.5.0", "@tanstack/react-query": "^5.51.21", "@tanstack/react-table": "^8.20.1", "element-internals-polyfill": "^1.3.10", diff --git a/packages/manager/apps/web-office/public/translations/dashboard/users/order-users/Messages_fr_FR.json b/packages/manager/apps/web-office/public/translations/dashboard/users/order-users/Messages_fr_FR.json new file mode 100644 index 000000000000..4bb072d76b9c --- /dev/null +++ b/packages/manager/apps/web-office/public/translations/dashboard/users/order-users/Messages_fr_FR.json @@ -0,0 +1,11 @@ +{ + "dashboard_users_order_users_lastname_label": "Nom", + "dashboard_users_order_users_firstname_label": "Prénom", + "dashboard_users_order_users_login_label": "Identifiant", + "dashboard_users_order_users_type": "Type de licence", + "dashboard_users_order_users_type_placeholder": "Sélectionner", + "dashboard_users_order_users_price": "Prix", + "dashboard_users_order_users_message": "Vous serez facturé sur le nombre de licences activées dans le mois en cours.", + "dashboard_users_order_users_message_error": "Une erreur s'est produite lors de la récupération des informations. {{error}}", + "dashboard_users_order_users_message_success": "Votre demande d'ajout d'utilisateur a bien été pris en compte." +} diff --git a/packages/manager/apps/web-office/public/translations/web-office-365/Messages_fr_FR.json b/packages/manager/apps/web-office/public/translations/web-office-365/Messages_fr_FR.json deleted file mode 100644 index 7ea7eb873732..000000000000 --- a/packages/manager/apps/web-office/public/translations/web-office-365/Messages_fr_FR.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Bienvenue uapp", - "crumb": "web-office", - "tabs_2": "Tabs 2", - "onboarding": "Onboarding" -} diff --git a/packages/manager/apps/web-office/public/translations/web-office-365/error/Messages_fr_FR.json b/packages/manager/apps/web-office/public/translations/web-office-365/error/Messages_fr_FR.json deleted file mode 100644 index 2c575c63588e..000000000000 --- a/packages/manager/apps/web-office/public/translations/web-office-365/error/Messages_fr_FR.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "manager_error_page_title": "Oops …!", - "manager_error_page_button_cancel": "Annuler", - "manager_error_page_detail_code": "Code d'erreur : ", - "manager_error_page_action_reload_label": "Réessayer", - "manager_error_page_action_home_label": "Retour à la page d'accueil", - "manager_error_page_default": "Une erreur est survenue lors du chargement de la page." -} diff --git a/packages/manager/apps/web-office/src/api/_mock_/index.ts b/packages/manager/apps/web-office/src/api/_mock_/index.ts index 956b8732dbe3..4a5b218eb0cd 100644 --- a/packages/manager/apps/web-office/src/api/_mock_/index.ts +++ b/packages/manager/apps/web-office/src/api/_mock_/index.ts @@ -1,3 +1,4 @@ export * from './license'; export * from './user'; export * from './order'; +export * from './price'; diff --git a/packages/manager/apps/web-office/src/api/_mock_/price.ts b/packages/manager/apps/web-office/src/api/_mock_/price.ts new file mode 100644 index 000000000000..cec3b51c8899 --- /dev/null +++ b/packages/manager/apps/web-office/src/api/_mock_/price.ts @@ -0,0 +1,5 @@ +export const priceMock = { + text: '7.99 €', + value: 7.99, + currencyCode: 'EUR', +}; diff --git a/packages/manager/apps/web-office/src/api/_mock_/user.ts b/packages/manager/apps/web-office/src/api/_mock_/user.ts index 7ad0b5334225..3db3b394abed 100644 --- a/packages/manager/apps/web-office/src/api/_mock_/user.ts +++ b/packages/manager/apps/web-office/src/api/_mock_/user.ts @@ -33,3 +33,5 @@ export const pendingTask: PendingTaskType = { status: TaskStatusEnum.TODO, todoDate: '2025-01-09T11:20:52+01:00', }; + +export const userDomainMock = ['test.office.ovh.com']; diff --git a/packages/manager/apps/web-office/src/api/api.type.ts b/packages/manager/apps/web-office/src/api/api.type.ts index a0635db53ae2..679a500dd351 100644 --- a/packages/manager/apps/web-office/src/api/api.type.ts +++ b/packages/manager/apps/web-office/src/api/api.type.ts @@ -1,3 +1,5 @@ +import { OvhSubsidiary } from '@ovh-ux/manager-react-components'; + export enum UserStateEnum { CREATING = 'creating', DELETING = 'deleting', @@ -26,6 +28,14 @@ export type UserParamsType = { firstName: string; lastName: string; }; +export type UserOrderParamsType = { + domain: string; + firstName: string; + lastName: string; + usageLocation: OvhSubsidiary; + licence: string; + login: string; +}; export type UserChangePasswordType = { password?: string; diff --git a/packages/manager/apps/web-office/src/api/order/api.ts b/packages/manager/apps/web-office/src/api/order/api.ts index 020b1b82504e..e2f0e596f3ae 100644 --- a/packages/manager/apps/web-office/src/api/order/api.ts +++ b/packages/manager/apps/web-office/src/api/order/api.ts @@ -3,7 +3,6 @@ import { OvhSubsidiary } from '@ovh-ux/manager-react-components'; import { order } from './type'; // GET - export const getOrderCatalog = async ({ ovhSubsidiary, productName, diff --git a/packages/manager/apps/web-office/src/api/order/type.ts b/packages/manager/apps/web-office/src/api/order/type.ts index 9d060f779de2..836c46940020 100644 --- a/packages/manager/apps/web-office/src/api/order/type.ts +++ b/packages/manager/apps/web-office/src/api/order/type.ts @@ -11,6 +11,11 @@ export enum OfficePrepaidPlanCodes { OFFICE_365_ENTERPRISE = 'microsoft-365-apps-for-enterprise-pp-nce', } +export enum OfficeUserEnum { + OFFICE_365_BUSINESS = 'officeBusiness', + OFFICE_365_PRO_PLUS = 'officeProPlus', +} + /* eslint-disable @typescript-eslint/no-namespace */ export namespace order { export namespace cart { diff --git a/packages/manager/apps/web-office/src/api/price/api.ts b/packages/manager/apps/web-office/src/api/price/api.ts new file mode 100644 index 000000000000..43d1970b3fed --- /dev/null +++ b/packages/manager/apps/web-office/src/api/price/api.ts @@ -0,0 +1,12 @@ +import { v6 } from '@ovh-ux/manager-core-api'; + +// GET + +export const getOfficePrice = async ({ + officeName, +}: { + officeName: string; +}) => { + const { data } = await v6.get(`/price/license/office/${officeName}`); + return data; +}; diff --git a/packages/manager/apps/web-office/src/api/price/index.ts b/packages/manager/apps/web-office/src/api/price/index.ts new file mode 100644 index 000000000000..c1c342b403eb --- /dev/null +++ b/packages/manager/apps/web-office/src/api/price/index.ts @@ -0,0 +1,2 @@ +export * from './api'; +export * from './key'; diff --git a/packages/manager/apps/web-office/src/api/price/key.ts b/packages/manager/apps/web-office/src/api/price/key.ts new file mode 100644 index 000000000000..c0f943e2dd64 --- /dev/null +++ b/packages/manager/apps/web-office/src/api/price/key.ts @@ -0,0 +1,7 @@ +export const getOfficePriceQueryKey = (officeName: string) => [ + 'get', + 'price', + 'license', + 'office', + officeName, +]; diff --git a/packages/manager/apps/web-office/src/api/users/api.ts b/packages/manager/apps/web-office/src/api/users/api.ts index 3921a146d5a1..2fa57b6b0b13 100644 --- a/packages/manager/apps/web-office/src/api/users/api.ts +++ b/packages/manager/apps/web-office/src/api/users/api.ts @@ -1,6 +1,10 @@ import { fetchIcebergV6, v6 } from '@ovh-ux/manager-core-api'; import { getApiPath } from '../utils/apiPath'; -import { UserChangePasswordType, UserParamsType } from '../api.type'; +import { + UserChangePasswordType, + UserOrderParamsType, + UserParamsType, +} from '../api.type'; import { UserNativeType } from './type'; import { useOfficeServiceType } from '@/hooks'; @@ -15,7 +19,10 @@ export const getOfficeUsers = async ( }); return data; }; - +export const getOfficeUsersDomain = async (serviceName: string) => { + const { data } = await v6.get(`${getApiPath(serviceName)}domain`); + return data?.length > 0 ? data[0] : null; +}; export const getOfficeUserDetail = async ( serviceName: string, activationEmail: string, @@ -43,6 +50,17 @@ export const postUsersPassword = async ( const { data } = await v6.post(endpoint, params); return data; }; +export const postOrderUsers = async ( + serviceName: string, + params: UserOrderParamsType, +) => { + const { data } = await v6.post(`/license/office/${serviceName}/user`, { + params, + usageLocation: params.usageLocation.toLowerCase(), + }); + return data; +}; + // PUT export const putOfficeUserDetail = async ( diff --git a/packages/manager/apps/web-office/src/api/users/key.ts b/packages/manager/apps/web-office/src/api/users/key.ts index 1bc58ef950d6..f86b067de824 100644 --- a/packages/manager/apps/web-office/src/api/users/key.ts +++ b/packages/manager/apps/web-office/src/api/users/key.ts @@ -10,3 +10,11 @@ export const getOfficeUserDetailQueryKey = ( serviceName: string, activationEmail: string, ) => ['get', 'license', 'office', serviceName, 'user', activationEmail]; + +export const getOfficeUserDomainQueryKey = (serviceName: string) => [ + 'get', + 'license', + 'office', + serviceName, + 'domain', +]; diff --git a/packages/manager/apps/web-office/src/pages/dashboard/index.tsx b/packages/manager/apps/web-office/src/pages/dashboard/index.tsx index 8c716e20e3a2..f923d6898208 100644 --- a/packages/manager/apps/web-office/src/pages/dashboard/index.tsx +++ b/packages/manager/apps/web-office/src/pages/dashboard/index.tsx @@ -66,7 +66,6 @@ export default function DashboardPage() { title: serviceName, headerButton: , }; - return ( } diff --git a/packages/manager/apps/web-office/src/pages/dashboard/users/ModalOrderLicenses.component.tsx b/packages/manager/apps/web-office/src/pages/dashboard/users/ModalOrderLicenses.component.tsx index 833432d93621..f025099ff289 100644 --- a/packages/manager/apps/web-office/src/pages/dashboard/users/ModalOrderLicenses.component.tsx +++ b/packages/manager/apps/web-office/src/pages/dashboard/users/ModalOrderLicenses.component.tsx @@ -139,6 +139,7 @@ export default function ModalOrderLicenses() { } max={300} min={1} + className="ml-10" /> )} /> diff --git a/packages/manager/apps/web-office/src/pages/dashboard/users/ModalOrderUsers.component.tsx b/packages/manager/apps/web-office/src/pages/dashboard/users/ModalOrderUsers.component.tsx index 989e1fab23b5..0709e198b8f6 100644 --- a/packages/manager/apps/web-office/src/pages/dashboard/users/ModalOrderUsers.component.tsx +++ b/packages/manager/apps/web-office/src/pages/dashboard/users/ModalOrderUsers.component.tsx @@ -1,6 +1,276 @@ import React from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { + OdsFormField, + OdsInput, + OdsMessage, + OdsSelect, + OdsText, +} from '@ovhcloud/ods-components/react'; +import { + ODS_BUTTON_VARIANT, + ODS_INPUT_TYPE, + ODS_TEXT_PRESET, +} from '@ovhcloud/ods-components'; +import { useMutation, useQuery } from '@tanstack/react-query'; +import { Controller, SubmitHandler, useForm } from 'react-hook-form'; +import { + IntervalUnitType, + OvhSubsidiary, + Price, + useNotifications, +} from '@ovh-ux/manager-react-components'; +import { ShellContext } from '@ovh-ux/manager-react-shell-client'; +import { ApiError } from '@ovh-ux/manager-core-api'; import Modal from '@/components/Modals/Modal'; +import { useGenerateUrl } from '@/hooks'; +import { + getOfficeUserDomainQueryKey, + getOfficeUsersDomain, + postOrderUsers, +} from '@/api/users'; +import { getOfficePrice, getOfficePriceQueryKey } from '@/api/price'; +import { OfficeUserEnum } from '@/api/order/type'; +import { UserOrderParamsType } from '@/api/api.type'; export default function ModalOrderUsers() { - return ; + const { t } = useTranslation(['dashboard/users/order-users', 'common']); + const navigate = useNavigate(); + const goBackUrl = useGenerateUrl('..', 'path'); + const onClose = () => navigate(goBackUrl); + const { serviceName } = useParams(); + const { environment } = React.useContext(ShellContext); + const { ovhSubsidiary } = environment.getUser(); + const userLocale = environment.getUserLocale(); + const { addError, addSuccess } = useNotifications(); + + const { data: domain } = useQuery({ + queryKey: [getOfficeUserDomainQueryKey(serviceName)], + queryFn: () => getOfficeUsersDomain(serviceName), + }); + + const offerOptions = [ + { label: 'Office Business', value: OfficeUserEnum.OFFICE_365_BUSINESS }, + { label: 'Office Pro Plus', value: OfficeUserEnum.OFFICE_365_PRO_PLUS }, + ]; + + const { + handleSubmit, + control, + watch, + formState: { isValid }, + } = useForm({ + defaultValues: { + licence: '', + login: '', + domain, + firstName: '', + lastName: '', + usageLocation: ovhSubsidiary, + }, + mode: 'onChange', + }); + + const selectedlicenseType = watch('licence'); + + const { data: officePrice } = useQuery({ + queryKey: [getOfficePriceQueryKey(selectedlicenseType)], + queryFn: async () => { + const price = await getOfficePrice({ officeName: selectedlicenseType }); + return { + ...price, + value: price?.value ? Math.round(price.value * 1e8) : null, + }; + }, + enabled: !!selectedlicenseType, + }); + + const { mutate: orderUsers } = useMutation({ + mutationFn: (params: UserOrderParamsType) => + postOrderUsers(serviceName, params), + onSuccess: () => { + addSuccess( + {t('dashboard_users_order_users_message_success')}, + true, + ); + }, + onError: (error: ApiError) => { + addError( + + {t('dashboard_users_order_users_message_error', { + error: error?.response?.data?.message, + })} + , + true, + ); + }, + onSettled: () => { + onClose(); + }, + }); + + const handleSaveClick: SubmitHandler<{ + licence: string; + login: string; + domain: string; + firstName: string; + lastName: string; + usageLocation: string; + }> = ({ firstName, lastName, login, licence }) => { + const selectedOffer = offerOptions.find( + (option) => option.value === licence, + ); + orderUsers({ + firstName, + lastName, + login, + usageLocation: ovhSubsidiary as OvhSubsidiary, + domain, + licence: selectedOffer.value, + }); + }; + const handleCancelClick = () => { + onClose(); + }; + return ( + +
+ ( + + + field.onChange(event.target.value)} + > + + )} + /> + ( + + + field.onChange(event.target.value)} + > + + )} + /> + + + +
+ ( + field.onChange(event.target.value)} + > + )} + /> + ( + + )} + /> +
+
+ +
+ + + ( + field.onChange(event.target.value)} + > + {offerOptions.map((option) => ( + + ))} + + )} + /> + +
+ {officePrice?.value && ( + + + + + )} + + {t('dashboard_users_order_users_message')} + + + {t('common:common_field_label_mandatory')} + + +
+ ); } diff --git a/packages/manager/apps/web-office/src/pages/dashboard/users/Users.tsx b/packages/manager/apps/web-office/src/pages/dashboard/users/Users.tsx index 4843768208c8..5eae1fe4c9cc 100644 --- a/packages/manager/apps/web-office/src/pages/dashboard/users/Users.tsx +++ b/packages/manager/apps/web-office/src/pages/dashboard/users/Users.tsx @@ -1,7 +1,11 @@ import React from 'react'; import { Outlet, useNavigate } from 'react-router-dom'; import { Trans, useTranslation } from 'react-i18next'; -import { Datagrid, DatagridColumn } from '@ovh-ux/manager-react-components'; +import { + Datagrid, + DatagridColumn, + ManagerButton, +} from '@ovh-ux/manager-react-components'; import { ODS_BUTTON_VARIANT, ODS_ICON_NAME, @@ -23,6 +27,7 @@ import { import { BadgeStatus } from '@/components/BadgeStatus'; import { UserStateEnum } from '@/api/api.type'; import ActionButtonUsers from './ActionButtonUsers.component'; +import { IAM_ACTIONS } from '@/utils/iamAction.constants'; export default function Users() { const { t } = useTranslation(['dashboard/users', 'common']); @@ -141,20 +146,27 @@ export default function Users() { ) : ( <> - + {!dataLicenceDetail?.serviceType ? ( + + ) : ( + + )} + ({ ...column, diff --git a/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/ModalOrderLicenses.component.spec.tsx b/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/ModalOrderLicenses.component.spec.tsx index 7c71cab0ae94..8ed992606a8d 100644 --- a/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/ModalOrderLicenses.component.spec.tsx +++ b/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/ModalOrderLicenses.component.spec.tsx @@ -8,14 +8,6 @@ import dashboardUsersOrderLicensesTranslation from '@/public/translations/dashbo import commonTranslation from '@/public/translations/common/Messages_fr_FR.json'; describe('modal order license', () => { - it('should render page correctly', () => { - const { getByTestId } = render(); - expect(getByTestId('modal')).toBeInTheDocument(); - expect(getByTestId('modal')).toHaveTextContent( - commonTranslation.users_order_licenses, - ); - }); - it('should render the submit button', () => { const { getByTestId } = render(); diff --git a/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/ModalOrderUsers.component.spec.tsx b/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/ModalOrderUsers.component.spec.tsx new file mode 100644 index 000000000000..f38a0ade788f --- /dev/null +++ b/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/ModalOrderUsers.component.spec.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import '@testing-library/jest-dom'; +import { useParams } from 'react-router-dom'; +import { describe, expect, it, vi } from 'vitest'; +import ModalOrderUsers from '../ModalOrderUsers.component'; +import commonTranslation from '@/public/translations/common/Messages_fr_FR.json'; + +import { fireEvent, render, act } from '@/utils/test.provider'; +import { postOrderUsers } from '@/api/users'; + +const hoistedMock = vi.hoisted(() => ({ + useContext: vi.fn(), +})); + +describe('ModalOrderUsers Component', () => { + it('should render the submit button', () => { + const { getByTestId } = render(); + + expect(getByTestId('confirm-btn')).toBeInTheDocument(); + expect(getByTestId('confirm-btn')).toHaveAttribute( + 'label', + commonTranslation.cta_confirm, + ); + }); + it('should enable save button and make API call on valid input', async () => { + vi.mocked(useParams).mockReturnValue({ + serviceName: 'test-service', + }); + + hoistedMock.useContext.mockReturnValue({ + environment: { + user: { + ovhSubsidiary: 'FR', + }, + }, + }); + + const { getByTestId } = render(); + const firstNameInput = getByTestId('input-firstName'); + const lastNameInput = getByTestId('input-lastName'); + const loginInput = getByTestId('input-login'); + const domainInput = getByTestId('input-domain'); + const licenceInput = getByTestId('input-licence'); + const saveButton = getByTestId('confirm-btn'); + + expect(firstNameInput).toBeInTheDocument(); + expect(lastNameInput).toBeInTheDocument(); + expect(loginInput).toBeInTheDocument(); + expect(domainInput).toBeInTheDocument(); + expect(licenceInput).toBeInTheDocument(); + + await act(() => { + fireEvent.change(licenceInput, { target: { value: 'licenceInput' } }); + }); + await act(() => { + fireEvent.input(firstNameInput, { + target: { value: 'John' }, + }); + firstNameInput.odsChange.emit({ + name: 'firstName', + value: 'test@ovhcloud.com', + }); + }); + await act(() => { + fireEvent.input(lastNameInput, { target: { value: 'Doe' } }); + lastNameInput.odsChange.emit({ name: 'lastName', value: 'Doe' }); + }); + await act(() => { + fireEvent.input(loginInput, { target: { value: 'johndoe' } }); + loginInput.odsChange.emit({ name: 'login', value: 'johndoe' }); + }); + await act(() => { + fireEvent.input(domainInput, { + target: { value: 'test.office.ovh.com' }, + }); + domainInput.odsChange.emit({ + name: 'domain', + value: 'test.office.ovh.com', + }); + }); + await act(() => { + fireEvent.input(licenceInput, { target: { value: 'officeBusiness' } }); + licenceInput.odsChange.emit({ + name: 'licence', + value: 'officeBusiness', + }); + }); + + await act(() => { + fireEvent.click(saveButton); + }); + + expect(postOrderUsers).toHaveBeenCalledOnce(); + }); +}); diff --git a/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/Users.spec.tsx b/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/Users.spec.tsx index 29e7ff6a99a9..ad26a4d58356 100644 --- a/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/Users.spec.tsx +++ b/packages/manager/apps/web-office/src/pages/dashboard/users/__test__/Users.spec.tsx @@ -35,7 +35,7 @@ describe('Users page', () => { }); const { getByTestId } = render(); - const orderButton = getByTestId('user-or-licenses-order-button'); + const orderButton = getByTestId('users-order-button'); expect(orderButton).toHaveAttribute('label', commonTranslation.order_users); }); @@ -50,7 +50,7 @@ describe('Users page', () => { }); const { getByTestId } = render(); - const orderButton = getByTestId('user-or-licenses-order-button'); + const orderButton = getByTestId('licenses-order-button'); expect(orderButton).toHaveAttribute( 'label', commonTranslation.order_licenses, diff --git a/packages/manager/apps/web-office/src/utils/test.provider.tsx b/packages/manager/apps/web-office/src/utils/test.provider.tsx index 0bd6cac1722e..76f19e270344 100644 --- a/packages/manager/apps/web-office/src/utils/test.provider.tsx +++ b/packages/manager/apps/web-office/src/utils/test.provider.tsx @@ -12,6 +12,8 @@ import userEvent from '@testing-library/user-event'; import dashboardUsersTranslation from '@/public/translations/dashboard/users/Messages_fr_FR.json'; import licensesTranslation from '@/public/translations/licenses/Messages_fr_FR.json'; import dashboardUsersOrderLicensesTranslation from '@/public/translations/dashboard/users/order-licenses/Messages_fr_FR.json'; +import dashboardUsersOrderUsersTranslation from '@/public/translations/dashboard/users/order-users/Messages_fr_FR.json'; + import onboardingTranslation from '@/public/translations/onboarding/Messages_fr_FR.json'; import commonTranslation from '@/public/translations/common/Messages_fr_FR.json'; import '@testing-library/jest-dom'; @@ -25,6 +27,7 @@ i18n.use(initReactI18next).init({ licenses: licensesTranslation, 'dashboard/users': dashboardUsersTranslation, 'dashboard/users/order-licenses': dashboardUsersOrderLicensesTranslation, + 'dashboard/users/order-users': dashboardUsersOrderUsersTranslation, onboarding: onboardingTranslation, common: commonTranslation, }, diff --git a/packages/manager/apps/web-office/src/utils/test.setup.tsx b/packages/manager/apps/web-office/src/utils/test.setup.tsx index 52132dcdf22a..9f9950ff73b3 100644 --- a/packages/manager/apps/web-office/src/utils/test.setup.tsx +++ b/packages/manager/apps/web-office/src/utils/test.setup.tsx @@ -7,6 +7,8 @@ import { pendingTask, tenantPendingTask, orderCatalogMock, + priceMock, + userDomainMock, } from '@/api/_mock_'; const mocksAxios = vi.hoisted(() => ({ @@ -76,15 +78,17 @@ vi.mock('@/api/license', async (importActual) => { vi.mock('@/api/users', async (importActual) => { return { ...(await importActual()), + deleteOfficeUser: vi.fn(() => Promise.resolve(tenantPendingTask)), getOfficeUsers: vi.fn(() => Promise.resolve(usersMock)), getOfficeUserDetail: vi.fn((_, activationEmail) => Promise.resolve( usersMock.find((user) => user.activationEmail === activationEmail), ), ), - deleteOfficeUser: vi.fn(() => Promise.resolve(tenantPendingTask)), - putOfficeUserDetail: vi.fn(() => Promise.resolve(null)), + getOfficeUsersDomain: vi.fn(() => Promise.resolve(userDomainMock)), postUsersPassword: vi.fn(() => Promise.resolve(null)), + putOfficeUserDetail: vi.fn(() => Promise.resolve(null)), + postOrderUsers: vi.fn(() => Promise.resolve(null)), }; }); vi.mock('@/api/order', async (importActual) => { @@ -96,6 +100,13 @@ vi.mock('@/api/order', async (importActual) => { }; }); +vi.mock('@/api/price', async (importActual) => { + return { + ...(await importActual()), + getOfficePrice: vi.fn(() => Promise.resolve(priceMock)), + }; +}); + vi.mock('@ovh-ux/manager-module-order', () => ({ getExpressOrderURL: vi.fn(), })); diff --git a/packages/manager/apps/web-office/tsconfig.json b/packages/manager/apps/web-office/tsconfig.json index 478190f4b45e..f135b95b2293 100644 --- a/packages/manager/apps/web-office/tsconfig.json +++ b/packages/manager/apps/web-office/tsconfig.json @@ -16,7 +16,7 @@ "declaration": true, "resolveJsonModule": true, "allowJs": true, - "jsx": "react", + "jsx": "react-jsx", "baseUrl": ".", "paths": { "@/public/*": ["./public/*"], diff --git a/yarn.lock b/yarn.lock index 71fdbcd433df..b12184149fef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5921,15 +5921,6 @@ resolved "https://registry.yarnpkg.com/@orchidjs/unicode-variants/-/unicode-variants-1.1.2.tgz#1fd71791a67fdd1591ebe0dcaadd3964537a824e" integrity sha512-5DobW1CHgnBROOEpFlEXytED5OosEWESFvg/VYmH0143oXcijYTprRYJTs+55HzGM4IqxiLFSuqEzu9mPNwVsA== -"@ovh-ux/manager-core-api@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@ovh-ux/manager-core-api/-/manager-core-api-0.9.0.tgz#a0e4a556e01583b63027c73c5b358f96d3016230" - integrity sha512-5Pok3Oj4zlWEIdbEAM6H3WNitRLBP+U6dvgEYWm8nDj+6gwxMgceb5mBuZvPsph4eoNE15t9EJDRRr2C3lQInA== - dependencies: - "@ovh-ux/manager-core-sso" "^0.3.0" - "@ovh-ux/request-tagger" "^0.4.0" - axios "^1.1.2" - "@ovh-ux/manager-pci-common@^0.14.4": version "0.14.4" resolved "https://registry.yarnpkg.com/@ovh-ux/manager-pci-common/-/manager-pci-common-0.14.4.tgz#1de97298b0041e42829e4390423986daabcb442b"