Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fleet] [Cloud Security] Add Testing Library ESLint for handling waitFor #198735

Merged
merged 13 commits into from
Nov 5, 2024
Merged
15 changes: 15 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -1954,6 +1956,19 @@ module.exports = {
},
},

/**
* Cloud Security Team overrides
*/
/**
* Fleet 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.
*/
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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) => {
Expand All @@ -86,11 +76,14 @@ 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 = () =>
(renderResult = testRenderer.render(
<StepDefinePackagePolicy
Expand All @@ -99,45 +92,58 @@ describe('StepDefinePackagePolicy', () => {
packagePolicy={packagePolicy}
updatePackagePolicy={mockUpdatePackagePolicy}
validationResults={validationResults}
submitAttempted={false}
submitAttempted={true}
/>
));

beforeEach(() => {
packagePolicy = {
name: '',
description: 'desc',
namespace: 'default',
namespace: undefined,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think that usually the package policies have either default or a custom namespace, I don't think it's possible to have it undefined in reality. Did you want to test something related to this field?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying it, I could see some integrations actually have empty package policy namespace, but not undefined, also they fallback to default when the namespace is empty, I updated the tests to reflect that.

it should fallback to the default namespace when namespace is not set in package policy and there's no agent policy

image

it should display namespace from agent policy when there's no package policy namespace
image

it should display vars coming from package policy
image

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();

await act(async () => {
fireEvent.click(renderResult.getByText('Advanced options').closest('button')!);
});
expect(renderResult.getByText('Required var is required')).toHaveClass('euiFormErrorText');

await userEvent.click(renderResult.getByText('Advanced options').closest('button')!);

waitFor(() => {
expect(renderResult.getByRole('switch')).toHaveAttribute('aria-label', 'Advanced var');
expect(renderResult.getByTestId('packagePolicyNamespaceInput')).toHaveAttribute(
await waitFor(() => {
expect(renderResult.getByRole('switch', { name: 'Advanced var' })).toBeInTheDocument();
expect(renderResult.getByTestId('comboBoxSearchInput')).toHaveAttribute(
'placeholder',
'ns'
);
Expand All @@ -147,17 +153,16 @@ describe('StepDefinePackagePolicy', () => {

describe('update', () => {
describe('when package vars are introduced in a new package version', () => {
it('should display new package vars', () => {
render();

waitFor(async () => {
expect(renderResult.getByDisplayValue('showUserVarVal')).toBeInTheDocument();
expect(renderResult.getByText('Required var')).toBeInTheDocument();
it('should display new package vars', async () => {
act(() => {
render();
});
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();
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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' }],
Expand All @@ -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'
Expand All @@ -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();

await userEvent.click(renderResult.getByText('Existing hosts').closest('button')!);

expect(
renderResult.container.querySelector('[data-test-subj="agentPolicySelect"]')?.textContent
).toContain('Agent policy 1');
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 () => {
Expand All @@ -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 userEvent.click(renderResult.getByText('Existing hosts').closest('button')!);

await act(async () => {
await waitFor(() => {
const select = renderResult.container.querySelector('[data-test-subj="agentPolicySelect"]');
expect((select as any)?.value).toEqual('');
});
Expand Down
Loading