Skip to content

Commit

Permalink
[Security Solution ] Fix - Inspect not working in Unified Timeline (e…
Browse files Browse the repository at this point in the history
…lastic#185924)

## Summary

Fixes 

- elastic/security-team#9598.
- elastic#181882

This PR fixes 2 issues.

### Inspect button not working
1. Inspect button was not working with Unified Timeline changes.
2. This PR Fixes that and adds test as well for same.

### Inspect Performance

Since in unified timeline we fetch 500 records at a time, the inspect
tab was facing performance issues as can be seen below:

|Before|After| 
|---|---|
|<video
src="https://github.com/elastic/kibana/assets/7485038/1f3a938b-06ab-4146-b76e-06b4c3712d47"/>|<video
src="https://github.com/elastic/kibana/assets/7485038/77833673-d904-4cb6-98ff-a67e78185520"
/>|

As a solution, `EuiCodeBlock` is being replaced with `MonacoCodeEditor`
which loads the code in lazily.
 




### Checklist

Delete any items that are not applicable to this PR.

- [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

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
logeekal and kibanamachine authored Jun 13, 2024
1 parent bd16e7e commit 584f4ee
Show file tree
Hide file tree
Showing 9 changed files with 327 additions and 270 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
* 2.0.
*/

import { mount } from 'enzyme';
import React from 'react';
import { TestProviders } from '../../mock';

import { NO_ALERT_INDEX } from '../../../../common/constants';
import type { ModalInspectProps } from './modal';
import { ModalInspectQuery, formatIndexPatternRequested } from './modal';
import { InputsModelId } from '../../store/inputs/constants';
import { fireEvent, render, screen } from '@testing-library/react';

jest.mock('react-router-dom', () => {
const original = jest.requireActual('react-router-dom');
Expand All @@ -35,61 +35,55 @@ const request = getRequest();
const response =
'{"took": 880,"timed_out": false,"_shards": {"total": 26,"successful": 26,"skipped": 0,"failed": 0},"hits": {"max_score": null,"hits": []},"aggregations": {"hosts": {"value": 541},"hosts_histogram": {"buckets": [{"key_as_string": "2019 - 07 - 05T01: 00: 00.000Z", "key": 1562288400000, "doc_count": 1492321, "count": { "value": 105 }}, {"key_as_string": "2019 - 07 - 05T13: 00: 00.000Z", "key": 1562331600000, "doc_count": 2412761, "count": { "value": 453}},{"key_as_string": "2019 - 07 - 06T01: 00: 00.000Z", "key": 1562374800000, "doc_count": 111658, "count": { "value": 15}}],"interval": "12h"}},"status": 200}';

const closeModal = jest.fn();

const defaultProps: ModalInspectProps = {
closeModal,
inputId: InputsModelId.timeline,
request,
response,
title: 'My title',
};
const renderModal = (props: ModalInspectProps = defaultProps) => {
return render(
<TestProviders>
<ModalInspectQuery {...props} />
</TestProviders>
);
};

describe('Modal Inspect', () => {
const closeModal = jest.fn();
const defaultProps: ModalInspectProps = {
closeModal,
inputId: InputsModelId.timeline,
request,
response,
title: 'My title',
};
describe('functionality from tab statistics', () => {
test('should show statistics tab correctly', () => {
renderModal();

fireEvent.click(screen.getByTestId('modal-inspect-statistics-tab'));
expect(screen.getByTestId('modal-inspect-statistics-tab')).toHaveAttribute(
'aria-selected',
'true'
);

describe('functionality from tab statistics/request/response', () => {
test('Click on statistic Tab', () => {
const wrapper = mount(
<TestProviders>
<ModalInspectQuery {...defaultProps} />
</TestProviders>
expect(screen.getByTestId('index-pattern-title')).toHaveTextContent('Index pattern');
expect(screen.getByTestId('index-pattern-description')).toHaveTextContent(
'auditbeat-*, filebeat-*, packetbeat-*, winlogbeat-*'
);
expect(screen.getByTestId('query-time-title')).toHaveTextContent('Query time');

wrapper.find('button.euiTab').first().simulate('click');
wrapper.update();

expect(
wrapper.find('.euiDescriptionList__title span[data-test-subj="index-pattern-title"]').text()
).toContain('Index pattern ');
expect(
wrapper
.find('.euiDescriptionList__description span[data-test-subj="index-pattern-description"]')
.text()
).toBe('auditbeat-*, filebeat-*, packetbeat-*, winlogbeat-*');
expect(
wrapper.find('.euiDescriptionList__title span[data-test-subj="query-time-title"]').text()
).toContain('Query time ');
expect(
wrapper
.find('.euiDescriptionList__description span[data-test-subj="query-time-description"]')
.text()
).toBe('880ms');
expect(
wrapper
.find('.euiDescriptionList__title span[data-test-subj="request-timestamp-title"]')
.text()
).toContain('Request timestamp ');
expect(screen.getByTestId('query-time-description')).toHaveTextContent('880ms');
expect(screen.getByTestId('request-timestamp-title')).toHaveTextContent('Request timestamp');
});

test('Click on request Tab', () => {
const wrapper = mount(
<TestProviders>
<ModalInspectQuery {...defaultProps} />
</TestProviders>
);
test('should show response Tab content correctly', () => {
renderModal();

wrapper.find('button.euiTab').at(2).simulate('click');
wrapper.update();
fireEvent.click(screen.getByTestId('modal-inspect-response-tab'));
expect(screen.getByTestId('modal-inspect-response-tab')).toHaveAttribute(
'aria-selected',
'true'
);

expect(JSON.parse(wrapper.find('EuiCodeBlock').text())).toEqual({
const responseTextContent = screen.getByRole('tabpanel').textContent ?? '';
expect(JSON.parse(responseTextContent)).toMatchObject({
took: 880,
timed_out: false,
_shards: {
Expand Down Expand Up @@ -140,17 +134,18 @@ describe('Modal Inspect', () => {
});
});

test('Click on response Tab', () => {
const wrapper = mount(
<TestProviders>
<ModalInspectQuery {...defaultProps} />
</TestProviders>
test('should show request tab correctly', () => {
renderModal();

fireEvent.click(screen.getByTestId('modal-inspect-request-tab'));
expect(screen.getByTestId('modal-inspect-request-tab')).toHaveAttribute(
'aria-selected',
'true'
);

wrapper.find('button.euiTab').at(1).simulate('click');
wrapper.update();
const requestTextContent = screen.getByRole('tabpanel').textContent ?? '';

expect(JSON.parse(wrapper.find('EuiCodeBlock').text())).toEqual({
expect(JSON.parse(requestTextContent)).toMatchObject({
aggregations: {
hosts: { cardinality: { field: 'host.name' } },
hosts_histogram: {
Expand All @@ -170,62 +165,56 @@ describe('Modal Inspect', () => {
});

describe('events', () => {
test('Make sure that toggle function has been called when you click on the close button', () => {
const wrapper = mount(
<TestProviders>
<ModalInspectQuery {...defaultProps} />
</TestProviders>
);
test('should make sure that toggle function has been called when you click on the close button', () => {
renderModal();

wrapper.find('button[data-test-subj="modal-inspect-close"]').simulate('click');
wrapper.update();
fireEvent.click(screen.getByTestId('modal-inspect-close'));
expect(closeModal).toHaveBeenCalled();
});
});

describe('formatIndexPatternRequested', () => {
test('Return specific messages to NO_ALERT_INDEX if we only have one index and we match the index name `NO_ALERT_INDEX`', () => {
test('should return specific messages to NO_ALERT_INDEX if we only have one index and we match the index name `NO_ALERT_INDEX`', () => {
const expected = formatIndexPatternRequested([NO_ALERT_INDEX]);
expect(expected).toEqual(<i>{'No alert index found'}</i>);
});

test('Ignore NO_ALERT_INDEX if you have more than one indices', () => {
test('should ignore NO_ALERT_INDEX if you have more than one indices', () => {
const expected = formatIndexPatternRequested([NO_ALERT_INDEX, 'indice-1']);
expect(expected).toEqual('indice-1');
});

test('Happy path', () => {
test('should format indices correctly', () => {
const expected = formatIndexPatternRequested(['indice-1, indice-2']);
expect(expected).toEqual('indice-1, indice-2');
});

test('Empty array with no indices', () => {
test('should show error when indices array is empty', () => {
const expected = formatIndexPatternRequested([]);
expect(expected).toEqual('Sorry about that, something went wrong.');
});

test('Undefined indices', () => {
test('should show error when indices are Undefined', () => {
const expected = formatIndexPatternRequested(undefined);
expect(expected).toEqual('Sorry about that, something went wrong.');
});
});

describe('index pattern messaging', () => {
test('no messaging when all patterns are in sourcerer selection', () => {
const wrapper = mount(
<TestProviders>
<ModalInspectQuery {...defaultProps} />
</TestProviders>
);
expect(wrapper.find('i[data-test-subj="not-sourcerer-msg"]').first().exists()).toEqual(false);
test('should show no messaging when all patterns match sourcerer selection', () => {
renderModal();

expect(screen.queryByTestId('not-sourcerer-msg')).toBeNull();
});
test('not-sourcerer-msg when not all patterns are in sourcerer selection', () => {
const wrapper = mount(
<TestProviders>
<ModalInspectQuery {...defaultProps} request={getRequest(['differentbeat-*'])} />
</TestProviders>
test('should show not-sourcerer-msg when not all patterns are in sourcerer selection', () => {
renderModal({
...defaultProps,
request: getRequest(['differentbeat-*']),
});

expect(screen.getByTestId('not-sourcerer-msg')).toHaveTextContent(
'This element has a unique index pattern separate from the data view setting.'
);
expect(wrapper.find('i[data-test-subj="not-sourcerer-msg"]').first().exists()).toEqual(true);
});
});
});
Loading

0 comments on commit 584f4ee

Please sign in to comment.