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

[8.x] 10973 migrate flaky e2e tests to jest 2 (#211363) #211587

Merged
merged 2 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('NoVulnerabilitiesStates', () => {
expect(button).toHaveAttribute('href', expect.stringContaining(cnvmintegrationLink));
});

it('Vulnerabilities - `Add Wiz integration`: should have link element to CNVM integration installation page', async () => {
it('Vulnerabilities - `Add Wiz integration`: should have link element to wiz integration installation page', async () => {
await waitFor(() =>
expect(screen.getByText(/Already using a\s+cloud security product?/i)).toBeInTheDocument()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ describe('<Findings />', () => {
expect(screen.getByText(/add kspm integration/i)).toBeInTheDocument();
});

it('verifies CSPM and KSPM integration buttons have link and are clickable', async () => {
server.use(statusHandlers.notInstalledHandler);
renderFindingsPage();

expect(screen.getByText(/loading/i)).toBeInTheDocument();
const cspmButton = await waitFor(() =>
screen.getByRole('link', { name: /add cspm integration/i })
);
const kspmButton = await waitFor(() =>
screen.getByRole('link', { name: /add kspm integration/i })
);

expect(cspmButton).toHaveAttribute('href', expect.stringContaining('add-integration/cspm'));
expect(cspmButton).toBeEnabled();
expect(kspmButton).toHaveAttribute('href', expect.stringContaining('add-integration/kspm'));
expect(kspmButton).toBeEnabled();
});

it("renders the 'latest misconfigurations findings' DataTable component when the CSPM/KSPM integration status is not installed but there are findings", async () => {
const finding1 = generateCspFinding('0003', 'failed');
const finding2 = generateCspFinding('0004', 'passed');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/
export * from './rules_counters.mock';
export * from './rules_table_headers.mock';
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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.
*/

export const benchmarkValuesMock = {
integrationType: 'KSPM',
integrationName: 'EKS',
resourceName: 'Clusters',
resourceCountLabel: 'clusters',
integrationLink: '/kbn/app/fleet/integrations/cloud_security_posture-1.12.0/add-integration/kspm',
learnMoreLink: 'https://ela.st/kspm-get-started',
};

export const itemsDataMock = [
{
id: 'cis_k8s',
name: 'CIS Kubernetes V1.23',
version: '1.0.1',
score: {
totalFailed: 47,
totalPassed: 321,
totalFindings: 368,
postureScore: 87.2,
resourcesEvaluated: 180,
},
evaluation: 1,
},
{
id: 'cis_azure',
name: 'CIS Microsoft Azure Foundations',
version: '2.0.0',
score: {
totalFailed: 0,
totalPassed: 0,
totalFindings: 0,
postureScore: 0,
},
evaluation: 0,
},
{
id: 'cis_gcp',
name: 'CIS Google Cloud Platform Foundation',
version: '2.0.0',
score: {
totalFailed: 366,
totalPassed: 62,
totalFindings: 428,
postureScore: 14.5,
resourcesEvaluated: 376,
},
evaluation: 1,
},
{
id: 'cis_aws',
name: 'CIS Amazon Web Services Foundations',
version: '1.5.0',
score: {
totalFailed: 0,
totalPassed: 0,
totalFindings: 0,
postureScore: 0,
},
evaluation: 0,
},
{
id: 'cis_eks',
name: 'CIS Amazon Elastic Kubernetes Service (EKS)',
version: '1.0.1',
score: {
totalFailed: 20,
totalPassed: 62,
totalFindings: 82,
postureScore: 75.6,
resourcesEvaluated: 14,
},
evaluation: 1,
},
];

export const paramsMock = {
benchmarkId: 'cis_eks',
benchmarkVersion: '1.0.1',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* 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.
*/

export const selectRulesMock = [
{
metadata: {
impact:
'Audit logs will be created on the master nodes, which will consume disk space. Care should be taken to avoid generating too large volumes of log information as this could impact the available of the cluster nodes.\nS3 lifecycle features can be used to manage the accumulation and management of logs over time. \n\nSee the following AWS resource for more information on these features:\nhttp://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html',
default_value:
"By default, cluster control plane logs aren't sent to CloudWatch Logs. ... When you enable a log type, the logs are sent with a log verbosity level of 2 . To enable or disable control plane logs with the console. Open the Amazon EKS console at https://console.aws.amazon.com/eks/home#/clusters . Amazon EKS Information in CloudTrail CloudTrail is enabled on your AWS account when you create the account. When activity occurs in Amazon EKS, that activity is recorded in a CloudTrail event along with other AWS service events in Event history.\n",
references:
'1. https://kubernetes.io/docs/tasks/debug-application-cluster/audit/\n2. https://aws.github.io/aws-eks-best-practices/detective/\n3. https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html\n4. https://docs.aws.amazon.com/eks/latest/userguide/logging-using-cloudtrail.html',
id: '66cd0518-cfa3-5917-a399-a7dfde4e19db',
name: 'Enable audit Logs',
profile_applicability: '* Level 1',
description:
'The audit logs are part of the EKS managed Kubernetes control plane logs that are managed by Amazon EKS.\nAmazon EKS is integrated with AWS CloudTrail, a service that provides a record of actions taken by a user, role, or an AWS service in Amazon EKS.\nCloudTrail captures all API calls for Amazon EKS as events.\nThe calls captured include calls from the Amazon EKS console and code calls to the Amazon EKS API operations.',
rationale:
'Exporting logs and metrics to a dedicated, persistent datastore such as CloudTrail ensures availability of audit data following a cluster security event, and provides a central location for analysis of log and metric data collated from multiple sources.',
audit:
'Perform the following to determine if CloudTrail is enabled for all regions:\n\n**Via the Management Console**\n\n1. Sign in to the AWS Management Console and open the EKS console at https://console.aws.amazon.com/eks\n2. Click on Cluster Name of the cluster you are auditing\n3. Click Logging\n You will see Control Plane Logging info\n\n ```\n API Server Audit Authenticator\n Enabled/Disabled Enabled/Disabled Enabled/Disabled\n\n Controller Manager Scheduler\n Enabled/Disabled Enabled/Disabled\n```\n4. Ensure all 5 choices are set to Enabled',
remediation:
'Perform the following to determine if CloudTrail is enabled for all regions:\n\n**Via The Management Console**\n\n1. Sign in to the AWS Management Console and open the EKS console at https://console.aws.amazon.com/eks\n2. Click on Cluster Name of the cluster you are auditing\n3. Click Logging\n4. Select Manage Logging from the button on the right hand side\n5. Toggle each selection to the Enabled position.\n6. Click Save Changes\n\n**Via CLI**\n\n`aws --region "${REGION_CODE}" eks describe-cluster --name "${CLUSTER_NAME}" --query \'cluster.logging.clusterLogging[?enabled==true].types`',
section: 'Logging',
version: '1.0',
tags: ['CIS', 'EKS', 'CIS 2.1.1', 'Logging'],
benchmark: {
name: 'CIS Amazon Elastic Kubernetes Service (EKS)',
version: 'v1.0.1',
id: 'cis_eks',
rule_number: '2.1.1',
posture_type: 'kspm',
},
rego_rule_id: 'cis_2_1_1',
},
state: 'unmuted',
},
{
metadata: {
impact: 'None.',
default_value: 'See the AWS EKS documentation for the default value.\n',
references: '1. https://kubernetes.io/docs/admin/kube-proxy/',
id: '90b8ae5e-df30-5ba6-9fe9-03aab2b7a1c3',
name: 'Ensure that the kubeconfig file permissions are set to 644 or more restrictive',
profile_applicability: '* Level 1',
description:
'If `kubelet` is running, and if it is using a file-based kubeconfig file, ensure that the proxy kubeconfig file has permissions of `644` or more restrictive.',
rationale:
'The `kubelet` kubeconfig file controls various parameters of the `kubelet` service in the worker node.\nYou should restrict its file permissions to maintain the integrity of the file.\nThe file should be writable by only the administrators on the system.\n\nIt is possible to run `kubelet` with the kubeconfig parameters configured as a Kubernetes ConfigMap instead of a file.\nIn this case, there is no proxy kubeconfig file.',
audit:
"SSH to the worker nodes\n\nTo check to see if the Kubelet Service is running:\n```\nsudo systemctl status kubelet\n```\nThe output should return `Active: active (running) since..`\n\nRun the following command on each node to find the appropriate kubeconfig file:\n\n```\nps -ef | grep kubelet\n```\nThe output of the above command should return something similar to `--kubeconfig /var/lib/kubelet/kubeconfig` which is the location of the kubeconfig file.\n\nRun this command to obtain the kubeconfig file permissions:\n\n```\nstat -c %a /var/lib/kubelet/kubeconfig\n```\nThe output of the above command gives you the kubeconfig file's permissions.\n\nVerify that if a file is specified and it exists, the permissions are `644` or more restrictive.",
remediation:
'Run the below command (based on the file location on your system) on the each worker\nnode.\nFor example,\n```\nchmod 644 <kubeconfig file>\n```',
section: 'Worker Node Configuration Files',
version: '1.0',
tags: ['CIS', 'EKS', 'CIS 3.1.1', 'Worker Node Configuration Files'],
benchmark: {
name: 'CIS Amazon Elastic Kubernetes Service (EKS)',
version: 'v1.0.1',
id: 'cis_eks',
rule_number: '3.1.1',
posture_type: 'kspm',
},
rego_rule_id: 'cis_3_1_1',
},
state: 'unmuted',
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* 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 } from '@testing-library/react';
import { RulesCounters } from './rules_counters';
import { useBenchmarkDynamicValues } from '../../common/hooks/use_benchmark_dynamic_values';
import { useParams } from 'react-router-dom';
import { RULE_COUNTERS_TEST_SUBJ } from './test_subjects';
import { useNavigateFindings } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings';
import { useCspBenchmarkIntegrationsV2 } from '../benchmarks/use_csp_benchmark_integrations';
import { useKibana } from '../../common/hooks/use_kibana';
import { within } from '@testing-library/dom';
import { cloudPosturePages } from '../../common/navigation/constants';
import { RULE_FAILED } from '../../../common/constants';
import userEvent from '@testing-library/user-event';
import { benchmarkValuesMock, itemsDataMock, paramsMock } from './__mocks__';

jest.mock('../../common/hooks/use_benchmark_dynamic_values');
jest.mock('react-router-dom', () => ({
useParams: jest.fn(),
}));
jest.mock('@kbn/cloud-security-posture/src/hooks/use_navigate_findings');
jest.mock('../benchmarks/use_csp_benchmark_integrations');
jest.mock('../../common/hooks/use_kibana');

describe('RulesCounters', () => {
const mockNavigate = jest.fn();

beforeEach(() => {
(useKibana as jest.Mock).mockReturnValue({
services: {
http: {
basePath: {
basePath: '/kbn',
serverBasePath: '/kbn',
assetsHrefBase: '/kbn/XXXXXXXXXXXX',
prepend: (path: string) => path,
},
},
charts: {
theme: {
useChartsBaseTheme: () => ({}),
},
},
},
});

(useCspBenchmarkIntegrationsV2 as jest.Mock).mockReturnValue({
status: 'success',
data: {
items: itemsDataMock,
},
});

(useBenchmarkDynamicValues as jest.Mock).mockReturnValue({
getBenchmarkDynamicValues: () => benchmarkValuesMock,
});

(useParams as jest.Mock).mockReturnValue(paramsMock);

(useNavigateFindings as jest.Mock).mockReturnValue(mockNavigate); // Store the mock function
});

it('should not show empty state and show correct posture score', () => {
render(<RulesCounters mutedRulesCount={0} setEnabledDisabledItemsFilter={() => {}} />);

expect(
screen.queryByTestId(RULE_COUNTERS_TEST_SUBJ.RULE_COUNTERS_EMPTY_STATE)
).not.toBeInTheDocument();
const postureScoreContainer = screen.getByTestId(RULE_COUNTERS_TEST_SUBJ.POSTURE_SCORE_COUNTER);

expect(within(postureScoreContainer).getByText('76%')).toBeInTheDocument();
});

it('have correct href on posture score button', () => {
render(<RulesCounters mutedRulesCount={0} setEnabledDisabledItemsFilter={() => {}} />);

const postureScoreButton = screen.getByTestId(RULE_COUNTERS_TEST_SUBJ.POSTURE_SCORE_BUTTON);
expect(postureScoreButton).toHaveAttribute(
'href',
expect.stringContaining(`/app/security${cloudPosturePages.dashboard.path}`)
);
});

it('shows integrations count when there are findings', () => {
render(<RulesCounters mutedRulesCount={0} setEnabledDisabledItemsFilter={() => {}} />);
screen.debug();
const integrationsCounter = screen.getByTestId(
RULE_COUNTERS_TEST_SUBJ.INTEGRATIONS_EVALUATED_COUNTER
);
expect(within(integrationsCounter).getByText('1')).toBeInTheDocument();
});

it('have correct href on integrations counter button', () => {
render(<RulesCounters mutedRulesCount={0} setEnabledDisabledItemsFilter={() => {}} />);

const postureScoreButton = screen.getByTestId(
RULE_COUNTERS_TEST_SUBJ.INTEGRATIONS_EVALUATED_BUTTON
);
expect(postureScoreButton).toHaveAttribute(
'href',
expect.stringContaining(benchmarkValuesMock.integrationLink)
);
});

it('shows the failed findings counter when there are findings', () => {
render(<RulesCounters mutedRulesCount={0} setEnabledDisabledItemsFilter={() => {}} />);
const failedFindingsCounter = screen.getByTestId(
RULE_COUNTERS_TEST_SUBJ.FAILED_FINDINGS_COUNTER
);
expect(within(failedFindingsCounter).getByText('20')).toBeInTheDocument();
});

it('call useNavigateFindings with correct params when clicking on failed findings button', async () => {
render(<RulesCounters mutedRulesCount={0} setEnabledDisabledItemsFilter={() => {}} />);

const failedFindingsButton = screen.getByTestId(RULE_COUNTERS_TEST_SUBJ.FAILED_FINDINGS_BUTTON);
await userEvent.click(failedFindingsButton);

expect(mockNavigate).toHaveBeenCalledWith({
'result.evaluation': RULE_FAILED,
'rule.benchmark.id': paramsMock.benchmarkId,
'rule.benchmark.version': `v${paramsMock.benchmarkVersion}`,
});
});

it('shows the disabled rules count', async () => {
render(<RulesCounters mutedRulesCount={0} setEnabledDisabledItemsFilter={() => {}} />);
const dislabedRulesCounter = screen.getByTestId(RULE_COUNTERS_TEST_SUBJ.DISABLED_RULES_COUNTER);
expect(within(dislabedRulesCounter).getByText('0')).toBeInTheDocument();
});
});
Loading