diff --git a/packages/manager/apps/key-management-service/src/mocks/credentials/credentials.handler.ts b/packages/manager/apps/key-management-service/src/mocks/credentials/credentials.handler.ts index 1e5eb78dfdb8..fa4ecc3b582c 100644 --- a/packages/manager/apps/key-management-service/src/mocks/credentials/credentials.handler.ts +++ b/packages/manager/apps/key-management-service/src/mocks/credentials/credentials.handler.ts @@ -8,7 +8,7 @@ export type GetCredentialsMockParams = { }; const findCredentialByID = (params: PathParams) => - credentialMock.find(({ id }) => id === params.id); + credentialMock.find(({ id }) => id === params.credentialId); export const getCredentialsMock = ({ isCredentialKO, @@ -23,7 +23,7 @@ export const getCredentialsMock = ({ message: 'credentials error', }, } - : (_: unknown, params: PathParams) => findCredentialByID(params), + : credentialMock.slice(0, nbCredential), status: isCredentialKO ? 500 : 200, api: 'v2', }, @@ -31,8 +31,27 @@ export const getCredentialsMock = ({ url: '/okms/resource/:okmsId/credential/:credentialId', response: isCredentialKO ? { message: 'credential error' } - : credentialMock.slice(0, nbCredential), + : (_: unknown, params: PathParams) => findCredentialByID(params), status: isCredentialKO ? 500 : 200, api: 'v2', }, ]; + +export type DeleteCredentialsMockParams = { + isCredentialDeleteKO?: boolean; +}; + +export const deleteCredentialMock = ({ + isCredentialDeleteKO, +}: DeleteCredentialsMockParams): Handler[] => [ + { + url: '/okms/resource/:okmsId/credential/:credentialId', + method: 'delete', + response: { + status: isCredentialDeleteKO ? 500 : 200, + data: {}, + }, + status: isCredentialDeleteKO ? 500 : 200, + api: 'v2', + }, +]; diff --git a/packages/manager/apps/key-management-service/src/pages/credential/Credential.page.spec.tsx b/packages/manager/apps/key-management-service/src/pages/credential/Credential.page.spec.tsx new file mode 100644 index 000000000000..a426cb02374d --- /dev/null +++ b/packages/manager/apps/key-management-service/src/pages/credential/Credential.page.spec.tsx @@ -0,0 +1,82 @@ +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { + WAIT_FOR_DEFAULT_OPTIONS, + assertTextVisibility, + getOdsButtonByLabel, +} from '@ovh-ux/manager-core-test-utils'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import { labels } from '@/utils/tests/init.i18n'; +import { okmsMock } from '@/mocks/kms/okms.mock'; +import { credentialMock } from '@/mocks/credentials/credentials.mock'; +import { FEATURES } from '@/utils/feature-availability/feature-availability.constants'; + +const mockPageUrl = `/${okmsMock[0].id}/credentials/${credentialMock[0].id}`; + +describe('Credential dashboard test suite', () => { + it('should display an error if the API is KO', async () => { + await renderTestApp(mockPageUrl, { isCredentialKO: true }); + + await waitFor( + () => expect(screen.getByAltText('OOPS')).toBeInTheDocument(), + WAIT_FOR_DEFAULT_OPTIONS, + ); + }); + + it('should display the credential dashboard page', async () => { + await renderTestApp(mockPageUrl, { feature: FEATURES.LOGS }); + + await waitFor(() => { + expect( + screen.getByText( + labels.credentials.key_management_service_credential_dashboard_name, + ), + ).toBeVisible(); + }, WAIT_FOR_DEFAULT_OPTIONS); + }); + + it(`should navigate back to the credentials list on click on ${labels.credentials.key_management_service_credential_dashboard_backlink}`, async () => { + const user = userEvent.setup(); + const { container } = await renderTestApp(mockPageUrl); + + const backLink = await getOdsButtonByLabel({ + container, + label: + labels.credentials.key_management_service_credential_dashboard_backlink, + isLink: true, + }); + + user.click(backLink); + + await assertTextVisibility( + labels.credentials.key_management_service_credential_headline, + ); + }); + + it(`should navigate to the identity page on click on ${labels.credentials.key_management_service_credential_identities} `, async () => { + const identitiesTabLabel = + labels.credentials + .key_management_service_credential_dashboard_tab_identities; + const userTitleLabel = + labels.credentials + .key_management_service_credential_identities_user_title; + const userGroupsTitleLabel = + labels.credentials + .key_management_service_credential_identities_usergroup_title; + + const user = userEvent.setup(); + await renderTestApp(mockPageUrl); + + await waitFor( + () => expect(screen.getByText(identitiesTabLabel)).toBeEnabled(), + WAIT_FOR_DEFAULT_OPTIONS, + ); + + user.click(screen.getByText(identitiesTabLabel)); + + await waitFor(() => { + expect(screen.getByText(userTitleLabel)).toBeVisible(); + expect(screen.getByText(userGroupsTitleLabel)).toBeVisible(); + }, WAIT_FOR_DEFAULT_OPTIONS); + }); +}); diff --git a/packages/manager/apps/key-management-service/src/pages/credential/generalInformations/delete/DeleteCredentialModal.page.spec.tsx b/packages/manager/apps/key-management-service/src/pages/credential/generalInformations/delete/DeleteCredentialModal.page.spec.tsx new file mode 100644 index 000000000000..084b289fa589 --- /dev/null +++ b/packages/manager/apps/key-management-service/src/pages/credential/generalInformations/delete/DeleteCredentialModal.page.spec.tsx @@ -0,0 +1,126 @@ +import { vi } from 'vitest'; +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { + getOdsButtonByLabel, + changeOdsInputValue, + assertOdsModalVisibility, + WAIT_FOR_DEFAULT_OPTIONS, +} from '@ovh-ux/manager-core-test-utils'; +import * as router from 'react-router-dom'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import { okmsMock } from '@/mocks/kms/okms.mock'; +import { credentialMock } from '@/mocks/credentials/credentials.mock'; +import { labels } from '@/utils/tests/init.i18n'; + +const mockCredentialItem = credentialMock[0]; +const mockPageUrl = `/${okmsMock[0].id}/credentials/${mockCredentialItem.id}/delete`; +const mockCredentialListPageUrl = `/${okmsMock[0].id}/credentials`; + +const deleteModalTitleLabel = + labels.credentials.key_management_service_credential_delete_modal_headline; + +describe('Credential delete modal test suite', () => { + const mockNavigate = vi.fn(); + + beforeEach(() => { + mockNavigate.mockReset(); + vi.spyOn(router, 'useNavigate').mockImplementation(() => mockNavigate); + }); + + test('should display the delete modal', async () => { + const { container } = await renderTestApp(mockPageUrl); + + // Check modal is opened + await waitFor(() => { + assertOdsModalVisibility({ container, isVisible: true }); + expect(screen.getByText(deleteModalTitleLabel)).toBeVisible(); + }, WAIT_FOR_DEFAULT_OPTIONS); + }); + + test('should navigate and show a notification after successful deletion', async () => { + const user = userEvent.setup(); + const { container } = await renderTestApp(mockPageUrl); + + // Wait for modal to open + await waitFor(() => { + expect(screen.getByText(deleteModalTitleLabel)).toBeVisible(); + }, WAIT_FOR_DEFAULT_OPTIONS); + + await changeOdsInputValue({ + inputLabel: + labels.credentials + .key_management_service_credential_delete_modal_input_label, + inputValue: 'TERMINATE', + }); + + const submitButton = await getOdsButtonByLabel({ + container, + label: 'Résilier', // Label from MRC + disabled: false, + }); + + user.click(submitButton); + + // Check navigation + await waitFor(() => { + expect(mockNavigate).toHaveBeenCalledWith(mockCredentialListPageUrl, { + state: { deletingCredentialId: mockCredentialItem.id }, + }); + }, WAIT_FOR_DEFAULT_OPTIONS); + + // Check notification + await waitFor(() => { + expect( + screen.getByText( + labels.credentials.key_management_service_credential_delete_success, + ), + ).toBeVisible(); + }); + }); + + test('should navigate and show a notification after failed deletion', async () => { + const user = userEvent.setup(); + const { container } = await renderTestApp(mockPageUrl, { + isCredentialDeleteKO: true, + }); + + // Wait for modal to open + await waitFor(() => { + expect(screen.getByText(deleteModalTitleLabel)).toBeVisible(); + }, WAIT_FOR_DEFAULT_OPTIONS); + + await changeOdsInputValue({ + inputLabel: + labels.credentials + .key_management_service_credential_delete_modal_input_label, + inputValue: 'TERMINATE', + }); + + const submitButton = await getOdsButtonByLabel({ + container, + label: 'Résilier', // Label from MRC + timeout: WAIT_FOR_DEFAULT_OPTIONS.timeout, + disabled: false, + }); + + user.click(submitButton); + + // Check navigation + await waitFor( + () => expect(mockNavigate).toHaveBeenCalledWith('..'), + WAIT_FOR_DEFAULT_OPTIONS, + ); + + // Check notification + await waitFor(() => { + const notificationLabel = labels.credentials.key_management_service_credential_delete_error.replace( + ' {{error}}', + '', + ); + expect( + screen.getByText((content) => content.includes(notificationLabel)), + ).toBeVisible(); + }); + }); +}); diff --git a/packages/manager/apps/key-management-service/src/pages/credential/generalInformations/generalInformations.page.spec.tsx b/packages/manager/apps/key-management-service/src/pages/credential/generalInformations/generalInformations.page.spec.tsx new file mode 100644 index 000000000000..d03dc1d2b754 --- /dev/null +++ b/packages/manager/apps/key-management-service/src/pages/credential/generalInformations/generalInformations.page.spec.tsx @@ -0,0 +1,76 @@ +import { screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { + getOdsButtonByLabel, + assertOdsModalVisibility, + WAIT_FOR_DEFAULT_OPTIONS, +} from '@ovh-ux/manager-core-test-utils'; +import { renderTestApp } from '@/utils/tests/renderTestApp'; +import { okmsMock } from '@/mocks/kms/okms.mock'; +import { credentialMock } from '@/mocks/credentials/credentials.mock'; +import { labels } from '@/utils/tests/init.i18n'; + +const mockCredentialItem = credentialMock[0]; +const mockPageUrl = `/${okmsMock[0].id}/credentials/${mockCredentialItem.id}`; + +describe('Credential general informations test suite', () => { + test('should display the credentials details', async () => { + const { container } = await renderTestApp(mockPageUrl); + + const titleLabel = + labels.credentials + .key_management_service_credential_dashboard_tile_general_informations; + + await waitFor(() => { + expect(screen.getByText(titleLabel)).toBeVisible(); + expect(screen.getAllByText(mockCredentialItem.name)[0]).toBeVisible(); + expect( + screen.getAllByText(mockCredentialItem.description)[0], + ).toBeVisible(); + + const clipboardElement = container.querySelector( + `[value="${mockCredentialItem.id}"]`, + ); + expect(clipboardElement).toBeVisible(); + }, WAIT_FOR_DEFAULT_OPTIONS); + }); + + test('should navigate to the delete modal on click on delete button', async () => { + const user = userEvent.setup(); + const { container } = await renderTestApp(mockPageUrl); + + const deleteButtonLabel = + labels.credentials.key_management_service_credential_delete; + const deleteModalTitleLabel = + labels.credentials + .key_management_service_credential_delete_modal_headline; + + // Check modal is closed + await waitFor(async () => { + assertOdsModalVisibility({ container, isVisible: false }); + }, WAIT_FOR_DEFAULT_OPTIONS); + + // Wait for the delete button to be enabled by iam rights + await waitFor(async () => { + await getOdsButtonByLabel({ + container, + label: deleteButtonLabel, + disabled: false, + }); + }, WAIT_FOR_DEFAULT_OPTIONS); + + // Click button + const deleteButton = await getOdsButtonByLabel({ + container, + label: deleteButtonLabel, + disabled: false, + }); + user.click(deleteButton); + + // Check modal is opened + await waitFor(() => { + assertOdsModalVisibility({ container, isVisible: true }); + expect(screen.getByText(deleteModalTitleLabel)).toBeVisible(); + }, WAIT_FOR_DEFAULT_OPTIONS); + }); +}); 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 d83786c14be6..a3a4ad797fa1 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 @@ -30,6 +30,8 @@ import { import { getCredentialsMock, GetCredentialsMockParams, + deleteCredentialMock, + DeleteCredentialsMockParams, } from '@/mocks/credentials/credentials.handler'; import { kmsServicesMock } from '@/mocks/services/services.mock'; import { @@ -57,7 +59,8 @@ export const renderTestApp = async ( GetFeatureAvailabilityMocksParams & GetCatalogKmsMocksParams & GetReferenceMockParams & - GetIamAuthorizationMockParams = {}, + GetIamAuthorizationMockParams & + DeleteCredentialsMockParams = {}, ) => { global.server?.resetHandlers( ...toMswHandlers([ @@ -70,6 +73,7 @@ export const renderTestApp = async ( ...getFeatureAvailabilityMocks(mockParams), ...getCatalogKmsMocks(mockParams), ...getReferenceMock(mockParams), + ...deleteCredentialMock(mockParams), ]), );