From 2da1d55a9d5f3934881130970e48adad25ad429d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tao=20Bojl=C3=A9n?= Date: Tue, 11 Aug 2026 22:27:57 +0100 Subject: [PATCH] Fix investigation policy select value Co-authored-by: Amp Amp-Thread-ID: https://ampcode.com/threads/T-019fec69-19ab-77e8-b6f0-85af1ed67eed --- client/src/components/ItemAction.test.tsx | 79 +++++++++++++++++++++++ client/src/components/ItemAction.tsx | 10 ++- 2 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 client/src/components/ItemAction.test.tsx diff --git a/client/src/components/ItemAction.test.tsx b/client/src/components/ItemAction.test.tsx new file mode 100644 index 00000000..cbadc668 --- /dev/null +++ b/client/src/components/ItemAction.test.tsx @@ -0,0 +1,79 @@ +import { fireEvent, render } from '@testing-library/react'; +import { vi } from 'vitest'; + +import '@testing-library/jest-dom/extend-expect'; + +import ItemAction from './ItemAction'; + +const mocks = vi.hoisted(() => ({ + allowMultiplePoliciesPerAction: false, + policyDropdownProps: undefined as + | { + multiple: boolean; + selectedPolicyIds: string | readonly string[] | undefined; + onChange: (value: string | readonly string[]) => void; + } + | undefined, +})); + +vi.mock('@/graphql/generated', async (importOriginal) => ({ + ...(await importOriginal()), + useGQLBulkActionsFormDataQuery: () => ({ + data: { + myOrg: { + actions: [ + { + id: 'action-1', + name: 'Action', + itemTypes: [{ id: 'item-type-1' }], + parameters: [], + }, + ], + policies: [], + allowMultiplePoliciesPerAction: mocks.allowMultiplePoliciesPerAction, + }, + }, + }), + useGQLBulkActionExecutionMutation: () => [vi.fn(), { loading: false }], +})); + +vi.mock('@/webpages/dashboard/components/PolicyDropdown', () => ({ + default: (props: typeof mocks.policyDropdownProps) => { + mocks.policyDropdownProps = props; + return ( + + ); + }, +})); + +describe('ItemAction policy selection', () => { + beforeEach(() => { + mocks.allowMultiplePoliciesPerAction = false; + mocks.policyDropdownProps = undefined; + }); + + it('passes a scalar selected policy value in single-policy mode', () => { + const { getByRole } = render( + , + ); + + expect(mocks.policyDropdownProps?.selectedPolicyIds).toBeUndefined(); + fireEvent.click(getByRole('button', { name: 'Select policies' })); + expect(mocks.policyDropdownProps?.selectedPolicyIds).toBe('policy-1'); + }); + + it('passes every selected policy value in multiple-policy mode', () => { + mocks.allowMultiplePoliciesPerAction = true; + const { getByRole } = render( + , + ); + + fireEvent.click(getByRole('button', { name: 'Select policies' })); + expect(mocks.policyDropdownProps?.selectedPolicyIds).toEqual([ + 'policy-1', + 'policy-2', + ]); + }); +}); diff --git a/client/src/components/ItemAction.tsx b/client/src/components/ItemAction.tsx index 1d3a2044..7aa83d6b 100644 --- a/client/src/components/ItemAction.tsx +++ b/client/src/components/ItemAction.tsx @@ -176,6 +176,8 @@ export default function ItemAction(props: { () => (policies ? policies.map((p) => stripTypename(p)) : []), [policies], ); + const allowMultiplePoliciesPerAction = + queryData?.myOrg?.allowMultiplePoliciesPerAction ?? false; const policiesDropdownOnChange = useCallback( (policyIds: string | readonly string[]) => { @@ -273,10 +275,12 @@ export default function ItemAction(props: { policies={policiesMemo} maxTagCount={1} onChange={policiesDropdownOnChange} - selectedPolicyIds={selectedPolicyIds} - multiple={ - queryData?.myOrg?.allowMultiplePoliciesPerAction ?? false + selectedPolicyIds={ + allowMultiplePoliciesPerAction + ? selectedPolicyIds + : selectedPolicyIds[0] } + multiple={allowMultiplePoliciesPerAction} />