From 5754814527ba2a4f562150110c32e794161b5f93 Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 10:33:49 +0100 Subject: [PATCH 01/10] Add empty state message --- assets/js/pages/ClusterDetails/SBDDetails.jsx | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/assets/js/pages/ClusterDetails/SBDDetails.jsx b/assets/js/pages/ClusterDetails/SBDDetails.jsx index c0a6cadaa5..846ff3ced7 100644 --- a/assets/js/pages/ClusterDetails/SBDDetails.jsx +++ b/assets/js/pages/ClusterDetails/SBDDetails.jsx @@ -10,20 +10,24 @@ const getStatusPill = (status) => ); function SBDDetails({ sbdDevices }) { + const sbdDetailsHeader = 'SBD/Fencing'; + const emptyStateMsg = 'No additional fencing details to display.'; return ( <>
-
-

SBD/Fencing

-
-
-
- {sbdDevices.map(({ device, status }) => ( -
- {getStatusPill(status)} {device} -
- ))} +

{sbdDetailsHeader}

+ {sbdDevices.length > 0 ? ( +
+ {sbdDevices.map(({ device, status }) => ( +
+ {getStatusPill(status)} {device} +
+ ))} +
+ ) : ( + <> {emptyStateMsg} + )} ); } From 04fa7039d6a1a709aeb11428dffbf50f1d6e2eb7 Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 11:50:18 +0100 Subject: [PATCH 02/10] Add SBDDetails test --- .../pages/ClusterDetails/SBDDetails.test.jsx | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 assets/js/pages/ClusterDetails/SBDDetails.test.jsx diff --git a/assets/js/pages/ClusterDetails/SBDDetails.test.jsx b/assets/js/pages/ClusterDetails/SBDDetails.test.jsx new file mode 100644 index 0000000000..eca06e6ab2 --- /dev/null +++ b/assets/js/pages/ClusterDetails/SBDDetails.test.jsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { faker } from '@faker-js/faker'; + +import { capitalize } from 'lodash'; + +import SBDDetails from './SBDDetails'; + +describe('SBDDetails', () => { + it('should show empty message', () => { + const expectedEmptyStateMsg = 'No additional fencing details to display.'; + const sbdDevices = []; + + render(); + expect(screen.getByText(expectedEmptyStateMsg)).toBeInTheDocument(); + }); + + it('should show healthy sbd device', () => { + const expectedDeviceName = faker.system.filePath(); + const expectedHealthStatus = 'healthy'; + const formattedHealthStatus = capitalize(expectedHealthStatus); + + const sbdDevices = [ + { device: expectedDeviceName, status: expectedHealthStatus }, + ]; + const { device, status: healthStatus } = sbdDevices[0]; + + render(); + + expect(screen.getByText(device)).toHaveTextContent(expectedDeviceName); + expect(screen.getByText(formattedHealthStatus)).toHaveTextContent( + capitalize(healthStatus) + ); + }); + + it('should show unhealthy sbd device', () => { + const expectedDeviceName = faker.system.filePath(); + const expectedHealthStatus = 'unhealthy'; + const formattedHealthStatus = capitalize(expectedHealthStatus); + + const sbdDevices = [ + { device: expectedDeviceName, status: expectedHealthStatus }, + ]; + const { device, status: healthStatus } = sbdDevices[0]; + + render(); + + expect(screen.getByText(device)).toHaveTextContent(expectedDeviceName); + expect(screen.getByText(formattedHealthStatus)).toHaveTextContent( + capitalize(healthStatus) + ); + }); +}); From bec3f5dc97a4b491f54b4abf43deef5086fcc24f Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 13:31:04 +0100 Subject: [PATCH 03/10] Refactor test and make usage of factory --- .../pages/ClusterDetails/SBDDetails.test.jsx | 65 +++++++++++-------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/assets/js/pages/ClusterDetails/SBDDetails.test.jsx b/assets/js/pages/ClusterDetails/SBDDetails.test.jsx index eca06e6ab2..acf23f3851 100644 --- a/assets/js/pages/ClusterDetails/SBDDetails.test.jsx +++ b/assets/js/pages/ClusterDetails/SBDDetails.test.jsx @@ -1,14 +1,15 @@ import React from 'react'; import { screen, render } from '@testing-library/react'; import '@testing-library/jest-dom'; -import { faker } from '@faker-js/faker'; + +import { sbdDevicesFactory } from '@lib/test-utils/factories'; import { capitalize } from 'lodash'; import SBDDetails from './SBDDetails'; describe('SBDDetails', () => { - it('should show empty message', () => { + it('should render empty state message when sbd devices are empty', () => { const expectedEmptyStateMsg = 'No additional fencing details to display.'; const sbdDevices = []; @@ -16,39 +17,49 @@ describe('SBDDetails', () => { expect(screen.getByText(expectedEmptyStateMsg)).toBeInTheDocument(); }); - it('should show healthy sbd device', () => { - const expectedDeviceName = faker.system.filePath(); - const expectedHealthStatus = 'healthy'; - const formattedHealthStatus = capitalize(expectedHealthStatus); + it('should render healthy sbd device', () => { + const expectedSBD = sbdDevicesFactory.buildList(1, { status: 'healthy' }); + const [{ device: expectedDeviceName, status: expectedHealthStatus }] = + expectedSBD; + const capitalizedHealthStatus = capitalize(expectedHealthStatus); + render(); + expect(screen.getByText(expectedDeviceName)).toHaveTextContent( + expectedDeviceName + ); + expect(screen.getByText(capitalizedHealthStatus)).toHaveTextContent( + capitalize(expectedHealthStatus) + ); + }); - const sbdDevices = [ - { device: expectedDeviceName, status: expectedHealthStatus }, - ]; - const { device, status: healthStatus } = sbdDevices[0]; + it('should render unhealthy sbd device', () => { + const expectedSBD = sbdDevicesFactory.buildList(1, { status: 'unhealthy' }); + const [{ device: expectedDeviceName, status: expectedHealthStatus }] = + expectedSBD; + const capitalizedHealthStatus = capitalize(expectedHealthStatus); - render(); + render(); - expect(screen.getByText(device)).toHaveTextContent(expectedDeviceName); - expect(screen.getByText(formattedHealthStatus)).toHaveTextContent( - capitalize(healthStatus) + expect(screen.getByText(expectedDeviceName)).toHaveTextContent( + expectedDeviceName + ); + expect(screen.getByText(capitalizedHealthStatus)).toHaveTextContent( + capitalize(expectedHealthStatus) ); }); - it('should show unhealthy sbd device', () => { - const expectedDeviceName = faker.system.filePath(); - const expectedHealthStatus = 'unhealthy'; - const formattedHealthStatus = capitalize(expectedHealthStatus); - - const sbdDevices = [ - { device: expectedDeviceName, status: expectedHealthStatus }, + it('should render multiple devices and their status', () => { + const expectedSBD = [ + sbdDevicesFactory.build({ status: 'unhealthy' }), + sbdDevicesFactory.build({ status: 'healthy' }), ]; - const { device, status: healthStatus } = sbdDevices[0]; - render(); + render(); - expect(screen.getByText(device)).toHaveTextContent(expectedDeviceName); - expect(screen.getByText(formattedHealthStatus)).toHaveTextContent( - capitalize(healthStatus) - ); + expectedSBD.forEach(({ device, status }) => { + expect(screen.getByText(device)).toBeInTheDocument(); + expect( + screen.getByText(status === 'healthy' ? 'Healthy' : 'Unhealthy') + ).toBeInTheDocument(); + }); }); }); From 7815b26094d04f2585490b999f33b68e510be2c2 Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 13:40:17 +0100 Subject: [PATCH 04/10] Add guard if sbdDevices are undefined --- assets/js/pages/ClusterDetails/SBDDetails.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/pages/ClusterDetails/SBDDetails.jsx b/assets/js/pages/ClusterDetails/SBDDetails.jsx index 846ff3ced7..4e7736c26d 100644 --- a/assets/js/pages/ClusterDetails/SBDDetails.jsx +++ b/assets/js/pages/ClusterDetails/SBDDetails.jsx @@ -17,7 +17,7 @@ function SBDDetails({ sbdDevices }) {

{sbdDetailsHeader}

- {sbdDevices.length > 0 ? ( + {sbdDevices?.length > 0 ? (
{sbdDevices.map(({ device, status }) => (
From 4e7132e0863f999c2c262193157ed14152a18341 Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 14:02:41 +0100 Subject: [PATCH 05/10] Add story for SBDDetails --- .../ClusterDetails/SBDDetails.stories.jsx | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 assets/js/pages/ClusterDetails/SBDDetails.stories.jsx diff --git a/assets/js/pages/ClusterDetails/SBDDetails.stories.jsx b/assets/js/pages/ClusterDetails/SBDDetails.stories.jsx new file mode 100644 index 0000000000..adc275f74e --- /dev/null +++ b/assets/js/pages/ClusterDetails/SBDDetails.stories.jsx @@ -0,0 +1,40 @@ +import { sbdDevicesFactory } from '@lib/test-utils/factories'; + +import SBDDetails from './SBDDetails'; + +const healthyDevice = sbdDevicesFactory.build({ status: 'healthy' }); +const unhealthyDevice = sbdDevicesFactory.build({ status: 'unhealthy' }); + +export default { + title: 'Components/SBDDetails', + component: SBDDetails, + argTypes: { + sbdDevices: { + description: 'Array of SBD device objects', + control: 'object', + }, + }, +}; +export const EmptyState = { + args: { + sbdDevices: [], + }, +}; + +export const HealthyDevice = { + args: { + sbdDevices: [healthyDevice], + }, +}; + +export const UnhealthyDevice = { + args: { + sbdDevices: [unhealthyDevice], + }, +}; + +export const MultipleDevices = { + args: { + sbdDevices: [healthyDevice, unhealthyDevice], + }, +}; From edc7ce682887a20d5a3249f28aa96d4b1832435c Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 16:22:57 +0100 Subject: [PATCH 06/10] Remove SBD Details story and add a story to Hana Cluster Details --- .../HanaClusterDetails.stories.jsx | 11 +++++ .../ClusterDetails/SBDDetails.stories.jsx | 40 ------------------- 2 files changed, 11 insertions(+), 40 deletions(-) delete mode 100644 assets/js/pages/ClusterDetails/SBDDetails.stories.jsx diff --git a/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx b/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx index afd83a2ef7..5e8a1b5b4f 100644 --- a/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx +++ b/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx @@ -199,3 +199,14 @@ export const WithUnmanagedResources = { details: unmanagedNodeResources, }, }; + +export const WithNoSBDDevices = { + args: { + ...HanaScaleOut.args, + details: { + ...HanaScaleOut.args.details, + fencing_type: 'Diskless SBD', + sbd_devices: [], + }, + }, +}; diff --git a/assets/js/pages/ClusterDetails/SBDDetails.stories.jsx b/assets/js/pages/ClusterDetails/SBDDetails.stories.jsx deleted file mode 100644 index adc275f74e..0000000000 --- a/assets/js/pages/ClusterDetails/SBDDetails.stories.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import { sbdDevicesFactory } from '@lib/test-utils/factories'; - -import SBDDetails from './SBDDetails'; - -const healthyDevice = sbdDevicesFactory.build({ status: 'healthy' }); -const unhealthyDevice = sbdDevicesFactory.build({ status: 'unhealthy' }); - -export default { - title: 'Components/SBDDetails', - component: SBDDetails, - argTypes: { - sbdDevices: { - description: 'Array of SBD device objects', - control: 'object', - }, - }, -}; -export const EmptyState = { - args: { - sbdDevices: [], - }, -}; - -export const HealthyDevice = { - args: { - sbdDevices: [healthyDevice], - }, -}; - -export const UnhealthyDevice = { - args: { - sbdDevices: [unhealthyDevice], - }, -}; - -export const MultipleDevices = { - args: { - sbdDevices: [healthyDevice, unhealthyDevice], - }, -}; From 95f7c6a5531e482c0428963e058d1cf9c7027ecd Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 16:35:06 +0100 Subject: [PATCH 07/10] Add margin top and rename emptyState variable --- assets/js/pages/ClusterDetails/SBDDetails.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/pages/ClusterDetails/SBDDetails.jsx b/assets/js/pages/ClusterDetails/SBDDetails.jsx index 4e7736c26d..84df962e87 100644 --- a/assets/js/pages/ClusterDetails/SBDDetails.jsx +++ b/assets/js/pages/ClusterDetails/SBDDetails.jsx @@ -11,7 +11,7 @@ const getStatusPill = (status) => function SBDDetails({ sbdDevices }) { const sbdDetailsHeader = 'SBD/Fencing'; - const emptyStateMsg = 'No additional fencing details to display.'; + const emptySBDListText = 'No additional fencing details to display.'; return ( <>
@@ -26,7 +26,7 @@ function SBDDetails({ sbdDevices }) { ))}
) : ( - <> {emptyStateMsg} +
{emptySBDListText}
)} ); From 581fc7f9331b3744530715fce1174bd9ffc03ea4 Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 16:59:30 +0100 Subject: [PATCH 08/10] Use hana for story instead of hana scale out --- assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx b/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx index 5e8a1b5b4f..dc63fea201 100644 --- a/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx +++ b/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx @@ -202,7 +202,7 @@ export const WithUnmanagedResources = { export const WithNoSBDDevices = { args: { - ...HanaScaleOut.args, + ...Hana.args, details: { ...HanaScaleOut.args.details, fencing_type: 'Diskless SBD', From 776044a535f473133ce2500119d10982bcd338d0 Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 17:01:15 +0100 Subject: [PATCH 09/10] Move consts outside of function scope --- assets/js/pages/ClusterDetails/SBDDetails.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/assets/js/pages/ClusterDetails/SBDDetails.jsx b/assets/js/pages/ClusterDetails/SBDDetails.jsx index 84df962e87..feb304a02a 100644 --- a/assets/js/pages/ClusterDetails/SBDDetails.jsx +++ b/assets/js/pages/ClusterDetails/SBDDetails.jsx @@ -2,6 +2,9 @@ import React from 'react'; import Pill from '@common/Pill'; +const sbdDetailsHeader = 'SBD/Fencing'; +const emptySBDListText = 'No additional fencing details to display.'; + const getStatusPill = (status) => status === 'healthy' ? ( Healthy @@ -10,8 +13,6 @@ const getStatusPill = (status) => ); function SBDDetails({ sbdDevices }) { - const sbdDetailsHeader = 'SBD/Fencing'; - const emptySBDListText = 'No additional fencing details to display.'; return ( <>
From 813a9cccece576cf4026bcaaf9ae869fe31ee31a Mon Sep 17 00:00:00 2001 From: EMaksy Date: Wed, 6 Mar 2024 17:16:58 +0100 Subject: [PATCH 10/10] Refactor test and use proper data for story --- .../HanaClusterDetails.stories.jsx | 2 +- .../pages/ClusterDetails/SBDDetails.test.jsx | 42 ++++++------------- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx b/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx index dc63fea201..0c196d941a 100644 --- a/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx +++ b/assets/js/pages/ClusterDetails/HanaClusterDetails.stories.jsx @@ -204,7 +204,7 @@ export const WithNoSBDDevices = { args: { ...Hana.args, details: { - ...HanaScaleOut.args.details, + ...Hana.args.details, fencing_type: 'Diskless SBD', sbd_devices: [], }, diff --git a/assets/js/pages/ClusterDetails/SBDDetails.test.jsx b/assets/js/pages/ClusterDetails/SBDDetails.test.jsx index acf23f3851..11c472441b 100644 --- a/assets/js/pages/ClusterDetails/SBDDetails.test.jsx +++ b/assets/js/pages/ClusterDetails/SBDDetails.test.jsx @@ -14,38 +14,22 @@ describe('SBDDetails', () => { const sbdDevices = []; render(); - expect(screen.getByText(expectedEmptyStateMsg)).toBeInTheDocument(); - }); - it('should render healthy sbd device', () => { - const expectedSBD = sbdDevicesFactory.buildList(1, { status: 'healthy' }); - const [{ device: expectedDeviceName, status: expectedHealthStatus }] = - expectedSBD; - const capitalizedHealthStatus = capitalize(expectedHealthStatus); - render(); - expect(screen.getByText(expectedDeviceName)).toHaveTextContent( - expectedDeviceName - ); - expect(screen.getByText(capitalizedHealthStatus)).toHaveTextContent( - capitalize(expectedHealthStatus) - ); + expect(screen.getByText(expectedEmptyStateMsg)).toBeInTheDocument(); }); - it('should render unhealthy sbd device', () => { - const expectedSBD = sbdDevicesFactory.buildList(1, { status: 'unhealthy' }); - const [{ device: expectedDeviceName, status: expectedHealthStatus }] = - expectedSBD; - const capitalizedHealthStatus = capitalize(expectedHealthStatus); + it.each([{ health: 'unhealthy' }, { health: 'healthy' }])( + 'should render sbd device with specified $health health', + ({ health }) => { + const sbdDevices = sbdDevicesFactory.buildList(1, { status: health }); + const { device: expectedDeviceName } = sbdDevices[0]; - render(); + render(); - expect(screen.getByText(expectedDeviceName)).toHaveTextContent( - expectedDeviceName - ); - expect(screen.getByText(capitalizedHealthStatus)).toHaveTextContent( - capitalize(expectedHealthStatus) - ); - }); + expect(screen.getByText(expectedDeviceName)).toBeTruthy(); + expect(screen.getByText(capitalize(health))).toBeTruthy(); + } + ); it('should render multiple devices and their status', () => { const expectedSBD = [ @@ -57,9 +41,7 @@ describe('SBDDetails', () => { expectedSBD.forEach(({ device, status }) => { expect(screen.getByText(device)).toBeInTheDocument(); - expect( - screen.getByText(status === 'healthy' ? 'Healthy' : 'Unhealthy') - ).toBeInTheDocument(); + expect(screen.getByText(capitalize(status))).toBeInTheDocument(); }); }); });