[8.16] [EDR Workflows] Fix agent count on policy deploy modal (#209593) (#210041)

# Backport

This will backport the following commits from `main` to `8.16`:
- [[EDR Workflows] Fix agent count on policy deploy modal
(#209593)](https://github.com/elastic/kibana/pull/209593)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Gergő
Ábrahám","email":"gergo.abraham@elastic.co"},"sourceCommit":{"committedDate":"2025-02-06T15:17:47Z","message":"[EDR
Workflows] Fix agent count on policy deploy modal (#209593)\n\n##
Summary\r\n\r\nFixes the agent count issue on the warning model when
saving a Defend\r\npackage policy. Now it uses the same `active` field
instead of `all`, as\r\nthe `AgentSummary` component.\r\n\r\nAlso,
re-enables flaky unit test for `PolicySettingsLayout`:\r\ncloses:
#179984\r\n\r\n### Checklist\r\n\r\nCheck the PR satisfies following
conditions. \r\n\r\nReviewers should verify this PR satisfies this list
as well.\r\n\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"16fae1c86597d2f43e9120578346e26a8b5a88a5","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Defend
Workflows","backport:prev-minor","backport:prev-major","v9.1.0"],"title":"[EDR
Workflows] Fix agent count on policy deploy
modal","number":209593,"url":"https://github.com/elastic/kibana/pull/209593","mergeCommit":{"message":"[EDR
Workflows] Fix agent count on policy deploy modal (#209593)\n\n##
Summary\r\n\r\nFixes the agent count issue on the warning model when
saving a Defend\r\npackage policy. Now it uses the same `active` field
instead of `all`, as\r\nthe `AgentSummary` component.\r\n\r\nAlso,
re-enables flaky unit test for `PolicySettingsLayout`:\r\ncloses:
#179984\r\n\r\n### Checklist\r\n\r\nCheck the PR satisfies following
conditions. \r\n\r\nReviewers should verify this PR satisfies this list
as well.\r\n\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"16fae1c86597d2f43e9120578346e26a8b5a88a5"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/209593","number":209593,"mergeCommit":{"message":"[EDR
Workflows] Fix agent count on policy deploy modal (#209593)\n\n##
Summary\r\n\r\nFixes the agent count issue on the warning model when
saving a Defend\r\npackage policy. Now it uses the same `active` field
instead of `all`, as\r\nthe `AgentSummary` component.\r\n\r\nAlso,
re-enables flaky unit test for `PolicySettingsLayout`:\r\ncloses:
#179984\r\n\r\n### Checklist\r\n\r\nCheck the PR satisfies following
conditions. \r\n\r\nReviewers should verify this PR satisfies this list
as well.\r\n\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"16fae1c86597d2f43e9120578346e26a8b5a88a5"}}]}]
BACKPORT-->

---------

Co-authored-by: Gergő Ábrahám <gergo.abraham@elastic.co>
This commit is contained in:
Kibana Machine 2025-02-07 23:53:31 +11:00 committed by GitHub
parent 4d74e2c041
commit f8365865c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 64 additions and 15 deletions

View file

@ -12,6 +12,7 @@ import type { PolicyData } from '../../../../common/endpoint/types';
import { allFleetHttpMocks } from '../../mocks';
import { FleetPackagePolicyGenerator } from '../../../../common/endpoint/data_generators/fleet_package_policy_generator';
import { useFetchAgentByAgentPolicySummary } from './use_fetch_endpoint_policy_agent_summary';
import type { GetAgentStatusResponse } from '@kbn/fleet-plugin/common';
import { agentRouteService, API_VERSIONS } from '@kbn/fleet-plugin/common';
const useQueryMock = _useQuery as jest.Mock;
@ -59,8 +60,10 @@ describe('When using the `useFetchEndpointPolicyAgentSummary()` hook', () => {
query: { policyId: policy.policy_ids[0] },
version: API_VERSIONS.public.v1,
});
expect(data).toEqual({
const expectedData: GetAgentStatusResponse['results'] = {
active: 50,
total: 50,
all: 0,
inactive: 5,
online: 40,
error: 0,
@ -68,7 +71,9 @@ describe('When using the `useFetchEndpointPolicyAgentSummary()` hook', () => {
updating: 0,
other: 0,
events: 0,
});
unenrolled: 0,
};
expect(data).toEqual(expectedData);
});
it('should apply default values to api returned data', async () => {

View file

@ -415,9 +415,10 @@ export const fleetGetAgentStatusHttpMock =
id: 'agentStatus',
path: AGENT_API_ROUTES.STATUS_PATTERN,
method: 'get',
handler: () => {
handler: (): GetAgentStatusResponse => {
return {
results: {
active: 50,
total: 50,
inactive: 5,
online: 40,
@ -426,6 +427,8 @@ export const fleetGetAgentStatusHttpMock =
updating: 0,
other: 0,
events: 0,
unenrolled: 0,
all: 0,
},
};
},

View file

@ -24,6 +24,7 @@ import {
import { cloneDeep, set } from 'lodash';
import { ProtectionModes } from '../../../../../../common/endpoint/types';
import { waitFor, cleanup } from '@testing-library/react';
import type { GetAgentStatusResponse } from '@kbn/fleet-plugin/common';
import { packagePolicyRouteService, API_VERSIONS } from '@kbn/fleet-plugin/common';
import { getPolicyDataForUpdate } from '../../../../../../common/endpoint/service/policy';
import { getDeferred } from '../../../../mocks/utils';
@ -33,8 +34,7 @@ jest.mock('../../../../../common/components/user_privileges');
const useUserPrivilegesMock = _useUserPrivileges as jest.Mock;
// Failing: See https://github.com/elastic/kibana/issues/179984
describe.skip('When rendering PolicySettingsLayout', () => {
describe('When rendering PolicySettingsLayout', () => {
jest.setTimeout(15000);
const testSubj = getPolicySettingsFormTestSubjects();
@ -83,6 +83,14 @@ describe.skip('When rendering PolicySettingsLayout', () => {
}
};
/**
* Performs a minimal number of updates to make 'Save' button enabled.
*/
const makeMinimalUpdates = async () => {
const { getByTestId } = renderResult;
await userEvent.click(getByTestId(testSubj.malware.enableDisableSwitch));
};
/**
* Makes updates to the policy form on the UI and return back a new (cloned) `PolicyData`
* with the updates reflected in it
@ -113,9 +121,11 @@ describe.skip('When rendering PolicySettingsLayout', () => {
await userEvent.type(getByTestId(testSubj.ransomware.notifyCustomMessage), 'foo message');
set(policySettings, 'windows.popup.ransomware.message', 'foo message');
await userEvent.click(getByTestId(testSubj.advancedSection.showHideButton));
await userEvent.type(getByTestId('linux.advanced.agent.connection_delay'), '1000');
set(policySettings, 'linux.advanced.agent.connection_delay', '1000');
// skipping Advanced Options as changing them takes too long.
// todo: re-enable them with this issue: https://github.com/elastic/security-team/issues/11765
// await userEvent.click(getByTestId(testSubj.advancedSection.showHideButton));
// await userEvent.type(getByTestId('linux.advanced.agent.connection_delay'), '1000');
// set(policySettings, 'linux.advanced.agent.connection_delay', '1000');
return expectedUpdates;
};
@ -130,7 +140,7 @@ describe.skip('When rendering PolicySettingsLayout', () => {
it('should render layout with expected content when changes have been made', async () => {
const { getByTestId } = render();
await makeUpdates();
await makeMinimalUpdates();
expect(getByTestId('endpointPolicyForm'));
expect(getByTestId('policyDetailsCancelButton')).not.toBeDisabled();
expect(getByTestId('policyDetailsSaveButton')).not.toBeDisabled();
@ -152,7 +162,7 @@ describe.skip('When rendering PolicySettingsLayout', () => {
const deferred = getDeferred();
apiMocks.responseProvider.updateEndpointPolicy.mockDelay.mockReturnValue(deferred.promise);
const { getByTestId } = render();
await makeUpdates();
await makeMinimalUpdates();
await clickSave(true, false);
await waitFor(() => {
@ -163,13 +173,11 @@ describe.skip('When rendering PolicySettingsLayout', () => {
expect(
getByTestId('policyDetailsSaveButton').querySelector('.euiLoadingSpinner')
).not.toBeNull();
deferred.resolve();
});
it('should show success toast on update success', async () => {
render();
await makeUpdates();
await makeMinimalUpdates();
await clickSave();
await waitFor(() => {
@ -188,7 +196,7 @@ describe.skip('When rendering PolicySettingsLayout', () => {
throw new Error('oh oh!');
});
render();
await makeUpdates();
await makeMinimalUpdates();
await clickSave();
await waitFor(() => {
@ -201,6 +209,39 @@ describe.skip('When rendering PolicySettingsLayout', () => {
title: 'Failed!',
});
});
it('should not show warning about endpoints if there are no active endpoints', async () => {
apiMocks.responseProvider.agentStatus.mockReturnValue({
results: { active: 0 },
} as GetAgentStatusResponse);
const { getByTestId, queryByTestId } = render();
await makeMinimalUpdates();
await userEvent.click(getByTestId('policyDetailsSaveButton'));
await waitFor(() => {
expect(getByTestId('confirmModalConfirmButton')).toBeInTheDocument();
});
expect(queryByTestId('policyDetailsWarningCallout')).not.toBeInTheDocument();
});
it('should show warning about endpoints with the number of active endpoints', async () => {
apiMocks.responseProvider.agentStatus.mockReturnValue({
results: { active: 6 },
} as GetAgentStatusResponse);
const { getByTestId } = render();
await makeMinimalUpdates();
await userEvent.click(getByTestId('policyDetailsSaveButton'));
await waitFor(() => {
expect(getByTestId('confirmModalConfirmButton')).toBeInTheDocument();
});
const callout = getByTestId('policyDetailsWarningCallout');
expect(callout).toBeInTheDocument();
expect(callout.textContent).toContain('This action will update 6 endpoints');
});
});
describe('and user has View Only permissions', () => {

View file

@ -170,7 +170,7 @@ export const PolicySettingsLayout = memo<PolicySettingsLayoutProps>(
<>
{showConfirm && (
<ConfirmUpdate
endpointCount={agentSummaryData ? agentSummaryData.all : 0}
endpointCount={agentSummaryData ? agentSummaryData.active : 0}
onCancel={handleSaveCancel}
onConfirm={handleSaveConfirmation}
/>