Skip to content

Commit 08f46cc

Browse files
test(kms): add tests for download public ca buttons
ref: #MANAGER-17309 Signed-off-by: Mathieu Mousnier <[email protected]>
1 parent 05b1800 commit 08f46cc

File tree

4 files changed

+270
-2
lines changed

4 files changed

+270
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import React from 'react';
2+
import { describe, vi, expect, test, beforeEach, afterEach } from 'vitest';
3+
import { render, waitFor } from '@testing-library/react';
4+
import userEvent from '@testing-library/user-event';
5+
import { getOdsButtonByLabel } from '@ovh-ux/manager-core-test-utils';
6+
import {
7+
CertificateType,
8+
DownloadKmsPublicCaLink,
9+
} from './DownloadKmsPublicCaLink';
10+
import * as api from '@/data/api/okms';
11+
import { initiateTextFileDownload } from '@/utils/dom/download';
12+
import {
13+
PUBLIC_CA_FILENAME,
14+
PUBLIC_RSA_CA_FILENAME,
15+
} from './DownloadKmsPublicCaLink.constants';
16+
17+
const addErrorMock = vi.fn();
18+
vi.mock('@ovh-ux/manager-react-components', () => ({
19+
useNotifications: () => ({
20+
addError: addErrorMock,
21+
}),
22+
}));
23+
24+
vi.mock('react-i18next', () => ({
25+
useTranslation: () => ({
26+
t: (translationKey: string) => translationKey,
27+
}),
28+
}));
29+
30+
vi.mock('@/utils/dom/download', () => ({
31+
initiateTextFileDownload: vi.fn(),
32+
}));
33+
34+
const okmsId = 'test-okms-id';
35+
const mockCertificates = {
36+
publicCA:
37+
'-----BEGIN CERTIFICATE-----\nMIIDDummyCertificate\n-----END CERTIFICATE-----',
38+
publicRsaCA:
39+
'-----BEGIN CERTIFICATE-----\nMIIDummyRsaCertificate\n-----END CERTIFICATE-----',
40+
};
41+
42+
const renderComponentAndGetLink = async ({
43+
type,
44+
label,
45+
}: {
46+
type: CertificateType;
47+
label: string;
48+
}) => {
49+
const { container } = render(
50+
<DownloadKmsPublicCaLink okmsId={okmsId} type={type} />,
51+
);
52+
53+
const downloadLink = await getOdsButtonByLabel({
54+
container,
55+
label,
56+
isLink: true,
57+
});
58+
59+
return { downloadLink };
60+
};
61+
62+
describe('DownloadKmsPublicCaLink component tests suite', () => {
63+
beforeEach(() => {
64+
vi.spyOn(api, 'getOkmsPublicCa').mockResolvedValue(mockCertificates);
65+
});
66+
67+
afterEach(() => {
68+
vi.clearAllMocks();
69+
});
70+
71+
test('should render publicCa download link correctly', async () => {
72+
const { downloadLink } = await renderComponentAndGetLink({
73+
type: 'publicCa',
74+
label: 'key_management_service_dashboard_button_label_download_ca',
75+
});
76+
expect(downloadLink).toBeInTheDocument();
77+
});
78+
79+
test('should render publicRsaCa download link correctly', async () => {
80+
const { downloadLink } = await renderComponentAndGetLink({
81+
type: 'publicRsaCa',
82+
label: 'key_management_service_dashboard_button_label_download_rsa_ca',
83+
});
84+
expect(downloadLink).toBeInTheDocument();
85+
});
86+
87+
test('should download publicCa certificate when clicked', async () => {
88+
const { downloadLink } = await renderComponentAndGetLink({
89+
type: 'publicCa',
90+
label: 'key_management_service_dashboard_button_label_download_ca',
91+
});
92+
93+
const user = userEvent.setup();
94+
await waitFor(() => user.click(downloadLink));
95+
96+
await waitFor(() => {
97+
expect(api.getOkmsPublicCa).toHaveBeenCalledWith(okmsId);
98+
});
99+
100+
await waitFor(() => {
101+
expect(initiateTextFileDownload).toHaveBeenCalledWith({
102+
text: mockCertificates.publicCA,
103+
filename: PUBLIC_CA_FILENAME,
104+
});
105+
});
106+
});
107+
108+
test('should download publicRsaCa certificate when clicked', async () => {
109+
const { downloadLink } = await renderComponentAndGetLink({
110+
type: 'publicRsaCa',
111+
label: 'key_management_service_dashboard_button_label_download_rsa_ca',
112+
});
113+
114+
const user = userEvent.setup();
115+
await waitFor(() => user.click(downloadLink));
116+
117+
await waitFor(() => {
118+
expect(api.getOkmsPublicCa).toHaveBeenCalledWith(okmsId);
119+
});
120+
121+
await waitFor(() => {
122+
expect(initiateTextFileDownload).toHaveBeenCalledWith({
123+
text: mockCertificates.publicRsaCA,
124+
filename: PUBLIC_RSA_CA_FILENAME,
125+
});
126+
});
127+
});
128+
129+
test('should show error notification when download fails', async () => {
130+
// Override the successful mock with an error
131+
vi.spyOn(api, 'getOkmsPublicCa').mockRejectedValueOnce(
132+
new Error('API Error'),
133+
);
134+
135+
const { downloadLink } = await renderComponentAndGetLink({
136+
type: 'publicCa',
137+
label: 'key_management_service_dashboard_button_label_download_ca',
138+
});
139+
140+
const user = userEvent.setup();
141+
await waitFor(() => user.click(downloadLink));
142+
143+
await waitFor(() => {
144+
// Error notification should be shown
145+
expect(addErrorMock).toHaveBeenCalledWith(
146+
'key_management_service_dashboard_error_download_ca',
147+
);
148+
});
149+
});
150+
});

packages/manager/apps/key-management-service/src/components/layout-helpers/Dashboard/GeneralInformationsTiles/KmipTile.spec.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import { describe, vi } from 'vitest';
33
import { screen, render, waitFor } from '@testing-library/react';
4+
import { getOdsButtonByLabel } from '@ovh-ux/manager-core-test-utils';
45
import { OKMS } from '@/types/okms.type';
56
import KmipTile from './KmipTile';
67
import { KMIP_ENPOINT_LABEL, KMIP_RSA_LABEL } from './KmipTile.constants';
@@ -19,6 +20,12 @@ vi.mock('react-router-dom', async () => {
1920
};
2021
});
2122

23+
vi.mock('react-i18next', () => ({
24+
useTranslation: () => ({
25+
t: (translationKey: string) => translationKey,
26+
}),
27+
}));
28+
2229
describe('KmipTile component tests suite', () => {
2330
const kms: OKMS = {
2431
id: 'id',
@@ -48,6 +55,14 @@ describe('KmipTile component tests suite', () => {
4855

4956
expect(screen.queryByText(KMIP_RSA_LABEL)).not.toBeInTheDocument();
5057
});
58+
59+
const downloadLink = await getOdsButtonByLabel({
60+
container,
61+
label: 'key_management_service_dashboard_button_label_download_ca',
62+
isLink: true,
63+
});
64+
65+
expect(downloadLink).toBeVisible();
5166
});
5267

5368
test('Should display KMIP tile with all kms data', async () => {
@@ -56,11 +71,19 @@ describe('KmipTile component tests suite', () => {
5671

5772
const { container } = renderComponent(kmsData);
5873

59-
await waitFor(() => {
74+
await waitFor(async () => {
6075
expect(screen.getByText(KMIP_RSA_LABEL)).toBeVisible();
6176
expect(
6277
container.querySelector(`ods-clipboard[value="${kmipRsaEndpoint}"]`),
6378
).toBeVisible();
79+
80+
const downloadLinkRsa = await getOdsButtonByLabel({
81+
container,
82+
label: 'key_management_service_dashboard_button_label_download_rsa_ca',
83+
isLink: true,
84+
});
85+
86+
expect(downloadLinkRsa).toBeVisible();
6487
});
6588
});
6689
});

packages/manager/apps/key-management-service/src/components/layout-helpers/Dashboard/GeneralInformationsTiles/RestApiTile.spec.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import { describe, vi } from 'vitest';
33
import { screen, render, waitFor } from '@testing-library/react';
4+
import { getOdsButtonByLabel } from '@ovh-ux/manager-core-test-utils';
45
import { OKMS } from '@/types/okms.type';
56
import RestApiTile from './RestApiTile';
67
import { REST_ENDPOINT_LABEL, SWAGGER_UI_LABEL } from './RestApiTile.constants';
@@ -19,6 +20,12 @@ vi.mock('react-router-dom', async () => {
1920
};
2021
});
2122

23+
vi.mock('react-i18next', () => ({
24+
useTranslation: () => ({
25+
t: (translationKey: string) => translationKey,
26+
}),
27+
}));
28+
2229
describe('RestApiTile component tests suite', () => {
2330
const kms: OKMS = {
2431
id: 'id',
@@ -41,7 +48,7 @@ describe('RestApiTile component tests suite', () => {
4148
test('Should display REST API tile with only all mandatory data', async () => {
4249
const { container } = renderComponent(kms);
4350

44-
await waitFor(() => {
51+
await waitFor(async () => {
4552
expect(screen.getByText(REST_ENDPOINT_LABEL)).toBeVisible();
4653

4754
expect(
@@ -54,6 +61,14 @@ describe('RestApiTile component tests suite', () => {
5461
`ods-link[href="${kms.swaggerEndpoint}"][label="${kms.swaggerEndpoint}"]`,
5562
),
5663
).toBeVisible();
64+
65+
const downloadLink = await getOdsButtonByLabel({
66+
container,
67+
label: 'key_management_service_dashboard_button_label_download_ca',
68+
isLink: true,
69+
});
70+
71+
expect(downloadLink).toBeVisible();
5772
});
5873
});
5974
});
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2+
import { initiateTextFileDownload } from './download';
3+
4+
// Define types for our mocks
5+
interface MockLink extends HTMLAnchorElement {
6+
click: () => void;
7+
}
8+
9+
describe('initiateTextFileDownload', () => {
10+
let createObjectURLMock: ReturnType<typeof vi.fn>;
11+
let appendChildMock: ReturnType<typeof vi.fn>;
12+
let removeChildMock: ReturnType<typeof vi.fn>;
13+
let clickMock: ReturnType<typeof vi.fn>;
14+
15+
beforeEach(() => {
16+
// Mock URL.createObjectURL
17+
createObjectURLMock = vi.fn().mockReturnValue('blob:mock-url');
18+
vi.stubGlobal('URL', { createObjectURL: createObjectURLMock });
19+
20+
// Mock document.body.appendChild and removeChild
21+
appendChildMock = vi.fn();
22+
removeChildMock = vi.fn();
23+
vi.spyOn(document.body, 'appendChild').mockImplementation(appendChildMock);
24+
vi.spyOn(document.body, 'removeChild').mockImplementation(removeChildMock);
25+
26+
// Mock link.click
27+
clickMock = vi.fn();
28+
vi.spyOn(document, 'createElement').mockImplementation(
29+
() =>
30+
(({
31+
click: clickMock,
32+
} as unknown) as HTMLElement),
33+
);
34+
});
35+
36+
afterEach(() => {
37+
vi.restoreAllMocks();
38+
});
39+
40+
it('should create a Blob with the correct content and type', () => {
41+
const filename = 'test.txt';
42+
const text = 'Hello, World!';
43+
44+
const mockBlob = vi.fn().mockImplementation((content, options) => ({
45+
content,
46+
options,
47+
}));
48+
vi.stubGlobal('Blob', mockBlob);
49+
50+
initiateTextFileDownload({ filename, text });
51+
52+
expect(mockBlob).toHaveBeenCalledWith([text], { type: 'text/plain' });
53+
});
54+
55+
it('should create a download link with correct attributes', () => {
56+
const filename = 'test.txt';
57+
const text = 'Hello, World!';
58+
59+
initiateTextFileDownload({ filename, text });
60+
61+
expect(createObjectURLMock).toHaveBeenCalled();
62+
expect(document.createElement).toHaveBeenCalledWith('a');
63+
expect(appendChildMock).toHaveBeenCalled();
64+
expect(clickMock).toHaveBeenCalled();
65+
expect(removeChildMock).toHaveBeenCalled();
66+
67+
const createdLink = appendChildMock.mock.calls[0][0] as MockLink;
68+
expect(createdLink.href).toBe('blob:mock-url');
69+
expect(createdLink.download).toBe(filename);
70+
});
71+
72+
it('should clean up after initiating the download', () => {
73+
const filename = 'test.txt';
74+
const text = 'Hello, World!';
75+
76+
initiateTextFileDownload({ filename, text });
77+
78+
expect(removeChildMock).toHaveBeenCalled();
79+
});
80+
});

0 commit comments

Comments
 (0)