Skip to content

Commit

Permalink
[Cloud Security] 10973 migrate flaky e2e tests to jest (#208345)
Browse files Browse the repository at this point in the history
## Summary

This PR tries to fix the following issues - which are flaky FTR tests:

- #197143 - convert to unit test
- #190967 - fixed
- #187470 - fixed
- #186302 - convert to unit test
- #186438 - convert to unit test


There will be an RFC document which is going to be released to help us
better understand and decide which tests are more suitable to make as
E2E tests and which as unit tests.

### Checklist
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed

### Closes
this PR closes the above mentioned issues in relation for this ticket -
elastic/security-team#10973
  • Loading branch information
alexreal1314 authored Jan 30, 2025
1 parent 0a0a4d8 commit cd9096c
Show file tree
Hide file tree
Showing 14 changed files with 580 additions and 149 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* 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 type { MonitoringType } from '../../../../../../../../../../common/types';

export const mockAgentPolicy = {
id: '888c9a80-cae6-4675-82ad-73553cb343f9',
name: 'Agent policy 1',
description: '',
namespace: 'default',
monitoring_enabled: ['logs', 'metrics', 'traces'] as MonitoringType,
inactivity_timeout: 1209600,
is_protected: false,
status: 'active' as const, // or 'Inactive' as const
is_managed: false,
revision: 1,
updated_at: '2025-01-29T14:12:36.256Z',
updated_by: 'elastic',
schema_version: '1.1.1',
};

export const mockPackagePolicy = {
id: '5811fb40-82e4-4808-b94e-5e02158936c7',
version: 'WzgyMSwxXQ==',
name: 'cspm-1',
namespace: 'default',
description: '',
package: {
name: 'cloud_security_posture',
title: 'Security Posture Management',
version: '1.12.0',
},
enabled: true,
policy_id: '888c9a80-cae6-4675-82ad-73553cb343f9',
policy_ids: ['888c9a80-cae6-4675-82ad-73553cb343f9'],
inputs: [
{
type: 'cloudbeat/cis_k8s',
policy_template: 'kspm',
enabled: false,
streams: [
{
enabled: false,
data_stream: {
type: 'logs',
dataset: 'cloud_security_posture.findings',
},
vars: {
condition: {
type: 'text',
},
},
id: 'cloudbeat/cis_k8s-cloud_security_posture.findings-5811fb40-82e4-4808-b94e-5e02158936c7',
},
],
},
{
type: 'cloudbeat/cis_eks',
policy_template: 'kspm',
enabled: false,
streams: [
{
enabled: false,
data_stream: {
type: 'logs',
dataset: 'cloud_security_posture.findings',
},
vars: {
condition: { type: 'text' },
access_key_id: { type: 'text' },
secret_access_key: { type: 'password' },
session_token: { type: 'text' },
shared_credential_file: { type: 'text' },
credential_profile_name: { type: 'text' },
role_arn: { type: 'text' },
aws_credentials_type: { type: 'text' },
},
id: 'cloudbeat/cis_eks-cloud_security_posture.findings-5811fb40-82e4-4808-b94e-5e02158936c7',
},
],
},
{
type: 'cloudbeat/cis_aws',
policy_template: 'cspm',
enabled: true,
streams: [
{
enabled: true,
data_stream: {
type: 'logs',
dataset: 'cloud_security_posture.findings',
},
vars: {
condition: { type: 'text' },
access_key_id: { type: 'text' },
secret_access_key: { type: 'password' },
session_token: { type: 'text' },
shared_credential_file: { type: 'text' },
credential_profile_name: { type: 'text' },
role_arn: { type: 'text' },
aws_credentials_type: { value: 'cloud_formation', type: 'text' },
aws_account_type: { value: 'organization-account', type: 'text' },
aws_supports_cloud_connectors: { type: 'bool' },
},
id: 'cloudbeat/cis_aws-cloud_security_posture.findings-5811fb40-82e4-4808-b94e-5e02158936c7',
compiled_stream: {
period: '24h',
fetchers: [
{ name: 'aws-iam' },
{ name: 'aws-ec2-network' },
{ name: 'aws-s3' },
{ name: 'aws-trail' },
{ name: 'aws-monitoring' },
{ name: 'aws-rds' },
],
config: {
v1: {
type: 'cspm',
deployment: 'aws',
benchmark: 'cis_aws',
aws: {
account_type: 'organization-account',
credentials: {
type: 'cloud_formation',
},
},
},
},
},
},
],
vars: {
cloud_formation_template: {
value:
'https://console.aws.amazon.com/cloudformation/home#/stacks/quickcreate?templateURL=https://elastic-cspm-cft.s3.eu-central-1.amazonaws.com/cloudformation-cspm-ACCOUNT_TYPE-8.17.0.yml&stackName=Elastic-Cloud-Security-Posture-Management&param_EnrollmentToken=FLEET_ENROLLMENT_TOKEN&param_FleetUrl=FLEET_URL&param_ElasticAgentVersion=KIBANA_VERSION&param_ElasticArtifactServer=https://artifacts.elastic.co/downloads/beats/elastic-agent',
type: 'text',
},
},
config: {
cloud_formation_template_url: {
value:
'https://console.aws.amazon.com/cloudformation/home#/stacks/quickcreate?templateURL=https://elastic-cspm-cft.s3.eu-central-1.amazonaws.com/cloudformation-cspm-ACCOUNT_TYPE-8.17.0.yml&stackName=Elastic-Cloud-Security-Posture-Management&param_EnrollmentToken=FLEET_ENROLLMENT_TOKEN&param_FleetUrl=FLEET_URL&param_ElasticAgentVersion=KIBANA_VERSION&param_ElasticArtifactServer=https://artifacts.elastic.co/downloads/beats/elastic-agent',
},
},
},
],
vars: {
posture: { value: 'cspm', type: 'text' },
deployment: { value: 'aws', type: 'text' },
},
revision: 1,
created_at: '2025-01-29T14:12:41.393Z',
created_by: 'system',
updated_at: '2025-01-29T14:12:41.393Z',
updated_by: 'system',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* 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 { fireEvent, render, screen } from '@testing-library/react';
import { useQuery } from '@tanstack/react-query';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';

import { PostInstallCloudFormationModal } from '../post_install_cloud_formation_modal';
import { useAgentPolicyWithPackagePolicies } from '../../../../../../../../../components/agent_enrollment_flyout/hooks';
import { useFleetServerHostsForPolicy } from '../../../../../../../../../hooks';

import { useCreateCloudFormationUrl } from '../../../../../../../../../components/cloud_security_posture/hooks';

import { mockAgentPolicy, mockPackagePolicy } from './mockData';

jest.mock('@tanstack/react-query');
jest.mock('../../../../../../../../../components/agent_enrollment_flyout/hooks');
jest.mock('../../../../../../../../../hooks');
jest.mock('../../../../../../../../../components/cloud_security_posture/hooks');

describe('PostInstallCloudFormationModal', () => {
const mockOnConfirm = jest.fn();
const mockOnCancel = jest.fn();

beforeAll(() => {
(useAgentPolicyWithPackagePolicies as jest.Mock).mockReturnValue({
agentPolicyWithPackagePolicies: null,
});

(useFleetServerHostsForPolicy as jest.Mock).mockReturnValue({
fleetServerHost: 'https://any-hostname:8220',
isLoadingInitialRequest: false,
});

(useCreateCloudFormationUrl as jest.Mock).mockReturnValue({
cloudFormationUrl: 'console.aws.amazon.com/cloudformation',
});
});

it('should render the modal with confirm button enabled', () => {
(useQuery as jest.Mock).mockReturnValueOnce({
data: {
data: {
items: [{ api_key: 'test-api-key' }],
},
},
isLoading: true,
});

render(
<IntlProvider>
<PostInstallCloudFormationModal
onConfirm={mockOnConfirm}
onCancel={mockOnCancel}
agentPolicy={mockAgentPolicy}
packagePolicy={mockPackagePolicy}
/>
</IntlProvider>
);

expect(screen.getByTestId('confirmCloudFormationModalConfirmButton')).toBeInTheDocument();
});

it('should render the modal with confirm button disabled', () => {
(useQuery as jest.Mock).mockReturnValueOnce({
data: {
data: {
items: [{ api_key: 'test-api-key' }],
},
},
isLoading: true,
});

render(
<IntlProvider>
<PostInstallCloudFormationModal
onConfirm={mockOnConfirm}
onCancel={mockOnCancel}
agentPolicy={mockAgentPolicy}
packagePolicy={mockPackagePolicy}
/>
</IntlProvider>
);

expect(screen.getByTestId('confirmCloudFormationModalConfirmButton')).toBeDisabled();
});

it('should open correct cloudFormation URL', () => {
// Mock window.open
const mockWindowOpen = jest.fn();
window.open = mockWindowOpen;

(useQuery as jest.Mock).mockReturnValueOnce({
data: {
data: {
items: [{ api_key: 'test-api-key' }],
},
},
isLoading: false,
});

render(
<IntlProvider>
<PostInstallCloudFormationModal
onConfirm={mockOnConfirm}
onCancel={mockOnCancel}
agentPolicy={mockAgentPolicy}
packagePolicy={mockPackagePolicy}
/>
</IntlProvider>
);

const confirmButton = screen.getByTestId('confirmCloudFormationModalConfirmButton');
fireEvent.click(confirmButton);

expect(mockWindowOpen).toHaveBeenCalledTimes(1);
expect(mockWindowOpen).toHaveBeenCalledWith('console.aws.amazon.com/cloudformation');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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 { render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { MemoryRouter } from 'react-router-dom';
import { NoVulnerabilitiesStates } from './no_vulnerabilities_states';
import * as useCspSetupStatusApi from '@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api';
import * as useCspIntegrationLink from '../common/navigation/use_csp_integration_link';
import * as useAdd3PIntegrationRoute from '../common/api/use_wiz_integration_route';
import {
CNVM_NOT_INSTALLED_ACTION_SUBJ,
THIRD_PARTY_NO_VULNERABILITIES_FINDINGS_PROMPT_WIZ_INTEGRATION_BUTTON,
} from './test_subjects';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
import { CLOUD_SECURITY_POSTURE_BASE_PATH } from '@kbn/cloud-security-posture-common';

jest.mock('@kbn/cloud-security-posture/src/hooks/use_csp_setup_status_api');
jest.mock('../common/navigation/use_csp_integration_link');
jest.mock('../common/api/use_wiz_integration_route');

describe('NoVulnerabilitiesStates', () => {
const cnvmintegrationLink = 'fleet/integrations/cloud_security_posture/add-integration';
const thirdPartyIntegrationLink = 'fleet/integrations/wiz/add-integration';
const vulnerabilitiesPath = `${CLOUD_SECURITY_POSTURE_BASE_PATH}/findings/vulnerabilities`;

beforeAll(() => {
(useCspIntegrationLink.useCspIntegrationLink as jest.Mock).mockReturnValue(cnvmintegrationLink);
(useAdd3PIntegrationRoute.useAdd3PIntegrationRoute as jest.Mock).mockReturnValue(
thirdPartyIntegrationLink
);
});

beforeEach(() => {
(useCspSetupStatusApi.useCspSetupStatusApi as jest.Mock).mockReturnValue({
data: {
vuln_mgmt: { status: 'not-installed' },
indicesDetails: [],
},
});

render(
<MemoryRouter initialEntries={[vulnerabilitiesPath]}>
<IntlProvider>
<NoVulnerabilitiesStates />
</IntlProvider>
</MemoryRouter>
);
});

it('Vulnerabilities - `Add CNVM integration`: should have link element to CNVM integration installation page', async () => {
await waitFor(() =>
expect(
screen.getByText(/Elastics Cloud Native\s+Vulnerability Management/i)
).toBeInTheDocument()
);

// Find the button
const button = screen.getByTestId(CNVM_NOT_INSTALLED_ACTION_SUBJ);
expect(button).toBeInTheDocument();
expect(button).toHaveAttribute('href', expect.stringContaining(cnvmintegrationLink));
});

it('Vulnerabilities - `Add Wiz integration`: should have link element to CNVM integration installation page', async () => {
await waitFor(() =>
expect(screen.getByText(/Already using a\s+cloud security product?/i)).toBeInTheDocument()
);

// Find the button
const button = screen.getByTestId(
THIRD_PARTY_NO_VULNERABILITIES_FINDINGS_PROMPT_WIZ_INTEGRATION_BUTTON
);
expect(button).toBeInTheDocument();
expect(button).toHaveAttribute('href', expect.stringContaining(thirdPartyIntegrationLink));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import equals from 'fast-deep-equal';
import { AGENTLESS_SECURITY_POSTURE_PACKAGE_VERSION } from '../constants';
import type { FtrProviderContext } from '../ftr_provider_context';
import { setupMockServer } from './mock_agentless_api';
import { testSubjectIds } from '../constants/test_subject_ids';

const { CIS_AWS_OPTION_TEST_ID, AWS_SINGLE_ACCOUNT_TEST_ID } = testSubjectIds;

// eslint-disable-next-line import/no-default-export
export default function ({ getPageObjects, getService }: FtrProviderContext) {
const agentCreationTimeout = 1000 * 60 * 1; // 1 minute
Expand All @@ -24,10 +28,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
'cisAddIntegration',
]);

const CIS_AWS_OPTION_TEST_ID = 'cisAwsTestId';

const AWS_SINGLE_ACCOUNT_TEST_ID = 'awsSingleTestId';

// Failing: See https://github.com/elastic/kibana/issues/208495
describe('Agentless cloud', function () {
let cisIntegration: typeof pageObjects.cisAddIntegration;
Expand Down
Loading

0 comments on commit cd9096c

Please sign in to comment.