diff --git a/assets/js/components/HostsList.jsx b/assets/js/components/HostsList.jsx index 108fbcfa1a..0302ee5745 100644 --- a/assets/js/components/HostsList.jsx +++ b/assets/js/components/HostsList.jsx @@ -1,10 +1,11 @@ -import React from 'react'; +import React, { useState } from 'react'; import { useSearchParams } from 'react-router-dom'; import { useSelector, useDispatch } from 'react-redux'; import { EOS_WARNING_OUTLINED } from 'eos-icons-react'; import Table from '@components/Table'; +import DeregistrationModal from '@components/DeregistrationModal'; import HealthIcon from '@components/Health/HealthIcon'; import Tags from '@components/Tags'; import HostLink from '@components/HostLink'; @@ -16,8 +17,10 @@ import HealthSummary from '@components/HealthSummary/HealthSummary'; import { getCounters } from '@components/HealthSummary/summarySelection'; import ProviderLabel from '@components/ProviderLabel'; import Tooltip from '@components/Tooltip'; +import CleanUpButton from '@components/CleanUpButton'; + +import { addTagToHost, removeTagFromHost, deregisterHost } from '@state/hosts'; -import { addTagToHost, removeTagFromHost } from '@state/hosts'; import { post, del } from '@lib/network'; import { agentVersionWarning } from '@lib/agent'; @@ -50,6 +53,8 @@ function HostsList() { ); const [searchParams, setSearchParams] = useSearchParams(); + const [cleanUpModalOpen, setCleanUpModalOpen] = useState(false); + const [selectedHost, setSelectedHost] = useState(undefined); const dispatch = useDispatch(); @@ -177,6 +182,21 @@ function HostsList() { /> ), }, + { + title: '', + key: 'deregisterable', + className: 'w-48', + render: (content, item) => + content ? ( + { + setSelectedHost(item); + setCleanUpModalOpen(true); + }} + /> + ) : null, + }, ], }; @@ -199,6 +219,8 @@ function HostsList() { id: host.id, tags: (host.tags && host.tags.map((tag) => tag.value)) || [], sap_systems: sapSystemList, + deregisterable: host.deregisterable, + deregistering: host.deregistering, }; }); @@ -206,6 +228,17 @@ function HostsList() { return ( <> Hosts + { + setCleanUpModalOpen(false); + dispatch(deregisterHost(selectedHost)); + }} + onCancel={() => { + setCleanUpModalOpen(false); + }} + />
{ }); }); + describe('deregistration', () => { + it('should show the clean up button when the host is deregisterable', () => { + const host1 = hostFactory.build({ deregisterable: true }); + const host2 = hostFactory.build({ deregisterable: false }); + const state = { + ...defaultInitialState, + hostsList: { + hosts: [].concat(host1, host2), + }, + }; + + const [StatefulHostsList] = withState(, state); + + renderWithRouter(StatefulHostsList); + const table = screen.getByRole('table'); + const cleanUpCell1 = table.querySelector( + 'tr:nth-child(1) > td:nth-child(9)' + ); + const cleanUpCell2 = table.querySelector( + 'tr:nth-child(1) > td:nth-child(9)' + ); + expect(cleanUpCell1).toHaveTextContent('Clean up'); + expect(cleanUpCell2).toHaveTextContent('Clean up'); + }); + + it('should show the host in deregistering state', () => { + const host = hostFactory.build({ + deregisterable: true, + deregistering: true, + }); + const state = { + ...defaultInitialState, + hostsList: { + hosts: [host], + }, + }; + + const [StatefulHostsList] = withState(, state); + + renderWithRouter(StatefulHostsList); + expect(screen.getByLabelText('Loading')).toBeInTheDocument(); + }); + + it('should request a deregistration when the clean up button in the modal is clicked', async () => { + const user = userEvent.setup(); + + const host = hostFactory.build({ deregisterable: true }); + const state = { + ...defaultInitialState, + hostsList: { + hosts: [host], + }, + }; + + const [StatefulHostsList, store] = withState(, state); + + renderWithRouter(StatefulHostsList); + + const table = screen.getByRole('table'); + const cleanUpButton = table.querySelector( + 'tr:nth-child(1) > td:nth-child(9) > button' + ); + + await user.click(cleanUpButton); + + expect( + screen.getByText( + `Clean up data discovered by agent on host ${host.hostname}` + ) + ).toBeInTheDocument(); + + const cleanUpModalButton = screen.getAllByRole('button', { + name: 'Clean up', + })[1]; + + await user.click(cleanUpModalButton); + + const actions = store.getActions(); + const expectedActions = [ + { + type: 'DEREGISTER_HOST', + payload: expect.objectContaining({ + id: host.id, + hostname: host.hostname, + }), + }, + ]; + expect(actions).toEqual(expect.arrayContaining(expectedActions)); + }); + }); + describe('filtering', () => { const cleanInitialState = { hostsList: {