diff --git a/packages/manager/apps/key-management-service/src/mocks/iam/iam.mock.ts b/packages/manager/apps/key-management-service/src/mocks/iam/iam.mock.ts index 4ee21531e347..c97e698b92b2 100644 --- a/packages/manager/apps/key-management-service/src/mocks/iam/iam.mock.ts +++ b/packages/manager/apps/key-management-service/src/mocks/iam/iam.mock.ts @@ -1,6 +1,7 @@ import { IamCheckResponse } from '@ovh-ux/manager-react-components'; import { kmsIamActions } from '@/utils/iam/iam.constants'; import { okmsMock } from '../kms/okms.mock'; +import { serviceKeyMock } from '../serviceKeys/serviceKeys.mock'; export const kmsIamMock: IamCheckResponse[] = [ { @@ -8,4 +9,9 @@ export const kmsIamMock: IamCheckResponse[] = [ authorizedActions: [...Object.values(kmsIamActions)], unauthorizedActions: [], }, + { + urn: serviceKeyMock[0].iam.urn, + authorizedActions: [...Object.values(kmsIamActions)], + unauthorizedActions: [], + }, ]; diff --git a/packages/manager/apps/key-management-service/src/mocks/reference/reference.handler.ts b/packages/manager/apps/key-management-service/src/mocks/reference/reference.handler.ts new file mode 100644 index 000000000000..1304e978570e --- /dev/null +++ b/packages/manager/apps/key-management-service/src/mocks/reference/reference.handler.ts @@ -0,0 +1,27 @@ +import { Handler } from '../../../../../../../playwright-helpers'; +import { referenceServiceKeyMock } from './reference.mock'; + +export type GetReferenceMockParams = { + isReferenceKO?: boolean; +}; + +export const getReferenceMock = ({ + isReferenceKO, +}: GetReferenceMockParams): Handler[] => [ + { + url: '/okms/reference/serviceKey', + response: isReferenceKO + ? { + status: 500, + data: { + message: 'serviceKeys error', + }, + } + : () => { + console.log(referenceServiceKeyMock); + return referenceServiceKeyMock; + }, + status: isReferenceKO ? 500 : 200, + api: 'v2', + }, +]; diff --git a/packages/manager/apps/key-management-service/src/mocks/reference/reference.mock.ts b/packages/manager/apps/key-management-service/src/mocks/reference/reference.mock.ts new file mode 100644 index 000000000000..e5bd18dc34b3 --- /dev/null +++ b/packages/manager/apps/key-management-service/src/mocks/reference/reference.mock.ts @@ -0,0 +1,53 @@ +import { + OkmsKeyTypes, + OkmsServiceKeyOperations, + OkmsServiceKeyTypeOctSize, +} from '@/types/okmsServiceKey.type'; +import OkmsServiceKeyReference, { + OkmsServiceKeyReferenceSize, +} from '@/types/okmsServiceKeyReference.type'; + +export const referenceServiceKeyMock: OkmsServiceKeyReference[] = [ + { + sizes: [ + { value: 128, default: false }, + { value: 192, default: false }, + { value: 256, default: true }, + ] as OkmsServiceKeyReferenceSize[], + type: OkmsKeyTypes.oct, + default: true, + operations: [ + { + value: [ + OkmsServiceKeyOperations.encrypt, + OkmsServiceKeyOperations.decrypt, + ], + default: true, + }, + { + value: [ + OkmsServiceKeyOperations.wrapKey, + OkmsServiceKeyOperations.unwrapKey, + ], + default: false, + }, + ], + curves: [], + }, + { + sizes: [], + type: OkmsKeyTypes.EC, + default: false, + operations: [ + { + value: [OkmsServiceKeyOperations.sign, OkmsServiceKeyOperations.verify], + default: true, + }, + ], + curves: [ + { default: true, value: 'P-256' }, + { default: false, value: 'P-384' }, + { default: false, value: 'P-521' }, + ], + }, +]; diff --git a/packages/manager/apps/key-management-service/src/mocks/serviceKeys/serviceKeys.handler.ts b/packages/manager/apps/key-management-service/src/mocks/serviceKeys/serviceKeys.handler.ts index 549ff1e38c16..571bc6bf9c42 100644 --- a/packages/manager/apps/key-management-service/src/mocks/serviceKeys/serviceKeys.handler.ts +++ b/packages/manager/apps/key-management-service/src/mocks/serviceKeys/serviceKeys.handler.ts @@ -7,8 +7,8 @@ export type GetServiceKeysMockParams = { nbServiceKey?: number; }; -const findOkmsById = (params: PathParams) => - serviceKeyMock.find(({ id }) => id === params.id); +const findServiceKeyById = (params: PathParams) => + serviceKeyMock.find(({ id }) => id === params.serviceKeyId); export const getServiceKeysMock = ({ isServiceKeyKO, @@ -23,7 +23,7 @@ export const getServiceKeysMock = ({ message: 'serviceKeys error', }, } - : (_: unknown, params: PathParams) => findOkmsById(params), + : serviceKeyMock.slice(0, nbServiceKey), status: isServiceKeyKO ? 500 : 200, api: 'v2', }, @@ -31,8 +31,24 @@ export const getServiceKeysMock = ({ url: '/okms/resource/:okmsId/serviceKey/:serviceKeyId', response: isServiceKeyKO ? { message: 'serviceKey error' } - : serviceKeyMock.slice(0, nbServiceKey), + : (_: unknown, params: PathParams) => findServiceKeyById(params), status: isServiceKeyKO ? 500 : 200, api: 'v2', }, + { + url: '/okms/resource/:okmsId/serviceKey/:serviceKeyId', + method: 'put', + response: (_: unknown, params: PathParams) => findServiceKeyById(params), + status: 200, + api: 'v2', + }, + { + url: '/okms/resource/:okmsId/serviceKey', + method: 'post', + response: (_: unknown, params: PathParams) => { + findServiceKeyById(params); + }, + status: 200, + api: 'v2', + }, ]; diff --git a/packages/manager/apps/key-management-service/src/mocks/serviceKeys/serviceKeys.mock.ts b/packages/manager/apps/key-management-service/src/mocks/serviceKeys/serviceKeys.mock.ts index 1cb4f34fdd01..99314a00bb5c 100644 --- a/packages/manager/apps/key-management-service/src/mocks/serviceKeys/serviceKeys.mock.ts +++ b/packages/manager/apps/key-management-service/src/mocks/serviceKeys/serviceKeys.mock.ts @@ -7,6 +7,7 @@ import { export const serviceKeyMock: OkmsAllServiceKeys[] = [ { + name: 'ServiceKeyTest', createdAt: '2024-10-23T15:24:23Z', id: '8f8a75b0-3bde-4b8d-a8c0-928ba2ceb8ed', operations: [ @@ -17,10 +18,26 @@ export const serviceKeyMock: OkmsAllServiceKeys[] = [ type: OkmsKeyTypes.EC, curve: 'P-256', iam: { - id: '8f8a75b0-3bde-4b8d-a8c0-928basvced', + id: '8f8a75b0-3bde-4b8d-a8c0-928ba2ceb8ed', urn: - 'urn:v1:eu:resource:okms:8f8a75b0-b57d-45fc-8d4f-256664DFE/serviceKey/dqd63-5688-409c-234-125e24538f34', + 'urn:v1:eu:resource:okms:7f3a82ac-a8d8-4c2a-ab0c-f6e86ddf6a7c/serviceKey/8f8a75b0-3bde-4b8d-a8c0-928ba2ceb8ed', displayName: 'ServiceKeyTest', }, }, ]; + +export const createdKeyMock: OkmsAllServiceKeys = { + name: 'New Key', + createdAt: '2024-10-23T15:24:23Z', + id: '4575b0-3bde-4b8d-a8c0-928ba2ceb8ed', + operations: [OkmsServiceKeyOperations.sign, OkmsServiceKeyOperations.verify], + state: OkmsServiceKeyState.active, + type: OkmsKeyTypes.EC, + curve: 'P-256', + iam: { + id: '4575b0-3bde-4b8d-a8c0-928ba2ceb8ed', + urn: + 'urn:v1:eu:resource:okms:7f3a82ac-a8d8-4c2a-ab0c-f6e86ddf6a7c/serviceKey/4575b0-3bde-4b8d-a8c0-928ba2ceb8ed', + displayName: 'New Key', + }, +}; diff --git a/packages/manager/apps/key-management-service/src/pages/dashboard/serviceKeyList/ServiceKeyList.page.spec.tsx b/packages/manager/apps/key-management-service/src/pages/dashboard/serviceKeyList/ServiceKeyList.page.spec.tsx new file mode 100644 index 000000000000..8bc2f25af268 --- /dev/null +++ b/packages/manager/apps/key-management-service/src/pages/dashboard/serviceKeyList/ServiceKeyList.page.spec.tsx @@ -0,0 +1,254 @@ +import { act, fireEvent, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import '@testing-library/jest-dom'; +import { labels } from '@/utils/tests/init.i18n'; +import { okmsMock } from '@/mocks/kms/okms.mock'; +import { serviceKeyMock } from '@/mocks/serviceKeys/serviceKeys.mock'; + +describe('Service Key dashboard test suite', () => { + it('should display an error if the API is KO', async () => { + await renderTestApp(`/${okmsMock[0].id}/keys`, { + isServiceKeyKO: true, + }); + + await waitFor( + () => expect(screen.getByAltText('OOPS')).toBeInTheDocument(), + { + timeout: 30_000, + }, + ); + }); + + it('should display the kms keys listing page', async () => { + await renderTestApp(`/${okmsMock[0].id}/keys`); + + await waitFor( + () => + expect( + screen.getByText( + labels.serviceKeys['key_management_service_service-keys_headline'], + ), + ).toBeVisible(), + + { timeout: 30_000 }, + ); + + expect(screen.queryByAltText('OOPS')).not.toBeInTheDocument(); + }); + + it(`should navigate to the service key page creation on click on ${labels.serviceKeys['key_management_service_service-keys_cta_create']} and then create a key `, async () => { + const user = userEvent.setup(); + await renderTestApp(`/${okmsMock[0].id}/keys`); + await waitFor( + () => + expect( + screen.getAllByText( + labels.serviceKeys['key_management_service_service-keys_headline'], + { exact: false }, + ).length, + ).toBeGreaterThan(0), + { timeout: 30_000 }, + ); + await waitFor( + () => + expect( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_create_title' + ], + ), + ).toBeEnabled(), + { + timeout: 30_000, + }, + ); + + await act(() => + user.click( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_create_title' + ], + ), + ), + ); + + await waitFor( + () => + expect( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_create_crypto_field_type_description_oct' + ], + ), + ).toBeVisible(), + { timeout: 30_000 }, + ); + await waitFor( + () => + expect( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_create_crypto_field_usage_description_encrypt_decrypt' + ], + ), + ).toBeVisible(), + { timeout: 30_000 }, + ); + const keyNameInput = screen.getByPlaceholderText( + labels.serviceKeys[ + 'key_management_service_service-keys_create_general_information_field_name_placeholder' + ], + ); + await act(() => { + fireEvent.change(keyNameInput, { target: { value: '' } }); + fireEvent.change(keyNameInput, { + target: { value: 'New Key' }, + }); + }); + await waitFor( + () => + expect( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_create_cta_submit' + ], + ), + ).toBeEnabled(), + { + timeout: 30_000, + }, + ); + + await act(() => + user.click( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_create_cta_submit' + ], + ), + ), + ); + await waitFor( + () => + expect( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_create_success' + ], + ), + ).toBeEnabled(), + { + timeout: 30_000, + }, + ); + }); + + it('should navigate to the service key dashboard page after clicking on a key from the listing', async () => { + await renderTestApp(`/${okmsMock[0].id}/keys`); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.serviceKeys['key_management_service_service-keys_headline'], + { exact: false }, + ).length, + ).toBeGreaterThan(0), + { timeout: 30_000 }, + ); + + await waitFor( + () => + userEvent.click(screen.getByText(serviceKeyMock[0].iam.displayName)), + { + timeout: 30_000, + }, + ); + await waitFor( + () => + expect( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_dashboard_tab_informations' + ], + ), + ).toBeVisible(), + { + timeout: 30_000, + }, + ); + }); + + it('should open the edit dialog, modify the name, and confirm the changes', async () => { + const user = userEvent.setup(); + await renderTestApp(`/${okmsMock[0].id}/keys/${serviceKeyMock[0].id}`); + + await waitFor( + () => + expect( + screen.getAllByText( + labels.serviceKeys[ + 'key_management_service_service-keys_dashboard_tab_informations' + ], + { exact: false }, + ).length, + ).toBeGreaterThan(0), + + { timeout: 30_000 }, + ); + await waitFor( + () => expect(screen.getByTestId('edit-button-modal')).toBeEnabled(), + { + timeout: 30_000, + }, + ); + await act(() => user.click(screen.getByTestId('edit-button-modal'))); + + await waitFor( + () => + expect( + screen.getByText(labels.common.key_management_service_modify), + ).toBeVisible(), + { + timeout: 30_000, + }, + ); + const nameInput = screen.getByLabelText('input-edit-service-key-name'); + await act(() => { + fireEvent.change(nameInput, { target: { value: '' } }); + fireEvent.change(nameInput, { + target: { value: 'Updated Encryption Key' }, + }); + }); + + await waitFor( + () => + expect( + screen.getByText(labels.common.key_management_service_modify), + ).toBeEnabled(), + { + timeout: 30_000, + }, + ); + await act(() => + user.click(screen.getByText(labels.common.key_management_service_modify)), + ); + + await waitFor( + () => { + expect( + screen.getByText( + labels.serviceKeys[ + 'key_management_service_service-keys_update_name_success' + ], + ), + ).toBeInTheDocument(); + }, + { + timeout: 30_000, + }, + ); + }); +}); diff --git a/packages/manager/apps/key-management-service/src/pages/serviceKey/ServiceKey.page.tsx b/packages/manager/apps/key-management-service/src/pages/serviceKey/ServiceKey.page.tsx index 1e531ae4d7c1..9dbd110511ae 100644 --- a/packages/manager/apps/key-management-service/src/pages/serviceKey/ServiceKey.page.tsx +++ b/packages/manager/apps/key-management-service/src/pages/serviceKey/ServiceKey.page.tsx @@ -162,6 +162,8 @@ export default function Key() { color={ODS_THEME_COLOR_INTENT.primary} urn={serviceKey.data.iam.urn} iamActions={[kmsIamActions.serviceKeyUpdate]} + aria-label="edit" + data-testid="edit-button-modal" onClick={() => { trackClick({ location: PageLocation.page, diff --git a/packages/manager/apps/key-management-service/src/types/okmsServiceKeyReference.type.ts b/packages/manager/apps/key-management-service/src/types/okmsServiceKeyReference.type.ts index d82a3371ee9b..802fc5c15767 100644 --- a/packages/manager/apps/key-management-service/src/types/okmsServiceKeyReference.type.ts +++ b/packages/manager/apps/key-management-service/src/types/okmsServiceKeyReference.type.ts @@ -6,12 +6,12 @@ import { OkmsServiceKeyTypeRSASize, } from './okmsServiceKey.type'; -type OkmsServiceKeyReferenceSize = { +export type OkmsServiceKeyReferenceSize = { default: boolean; value: OkmsServiceKeyTypeOctSize & OkmsServiceKeyTypeRSASize; }; -type OkmsServiceKeyReferenceCurve = { +export type OkmsServiceKeyReferenceCurve = { default: boolean; value: OkmsServiceKeyTypeECCurve; }; diff --git a/packages/manager/apps/key-management-service/src/utils/tests/renderTestApp.tsx b/packages/manager/apps/key-management-service/src/utils/tests/renderTestApp.tsx index 2d6041859635..4406a2abf03f 100644 --- a/packages/manager/apps/key-management-service/src/utils/tests/renderTestApp.tsx +++ b/packages/manager/apps/key-management-service/src/utils/tests/renderTestApp.tsx @@ -37,6 +37,10 @@ import { getCatalogKmsMocks, GetCatalogKmsMocksParams, } from '@/mocks/catalog/catalog.handler'; +import { + getReferenceMock, + GetReferenceMockParams, +} from '@/mocks/reference/reference.handler'; let context: ShellContextType; let i18nValue: i18n; @@ -49,6 +53,7 @@ export const renderTestApp = async ( GetServicesMocksParams & GetFeatureAvailabilituMocksParams & GetCatalogKmsMocksParams & + GetReferenceMockParams & GetIamAuthorizationMockParams = {}, ) => { global.server?.resetHandlers( @@ -61,6 +66,7 @@ export const renderTestApp = async ( ...getCredentialsMock(mockParams), ...getFeatureAvailabilityMocks(mockParams), ...getCatalogKmsMocks(mockParams), + ...getReferenceMock(mockParams), ]), );