diff --git a/assets/js/components/ClusterDetails/AscsErsClusterDetails.jsx b/assets/js/components/ClusterDetails/AscsErsClusterDetails.jsx index 700cde1b11..90bdabc631 100644 --- a/assets/js/components/ClusterDetails/AscsErsClusterDetails.jsx +++ b/assets/js/components/ClusterDetails/AscsErsClusterDetails.jsx @@ -6,7 +6,7 @@ import Table from '@components/Table'; import ListView from '@components/ListView'; import ProviderLabel from '@components/ProviderLabel'; import DottedPagination from '@components/DottedPagination'; -import HostLink from '@components/HostLink'; +import ClusterNodeLink from '@components/ClusterDetails/ClusterNodeLink'; import SapSystemLink from '@components/SapSystemLink'; import { renderEnsaVersion } from '@components/SapSystemDetails'; @@ -23,7 +23,9 @@ const nodeDetailsConfig = { { title: 'Hostname', key: '', - render: (_, { id, name }) => {name}, + render: (_, { id, name }) => ( + {name} + ), }, { title: 'Role', diff --git a/assets/js/components/ClusterDetails/AscsErsClusterDetails.stories.jsx b/assets/js/components/ClusterDetails/AscsErsClusterDetails.stories.jsx index 787a160466..8f5371f51d 100644 --- a/assets/js/components/ClusterDetails/AscsErsClusterDetails.stories.jsx +++ b/assets/js/components/ClusterDetails/AscsErsClusterDetails.stories.jsx @@ -76,6 +76,18 @@ export const Single = { ), }; +export const WithUnregisteredHost = { + args: { + ...Single.args, + hosts: Single.args.hosts.slice(0, 1), + }, + render: (args) => ( + + + + ), +}; + export const MultiSID = { args: { ...Single.args, diff --git a/assets/js/components/ClusterDetails/AscsErsClusterDetails.test.jsx b/assets/js/components/ClusterDetails/AscsErsClusterDetails.test.jsx index 33f4b408d5..a4a449c7e2 100644 --- a/assets/js/components/ClusterDetails/AscsErsClusterDetails.test.jsx +++ b/assets/js/components/ClusterDetails/AscsErsClusterDetails.test.jsx @@ -104,13 +104,7 @@ describe('ClusterDetails AscsErsClusterDetails component', () => { nodes.forEach( async ( - { - id: clusterID, - name: nodeName, - role, - virtual_ip: virtualIp, - filesysten, - }, + { id: hostId, name: nodeName, role, virtual_ip: virtualIp, filesysten }, index ) => { await waitFor(() => { @@ -119,7 +113,7 @@ describe('ClusterDetails AscsErsClusterDetails component', () => { expect(hostnameCell).toHaveTextContent(nodeName); expect(hostnameCell) .querySelector('a') - .toHaveAttributes('href', clusterID); + .toHaveAttributes('href', hostId); expect(row.querySelector('td:nth-child(1)')).toHaveTextContent(role); expect(row.querySelector('td:nth-child(2)')).toHaveTextContent( virtualIp @@ -200,4 +194,32 @@ describe('ClusterDetails AscsErsClusterDetails component', () => { expect(sidContainer).toHaveTextContent(sid); expect(sidContainer.querySelector('a')).toBeNull(); }); + + it('should not display a host link for unregistered hosts', () => { + const { + name, + cib_last_written: cibLastWritten, + provider, + details, + } = clusterFactory.build({ type: 'ascs_ers' }); + + const hosts = buildHostsFromAscsErsClusterDetails(details); + const unregisteredHost = hosts.pop(); + + renderWithRouter( + + ); + const unregisteredHostContainer = screen.getByText( + unregisteredHost.hostname + ); + + expect(unregisteredHostContainer).not.toHaveAttribute('href'); + }); }); diff --git a/assets/js/components/ClusterDetails/ClusterNodeLink.jsx b/assets/js/components/ClusterDetails/ClusterNodeLink.jsx new file mode 100644 index 0000000000..f032196f58 --- /dev/null +++ b/assets/js/components/ClusterDetails/ClusterNodeLink.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { EOS_WARNING_OUTLINED } from 'eos-icons-react'; + +import Tooltip from '@components/Tooltip'; +import HostLink from '@components/HostLink'; + +function ClusterNodeLink({ hostId, children }) { + if (hostId) { + return {children}; + } + return ( + + + {children} + + + ); +} + +export default ClusterNodeLink; diff --git a/assets/js/components/ClusterDetails/ClusterNodeLink.test.jsx b/assets/js/components/ClusterDetails/ClusterNodeLink.test.jsx new file mode 100644 index 0000000000..f620fdca96 --- /dev/null +++ b/assets/js/components/ClusterDetails/ClusterNodeLink.test.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { renderWithRouter } from '@lib/test-utils'; +import ClusterNodeLink from '@components/ClusterDetails/ClusterNodeLink'; +import { hostFactory } from '@lib/test-utils/factories'; + +describe('ClusterNodeLink', () => { + it('renders HostLink when hostId is provided', () => { + const { id, hostname } = hostFactory.build(); + + renderWithRouter({hostname}); + + const hostLinkElement = screen.getByRole('link', { hostname }); + + expect(hostLinkElement).toBeInTheDocument(); + expect(hostLinkElement).toHaveAttribute('href', `/hosts/${id}`); + }); + + it('renders warning span when hostId is not provided', () => { + const { hostname } = hostFactory.build(); + + render({hostname}); + expect( + screen.getByText('Host currently not registered.') + ).toBeInTheDocument(); + }); +}); diff --git a/assets/js/components/ClusterDetails/HanaClusterDetails.jsx b/assets/js/components/ClusterDetails/HanaClusterDetails.jsx index ca96681256..bbfcc3a29f 100644 --- a/assets/js/components/ClusterDetails/HanaClusterDetails.jsx +++ b/assets/js/components/ClusterDetails/HanaClusterDetails.jsx @@ -10,7 +10,7 @@ import ListView from '@components/ListView'; import Table from '@components/Table'; import Tooltip from '@components/Tooltip'; import TriggerChecksExecutionRequest from '@components/TriggerChecksExecutionRequest'; -import HostLink from '@components/HostLink'; +import ClusterNodeLink from '@components/ClusterDetails/ClusterNodeLink'; import ChecksResultOverview from '@components/ClusterDetails/ChecksResultOverview'; import ProviderLabel from '@components/ProviderLabel'; import SapSystemLink from '@components/SapSystemLink'; @@ -34,7 +34,7 @@ const siteDetailsConfig = { title: 'Hostname', key: '', render: (_, hostData) => ( - {hostData.name} + {hostData.name} ), }, { title: 'Role', key: 'hana_status' }, diff --git a/assets/js/components/ClusterDetails/HanaClusterDetails.stories.jsx b/assets/js/components/ClusterDetails/HanaClusterDetails.stories.jsx index 1708f083b0..24c785b2fd 100644 --- a/assets/js/components/ClusterDetails/HanaClusterDetails.stories.jsx +++ b/assets/js/components/ClusterDetails/HanaClusterDetails.stories.jsx @@ -80,6 +80,13 @@ export const Hana = { }, }; +export const WithUnregisteredHost = { + args: { + ...Hana.args, + hosts: hosts.slice(0, 1), + }, +}; + export const WithNoSelectedChecks = { args: { ...Hana.args, diff --git a/assets/js/components/ClusterDetails/HanaClusterDetails.test.jsx b/assets/js/components/ClusterDetails/HanaClusterDetails.test.jsx index f31dedad53..e5ad12ea9e 100644 --- a/assets/js/components/ClusterDetails/HanaClusterDetails.test.jsx +++ b/assets/js/components/ClusterDetails/HanaClusterDetails.test.jsx @@ -6,6 +6,7 @@ import { renderWithRouter } from '@lib/test-utils'; import { clusterFactory, hostFactory, + hanaClusterDetailsNodesFactory, checksExecutionCompletedFactory, checksExecutionRunningFactory, sapSystemFactory, @@ -181,4 +182,51 @@ describe('HanaClusterDetails component', () => { expect(sidContainer).toHaveTextContent(sid); expect(sidContainer.querySelector('a')).toBeNull(); }); + + it('should display a host link in the site details if the host is registered', () => { + const registeredClusterNode = hanaClusterDetailsNodesFactory.build(); + + const { + clusterID, + clusterName, + cib_last_written: cibLastWritten, + type: clusterType, + sid, + provider, + details, + } = clusterFactory.build({ details: { nodes: [registeredClusterNode] } }); + + const host = hostFactory.build({ + hostname: registeredClusterNode.name, + cluster_id: clusterID, + }); + + const sapSystems = sapSystemFactory.buildList(2, { tenant: sid }); + + renderWithRouter( + + ); + + const registeredHostContainer = screen.getByText( + registeredClusterNode.name + ); + + expect(registeredHostContainer).toHaveAttribute( + 'href', + `/hosts/${host.id}` + ); + }); });