diff --git a/assets/js/components/ClusterDetails/ClusterDetailsPage.jsx b/assets/js/components/ClusterDetails/ClusterDetailsPage.jsx
index 2e53a01882..c3c948ad2f 100644
--- a/assets/js/components/ClusterDetails/ClusterDetailsPage.jsx
+++ b/assets/js/components/ClusterDetails/ClusterDetailsPage.jsx
@@ -2,17 +2,13 @@ import React, { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
-import {
- getCluster,
- getClusterHosts,
- getClusterHostIDs,
-} from '@state/selectors/cluster';
+import { getCluster, getClusterHosts } from '@state/selectors/cluster';
import {
updateLastExecution,
executionRequested,
} from '@state/actions/lastExecutions';
import { getLastExecution } from '@state/selectors/lastExecutions';
-import ClusterDetails from './ClusterDetails';
+import HanaClusterDetails from './HanaClusterDetails';
import { getClusterName } from '../ClusterLink';
export function ClusterDetailsPage() {
@@ -23,7 +19,6 @@ export function ClusterDetailsPage() {
const dispatch = useDispatch();
const lastExecution = useSelector(getLastExecution(clusterID));
- const hosts = useSelector(getClusterHostIDs(clusterID));
useEffect(() => {
dispatch(updateLastExecution(clusterID));
}, [dispatch]);
@@ -34,33 +29,35 @@ export function ClusterDetailsPage() {
return
Loading...
;
}
- const renderedNodes = cluster.details?.nodes?.map((node) => ({
- ...node,
- ...clusterHosts.find(({ hostname }) => hostname === node.name),
- }));
-
const hasSelectedChecks = cluster.selected_checks.length > 0;
- return (
-
- dispatch(
- executionRequested(clusterID, hostList, checks, navigateFunction)
- )
- }
- navigate={navigate}
- />
- );
+ switch (cluster.type) {
+ case 'hana_scale_up':
+ case 'hana_scale_out':
+ return (
+
+ dispatch(
+ executionRequested(clusterID, hostList, checks, navigateFunction)
+ )
+ }
+ navigate={navigate}
+ />
+ );
+ case 'ascs_ers':
+ return ASCS/ERS
;
+ default:
+ return Unknown cluster type
;
+ }
}
diff --git a/assets/js/components/ClusterDetails/ClusterDetailsPage.test.jsx b/assets/js/components/ClusterDetails/ClusterDetailsPage.test.jsx
new file mode 100644
index 0000000000..6f70c1405f
--- /dev/null
+++ b/assets/js/components/ClusterDetails/ClusterDetailsPage.test.jsx
@@ -0,0 +1,41 @@
+import React from 'react';
+
+import { screen } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import { withState, renderWithRouterMatch } from '@lib/test-utils';
+
+import { clusterFactory } from '@lib/test-utils/factories';
+
+import { ClusterDetailsPage } from './ClusterDetailsPage';
+
+describe('ClusterDetails ClusterDetailsPage component', () => {
+ it.each([
+ { type: 'hana_scale_up', label: 'HANA scale-up' },
+ { type: 'ascs_ers', label: 'ASCS/ERS' },
+ { type: 'unknwon', label: 'Unknown cluster type' },
+ ])(
+ 'should display the $type details based on cluster type',
+ ({ type, label }) => {
+ const cluster = clusterFactory.build({ type });
+ const initialState = {
+ clustersList: { clusters: [cluster] },
+ hostsList: { hosts: [] },
+ lastExecutions: {
+ [cluster.id]: { data: null, loading: false, error: null },
+ },
+ };
+
+ const [statefulClusterDetailsPage, _] = withState(
+ ,
+ initialState
+ );
+
+ renderWithRouterMatch(statefulClusterDetailsPage, {
+ path: 'clusters/:clusterID',
+ route: `/clusters/${cluster.id}`,
+ });
+
+ expect(screen.getByText(label)).toBeInTheDocument();
+ }
+ );
+});
diff --git a/assets/js/components/ClusterDetails/ClusterDetails.jsx b/assets/js/components/ClusterDetails/HanaClusterDetails.jsx
similarity index 95%
rename from assets/js/components/ClusterDetails/ClusterDetails.jsx
rename to assets/js/components/ClusterDetails/HanaClusterDetails.jsx
index db8dcd2189..88e202bb68 100644
--- a/assets/js/components/ClusterDetails/ClusterDetails.jsx
+++ b/assets/js/components/ClusterDetails/HanaClusterDetails.jsx
@@ -54,7 +54,7 @@ const siteDetailsConfig = {
],
};
-function ClusterDetails({
+function HanaClusterDetails({
clusterID,
clusterName,
selectedChecks,
@@ -64,12 +64,16 @@ function ClusterDetails({
cibLastWritten,
sid,
provider,
- clusterNodes,
details,
lastExecution,
onStartExecution,
navigate,
}) {
+ const enrichedNodes = details?.nodes?.map((node) => ({
+ ...node,
+ ...hosts.find(({ hostname }) => hostname === node.name),
+ }));
+
return (
Back to Clusters
@@ -106,7 +110,7 @@ function ClusterDetails({
cssClasses="flex rounded relative ml-0.5 disabled:bg-slate-50 disabled:text-slate-500 disabled:border-gray-400"
clusterId={clusterID}
disabled={!hasSelectedChecks}
- hosts={hosts}
+ hosts={hosts.map(({ id }) => id)}
checks={selectedChecks}
onStartExecution={onStartExecution}
>
@@ -197,7 +201,7 @@ function ClusterDetails({
site === siteName)}
+ data={enrichedNodes.filter(({ site }) => site === siteName)}
/>
))}
@@ -207,4 +211,4 @@ function ClusterDetails({
);
}
-export default ClusterDetails;
+export default HanaClusterDetails;
diff --git a/assets/js/components/ClusterDetails/ClusterDetails.stories.jsx b/assets/js/components/ClusterDetails/HanaClusterDetails.stories.jsx
similarity index 79%
rename from assets/js/components/ClusterDetails/ClusterDetails.stories.jsx
rename to assets/js/components/ClusterDetails/HanaClusterDetails.stories.jsx
index 1455c394ad..74c9134a23 100644
--- a/assets/js/components/ClusterDetails/ClusterDetails.stories.jsx
+++ b/assets/js/components/ClusterDetails/HanaClusterDetails.stories.jsx
@@ -7,7 +7,7 @@ import {
hostFactory,
} from '@lib/test-utils/factories';
-import ClusterDetails from './ClusterDetails';
+import HanaClusterDetails from './HanaClusterDetails';
const {
id: clusterID,
@@ -34,14 +34,9 @@ const hosts = [
hostFactory.build({ hostname: details.nodes[1].name }),
];
-const clusterNodes = details.nodes.map((node) => ({
- ...node,
- ...hosts.find(({ hostname }) => hostname === node.name),
-}));
-
export default {
- title: 'ClusterDetails',
- components: ClusterDetails,
+ title: 'HanaClusterDetails',
+ components: HanaClusterDetails,
decorators: [
(Story) => (
@@ -63,12 +58,11 @@ export const Hana = {
clusterName,
selectedChecks,
hasSelectedChecks: true,
- hosts: hosts.map(({ id: hostID }) => hostID),
+ hosts,
clusterType,
cibLastWritten,
sid,
provider,
- clusterNodes,
details,
lastExecution,
onStartExecution: () => {},
@@ -76,7 +70,7 @@ export const Hana = {
},
render: (args) => (
-
+
),
};
diff --git a/assets/js/components/ClusterLink.jsx b/assets/js/components/ClusterLink.jsx
index 0bed888482..7745df8d33 100644
--- a/assets/js/components/ClusterLink.jsx
+++ b/assets/js/components/ClusterLink.jsx
@@ -3,6 +3,8 @@ import React from 'react';
import { Link } from 'react-router-dom';
import classNames from 'classnames';
+import { CLUSTER_TYPES } from '@lib/model';
+
export const getClusterName = (cluster) => cluster?.name || cluster?.id;
function ClusterLink({ cluster }) {
@@ -11,7 +13,7 @@ function ClusterLink({ cluster }) {
'truncate w-32 inline-block align-middle'
);
- if (cluster?.type === 'hana_scale_up' || cluster?.type === 'hana_scale_out') {
+ if (CLUSTER_TYPES.includes(cluster?.type)) {
return (
{
+ it.each(['hana_scale_up', 'hana_scale_out', 'ascs_ers'])(
+ 'should render a link if the cluster type is %s',
+ (type) => {
+ const cluster = clusterFactory.build({ type });
+
+ renderWithRouter();
+
+ const link = screen.getByRole('link');
+
+ expect(link).toHaveTextContent(cluster.name);
+ expect(link).toHaveAttribute('href', `/clusters/${cluster.id}`);
+ }
+ );
+
+ it('should show a simple text if the cluster type is unknown', () => {
+ const cluster = clusterFactory.build({ type: 'unknown' });
+
+ renderWithRouter();
+
+ expect(screen.queryByRole('link')).not.toBeInTheDocument();
+ expect(screen.getByText(cluster.name)).toBeInTheDocument();
+ });
+
+ it('should show the cluster ID if the name is not available', () => {
+ const cluster = clusterFactory.build({ name: '' });
+
+ renderWithRouter();
+
+ expect(screen.getByText(cluster.id)).toBeInTheDocument();
+ });
+});
diff --git a/assets/js/lib/model/index.js b/assets/js/lib/model/index.js
index 7775d47144..79a5b8a7b8 100644
--- a/assets/js/lib/model/index.js
+++ b/assets/js/lib/model/index.js
@@ -12,3 +12,5 @@ export const isValidTargetType = (targetType) =>
export const UNKNOWN_PROVIDER = 'unknown';
export const VMWARE_PROVIDER = 'vmware';
+
+export const CLUSTER_TYPES = ['hana_scale_up', 'hana_scale_out', 'ascs_ers'];
diff --git a/assets/js/lib/test-utils/factories/clusters.js b/assets/js/lib/test-utils/factories/clusters.js
index 13106ce069..503ec65e96 100644
--- a/assets/js/lib/test-utils/factories/clusters.js
+++ b/assets/js/lib/test-utils/factories/clusters.js
@@ -10,6 +10,11 @@ const clusterTypeEnum = () =>
const hanaStatus = () => faker.helpers.arrayElement(['Primary', 'Failed']);
+export const sbdDevicesFactory = Factory.define(() => ({
+ device: faker.system.filePath(),
+ status: faker.helpers.arrayElement(['healthy', 'unhealthy']),
+}));
+
export const clusterResourceFactory = Factory.define(() => ({
id: faker.datatype.uuid(),
role: faker.animal.bear(),
@@ -18,7 +23,7 @@ export const clusterResourceFactory = Factory.define(() => ({
fail_count: faker.datatype.number(),
}));
-export const clusterDetailsNodesFactory = Factory.define(() => ({
+export const hanaClusterDetailsNodesFactory = Factory.define(() => ({
name: faker.animal.dog(),
site: faker.address.city(),
virtual_ip: faker.internet.ip(),
@@ -33,12 +38,18 @@ export const clusterDetailsNodesFactory = Factory.define(() => ({
resources: clusterResourceFactory.buildList(5),
}));
-export const sbdDevicesFactory = Factory.define(() => ({
- device: faker.system.filePath(),
- status: faker.helpers.arrayElement(['healthy', 'unhealthy']),
+export const hanaClusterDetailsFactory = Factory.define(() => ({
+ fencing_type: 'external/sbd',
+ nodes: hanaClusterDetailsNodesFactory.buildList(2),
+ sbd_devices: sbdDevicesFactory.buildList(3),
+ secondary_sync_state: 'SOK',
+ sr_health_state: '4',
+ stopped_resources: clusterResourceFactory.buildList(2),
+ system_replication_mode: 'sync',
+ system_replication_operation_mode: 'logreplay',
}));
-export const clusterFactory = Factory.define(({ sequence }) => ({
+export const clusterFactory = Factory.define(({ sequence, params }) => ({
id: faker.datatype.uuid(),
name: `${faker.name.firstName()}_${sequence}`,
sid: faker.random.alphaNumeric(3, { casing: 'upper' }),
@@ -49,14 +60,5 @@ export const clusterFactory = Factory.define(({ sequence }) => ({
selected_checks: [],
provider: cloudProviderEnum(),
cib_last_written: day(faker.date.recent()).format(),
- details: {
- fencing_type: 'external/sbd',
- nodes: clusterDetailsNodesFactory.buildList(2),
- sbd_devices: sbdDevicesFactory.buildList(3),
- secondary_sync_state: 'SOK',
- sr_health_state: '4',
- stopped_resources: clusterResourceFactory.buildList(2),
- system_replication_mode: 'sync',
- system_replication_operation_mode: 'logreplay',
- },
+ details: hanaClusterDetailsFactory.build(params.details),
}));