From 8f3faf11ccc9fe3168c66cbef214b01f430d3a21 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Wed, 8 Sep 2021 11:21:54 +0100 Subject: [PATCH 1/4] fix: consolidate hasUpgrade logic --- .../detail/policies/package_policies.tsx | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx index 677ca545029fe..122e348665471 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx @@ -45,7 +45,6 @@ import { PackagePolicyActionsMenu, } from '../../../../../components'; -import type { PackagePolicyAndAgentPolicy } from './use_package_policies_with_agent_policy'; import { usePackagePoliciesWithAgentPolicy } from './use_package_policies_with_agent_policy'; import { Persona } from './persona'; @@ -54,7 +53,7 @@ const AddAgentButton = styled(EuiButtonIcon)` `; const IntegrationDetailsLink = memo<{ - packagePolicy: PackagePolicyAndAgentPolicy['packagePolicy']; + packagePolicy: InMemoryPackagePolicyAndAgentPolicy['packagePolicy']; }>(({ packagePolicy }) => { const { getHref } = useLink(); return ( @@ -75,6 +74,12 @@ interface PackagePoliciesPanelProps { name: string; version: string; } + +interface InMemoryPackagePolicyAndAgentPolicy { + packagePolicy: InMemoryPackagePolicy; + agentPolicy: GetAgentPoliciesResponseItem; +} + export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps) => { const { search } = useLocation(); const history = useHistory(); @@ -109,12 +114,12 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps const updatableIntegrationRecord = updatableIntegrations.get( packagePolicy.package?.name ?? '' ); - const hasUpgrade = !!updatableIntegrationRecord && updatableIntegrationRecord.policiesToUpgrade.some( - ({ id }) => id === packagePolicy.policy_id + ({ pkgPolicyId }) => pkgPolicyId === packagePolicy.id ); + return { agentPolicy, packagePolicy: { @@ -143,7 +148,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps }, [history]); const handleTableOnChange = useCallback( - ({ page }: CriteriaWithPagination) => { + ({ page }: CriteriaWithPagination) => { setPagination({ currentPage: page.index + 1, pageSize: page.size, @@ -196,7 +201,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps }; }, [name, version, getHref, agentEnrollmentFlyoutExtension]); - const columns: Array> = useMemo( + const columns: Array> = useMemo( () => [ { field: 'packagePolicy.name', @@ -213,16 +218,6 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps defaultMessage: 'Version', }), render(_version, { agentPolicy, packagePolicy }) { - const updatableIntegrationRecord = updatableIntegrations.get( - packagePolicy.package?.name ?? '' - ); - - const hasUpgrade = - !!updatableIntegrationRecord && - updatableIntegrationRecord.policiesToUpgrade.some( - ({ pkgPolicyId }) => pkgPolicyId === packagePolicy.id - ); - return ( @@ -235,7 +230,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps - {hasUpgrade && ( + {packagePolicy.hasUpgrade && ( @@ -358,7 +353,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps }, }, ], - [getHref, updatableIntegrations, viewDataStep] + [getHref, viewDataStep] ); const noItemsMessage = useMemo(() => { From 42f39a3da658d98c8c17096c3816e28a8f375eef Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Wed, 8 Sep 2021 11:54:57 +0100 Subject: [PATCH 2/4] tidy: move type defs to top of file --- .../detail/policies/package_policies.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx index 122e348665471..07a61410e9a6b 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx @@ -48,6 +48,16 @@ import { import { usePackagePoliciesWithAgentPolicy } from './use_package_policies_with_agent_policy'; import { Persona } from './persona'; +interface PackagePoliciesPanelProps { + name: string; + version: string; +} + +interface InMemoryPackagePolicyAndAgentPolicy { + packagePolicy: InMemoryPackagePolicy; + agentPolicy: GetAgentPoliciesResponseItem; +} + const AddAgentButton = styled(EuiButtonIcon)` margin-left: ${(props) => props.theme.eui.euiSizeS}; `; @@ -70,16 +80,6 @@ const IntegrationDetailsLink = memo<{ ); }); -interface PackagePoliciesPanelProps { - name: string; - version: string; -} - -interface InMemoryPackagePolicyAndAgentPolicy { - packagePolicy: InMemoryPackagePolicy; - agentPolicy: GetAgentPoliciesResponseItem; -} - export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps) => { const { search } = useLocation(); const history = useHistory(); From d00371340338ccb1e79ac3278759f6a09c0b2c4e Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Fri, 10 Sep 2021 17:04:28 +0100 Subject: [PATCH 3/4] test: add unit tests for actions menu --- .../package_policy_actions_menu.test.tsx | 121 ++++++++++++++++++ .../package_policy_actions_menu.tsx | 15 ++- 2 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx new file mode 100644 index 0000000000000..55e2446241da2 --- /dev/null +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { act } from '@testing-library/react'; + +import type { AgentPolicy, InMemoryPackagePolicy } from '../types'; +import { createIntegrationsTestRendererMock } from '../mock'; + +import { PackagePolicyActionsMenu } from './package_policy_actions_menu'; + +function renderMenu({ + agentPolicy, + packagePolicy, + showAddAgent = false, + isOpen = true, +}: { + agentPolicy: AgentPolicy; + packagePolicy: InMemoryPackagePolicy; + showAddAgent?: boolean; + isOpen?: boolean; +}) { + const renderer = createIntegrationsTestRendererMock(); + + const utils = renderer.render( + + ); + + return { utils }; +} + +function createMockAgentPolicy(props: Partial = {}): AgentPolicy { + return { + id: 'some-uuid1', + namespace: 'default', + monitoring_enabled: [], + name: 'Test Policy', + description: '', + is_default: false, + is_preconfigured: false, + status: 'active', + is_managed: false, + revision: 1, + updated_at: '', + updated_by: 'elastic', + package_policies: [], + ...props, + }; +} + +function createMockPackagePolicy( + props: Partial = {} +): InMemoryPackagePolicy { + return { + id: 'some-uuid2', + name: 'mock-package-policy', + description: '', + created_at: '', + created_by: '', + updated_at: '', + updated_by: '', + policy_id: '', + enabled: true, + output_id: '', + namespace: 'default', + inputs: [], + revision: 1, + hasUpgrade: false, + ...props, + }; +} + +test('Should disable upgrade button if package does not have upgrade', async () => { + const agentPolicy = createMockAgentPolicy(); + const packagePolicy = createMockPackagePolicy({ hasUpgrade: false }); + const { utils } = renderMenu({ agentPolicy, packagePolicy }); + await act(async () => { + const upgradeButton = utils.getByText('Upgrade package policy').closest('button'); + expect(upgradeButton).toBeDisabled(); + }); +}); + +test('Should enable upgrade button if package does has upgrade', async () => { + const agentPolicy = createMockAgentPolicy(); + const packagePolicy = createMockPackagePolicy({ hasUpgrade: true }); + const { utils } = renderMenu({ agentPolicy, packagePolicy }); + await act(async () => { + const upgradeButton = utils.getByText('Upgrade package policy').closest('button'); + expect(upgradeButton).not.toBeDisabled(); + }); +}); + +test('Should not be able to delete integration from a managed policy', async () => { + const agentPolicy = createMockAgentPolicy({ is_managed: true }); + const packagePolicy = createMockPackagePolicy(); + const { utils } = renderMenu({ agentPolicy, packagePolicy }); + await act(async () => { + expect(utils.queryByText('Delete integration')).toBeNull(); + }); +}); + +test('Should be able to delete integration from a non-managed policy', async () => { + const agentPolicy = createMockAgentPolicy({ is_managed: false }); + const packagePolicy = createMockPackagePolicy(); + const { utils } = renderMenu({ agentPolicy, packagePolicy }); + await act(async () => { + expect(utils.queryByText('Delete integration')).not.toBeNull(); + }); +}); diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx index a87cd7e39bfb2..cf5d2416d4564 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx @@ -24,13 +24,21 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ packagePolicy: InMemoryPackagePolicy; viewDataStep?: EuiStepProps; showAddAgent?: boolean; + isOpen?: boolean; upgradePackagePolicyHref: string; -}> = ({ agentPolicy, packagePolicy, viewDataStep, showAddAgent, upgradePackagePolicyHref }) => { +}> = ({ + agentPolicy, + packagePolicy, + viewDataStep, + showAddAgent, + upgradePackagePolicyHref, + isOpen = false, +}) => { const [isEnrollmentFlyoutOpen, setIsEnrollmentFlyoutOpen] = useState(false); const { getHref } = useLink(); const hasWriteCapabilities = useCapabilities().write; const refreshAgentPolicy = useAgentPolicyRefresh(); - const [isActionsMenuOpen, setIsActionsMenuOpen] = useState(false); + const [isActionsMenuOpen, setIsActionsMenuOpen] = useState(isOpen); const onEnrollmentFlyoutClose = useMemo(() => { return () => setIsEnrollmentFlyoutOpen(false); @@ -84,6 +92,7 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ disabled={!packagePolicy.hasUpgrade} icon="refresh" href={upgradePackagePolicyHref} + key="packagePolicyUpgrade" > setIsActionsMenuOpen(isOpen)} + onChange={(open) => setIsActionsMenuOpen(open)} /> ); From 2d5334fb90b53efabc0d155489fe1f519c57ff22 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Mon, 13 Sep 2021 09:56:02 +0100 Subject: [PATCH 4/4] tidy: PR feedback --- .../components/package_policy_actions_menu.test.tsx | 12 ++++++------ .../components/package_policy_actions_menu.tsx | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx index 55e2446241da2..63a3a93b7e894 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx @@ -18,12 +18,12 @@ function renderMenu({ agentPolicy, packagePolicy, showAddAgent = false, - isOpen = true, + defaultIsOpen = true, }: { agentPolicy: AgentPolicy; packagePolicy: InMemoryPackagePolicy; showAddAgent?: boolean; - isOpen?: boolean; + defaultIsOpen?: boolean; }) { const renderer = createIntegrationsTestRendererMock(); @@ -33,7 +33,7 @@ function renderMenu({ packagePolicy={packagePolicy} showAddAgent={showAddAgent} upgradePackagePolicyHref="" - isOpen={isOpen} + defaultIsOpen={defaultIsOpen} key="test1" /> ); @@ -87,17 +87,17 @@ test('Should disable upgrade button if package does not have upgrade', async () const packagePolicy = createMockPackagePolicy({ hasUpgrade: false }); const { utils } = renderMenu({ agentPolicy, packagePolicy }); await act(async () => { - const upgradeButton = utils.getByText('Upgrade package policy').closest('button'); + const upgradeButton = utils.getByText('Upgrade integration policy').closest('button'); expect(upgradeButton).toBeDisabled(); }); }); -test('Should enable upgrade button if package does has upgrade', async () => { +test('Should enable upgrade button if package has upgrade', async () => { const agentPolicy = createMockAgentPolicy(); const packagePolicy = createMockPackagePolicy({ hasUpgrade: true }); const { utils } = renderMenu({ agentPolicy, packagePolicy }); await act(async () => { - const upgradeButton = utils.getByText('Upgrade package policy').closest('button'); + const upgradeButton = utils.getByText('Upgrade integration policy').closest('button'); expect(upgradeButton).not.toBeDisabled(); }); }); diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx index 165f01361edaf..eefa3c870f283 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx @@ -24,7 +24,7 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ packagePolicy: InMemoryPackagePolicy; viewDataStep?: EuiStepProps; showAddAgent?: boolean; - isOpen?: boolean; + defaultIsOpen?: boolean; upgradePackagePolicyHref: string; }> = ({ agentPolicy, @@ -32,13 +32,13 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ viewDataStep, showAddAgent, upgradePackagePolicyHref, - isOpen = false, + defaultIsOpen = false, }) => { const [isEnrollmentFlyoutOpen, setIsEnrollmentFlyoutOpen] = useState(false); const { getHref } = useLink(); const hasWriteCapabilities = useCapabilities().write; const refreshAgentPolicy = useAgentPolicyRefresh(); - const [isActionsMenuOpen, setIsActionsMenuOpen] = useState(isOpen); + const [isActionsMenuOpen, setIsActionsMenuOpen] = useState(defaultIsOpen); const onEnrollmentFlyoutClose = useMemo(() => { return () => setIsEnrollmentFlyoutOpen(false);