mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[Fleet] [Cloud Security] Add Testing Library ESLint for handling waitFor (#198735)
## Summary This PR aims to fix Flaky tests related to agentless detected by https://github.com/elastic/kibana/issues/189038 and https://github.com/elastic/kibana/issues/192126 by adding proper handling of the `waitFor` methods. It was also detected with https://github.com/elastic/security-team/issues/10979 that some other methods were not proper handled by `waitFor`, leading to the assertions inside those unhandled `waitFor` being skipped by Jest. This PR also introduces ESLint to enforce proper handling of waitFor methods in tests files for Fleet and Cloud Security plugins. Additional note: These changes should also unblock the failing tests on the [React18 use waitFor with assertion callbacks in place of waitForNextUpdate](https://github.com/elastic/kibana/pull/195087) PR **Fleet changes** - ESLint rule added to enforce handling `waitFor` on React Testing Library. - `useSetupTechnology` hook tests reviewed and updated to handle the waitFor. Fixed issue identified when reviewing the tests. - step_define_package_policy.test.tsx: Added package policy vars to the mock to proper handle the use cases - step_select_hosts.test.tsx: Handled waitFor, identified outdated test - step_edit_hosts.test.tsx: Handled waitFor, identified outdated test With the introduction of the ESLint rule other tests were triggering ESLint errors, I attempted to fix them while retaining the same intention, let me know if more changes are needed. **Cloud Security changes** - ESLint rule added to enforce handling `waitFor` on React Testing Library. - Updated cloud security posture version to include agentless global tags on End to End tests **@elastic/kibana-operations changes** - Added [eslint-plugin-testing-library](https://testing-library.com/docs/ecosystem-eslint-plugin-testing-library/) an ESLint plugin for Testing Library that helps users to follow best practices and anticipate common mistakes when writing tests. - The adoption and enablement of the rules are opt-in.
This commit is contained in:
parent
8ebe78857b
commit
5ab59fba40
9 changed files with 303 additions and 165 deletions
12
.eslintrc.js
12
.eslintrc.js
|
@ -1026,7 +1026,9 @@ module.exports = {
|
|||
*/
|
||||
{
|
||||
files: ['x-pack/plugins/fleet/**/*.{js,mjs,ts,tsx}'],
|
||||
plugins: ['testing-library'],
|
||||
rules: {
|
||||
'testing-library/await-async-utils': 'error',
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'import/order': [
|
||||
'warn',
|
||||
|
@ -1954,6 +1956,16 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Cloud Security Team overrides
|
||||
*/
|
||||
{
|
||||
files: ['x-pack/plugins/cloud_security_posture/**/*.{js,mjs,ts,tsx}'],
|
||||
plugins: ['testing-library'],
|
||||
rules: {
|
||||
'testing-library/await-async-utils': 'error',
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Code inside .buildkite runs separately from everything else in CI, before bootstrap, with ts-node. It needs a few tweaks because of this.
|
||||
*/
|
||||
|
|
|
@ -1714,6 +1714,7 @@
|
|||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-perf": "^3.3.1",
|
||||
"eslint-plugin-testing-library": "^6.4.0",
|
||||
"eslint-traverse": "^1.0.0",
|
||||
"exit-hook": "^2.2.0",
|
||||
"expect": "^29.7.0",
|
||||
|
|
|
@ -174,4 +174,4 @@ export const SINGLE_ACCOUNT = 'single-account';
|
|||
|
||||
export const CLOUD_SECURITY_PLUGIN_VERSION = '1.9.0';
|
||||
// Cloud Credentials Template url was implemented in 1.10.0-preview01. See PR - https://github.com/elastic/integrations/pull/9828
|
||||
export const CLOUD_CREDENTIALS_PACKAGE_VERSION = '1.11.0-preview10';
|
||||
export const CLOUD_CREDENTIALS_PACKAGE_VERSION = '1.11.0-preview13';
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { act, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { waitFor, act } from '@testing-library/react';
|
||||
|
||||
import { userEvent } from '@testing-library/user-event';
|
||||
|
||||
import { getInheritedNamespace } from '../../../../../../../../common/services';
|
||||
|
||||
|
@ -60,18 +62,6 @@ describe('StepDefinePackagePolicy', () => {
|
|||
package_policies: [],
|
||||
is_protected: false,
|
||||
},
|
||||
{
|
||||
id: 'agent-policy-2',
|
||||
namespace: 'default',
|
||||
name: 'Agent policy 2',
|
||||
is_managed: false,
|
||||
status: 'active',
|
||||
updated_at: '',
|
||||
updated_by: '',
|
||||
revision: 1,
|
||||
package_policies: [],
|
||||
is_protected: false,
|
||||
},
|
||||
];
|
||||
let packagePolicy: NewPackagePolicy;
|
||||
const mockUpdatePackagePolicy = jest.fn().mockImplementation((val: any) => {
|
||||
|
@ -86,20 +76,23 @@ describe('StepDefinePackagePolicy', () => {
|
|||
description: null,
|
||||
namespace: null,
|
||||
inputs: {},
|
||||
vars: {},
|
||||
vars: {
|
||||
'Required var': ['Required var is required'],
|
||||
},
|
||||
};
|
||||
|
||||
let testRenderer: TestRenderer;
|
||||
let renderResult: ReturnType<typeof testRenderer.render>;
|
||||
const render = () =>
|
||||
|
||||
const render = (namespacePlaceholder = getInheritedNamespace(agentPolicies)) =>
|
||||
(renderResult = testRenderer.render(
|
||||
<StepDefinePackagePolicy
|
||||
namespacePlaceholder={getInheritedNamespace(agentPolicies)}
|
||||
namespacePlaceholder={namespacePlaceholder}
|
||||
packageInfo={packageInfo}
|
||||
packagePolicy={packagePolicy}
|
||||
updatePackagePolicy={mockUpdatePackagePolicy}
|
||||
validationResults={validationResults}
|
||||
submitAttempted={false}
|
||||
submitAttempted={true}
|
||||
/>
|
||||
));
|
||||
|
||||
|
@ -107,57 +100,100 @@ describe('StepDefinePackagePolicy', () => {
|
|||
packagePolicy = {
|
||||
name: '',
|
||||
description: 'desc',
|
||||
namespace: 'default',
|
||||
namespace: 'package-policy-ns',
|
||||
enabled: true,
|
||||
policy_id: '',
|
||||
policy_ids: [''],
|
||||
enabled: true,
|
||||
package: {
|
||||
name: 'apache',
|
||||
title: 'Apache',
|
||||
version: '1.0.0',
|
||||
},
|
||||
inputs: [],
|
||||
vars: {
|
||||
'Show user var': {
|
||||
type: 'string',
|
||||
value: 'showUserVarVal',
|
||||
},
|
||||
'Required var': {
|
||||
type: 'bool',
|
||||
value: undefined,
|
||||
},
|
||||
'Advanced var': {
|
||||
type: 'bool',
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
testRenderer = createFleetTestRendererMock();
|
||||
});
|
||||
|
||||
describe('default API response', () => {
|
||||
beforeEach(() => {
|
||||
render();
|
||||
});
|
||||
|
||||
it('should display vars coming from package policy', async () => {
|
||||
waitFor(() => {
|
||||
expect(renderResult.getByDisplayValue('showUserVarVal')).toBeInTheDocument();
|
||||
expect(renderResult.getByRole('switch')).toHaveAttribute('aria-label', 'Required var');
|
||||
expect(renderResult.getByText('Required var is required')).toHaveAttribute(
|
||||
'class',
|
||||
'euiFormErrorText'
|
||||
act(() => {
|
||||
render();
|
||||
});
|
||||
expect(renderResult.getByDisplayValue('showUserVarVal')).toBeInTheDocument();
|
||||
expect(renderResult.getByRole('switch', { name: 'Required var' })).toBeInTheDocument();
|
||||
expect(renderResult.queryByRole('switch', { name: 'Advanced var' })).not.toBeInTheDocument();
|
||||
|
||||
expect(renderResult.getByText('Required var is required')).toHaveClass('euiFormErrorText');
|
||||
|
||||
await userEvent.click(renderResult.getByText('Advanced options').closest('button')!);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(renderResult.getByRole('switch', { name: 'Advanced var' })).toBeInTheDocument();
|
||||
expect(renderResult.getByTestId('packagePolicyNamespaceInput')).toHaveTextContent(
|
||||
'package-policy-ns'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(renderResult.getByText('Advanced options').closest('button')!);
|
||||
it(`should display namespace from agent policy when there's no package policy namespace`, async () => {
|
||||
packagePolicy.namespace = '';
|
||||
act(() => {
|
||||
render();
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
expect(renderResult.getByRole('switch')).toHaveAttribute('aria-label', 'Advanced var');
|
||||
expect(renderResult.getByTestId('packagePolicyNamespaceInput')).toHaveAttribute(
|
||||
await userEvent.click(renderResult.getByText('Advanced options').closest('button')!);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(renderResult.getByTestId('comboBoxSearchInput')).toHaveAttribute(
|
||||
'placeholder',
|
||||
'ns'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should fallback to the default namespace when namespace is not set in package policy and there's no agent policy`, async () => {
|
||||
packagePolicy.namespace = '';
|
||||
act(() => {
|
||||
render(getInheritedNamespace([]));
|
||||
});
|
||||
|
||||
await userEvent.click(renderResult.getByText('Advanced options').closest('button')!);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(renderResult.getByTestId('comboBoxSearchInput')).toHaveAttribute(
|
||||
'placeholder',
|
||||
'default'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
describe('when package vars are introduced in a new package version', () => {
|
||||
it('should display new package vars', () => {
|
||||
render();
|
||||
it('should display new package vars', async () => {
|
||||
act(() => {
|
||||
render();
|
||||
});
|
||||
expect(renderResult.getByDisplayValue('showUserVarVal')).toBeInTheDocument();
|
||||
expect(renderResult.getByText('Required var')).toBeInTheDocument();
|
||||
|
||||
waitFor(async () => {
|
||||
expect(renderResult.getByDisplayValue('showUserVarVal')).toBeInTheDocument();
|
||||
expect(renderResult.getByText('Required var')).toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(renderResult.getByText('Advanced options').closest('button')!);
|
||||
});
|
||||
await userEvent.click(renderResult.getByText('Advanced options').closest('button')!);
|
||||
|
||||
await waitFor(async () => {
|
||||
expect(renderResult.getByText('Advanced var')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { act, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
|
||||
import { userEvent } from '@testing-library/user-event';
|
||||
|
||||
import type { TestRenderer } from '../../../../../../../mock';
|
||||
import { createFleetTestRendererMock } from '../../../../../../../mock';
|
||||
|
@ -108,22 +110,23 @@ describe('StepSelectHosts', () => {
|
|||
testRenderer = createFleetTestRendererMock();
|
||||
});
|
||||
|
||||
it('should display create form when no agent policies', () => {
|
||||
it('should display create form when no agent policies', async () => {
|
||||
(useGetAgentPolicies as jest.MockedFunction<any>).mockReturnValue({
|
||||
data: {
|
||||
items: [],
|
||||
},
|
||||
});
|
||||
(useAllNonManagedAgentPolicies as jest.MockedFunction<any>).mockReturnValue([]);
|
||||
|
||||
render();
|
||||
|
||||
waitFor(() => {
|
||||
expect(renderResult.getByText('Agent policy 1')).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(renderResult.getByText('New agent policy name')).toBeInTheDocument();
|
||||
});
|
||||
expect(renderResult.queryByRole('tablist')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display tabs with New hosts selected when agent policies exist', () => {
|
||||
it('should display tabs with New hosts selected when agent policies exist', async () => {
|
||||
(useGetAgentPolicies as jest.MockedFunction<any>).mockReturnValue({
|
||||
data: {
|
||||
items: [{ id: '1', name: 'Agent policy 1', namespace: 'default' }],
|
||||
|
@ -135,10 +138,7 @@ describe('StepSelectHosts', () => {
|
|||
|
||||
render();
|
||||
|
||||
waitFor(() => {
|
||||
expect(renderResult.getByRole('tablist')).toBeInTheDocument();
|
||||
expect(renderResult.getByText('Agent policy 3')).toBeInTheDocument();
|
||||
});
|
||||
expect(renderResult.getByRole('tablist')).toBeInTheDocument();
|
||||
expect(renderResult.getByText('New hosts').closest('button')).toHaveAttribute(
|
||||
'aria-selected',
|
||||
'true'
|
||||
|
@ -157,16 +157,15 @@ describe('StepSelectHosts', () => {
|
|||
|
||||
render();
|
||||
|
||||
waitFor(() => {
|
||||
expect(renderResult.getByRole('tablist')).toBeInTheDocument();
|
||||
});
|
||||
act(() => {
|
||||
fireEvent.click(renderResult.getByText('Existing hosts').closest('button')!);
|
||||
});
|
||||
expect(renderResult.getByRole('tablist')).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
renderResult.container.querySelector('[data-test-subj="agentPolicySelect"]')?.textContent
|
||||
).toContain('Agent policy 1');
|
||||
await userEvent.click(renderResult.getByText('Existing hosts').closest('button')!);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
renderResult.container.querySelector('[data-test-subj="agentPolicySelect"]')?.textContent
|
||||
).toContain('Agent policy 1');
|
||||
});
|
||||
});
|
||||
|
||||
it('should display dropdown without preselected value when Existing hosts selected with mulitple agent policies', async () => {
|
||||
|
@ -185,14 +184,11 @@ describe('StepSelectHosts', () => {
|
|||
|
||||
render();
|
||||
|
||||
waitFor(() => {
|
||||
expect(renderResult.getByRole('tablist')).toBeInTheDocument();
|
||||
});
|
||||
act(() => {
|
||||
fireEvent.click(renderResult.getByText('Existing hosts').closest('button')!);
|
||||
});
|
||||
expect(renderResult.getByRole('tablist')).toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
await userEvent.click(renderResult.getByText('Existing hosts').closest('button')!);
|
||||
|
||||
await waitFor(() => {
|
||||
const select = renderResult.container.querySelector('[data-test-subj="agentPolicySelect"]');
|
||||
expect((select as any)?.value).toEqual('');
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import { renderHook, act } from '@testing-library/react-hooks/dom';
|
||||
|
||||
import { waitFor } from '@testing-library/react';
|
||||
|
||||
|
@ -135,9 +135,7 @@ describe('useAgentless', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/189038
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/192126
|
||||
describe.skip('useSetupTechnology', () => {
|
||||
describe('useSetupTechnology', () => {
|
||||
const setNewAgentPolicy = jest.fn();
|
||||
const updateAgentPoliciesMock = jest.fn();
|
||||
const setSelectedPolicyTabMock = jest.fn();
|
||||
|
@ -298,7 +296,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
});
|
||||
|
||||
it('should fetch agentless policy if agentless feature is enabled and isServerless is true', async () => {
|
||||
const { waitForNextUpdate } = renderHook(() =>
|
||||
renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
|
@ -308,9 +306,9 @@ describe.skip('useSetupTechnology', () => {
|
|||
})
|
||||
);
|
||||
|
||||
await waitForNextUpdate();
|
||||
|
||||
expect(sendGetOneAgentPolicy).toHaveBeenCalled();
|
||||
await waitFor(() => {
|
||||
expect(sendGetOneAgentPolicy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should set agentless setup technology if agent policy supports agentless in edit page', async () => {
|
||||
|
@ -356,7 +354,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
isCloudEnabled: true,
|
||||
},
|
||||
});
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
|
@ -371,14 +369,13 @@ describe.skip('useSetupTechnology', () => {
|
|||
act(() => {
|
||||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS);
|
||||
});
|
||||
|
||||
waitForNextUpdate();
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS);
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
name: 'Agentless policy for endpoint-1',
|
||||
supports_agentless: true,
|
||||
inactivity_timeout: 3600,
|
||||
await waitFor(() => {
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS);
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
name: 'Agentless policy for endpoint-1',
|
||||
supports_agentless: true,
|
||||
inactivity_timeout: 3600,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -396,22 +393,21 @@ describe.skip('useSetupTechnology', () => {
|
|||
isCloudEnabled: true,
|
||||
},
|
||||
});
|
||||
const { result, rerender } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
updateAgentPolicies: updateAgentPoliciesMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
})
|
||||
);
|
||||
|
||||
await rerender();
|
||||
const initialProps = {
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
updateAgentPolicies: updateAgentPoliciesMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
};
|
||||
|
||||
const { result, rerender } = renderHook((props = initialProps) => useSetupTechnology(props), {
|
||||
initialProps,
|
||||
});
|
||||
|
||||
expect(generateNewAgentPolicyWithDefaults).toHaveBeenCalled();
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
|
||||
act(() => {
|
||||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS);
|
||||
});
|
||||
|
@ -434,7 +430,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
},
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
name: 'Agentless policy for endpoint-2',
|
||||
inactivity_timeout: 3600,
|
||||
|
@ -451,7 +447,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
|
@ -467,8 +463,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENT_BASED);
|
||||
});
|
||||
|
||||
waitForNextUpdate();
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledTimes(0);
|
||||
await waitFor(() => expect(setNewAgentPolicy).toHaveBeenCalledTimes(0));
|
||||
});
|
||||
|
||||
it('should not fetch agentless policy if agentless is enabled but serverless is disabled', async () => {
|
||||
|
@ -493,7 +488,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
});
|
||||
|
||||
it('should update agent policy and selected policy tab when setup technology is agentless', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
|
@ -503,18 +498,24 @@ describe.skip('useSetupTechnology', () => {
|
|||
})
|
||||
);
|
||||
|
||||
await waitForNextUpdate();
|
||||
|
||||
act(() => {
|
||||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS);
|
||||
});
|
||||
|
||||
expect(updateAgentPoliciesMock).toHaveBeenCalledWith([{ id: 'agentless-policy-id' }]);
|
||||
expect(setSelectedPolicyTabMock).toHaveBeenCalledWith(SelectedPolicyTab.EXISTING);
|
||||
await waitFor(() => {
|
||||
expect(updateAgentPoliciesMock).toHaveBeenCalledWith([
|
||||
{
|
||||
inactivity_timeout: 3600,
|
||||
name: 'Agentless policy for endpoint-1',
|
||||
supports_agentless: true,
|
||||
},
|
||||
]);
|
||||
expect(setSelectedPolicyTabMock).toHaveBeenCalledWith(SelectedPolicyTab.EXISTING);
|
||||
});
|
||||
});
|
||||
|
||||
it('should update new agent policy and selected policy tab when setup technology is agent-based', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
|
@ -524,8 +525,6 @@ describe.skip('useSetupTechnology', () => {
|
|||
})
|
||||
);
|
||||
|
||||
await waitForNextUpdate();
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
|
||||
act(() => {
|
||||
|
@ -540,8 +539,10 @@ describe.skip('useSetupTechnology', () => {
|
|||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith(newAgentPolicyMock);
|
||||
expect(setSelectedPolicyTabMock).toHaveBeenCalledWith(SelectedPolicyTab.NEW);
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith(newAgentPolicyMock);
|
||||
expect(setSelectedPolicyTabMock).toHaveBeenCalledWith(SelectedPolicyTab.NEW);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not update agent policy and selected policy tab when agentless is disabled', async () => {
|
||||
|
@ -569,7 +570,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
});
|
||||
|
||||
it('should not update agent policy and selected policy tab when setup technology matches the current one ', async () => {
|
||||
const { result, waitForNextUpdate } = renderHook(() =>
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
|
@ -579,7 +580,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
})
|
||||
);
|
||||
|
||||
await waitForNextUpdate();
|
||||
await waitFor(() => new Promise((resolve) => resolve(null)));
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
|
||||
|
@ -594,7 +595,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
});
|
||||
|
||||
it('should revert the agent policy name to the original value when switching from agentless back to agent-based', async () => {
|
||||
const { result, rerender } = renderHook(() =>
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
|
@ -603,7 +604,6 @@ describe.skip('useSetupTechnology', () => {
|
|||
packagePolicy: packagePolicyMock,
|
||||
})
|
||||
);
|
||||
await rerender();
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
|
||||
|
@ -612,20 +612,24 @@ describe.skip('useSetupTechnology', () => {
|
|||
});
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS);
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
id: 'agentless-policy-id',
|
||||
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
name: 'Agentless policy for endpoint-1',
|
||||
supports_agentless: true,
|
||||
inactivity_timeout: 3600,
|
||||
});
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENT_BASED);
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith(newAgentPolicyMock);
|
||||
});
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith(newAgentPolicyMock);
|
||||
});
|
||||
|
||||
it('should have global_data_tags with the integration team when updating the agentless policy', async () => {
|
||||
it('should have global_data_tags with the integration team when creating agentless policy with global_data_tags', async () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
|
@ -648,8 +652,6 @@ describe.skip('useSetupTechnology', () => {
|
|||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
packageInfo: packageInfoMock,
|
||||
isEditPage: true,
|
||||
agentPolicies: [{ id: 'agentless-policy-id', supports_agentless: true } as any],
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -657,20 +659,21 @@ describe.skip('useSetupTechnology', () => {
|
|||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS, 'cspm');
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
...newAgentPolicyMock,
|
||||
supports_agentless: true,
|
||||
global_data_tags: [
|
||||
{ name: 'organization', value: 'org' },
|
||||
{ name: 'division', value: 'div' },
|
||||
{ name: 'team', value: 'team' },
|
||||
],
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
supports_agentless: true,
|
||||
global_data_tags: [
|
||||
{ name: 'organization', value: 'org' },
|
||||
{ name: 'division', value: 'div' },
|
||||
{ name: 'team', value: 'team' },
|
||||
],
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not fail and not have global_data_tags when updating the agentless policy when it cannot find the policy template', async () => {
|
||||
it('should not fail and not have global_data_tags when creating the agentless policy when it cannot find the policy template', async () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
|
@ -692,8 +695,7 @@ describe.skip('useSetupTechnology', () => {
|
|||
updateAgentPolicies: updateAgentPoliciesMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
isEditPage: true,
|
||||
agentPolicies: [{ id: 'agentless-policy-id', supports_agentless: true } as any],
|
||||
packageInfo: packageInfoMock,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -704,15 +706,23 @@ describe.skip('useSetupTechnology', () => {
|
|||
);
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
...newAgentPolicyMock,
|
||||
name: 'Agentless policy for endpoint-1',
|
||||
supports_agentless: true,
|
||||
inactivity_timeout: 3600,
|
||||
});
|
||||
expect(setNewAgentPolicy).not.toHaveBeenCalledWith({
|
||||
global_data_tags: [
|
||||
{ name: 'organization', value: 'org' },
|
||||
{ name: 'division', value: 'div' },
|
||||
{ name: 'team', value: 'team' },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not fail and not have global_data_tags when updating the agentless policy without the policy temaplte name', async () => {
|
||||
it('should not fail and not have global_data_tags when creating the agentless policy without the policy template name', async () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
|
@ -735,8 +745,6 @@ describe.skip('useSetupTechnology', () => {
|
|||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
packageInfo: packageInfoMock,
|
||||
isEditPage: true,
|
||||
agentPolicies: [{ id: 'agentless-policy-id', supports_agentless: true } as any],
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -744,15 +752,23 @@ describe.skip('useSetupTechnology', () => {
|
|||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS);
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
...newAgentPolicyMock,
|
||||
name: 'Agentless policy for endpoint-1',
|
||||
supports_agentless: true,
|
||||
inactivity_timeout: 3600,
|
||||
});
|
||||
expect(setNewAgentPolicy).not.toHaveBeenCalledWith({
|
||||
global_data_tags: [
|
||||
{ name: 'organization', value: 'org' },
|
||||
{ name: 'division', value: 'div' },
|
||||
{ name: 'team', value: 'team' },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not fail and not have global_data_tags when updating the agentless policy without the packageInfo', async () => {
|
||||
it('should not fail and not have global_data_tags when creating the agentless policy without the packageInfo', async () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
|
@ -774,8 +790,6 @@ describe.skip('useSetupTechnology', () => {
|
|||
updateAgentPolicies: updateAgentPoliciesMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
isEditPage: true,
|
||||
agentPolicies: [{ id: 'agentless-policy-id', supports_agentless: true } as any],
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -783,10 +797,77 @@ describe.skip('useSetupTechnology', () => {
|
|||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS, 'cspm');
|
||||
});
|
||||
|
||||
waitFor(() => {
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith({
|
||||
...newAgentPolicyMock,
|
||||
name: 'Agentless policy for endpoint-1',
|
||||
supports_agentless: true,
|
||||
inactivity_timeout: 3600,
|
||||
});
|
||||
expect(setNewAgentPolicy).not.toHaveBeenCalledWith({
|
||||
global_data_tags: [
|
||||
{ name: 'organization', value: 'org' },
|
||||
{ name: 'division', value: 'div' },
|
||||
{ name: 'team', value: 'team' },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not have global_data_tags when switching from agentless to agent-based policy', async () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
api: {
|
||||
url: 'https://agentless.api.url',
|
||||
},
|
||||
},
|
||||
} as any);
|
||||
(useStartServices as MockFn).mockReturnValue({
|
||||
cloud: {
|
||||
isCloudEnabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
updateAgentPolicies: updateAgentPoliciesMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
packageInfo: packageInfoMock,
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENTLESS, 'cspm');
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
supports_agentless: true,
|
||||
global_data_tags: [
|
||||
{ name: 'organization', value: 'org' },
|
||||
{ name: 'division', value: 'div' },
|
||||
{ name: 'team', value: 'team' },
|
||||
],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.handleSetupTechnologyChange(SetupTechnology.AGENT_BASED);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(setNewAgentPolicy).toHaveBeenCalledWith(newAgentPolicyMock);
|
||||
expect(setNewAgentPolicy).not.toHaveBeenCalledWith({
|
||||
global_data_tags: [
|
||||
{ name: 'organization', value: 'org' },
|
||||
{ name: 'division', value: 'div' },
|
||||
{ name: 'team', value: 'team' },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -180,6 +180,7 @@ export function useSetupTechnology({
|
|||
} as NewAgentPolicy;
|
||||
|
||||
setNewAgentPolicy(agentlessPolicy);
|
||||
setNewAgentlessPolicy(agentlessPolicy);
|
||||
setSelectedPolicyTab(SelectedPolicyTab.NEW);
|
||||
updateAgentPolicies([agentlessPolicy] as AgentPolicy[]);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { act, fireEvent, waitFor } from '@testing-library/react';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
|
||||
import { userEvent } from '@testing-library/user-event';
|
||||
|
||||
import type { TestRenderer } from '../../../../../../mock';
|
||||
import { createFleetTestRendererMock } from '../../../../../../mock';
|
||||
|
@ -111,18 +113,18 @@ describe('StepEditHosts', () => {
|
|||
testRenderer = createFleetTestRendererMock();
|
||||
});
|
||||
|
||||
it('should display create form when no agent policies', () => {
|
||||
it('should display create form when no agent policies', async () => {
|
||||
(useGetAgentPolicies as jest.MockedFunction<any>).mockReturnValue({
|
||||
data: {
|
||||
items: [],
|
||||
},
|
||||
});
|
||||
|
||||
(useAllNonManagedAgentPolicies as jest.MockedFunction<any>).mockReturnValue([]);
|
||||
|
||||
render();
|
||||
|
||||
waitFor(() => {
|
||||
expect(renderResult.getByText('Agent policy 1')).toBeInTheDocument();
|
||||
});
|
||||
expect(renderResult.getByText('New agent policy name')).toBeInTheDocument();
|
||||
expect(renderResult.queryByRole('tablist')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -144,7 +146,7 @@ describe('StepEditHosts', () => {
|
|||
).toContain('Agent policy 1');
|
||||
});
|
||||
|
||||
it('should display dropdown without preselected value when mulitple agent policies', () => {
|
||||
it('should display dropdown without preselected value when multiple agent policies', async () => {
|
||||
(useGetAgentPolicies as jest.MockedFunction<any>).mockReturnValue({
|
||||
data: {
|
||||
items: [
|
||||
|
@ -156,12 +158,12 @@ describe('StepEditHosts', () => {
|
|||
|
||||
render();
|
||||
|
||||
waitFor(() => {
|
||||
expect(renderResult.getByText('At least one agent policy is required.')).toBeInTheDocument();
|
||||
});
|
||||
expect(
|
||||
renderResult.getByText('Select an agent policy to add this integration to')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display delete button when add button clicked', () => {
|
||||
it('should display delete button when add button clicked', async () => {
|
||||
(useGetAgentPolicies as jest.MockedFunction<any>).mockReturnValue({
|
||||
data: {
|
||||
items: [{ id: '1', name: 'Agent policy 1', namespace: 'default' }],
|
||||
|
@ -173,10 +175,12 @@ describe('StepEditHosts', () => {
|
|||
|
||||
render();
|
||||
|
||||
act(() => {
|
||||
fireEvent.click(renderResult.getByTestId('createNewAgentPolicyButton').closest('button')!);
|
||||
});
|
||||
await userEvent.click(
|
||||
renderResult.getByTestId('createNewAgentPolicyButton').closest('button')!
|
||||
);
|
||||
|
||||
expect(renderResult.getByTestId('deleteNewAgentPolicyButton')).toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(renderResult.getByTestId('deleteNewAgentPolicyButton')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11724,7 +11724,7 @@
|
|||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^6.18.1":
|
||||
"@typescript-eslint/utils@5.62.0", "@typescript-eslint/utils@^5.10.0", "@typescript-eslint/utils@^5.62.0", "@typescript-eslint/utils@^6.18.1":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86"
|
||||
integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==
|
||||
|
@ -17472,6 +17472,13 @@ eslint-plugin-react@^7.32.2:
|
|||
semver "^6.3.0"
|
||||
string.prototype.matchall "^4.0.8"
|
||||
|
||||
eslint-plugin-testing-library@^6.4.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.4.0.tgz#1ba8a7422e3e31cc315a73ff17c34908f56f9838"
|
||||
integrity sha512-yeWF+YgCgvNyPNI9UKnG0FjeE2sk93N/3lsKqcmR8dSfeXJwFT5irnWo7NjLf152HkRzfoFjh3LsBUrhvFz4eA==
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "^5.62.0"
|
||||
|
||||
eslint-rule-composer@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue