[SecuritySolution] Migrate (some) timlines tests to testing-library (#134688)

* test: migrate some tests to testing-library

* test: re-add some data-test-sub attributes

* test: re-add some more data-test-subj attributes

* test: test: migrate some more tests to testing-library

* test: update snapshots
This commit is contained in:
Jan Monschke 2022-06-23 17:10:51 +02:00 committed by GitHub
parent 85dc5b3578
commit 58ba0b8861
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 7216 additions and 1402 deletions

View file

@ -64,7 +64,6 @@ export const DirectionBadge = React.memo<{
}>(({ contextId, eventId, direction, isDraggable }) => (
<DraggableBadge
contextId={contextId}
data-test-subj="network-direction"
eventId={eventId}
field={NETWORK_DIRECTION_FIELD_NAME}
iconType={getDirectionIcon(direction)}

View file

@ -1,130 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SourceDestination renders correctly against snapshot 1`] = `
<div>
<SourceDestination
contextId="test"
destinationBytes={
Array [
40,
]
}
destinationGeoCityName={
Array [
"New York",
]
}
destinationGeoContinentName={
Array [
"North America",
]
}
destinationGeoCountryIsoCode={
Array [
"US",
]
}
destinationGeoCountryName={
Array [
"United States",
]
}
destinationGeoRegionName={
Array [
"New York",
]
}
destinationIp={
Array [
"10.1.2.3",
]
}
destinationPackets={
Array [
1,
]
}
destinationPort={
Array [
80,
]
}
eventId="abcd"
networkBytes={
Array [
100,
]
}
networkCommunityId={
Array [
"we.live.in.a",
]
}
networkDirection={
Array [
"outgoing",
]
}
networkPackets={
Array [
3,
]
}
networkProtocol={
Array [
"http",
]
}
sourceBytes={
Array [
60,
]
}
sourceGeoCityName={
Array [
"Atlanta",
]
}
sourceGeoContinentName={
Array [
"North America",
]
}
sourceGeoCountryIsoCode={
Array [
"US",
]
}
sourceGeoCountryName={
Array [
"United States",
]
}
sourceGeoRegionName={
Array [
"Georgia",
]
}
sourceIp={
Array [
"192.168.1.2",
]
}
sourcePackets={
Array [
2,
]
}
sourcePort={
Array [
9987,
]
}
transport={
Array [
"tcp",
]
}
/>
</div>
`;
exports[`SourceDestination renders correctly against snapshot 1`] = `[Function]`;

View file

@ -6,17 +6,15 @@
*/
import numeral from '@elastic/numeral';
import { shallow } from 'enzyme';
import { get } from 'lodash/fp';
import React from 'react';
import { render, screen, within } from '@testing-library/react';
import { removeExternalLinkText } from '@kbn/securitysolution-io-ts-utils';
import { asArrayIfExists } from '../../../common/lib/helpers';
import { getMockNetflowData } from '../../../common/mock';
import '../../../common/mock/match_media';
import { TestProviders } from '../../../common/mock/test_providers';
import { ID_FIELD_NAME } from '../../../common/components/event_details/event_id';
import { useMountAppended } from '../../../common/utils/use_mount_appended';
import { DESTINATION_IP_FIELD_NAME, SOURCE_IP_FIELD_NAME } from '../ip';
import { DESTINATION_PORT_FIELD_NAME, SOURCE_PORT_FIELD_NAME } from '../port/helpers';
import {
@ -121,29 +119,25 @@ jest.mock('react-router-dom', () => {
});
describe('SourceDestination', () => {
const mount = useMountAppended();
test('renders correctly against snapshot', () => {
const wrapper = shallow(<div>{getSourceDestinationInstance()}</div>);
expect(wrapper).toMatchSnapshot();
const { asFragment } = render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(asFragment).toMatchSnapshot();
});
test('it renders a destination label', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination-label"]').first().text()).toEqual(
i18n.DESTINATION
);
expect(screen.getByText(i18n.DESTINATION)).toBeInTheDocument();
});
test('it renders destination.bytes', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination-bytes"]').first().text()).toEqual('40B');
expect(screen.getByText('40B')).toBeInTheDocument();
});
test('it renders percent destination.bytes', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
const destinationBytes = asArrayIfExists(
get(DESTINATION_BYTES_FIELD_NAME, getMockNetflowData())
);
@ -153,127 +147,116 @@ describe('SourceDestination', () => {
percent = `(${numeral((destinationBytes[0] / sumBytes[0]) * 100).format('0.00')}%)`;
}
expect(wrapper.find('[data-test-subj="destination-bytes-percent"]').first().text()).toEqual(
percent
);
expect(screen.getByText(percent)).toBeInTheDocument();
});
test('it renders destination.geo.continent_name', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(
wrapper.find('[data-test-subj="destination.geo.continent_name"]').first().text()
).toEqual('North America');
expect(screen.getByTestId('draggable-content-destination.geo.continent_name').textContent).toBe(
'North America'
);
});
test('it renders destination.geo.country_name', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination.geo.country_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-destination.geo.country_name').textContent).toBe(
'United States'
);
});
test('it renders destination.geo.country_iso_code', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(
wrapper.find('[data-test-subj="destination.geo.country_iso_code"]').first().text()
).toEqual('US');
screen.getByTestId('draggable-content-destination.geo.country_iso_code').textContent
).toBe('US');
});
test('it renders destination.geo.region_name', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination.geo.region_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-destination.geo.region_name').textContent).toBe(
'New York'
);
});
test('it renders destination.geo.city_name', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination.geo.city_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-destination.geo.city_name').textContent).toBe(
'New York'
);
});
test('it renders the destination ip and port, separated with a colon', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(
removeExternalLinkText(
wrapper.find('[data-test-subj="destination-ip-and-port"]').first().text()
)
).toContain('10.1.2.3:80');
expect(screen.getByTestId('destination-ip-badge').textContent).toContain('10.1.2.3:80');
});
test('it renders destination.packets', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination-packets"]').first().text()).toEqual('1 pkts');
expect(screen.getByText('1 pkts')).toBeInTheDocument();
});
test('it hyperlinks links destination.port to an external service that describes the purpose of the port', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(
wrapper
.find('[data-test-subj="destination-ip-and-port"]')
.find('[data-test-subj="port-or-service-name-link"]')
.first()
.props().href
).toEqual(
within(screen.getByTestId('destination-ip-group')).getByTestId('port-or-service-name-link')
).toHaveAttribute(
'href',
'https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=80'
);
});
test('it renders network.bytes', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-bytes"]').first().text()).toEqual('100B');
expect(screen.getByText('100B')).toBeInTheDocument();
});
test('it renders network.community_id', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-community-id"]').first().text()).toEqual(
'we.live.in.a'
);
expect(screen.getByText('we.live.in.a')).toBeInTheDocument();
});
test('it renders network.direction', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-direction"]').first().text()).toEqual('outgoing');
expect(screen.getByText('outgoing')).toBeInTheDocument();
});
test('it renders network.packets', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-packets"]').first().text()).toEqual('3 pkts');
expect(screen.getByText('3 pkts')).toBeInTheDocument();
});
test('it renders network.protocol', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-protocol"]').first().text()).toEqual('http');
expect(screen.getByText('http')).toBeInTheDocument();
});
test('it renders a source label', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source-label"]').first().text()).toEqual(i18n.SOURCE);
expect(screen.getByText(i18n.SOURCE)).toBeInTheDocument();
});
test('it renders source.bytes', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source-bytes"]').first().text()).toEqual('60B');
expect(screen.getByText('60B')).toBeInTheDocument();
});
test('it renders percent source.bytes', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
const sourceBytes = asArrayIfExists(get(SOURCE_BYTES_FIELD_NAME, getMockNetflowData()));
const sumBytes = asArrayIfExists(get(NETWORK_BYTES_FIELD_NAME, getMockNetflowData()));
let percent = '';
@ -281,66 +264,64 @@ describe('SourceDestination', () => {
percent = `(${numeral((sourceBytes[0] / sumBytes[0]) * 100).format('0.00')}%)`;
}
expect(wrapper.find('[data-test-subj="source-bytes-percent"]').first().text()).toEqual(percent);
expect(screen.getByText(percent)).toBeInTheDocument();
});
test('it renders source.geo.continent_name', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.continent_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.continent_name').textContent).toBe(
'North America'
);
});
test('it renders source.geo.country_name', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.country_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.country_name').textContent).toBe(
'United States'
);
});
test('it renders source.geo.country_iso_code', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.country_iso_code"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.country_iso_code').textContent).toBe(
'US'
);
});
test('it renders source.geo.region_name', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.region_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.region_name').textContent).toBe(
'Georgia'
);
});
test('it renders source.geo.city_name', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.city_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.city_name').textContent).toBe(
'Atlanta'
);
});
test('it renders the source ip and port, separated with a colon', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(
removeExternalLinkText(wrapper.find('[data-test-subj="source-ip-and-port"]').first().text())
).toContain('192.168.1.2:9987');
expect(screen.getByTestId('source-ip-badge').textContent).toContain('192.168.1.2:9987');
});
test('it renders source.packets', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source-packets"]').first().text()).toEqual('2 pkts');
expect(screen.getByText('2 pkts')).toBeInTheDocument();
});
test('it renders network.transport', () => {
const wrapper = mount(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
render(<TestProviders>{getSourceDestinationInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-transport"]').first().text()).toEqual('tcp');
expect(screen.getByText('tcp')).toBeInTheDocument();
});
});

View file

@ -80,7 +80,6 @@ export const Network = React.memo<{
<EuiFlexItemMarginRight grow={false} key={proto}>
<DraggableBadge
contextId={contextId}
data-test-subj="network-protocol"
eventId={eventId}
field={NETWORK_PROTOCOL_FIELD_NAME}
isDraggable={isDraggable}
@ -103,7 +102,7 @@ export const Network = React.memo<{
value={b}
>
<Stats size="xs">
<span data-test-subj="network-bytes">
<span>
<PreferenceFormattedBytes value={b} />
</span>
</Stats>
@ -123,7 +122,7 @@ export const Network = React.memo<{
value={p}
>
<Stats size="xs">
<span data-test-subj="network-packets">{`${p} ${i18n.PACKETS}`}</span>
<span>{`${p} ${i18n.PACKETS}`}</span>
</Stats>
</DefaultDraggable>
</EuiFlexItemMarginRight>
@ -152,7 +151,6 @@ export const Network = React.memo<{
<EuiFlexItem grow={false} key={trans}>
<DraggableBadge
contextId={contextId}
data-test-subj="network-community-id"
eventId={eventId}
field={NETWORK_COMMUNITY_ID_FIELD_NAME}
isDraggable={isDraggable}

View file

@ -82,11 +82,9 @@ const SourceArrow = React.memo<{
>
<Data size="xs">
{sourceBytesPercent != null ? (
<Percent data-test-subj="source-bytes-percent">
{`(${numeral(sourceBytesPercent).format('0.00')}%)`}
</Percent>
<Percent>{`(${numeral(sourceBytesPercent).format('0.00')}%)`}</Percent>
) : null}
<span data-test-subj="source-bytes">
<span>
<PreferenceFormattedBytes value={sourceBytes} />
</span>
</Data>
@ -95,7 +93,7 @@ const SourceArrow = React.memo<{
) : null}
<EuiFlexItem grow={false}>
<ArrowBody data-test-subj="source-arrow" height={sourceArrowHeight ?? 0} />
<ArrowBody height={sourceArrowHeight ?? 0} />
</EuiFlexItem>
{sourcePackets != null && !isNaN(Number(sourcePackets)) ? (
@ -107,7 +105,7 @@ const SourceArrow = React.memo<{
value={sourcePackets}
>
<Data size="xs">
<span data-test-subj="source-packets">{`${sourcePackets} ${i18n.PACKETS}`}</span>
<span>{`${sourcePackets} ${i18n.PACKETS}`}</span>
</Data>
</DefaultDraggable>
</EuiFlexItem>
@ -171,11 +169,9 @@ const DestinationArrow = React.memo<{
>
<Data size="xs">
{destinationBytesPercent != null ? (
<Percent data-test-subj="destination-bytes-percent">
{`(${numeral(destinationBytesPercent).format('0.00')}%)`}
</Percent>
<Percent>{`(${numeral(destinationBytesPercent).format('0.00')}%)`}</Percent>
) : null}
<span data-test-subj="destination-bytes">
<span>
<PreferenceFormattedBytes value={destinationBytes} />
</span>
</Data>
@ -196,9 +192,7 @@ const DestinationArrow = React.memo<{
value={destinationPackets}
>
<Data size="xs">
<span data-test-subj="destination-packets">{`${numeral(destinationPackets).format(
'0,0'
)} ${i18n.PACKETS}`}</span>
<span>{`${numeral(destinationPackets).format('0,0')} ${i18n.PACKETS}`}</span>
</Data>
</DefaultDraggable>
</EuiFlexItem>
@ -264,7 +258,6 @@ export const SourceDestinationArrows = React.memo<{
return (
<SourceDestinationArrowsContainer
alignItems="center"
data-test-subj="source-destination-arrows-container"
justifyContent="center"
direction="column"
gutterSize="none"

View file

@ -7,8 +7,8 @@
import { get } from 'lodash/fp';
import React from 'react';
import { render, screen } from '@testing-library/react';
import { removeExternalLinkText } from '@kbn/securitysolution-io-ts-utils';
import { asArrayIfExists } from '../../../common/lib/helpers';
import { getMockNetflowData } from '../../../common/mock';
import '../../../common/mock/match_media';
@ -17,7 +17,6 @@ import { ID_FIELD_NAME } from '../../../common/components/event_details/event_id
import { DESTINATION_IP_FIELD_NAME, SOURCE_IP_FIELD_NAME } from '../ip';
import { DESTINATION_PORT_FIELD_NAME, SOURCE_PORT_FIELD_NAME } from '../port/helpers';
import * as i18n from '../../../timelines/components/timeline/body/renderers/translations';
import { useMountAppended } from '../../../common/utils/use_mount_appended';
import {
getPorts,
@ -43,8 +42,6 @@ jest.mock('../../../common/lib/kibana');
jest.mock('../../../common/components/link_to');
describe('SourceDestinationIp', () => {
const mount = useMountAppended();
describe('#isIpFieldPopulated', () => {
test('it returns true when type is `source` and sourceIp has an IP address', () => {
expect(
@ -333,7 +330,7 @@ describe('SourceDestinationIp', () => {
test('it renders a `Source` label when type is `source` and (just) the sourceIp field is populated', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -377,12 +374,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="source-label"]').first().text()).toEqual(i18n.SOURCE);
expect(screen.getByText(i18n.SOURCE)).toBeInTheDocument();
});
test('it renders a `Destination` label when type is `destination` and (just) the destinationIp field is populated', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -426,14 +423,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="destination-label"]').first().text()).toEqual(
i18n.DESTINATION
);
expect(screen.getByText(i18n.DESTINATION)).toBeInTheDocument();
});
test('it renders a `Source` label when type is `source` (just) the sourcePort field is populated', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -477,12 +472,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="source-label"]').first().text()).toEqual(i18n.SOURCE);
expect(screen.getByText(i18n.SOURCE)).toBeInTheDocument();
});
test('it renders a `Destination` label when type is `destination` and (just) the destinationPort field is populated', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -526,15 +521,13 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="destination-label"]').first().text()).toEqual(
i18n.DESTINATION
);
expect(screen.getByText(i18n.DESTINATION)).toBeInTheDocument();
});
test('it renders a `Source` label when type is `source` and both sourceIp and sourcePort are populated', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -578,12 +571,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="source-label"]').first().text()).toEqual(i18n.SOURCE);
expect(screen.getByText(i18n.SOURCE)).toBeInTheDocument();
});
test('it renders a `Destination` label when type is `destination` and both destinationIp and destinationPort are populated', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -627,14 +620,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="destination-label"]').first().text()).toEqual(
i18n.DESTINATION
);
expect(screen.getByText(i18n.DESTINATION)).toBeInTheDocument();
});
test('it does NOT render a `Source` label when type is `source` and both sourceIp and sourcePort are empty', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -678,12 +669,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.exists('[data-test-subj="source-label"]')).toBe(false);
expect(screen.queryByText(i18n.SOURCE)).not.toBeInTheDocument();
});
test('it does NOT render a `Destination` label when type is `destination` and both destinationIp and destinationPort are empty', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -727,12 +718,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.exists('[data-test-subj="destination-label"]')).toBe(false);
expect(screen.queryByText(i18n.DESTINATION)).not.toBeInTheDocument();
});
test('it renders the expected source IP when type is `source`, and both sourceIp and sourcePort are populated', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -776,14 +767,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="draggable-truncatable-content"]').first().text()).toEqual(
'192.168.1.2'
);
expect(screen.getByText('192.168.1.2')).toBeInTheDocument();
});
test('it renders the expected source IP when type is `source`, but the length of the sourceIp and sourcePort arrays is different', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -827,14 +816,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="draggable-truncatable-content"]').first().text()).toEqual(
'192.168.1.2'
);
expect(screen.getByText('192.168.1.2')).toBeInTheDocument();
});
test('it renders the expected destination IP when type is `destination`, and both destinationIp and destinationPort are populated', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -878,14 +865,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="draggable-truncatable-content"]').first().text()).toEqual(
'10.1.2.3'
);
expect(screen.getByText('10.1.2.3')).toBeInTheDocument();
});
test('it renders the expected destination IP when type is `destination`, but the length of the destinationIp and destinationPort port arrays is different', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -929,14 +914,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="draggable-truncatable-content"]').first().text()).toEqual(
'10.1.2.3'
);
expect(screen.getByText('10.1.2.3')).toBeInTheDocument();
});
test('it renders the expected source port when type is `source`, and both sourceIp and sourcePort are populated', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -980,16 +963,13 @@ describe('SourceDestinationIp', () => {
/>
</TestProviders>
);
expect(
removeExternalLinkText(
wrapper.find('[data-test-subj="draggable-content-source.port"]').first().text()
)
).toContain('9987');
expect(screen.getByTestId('source-ip-badge').textContent).toContain('9987');
});
test('it renders the expected destination port when type is `destination`, and both destinationIp and destinationPort are populated', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -1034,16 +1014,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(
removeExternalLinkText(
wrapper.find('[data-test-subj="draggable-content-destination.port"]').first().text()
)
).toContain('80');
expect(screen.getByTestId('destination-ip-badge').textContent).toContain('80');
});
test('it renders the expected source port when type is `source`, but only sourcePort is populated', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -1088,17 +1064,13 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(
removeExternalLinkText(
wrapper.find('[data-test-subj="draggable-content-source.port"]').first().text()
)
).toContain('9987');
expect(screen.getByTestId('source-ip-badge').textContent).toContain('9987');
});
test('it renders the expected destination port when type is `destination`, and only destinationPort is populated', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -1143,17 +1115,13 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(
removeExternalLinkText(
wrapper.find('[data-test-subj="draggable-content-destination.port"]').first().text()
)
).toContain('80');
expect(screen.getByTestId('destination-ip-badge').textContent).toContain('80');
});
test('it does NOT render the badge when type is `source`, but both sourceIp and sourcePort are undefined', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -1197,13 +1165,13 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.exists(`[data-test-subj="${type}-ip-badge"]`)).toBe(false);
expect(screen.queryByTestId(`${type}-ip-badge`)).not.toBeInTheDocument();
});
test('it does NOT render the badge when type is `destination`, but both destinationIp and destinationPort are undefined', () => {
const type = 'destination';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -1247,12 +1215,12 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(wrapper.exists(`[data-test-subj="${type}-ip-badge"]`)).toBe(false);
expect(screen.queryByTestId(`${type}-ip-badge`)).not.toBeInTheDocument();
});
test('it renders geo fields', () => {
const type = 'source';
const wrapper = mount(
render(
<TestProviders>
<SourceDestinationIp
contextId="test"
@ -1297,8 +1265,8 @@ describe('SourceDestinationIp', () => {
</TestProviders>
);
expect(
wrapper.find('[data-test-subj="draggable-content-source.geo.continent_name"]').first().text()
).toEqual('North America');
expect(screen.getByTestId('draggable-content-source.geo.continent_name').textContent).toBe(
'North America'
);
});
});

View file

@ -195,7 +195,7 @@ export const SourceDestinationIp = React.memo<SourceDestinationIpProps>(
gutterSize="xs"
>
<EuiFlexItem grow={false}>
<Label data-test-subj={`${type}-label`}>{label}</Label>
<Label>{label}</Label>
</EuiFlexItem>
<EuiFlexItem grow={false}>
{isIpFieldPopulated({ destinationIp, sourceIp, type }) ? (

View file

@ -6,20 +6,18 @@
*/
import React from 'react';
import { render, screen } from '@testing-library/react';
import { removeExternalLinkText } from '@kbn/securitysolution-io-ts-utils';
import { TestProviders } from '../../../common/mock';
import '../../../common/mock/match_media';
import { useMountAppended } from '../../../common/utils/use_mount_appended';
import { CertificateFingerprint } from '.';
jest.mock('../../../common/lib/kibana');
describe('CertificateFingerprint', () => {
const mount = useMountAppended();
test('renders the expected label', () => {
const wrapper = mount(
render(
<TestProviders>
<CertificateFingerprint
eventId="Tgwnt2kBqd-n62SwPZDP"
@ -30,13 +28,11 @@ describe('CertificateFingerprint', () => {
/>
</TestProviders>
);
expect(wrapper.find('[data-test-subj="fingerprint-label"]').first().text()).toEqual(
'client cert'
);
expect(screen.getByText('client cert')).toBeInTheDocument();
});
test('renders the fingerprint as text', () => {
const wrapper = mount(
render(
<TestProviders>
<CertificateFingerprint
eventId="Tgwnt2kBqd-n62SwPZDP"
@ -47,15 +43,11 @@ describe('CertificateFingerprint', () => {
/>
</TestProviders>
);
expect(
removeExternalLinkText(
wrapper.find('[data-test-subj="certificate-fingerprint-link"]').first().text()
)
).toContain('3f4c57934e089f02ae7511200aee2d7e7aabd272');
expect(screen.getByText('3f4c57934e089f02ae7511200aee2d7e7aabd272')).toBeInTheDocument();
});
test('it renders a hyperlink to an external site to compare the fingerprint against a known set of signatures', () => {
const wrapper = mount(
render(
<TestProviders>
<CertificateFingerprint
eventId="Tgwnt2kBqd-n62SwPZDP"
@ -66,10 +58,8 @@ describe('CertificateFingerprint', () => {
/>
</TestProviders>
);
expect(
wrapper.find('[data-test-subj="certificate-fingerprint-link"]').first().props().href
).toEqual(
expect(screen.getByText('3f4c57934e089f02ae7511200aee2d7e7aabd272')).toHaveAttribute(
'href',
'https://sslbl.abuse.ch/ssl-certificates/sha1/3f4c57934e089f02ae7511200aee2d7e7aabd272'
);
});

View file

@ -60,7 +60,7 @@ export const CertificateFingerprint = React.memo<{
isAggregatable={true}
fieldType="keyword"
>
<FingerprintLabel data-test-subj="fingerprint-label">
<FingerprintLabel>
{certificateType === 'client' ? i18n.CLIENT_CERT : i18n.SERVER_CERT}
</FingerprintLabel>
<CertificateFingerprintLink certificateFingerprint={value || ''} />

View file

@ -6,21 +6,19 @@
*/
import React from 'react';
import { render, screen } from '@testing-library/react';
import '../../../common/mock/match_media';
import { TestProviders } from '../../../common/mock';
import { ONE_MILLISECOND_AS_NANOSECONDS } from '../formatted_duration/helpers';
import { useMountAppended } from '../../../common/utils/use_mount_appended';
import { Duration } from '.';
jest.mock('../../../common/lib/kibana');
describe('Duration', () => {
const mount = useMountAppended();
test('it renders the expected formatted duration', () => {
const wrapper = mount(
render(
<TestProviders>
<Duration
contextId="test"
@ -33,6 +31,6 @@ describe('Duration', () => {
/>
</TestProviders>
);
expect(wrapper.find('[data-test-subj="formatted-duration"]').first().text()).toEqual('1ms');
expect(screen.getByText('1ms')).toBeInTheDocument();
});
});

View file

@ -5,7 +5,8 @@
* 2.0.
*/
import { mount } from 'enzyme';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { mockBrowserFields } from '../../../common/containers/source/mock';
@ -18,17 +19,13 @@ import {
import { StatefulEditDataProvider } from '.';
interface HasIsDisabled {
isDisabled: boolean;
}
describe('StatefulEditDataProvider', () => {
const field = 'client.address';
const timelineId = 'test';
const value = 'test-host';
test('it renders the current field', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -44,11 +41,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="field"]').first().text()).toEqual(field);
expect(screen.getByText(field)).toBeInTheDocument();
});
test('it renders the expected placeholder for the current field when field is empty', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -64,13 +61,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="field"]').first().props().placeholder).toEqual(
'Select a field'
);
expect(screen.getByText(/Select a field/)).toBeInTheDocument();
});
test('it renders the "is" operator in a humanized format', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -86,11 +81,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="operator"]').first().text()).toEqual('is');
expect(screen.getByText('is')).toBeInTheDocument();
});
test('it renders the negated "is" operator in a humanized format when isExcluded is true', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -106,11 +101,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="operator"]').first().text()).toEqual('is not');
expect(screen.getByText('is not')).toBeInTheDocument();
});
test('it renders the "exists" operator in human-readable format', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -126,11 +121,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="operator"]').first().text()).toEqual('exists');
expect(screen.getByText('exists')).toBeInTheDocument();
});
test('it renders the negated "exists" operator in a humanized format when isExcluded is true', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -146,11 +141,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="operator"]').first().text()).toEqual('does not exist');
expect(screen.getByText('does not exist')).toBeInTheDocument();
});
test('it renders the current value when the operator is "is"', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -166,13 +161,13 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="value"]').first().props().value).toEqual(value);
expect(screen.getByDisplayValue(value)).toBeInTheDocument();
});
test('it renders the current value when the type of value is an array', () => {
const reallyAnArray = [value] as unknown as string;
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -188,11 +183,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="value"]').first().props().value).toEqual(value);
expect(screen.getByDisplayValue(value)).toBeInTheDocument();
});
test('it does NOT render the current value when the operator is "is not" (isExcluded is true)', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -208,11 +203,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="value"]').first().props().value).toEqual(value);
expect(screen.getByDisplayValue(value)).toBeInTheDocument();
});
test('it renders the expected placeholder when value is empty', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -228,11 +223,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="value"]').first().props().placeholder).toEqual('value');
expect(screen.getByPlaceholderText('value')).toBeInTheDocument();
});
test('it does NOT render value when the operator is "exists"', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -248,11 +243,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="value"]').exists()).toBe(false);
expect(screen.queryByPlaceholderText('value')).not.toBeInTheDocument();
});
test('it does NOT render value when the operator is "not exists" (isExcluded is true)', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -268,11 +263,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="value"]').exists()).toBe(false);
expect(screen.queryByPlaceholderText('value')).not.toBeInTheDocument();
});
test('it does NOT render value when is template field', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -289,11 +284,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="value"]').exists()).toBe(false);
expect(screen.queryByPlaceholderText('value')).not.toBeInTheDocument();
});
test('it does NOT disable the save button when field is valid', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -309,13 +304,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
const props = wrapper.find('[data-test-subj="save"]').first().props() as HasIsDisabled;
expect(props.isDisabled).toBe(false);
expect(screen.getByTestId('save')).not.toBeDisabled();
});
test('it disables the save button when field is invalid because it is empty', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -331,13 +324,11 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
const props = wrapper.find('[data-test-subj="save"]').first().props() as HasIsDisabled;
expect(props.isDisabled).toBe(true);
expect(screen.getByTestId('save')).toBeDisabled();
});
test('it disables the save button when field is invalid because it is not contained in the browser fields', () => {
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -353,15 +344,13 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
const props = wrapper.find('[data-test-subj="save"]').first().props() as HasIsDisabled;
expect(props.isDisabled).toBe(true);
expect(screen.getByTestId('save')).toBeDisabled();
});
test('it invokes onDataProviderEdited with the expected values when the user clicks the save button', () => {
const onDataProviderEdited = jest.fn();
const wrapper = mount(
render(
<TestProviders>
<StatefulEditDataProvider
andProviderId={undefined}
@ -377,9 +366,7 @@ describe('StatefulEditDataProvider', () => {
</TestProviders>
);
wrapper.find('[data-test-subj="save"]').first().simulate('click');
wrapper.update();
userEvent.click(screen.getByTestId('save'));
expect(onDataProviderEdited).toBeCalledWith({
andProviderId: undefined,

View file

@ -235,7 +235,6 @@ export const StatefulEditDataProvider = React.memo<Props>(
<EuiFormRow label={i18n.VALUE_LABEL}>
<EuiFieldText
className={VALUE_INPUT_CLASS_NAME}
data-test-subj="value"
onChange={onValueChange}
placeholder={i18n.VALUE}
value={sanatizeValue(updatedValue)}

View file

@ -1,156 +1,340 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Field Renderers #autonomousSystemRenderer it renders correctly against snapshot 1`] = `
<DocumentFragment>
.c0 .euiPopover__anchor {
width: 100%;
}
.c1 > span.euiToolTipAnchor {
display: block;
}
.c1 > span.euiToolTipAnchor.eui-textTruncate {
display: inline-block;
}
<div
className="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<EuiFlexItem
grow={false}
class="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<DefaultDraggable
field="source.as.organization.name"
id="autonomous-system-renderer-default-draggable-ip-overview-source.as.organization.name"
isDraggable={false}
value="Test Org"
/>
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
/
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
<DefaultDraggable
field="source.as.number"
fieldType="number"
id="autonomous-system-renderer-default-draggable-ip-overview-source.as.number"
isAggregatable={true}
isDraggable={false}
value="12345"
/>
</EuiFlexItem>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<div
class=""
>
<div
class="euiPopover euiPopover--anchorDownCenter c0"
>
<div
class="euiPopover__anchor"
>
<div
data-test-subj="withHoverActionsButton"
>
<div
data-provider-id="draggableId.content.autonomous-system-renderer-default-draggable-ip-overview-source_as_organization_name"
tabindex="-1"
>
<span
class="c1"
data-test-subj="render-content-source.as.organization.name"
>
<span
class="euiToolTipAnchor"
>
Test Org
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
/
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<div
class=""
>
<div
class="euiPopover euiPopover--anchorDownCenter c0"
>
<div
class="euiPopover__anchor"
>
<div
data-test-subj="withHoverActionsButton"
>
<div
data-provider-id="draggableId.content.autonomous-system-renderer-default-draggable-ip-overview-source_as_number"
tabindex="-1"
>
<span
class="c1"
data-test-subj="render-content-source.as.number"
>
<span
class="euiToolTipAnchor"
>
12345
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</DocumentFragment>
`;
exports[`Field Renderers #dateRenderer it renders correctly against snapshot 1`] = `
<LocalizedDateTooltip
date={2019-02-07T17:19:41.636Z}
>
<PreferenceFormattedDate
data-test-subj="preference-time"
value={2019-02-07T17:19:41.636Z}
/>
</LocalizedDateTooltip>
<DocumentFragment>
<span
class="euiToolTipAnchor"
>
Feb 7, 2019 @ 17:19:41.636
</span>
</DocumentFragment>
`;
exports[`Field Renderers #hostIdRenderer it renders correctly against snapshot 1`] = `
<DraggableWrapper
dataProvider={
Object {
"and": Array [],
"enabled": true,
"excluded": false,
"id": "host-name-renderer-default-draggable-ip-overview-host-name",
"kqlQuery": "",
"name": "raspberrypi",
"queryMatch": Object {
"field": "host.name",
"operator": ":",
"value": "raspberrypi",
},
}
}
fieldType="keyword"
hideTopN={false}
isAggregatable={true}
isDraggable={false}
render={[Function]}
/>
<DocumentFragment>
.c0 .euiPopover__anchor {
width: 100%;
}
.c1 > span.euiToolTipAnchor {
display: block;
}
.c1 > span.euiToolTipAnchor.eui-textTruncate {
display: inline-block;
}
<div
class=""
>
<div
class="euiPopover euiPopover--anchorDownCenter c0"
>
<div
class="euiPopover__anchor"
>
<div
data-test-subj="withHoverActionsButton"
>
<div
data-provider-id="draggableId.content.host-name-renderer-default-draggable-ip-overview-host-name"
tabindex="-1"
>
<span
class="c1"
data-test-subj="render-content-host.name"
>
<span
class="euiToolTipAnchor"
>
<a
class="euiLink css-102pf9n-euiLink-primary"
data-test-subj="host-details-button"
href="securitySolutionUI/hosts/raspberrypi?sourcerer=(default:(id:security-solution,selectedPatterns:!('apm-*-transaction*','auditbeat-*','endgame-*','filebeat-*','logs-*','packetbeat-*','traces-apm*','winlogbeat-*','-*elastic-cloud-logs-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now%2Fd,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now%2Fd)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now%2Fd,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now%2Fd)))"
rel="noreferrer"
>
raspberrypi
</a>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</DocumentFragment>
`;
exports[`Field Renderers #hostNameRenderer it renders correctly against snapshot 1`] = `
<DraggableWrapper
dataProvider={
Object {
"and": Array [],
"enabled": true,
"excluded": false,
"id": "host-name-renderer-default-draggable-ip-overview-host-name",
"kqlQuery": "",
"name": "raspberrypi",
"queryMatch": Object {
"field": "host.name",
"operator": ":",
"value": "raspberrypi",
},
}
}
fieldType="keyword"
hideTopN={false}
isAggregatable={true}
isDraggable={false}
render={[Function]}
/>
<DocumentFragment>
.c0 .euiPopover__anchor {
width: 100%;
}
.c1 > span.euiToolTipAnchor {
display: block;
}
.c1 > span.euiToolTipAnchor.eui-textTruncate {
display: inline-block;
}
<div
class=""
>
<div
class="euiPopover euiPopover--anchorDownCenter c0"
>
<div
class="euiPopover__anchor"
>
<div
data-test-subj="withHoverActionsButton"
>
<div
data-provider-id="draggableId.content.host-name-renderer-default-draggable-ip-overview-host-name"
tabindex="-1"
>
<span
class="c1"
data-test-subj="render-content-host.name"
>
<span
class="euiToolTipAnchor"
>
<a
class="euiLink css-102pf9n-euiLink-primary"
data-test-subj="host-details-button"
href="securitySolutionUI/hosts/raspberrypi?sourcerer=(default:(id:security-solution,selectedPatterns:!('apm-*-transaction*','auditbeat-*','endgame-*','filebeat-*','logs-*','packetbeat-*','traces-apm*','winlogbeat-*','-*elastic-cloud-logs-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now%2Fd,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now%2Fd)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now%2Fd,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now%2Fd)))"
rel="noreferrer"
>
raspberrypi
</a>
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</DocumentFragment>
`;
exports[`Field Renderers #locationRenderer it renders correctly against snapshot 1`] = `
<DocumentFragment>
.c0 .euiPopover__anchor {
width: 100%;
}
.c1 > span.euiToolTipAnchor {
display: block;
}
.c1 > span.euiToolTipAnchor.eui-textTruncate {
display: inline-block;
}
<div
className="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
data-test-subj="location-field"
>
<EuiFlexItem
grow={false}
class="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<DefaultDraggable
field="source.geo.city_name"
fieldType="keyword"
id="location-renderer-default-draggable-ip-overview-source.geo.city_name"
isAggregatable={true}
isDraggable={false}
value={
Array [
"New York",
]
}
/>
</EuiFlexItem>
, 
<EuiFlexItem
grow={false}
>
<DefaultDraggable
field="source.geo.region_name"
fieldType="keyword"
id="location-renderer-default-draggable-ip-overview-source.geo.region_name"
isAggregatable={true}
isDraggable={false}
value={
Array [
"New York",
]
}
/>
</EuiFlexItem>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<div
class=""
>
<div
class="euiPopover euiPopover--anchorDownCenter c0"
>
<div
class="euiPopover__anchor"
>
<div
data-test-subj="withHoverActionsButton"
>
<div
data-provider-id="draggableId.content.location-renderer-default-draggable-ip-overview-source_geo_city_name"
tabindex="-1"
>
<span
class="c1"
data-test-subj="render-content-source.geo.city_name"
>
<span
class="euiToolTipAnchor"
>
New York
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
, 
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<div
class=""
>
<div
class="euiPopover euiPopover--anchorDownCenter c0"
>
<div
class="euiPopover__anchor"
>
<div
data-test-subj="withHoverActionsButton"
>
<div
data-provider-id="draggableId.content.location-renderer-default-draggable-ip-overview-source_geo_region_name"
tabindex="-1"
>
<span
class="c1"
data-test-subj="render-content-source.geo.region_name"
>
<span
class="euiToolTipAnchor"
>
New York
</span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</DocumentFragment>
`;
exports[`Field Renderers #reputationRenderer it renders correctly against snapshot 1`] = `
<DragDropContext
onDragEnd={[MockFunction]}
>
<Memo(ReputationLinkComponent)
direction="column"
domain="10.10.10.10"
/>
</DragDropContext>
`;
exports[`Field Renderers #reputationRenderer it renders correctly against snapshot 1`] = `<DocumentFragment />`;
exports[`Field Renderers #whoisRenderer it renders correctly against snapshot 1`] = `
<ExternalLink
url="https://www.iana.org/whois?q=10.10.10.10"
>
iana.org
</ExternalLink>
<DocumentFragment>
<span
class="euiToolTipAnchor"
>
<a
class="euiLink css-102pf9n-euiLink-primary"
data-test-subj="externalLink"
href="https://www.iana.org/whois?q=10.10.10.10"
rel="noopener noreferrer"
target="_blank"
>
iana.org
<span
class="css-q4vwwx-euiLink__externalIcon"
data-euiicon-type="popout"
>
External link
</span>
<span
class="euiScreenReaderOnly"
>
(opens in a new tab or window)
</span>
</a>
</span>
</DocumentFragment>
`;

View file

@ -5,8 +5,9 @@
* 2.0.
*/
import { shallow } from 'enzyme';
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TestProviders } from '../../../common/mock';
import '../../../common/mock/match_media';
@ -25,60 +26,58 @@ import {
MoreContainer,
} from './field_renderers';
import { mockData } from '../../../network/components/details/mock';
import { useMountAppended } from '../../../common/utils/use_mount_appended';
import { AutonomousSystem, FlowTarget } from '../../../../common/search_strategy';
import { HostEcs } from '../../../../common/ecs/host';
import { DataProvider } from '../../../../common/types';
jest.mock('../../../common/lib/kibana');
jest.mock('@elastic/eui', () => {
const original = jest.requireActual('@elastic/eui');
jest.mock('../../../common/lib/kibana/kibana_react', () => {
return {
...original,
EuiScreenReaderOnly: () => <></>,
useKibana: () => ({
services: {
application: {
getUrlForApp: (appId: string, options?: { path?: string; deepLinkId?: boolean }) =>
`${appId}/${options?.deepLinkId ?? ''}${options?.path ?? ''}`,
},
},
}),
};
});
describe('Field Renderers', () => {
const mount = useMountAppended();
describe('#locationRenderer', () => {
test('it renders correctly against snapshot', () => {
const wrapper = shallow(
const { asFragment } = render(
locationRenderer(['source.geo.city_name', 'source.geo.region_name'], mockData.complete)
);
expect(wrapper).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('it renders emptyTagValue when no fields provided', () => {
const wrapper = mount(
<TestProviders>{locationRenderer([], mockData.complete)}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
render(<TestProviders>{locationRenderer([], mockData.complete)}</TestProviders>);
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
test('it renders emptyTagValue when invalid fields provided', () => {
const wrapper = mount(
render(
<TestProviders>
{locationRenderer(['source.geo.my_house'], mockData.complete)}
</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
});
describe('#dateRenderer', () => {
test('it renders correctly against snapshot', () => {
const wrapper = shallow(dateRenderer(mockData.complete.source?.firstSeen));
const { asFragment } = render(dateRenderer(mockData.complete.source?.firstSeen));
expect(wrapper).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('it renders emptyTagValue when invalid field provided', () => {
const wrapper = mount(<TestProviders>{dateRenderer(null)}</TestProviders>);
expect(wrapper.text()).toEqual(getEmptyValue());
render(<TestProviders>{dateRenderer(null)}</TestProviders>);
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
});
@ -87,25 +86,25 @@ describe('Field Renderers', () => {
const halfEmptyMock: AutonomousSystem = { organization: { name: 'Test Org' }, number: null };
test('it renders correctly against snapshot', () => {
const wrapper = shallow(
const { asFragment } = render(
autonomousSystemRenderer(mockData.complete.source!.autonomousSystem!, FlowTarget.source)
);
expect(wrapper).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('it renders emptyTagValue when non-string field provided', () => {
const wrapper = mount(
render(
<TestProviders>{autonomousSystemRenderer(halfEmptyMock, FlowTarget.source)}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
test('it renders emptyTagValue when invalid field provided', () => {
const wrapper = mount(
render(
<TestProviders>{autonomousSystemRenderer(emptyMock, FlowTarget.source)}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
});
@ -121,29 +120,26 @@ describe('Field Renderers', () => {
ip: undefined,
};
test('it renders correctly against snapshot', () => {
const wrapper = shallow(hostNameRenderer(mockData.complete.host, '10.10.10.10'));
expect(wrapper).toMatchSnapshot();
const { asFragment } = render(
<TestProviders>{hostNameRenderer(mockData.complete.host, '10.10.10.10')}</TestProviders>
);
expect(asFragment()).toMatchSnapshot();
});
test('it renders emptyTagValue when non-matching IP is provided', () => {
const wrapper = mount(
render(
<TestProviders>{hostNameRenderer(mockData.complete.host, '10.10.10.11')}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
test('it renders emptyTagValue when no host.id is provided', () => {
const wrapper = mount(
<TestProviders>{hostNameRenderer(emptyIdHost, FlowTarget.source)}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
render(<TestProviders>{hostNameRenderer(emptyIdHost, FlowTarget.source)}</TestProviders>);
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
test('it renders emptyTagValue when no host.ip is provided', () => {
const wrapper = mount(
<TestProviders>{hostNameRenderer(emptyIpHost, FlowTarget.source)}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
render(<TestProviders>{hostNameRenderer(emptyIpHost, FlowTarget.source)}</TestProviders>);
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
});
@ -164,66 +160,64 @@ describe('Field Renderers', () => {
ip: ['10.10.10.10'],
};
test('it renders correctly against snapshot', () => {
const wrapper = shallow(hostNameRenderer(mockData.complete.host, '10.10.10.10'));
const { asFragment } = render(
<TestProviders>{hostNameRenderer(mockData.complete.host, '10.10.10.10')}</TestProviders>
);
expect(wrapper).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('it renders emptyTagValue when non-matching IP is provided', () => {
const wrapper = mount(
render(
<TestProviders>{hostNameRenderer(mockData.complete.host, '10.10.10.11')}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
test('it renders emptyTagValue when no host.id is provided', () => {
const wrapper = mount(
<TestProviders>{hostNameRenderer(emptyIdHost, FlowTarget.source)}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
render(<TestProviders>{hostNameRenderer(emptyIdHost, FlowTarget.source)}</TestProviders>);
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
test('it renders emptyTagValue when no host.ip is provided', () => {
const wrapper = mount(
<TestProviders>{hostNameRenderer(emptyIpHost, FlowTarget.source)}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
render(<TestProviders>{hostNameRenderer(emptyIpHost, FlowTarget.source)}</TestProviders>);
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
test('it renders emptyTagValue when no host.name is provided', () => {
const wrapper = mount(
<TestProviders>{hostNameRenderer(emptyNameHost, FlowTarget.source)}</TestProviders>
);
expect(wrapper.text()).toEqual(getEmptyValue());
render(<TestProviders>{hostNameRenderer(emptyNameHost, FlowTarget.source)}</TestProviders>);
expect(screen.getByText(getEmptyValue())).toBeInTheDocument();
});
});
describe('#whoisRenderer', () => {
test('it renders correctly against snapshot', () => {
const wrapper = shallow(whoisRenderer('10.10.10.10'));
const { asFragment } = render(whoisRenderer('10.10.10.10'));
expect(wrapper).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});
describe('#reputationRenderer', () => {
test('it renders correctly against snapshot', () => {
const wrapper = shallow(<TestProviders>{reputationRenderer('10.10.10.10')}</TestProviders>);
const { asFragment } = render(
<TestProviders>{reputationRenderer('10.10.10.10')}</TestProviders>
);
expect(wrapper.find('DragDropContext')).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});
describe('DefaultFieldRenderer', () => {
test('it should render a single item', () => {
const wrapper = mount(
render(
<TestProviders>
<DefaultFieldRenderer rowItems={['item1']} attrName={'item1'} idPrefix={'prefix-1'} />
</TestProviders>
);
expect(wrapper.text()).toEqual('item1 ');
expect(screen.getByTestId('DefaultFieldRendererComponent').textContent).toEqual('item1 ');
});
test('it should render two items', () => {
const wrapper = mount(
render(
<TestProviders>
<DefaultFieldRenderer
displayCount={5}
@ -233,11 +227,14 @@ describe('Field Renderers', () => {
/>
</TestProviders>
);
expect(wrapper.text()).toEqual('item1,item2 ');
expect(screen.getByTestId('DefaultFieldRendererComponent').textContent).toEqual(
'item1,item2 '
);
});
test('it should render all items when the item count exactly equals displayCount', () => {
const wrapper = mount(
render(
<TestProviders>
<DefaultFieldRenderer
displayCount={5}
@ -248,11 +245,13 @@ describe('Field Renderers', () => {
</TestProviders>
);
expect(wrapper.text()).toEqual('item1,item2,item3,item4,item5 ');
expect(screen.getByTestId('DefaultFieldRendererComponent').textContent).toEqual(
'item1,item2,item3,item4,item5 '
);
});
test('it should render all items up to displayCount and the expected "+ n More" popover anchor text for items greater than displayCount', () => {
const wrapper = mount(
render(
<TestProviders>
<DefaultFieldRenderer
displayCount={5}
@ -262,8 +261,9 @@ describe('Field Renderers', () => {
/>
</TestProviders>
);
expect(wrapper.text()).toEqual('item1,item2,item3,item4,item5 ,+2 More');
expect(screen.getByTestId('DefaultFieldRendererComponent').textContent).toEqual(
'item1,item2,item3,item4,item5 ,+2 More'
);
});
});
@ -272,7 +272,7 @@ describe('Field Renderers', () => {
const rowItems = ['item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7'];
test('it should only render the items after overflowIndexStart', () => {
const wrapper = mount(
render(
<MoreContainer
fieldType="keyword"
idPrefix={idPrefix}
@ -283,11 +283,11 @@ describe('Field Renderers', () => {
/>
);
expect(wrapper.text()).toEqual('item6item7');
expect(screen.getByTestId('more-container').textContent).toEqual('item6item7');
});
test('it should render all the items when overflowIndexStart is zero', () => {
const wrapper = mount(
render(
<MoreContainer
fieldType="keyword"
idPrefix={idPrefix}
@ -298,11 +298,13 @@ describe('Field Renderers', () => {
/>
);
expect(wrapper.text()).toEqual('item1item2item3item4item5item6item7');
expect(screen.getByTestId('more-container').textContent).toEqual(
'item1item2item3item4item5item6item7'
);
});
test('it should have the eui-yScroll to enable scrolling when necessary', () => {
const wrapper = mount(
render(
<MoreContainer
fieldType="keyword"
idPrefix={idPrefix}
@ -313,13 +315,11 @@ describe('Field Renderers', () => {
/>
);
expect(wrapper.find('[data-test-subj="more-container"]').first().props().className).toEqual(
'eui-yScroll'
);
expect(screen.getByTestId('more-container')).toHaveClass('eui-yScroll');
});
test('it should use the moreMaxHeight prop as the value for the max-height style', () => {
const wrapper = mount(
render(
<MoreContainer
fieldType="keyword"
idPrefix={idPrefix}
@ -330,13 +330,13 @@ describe('Field Renderers', () => {
/>
);
expect(
wrapper.find('[data-test-subj="more-container"]').first().props().style?.maxHeight
).toEqual(DEFAULT_MORE_MAX_HEIGHT);
expect(screen.getByTestId('more-container')).toHaveStyle(
`max-height: ${DEFAULT_MORE_MAX_HEIGHT}`
);
});
test('it should render with correct attrName prop', () => {
const wrapper = mount(
render(
<MoreContainer
fieldType="keyword"
idPrefix={idPrefix}
@ -348,61 +348,27 @@ describe('Field Renderers', () => {
/>
);
expect(
wrapper.find('DraggableWrapper').first().prop<DataProvider>('dataProvider').queryMatch.field
).toEqual('mock.attr');
});
test('it should render with correct fieldType prop', () => {
const wrapper = mount(
<MoreContainer
fieldType="keyword"
idPrefix={idPrefix}
isAggregatable={true}
moreMaxHeight={DEFAULT_MORE_MAX_HEIGHT}
overflowIndexStart={5}
rowItems={rowItems}
attrName="mock.attr"
/>
);
expect(wrapper.find('DraggableWrapper').first().prop<string>('fieldType')).toEqual('keyword');
});
test('it should render with correct isAggregatable prop', () => {
const wrapper = mount(
<MoreContainer
fieldType="keyword"
idPrefix={idPrefix}
isAggregatable={true}
moreMaxHeight={DEFAULT_MORE_MAX_HEIGHT}
overflowIndexStart={5}
rowItems={rowItems}
attrName="mock.attr"
/>
);
expect(wrapper.find('DraggableWrapper').first().prop<boolean>('isAggregatable')).toEqual(
true
);
screen
.getAllByTestId('render-content-mock.attr')
.forEach((element) => expect(element).toBeInTheDocument());
});
test('it should only invoke the optional render function, when provided, for the items after overflowIndexStart', () => {
const render = jest.fn();
const renderFn = jest.fn();
mount(
render(
<MoreContainer
fieldType="keyword"
idPrefix={idPrefix}
isAggregatable={true}
moreMaxHeight={DEFAULT_MORE_MAX_HEIGHT}
overflowIndexStart={5}
render={render}
render={renderFn}
rowItems={rowItems}
/>
);
expect(render).toHaveBeenCalledTimes(2);
expect(renderFn).toHaveBeenCalledTimes(2);
});
});
@ -411,7 +377,7 @@ describe('Field Renderers', () => {
const rowItems = ['item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7'];
test('it should render the length of items after the overflowIndexStart', () => {
const wrapper = mount(
render(
<TestProviders>
<DefaultFieldRendererOverflow
fieldType="keyword"
@ -424,12 +390,14 @@ describe('Field Renderers', () => {
</TestProviders>
);
expect(wrapper.text()).toEqual(' ,+2 More');
expect(wrapper.find('[data-test-subj="more-container"]').first().exists()).toBe(false);
expect(screen.getByTestId('DefaultFieldRendererOverflow-button').textContent).toEqual(
'+2 More'
);
expect(screen.queryByTestId('more-container')).not.toBeInTheDocument();
});
test('it should render the items after overflowIndexStart in the popover', () => {
const wrapper = mount(
render(
<TestProviders>
<DefaultFieldRendererOverflow
fieldType="keyword"
@ -442,12 +410,12 @@ describe('Field Renderers', () => {
</TestProviders>
);
wrapper.find('button').first().simulate('click');
wrapper.update();
expect(wrapper.find('.euiPopover').first().exists()).toBe(true);
expect(wrapper.find('[data-test-subj="more-container"]').first().text()).toEqual(
'item6item7'
);
userEvent.click(screen.getByTestId('DefaultFieldRendererOverflow-button'));
expect(
screen.getByText('You are in a dialog. To close this dialog, hit escape.')
).toBeInTheDocument();
expect(screen.getByTestId('more-container').textContent).toEqual('item6item7');
});
});
});

View file

@ -44,7 +44,7 @@ export const locationRenderer = (
isDraggable?: boolean
): React.ReactElement =>
fieldNames.length > 0 && fieldNames.every((fieldName) => getOr(null, fieldName, data)) ? (
<EuiFlexGroup alignItems="center" gutterSize="none" data-test-subj="location-field">
<EuiFlexGroup alignItems="center" gutterSize="none">
{fieldNames.map((fieldName, index) => {
const locationValue = getOr('', fieldName, data);
return (
@ -236,7 +236,12 @@ export const DefaultFieldRendererComponent: React.FC<DefaultFieldRendererProps>
});
return draggables.length > 0 ? (
<DraggableContainerFlexGroup alignItems="center" gutterSize="none" component="span">
<DraggableContainerFlexGroup
alignItems="center"
gutterSize="none"
component="span"
data-test-subj="DefaultFieldRendererComponent"
>
<EuiFlexItem grow={false}>{draggables} </EuiFlexItem>
<EuiFlexItem grow={false}>
<DefaultFieldRendererOverflow
@ -397,7 +402,11 @@ export const DefaultFieldRendererOverflow = React.memo<DefaultFieldRendererOverf
() => (
<>
{' ,'}
<EuiButtonEmpty size="xs" onClick={togglePopover}>
<EuiButtonEmpty
size="xs"
onClick={togglePopover}
data-test-subj="DefaultFieldRendererOverflow-button"
>
{`+${rowItems.length - overflowIndexStart} `}
<FormattedMessage
id="xpack.securitySolution.fieldRenderers.moreLabel"

View file

@ -1,8 +1,426 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Flyout rendering it renders correctly against snapshot 1`] = `
<Flyout
onAppLeave={[MockFunction]}
timelineId="test"
/>
<DocumentFragment>
<div
data-eui="EuiFocusTrap"
>
<div
data-test-subj="flyout-pane"
style="display: none;"
>
<div
data-eui="EuiFlyout"
data-test-subj="eui-flyout"
role="dialog"
>
<div />
</div>
</div>
</div>
.c8 {
-webkit-transition: background-color 0.7s ease;
transition: background-color 0.7s ease;
width: 100%;
height: 100%;
}
.c8 .flyout-overlay .euiPanel {
background-color: #16171c;
}
.c8 > div.timeline-drop-area .drop-and-provider-timeline {
display: none;
}
.c8 > div.timeline-drop-area + div {
display: none !important;
}
.c14 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
border-radius: 100%;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
font-size: 9px;
height: 34px;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
margin: 0 5px 0 5px;
padding: 7px 6px 4px 6px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
width: 34px;
}
.c14 .euiBadge__content {
position: relative;
top: -1px;
}
.c14 .euiBadge__text {
text-overflow: clip;
}
.c11 {
overflow: hidden;
margin: 5px 0 5px 0;
padding: 3px;
white-space: nowrap;
}
.c13 {
height: 20px;
margin: 0 5px 0 5px;
maxwidth: 85px;
minwidth: 85px;
}
.c12 {
background-color: #343741;
}
.c9 {
width: auto;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-align-content: center;
-ms-flex-line-pack: center;
align-content: center;
min-height: 100px;
}
.c9 + div {
display: none !important;
}
.c10 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: no-wrap;
-ms-flex-wrap: no-wrap;
flex-wrap: no-wrap;
}
.c6 {
padding: 2px 0 4px 0;
}
.is-dragging .c6 .drop-target-data-providers {
background: rgba(125,222,216,0.1);
border: 0.2rem dashed #7dded8;
}
.is-dragging .c6 .drop-target-data-providers .timeline-drop-area-empty__text {
color: #7dded8;
}
.is-dragging .c6 .drop-target-data-providers .euiFormHelpText {
color: #7dded8;
}
.c7 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
padding-bottom: 2px;
position: relative;
border: 0.2rem dashed #535966;
border-radius: 5px;
padding: 4px 0;
margin: 2px 0 2px 0;
max-height: 33vh;
min-height: 100px;
overflow: auto;
resize: vertical;
background-color: #16171c;
}
.c3 {
display: block;
}
.c2 > span {
padding: 0;
}
.c4 {
overflow: hidden;
display: inline-block;
text-overflow: ellipsis;
}
.c0 {
margin: 0 -1px 0;
}
.c1 {
overflow: hidden;
}
.c5 {
border-radius: 0;
padding: 0 4px 0 4px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
z-index: 9000;
}
<div
class="timeline-flyout-button-bar"
data-test-subj="flyoutBottomBar"
>
<div
class="euiPanel euiPanel--plain euiPanel--paddingSmall c0 css-1sriiwr-euiPanel-none-s-plain"
data-test-subj="timeline-flyout-header-panel"
>
<div
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow"
>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<div
class="euiPopover euiPopover--anchorDownRight"
id="timelineSettingsPopover"
>
<div
class="euiPopover__anchor"
>
<button
aria-label="Add new timeline or template"
class="euiButtonIcon euiButtonIcon--primary euiButtonIcon--empty euiButtonIcon--medium add-timeline-button"
data-test-subj="settings-plus-in-circle"
type="button"
>
<span
aria-hidden="true"
class="euiButtonIcon__icon"
color="inherit"
data-euiicon-type="plusInCircle"
/>
</button>
</div>
</div>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero c1"
>
<button
aria-label="Open timeline Untitled timeline"
aria-pressed="false"
class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--small euiButtonEmpty--flushBoth c2 active-timeline-button"
data-test-subj="flyoutOverlay"
type="button"
>
<span
class="euiButtonContent euiButtonEmpty__content"
>
<span
class="euiButtonEmpty__text"
>
<div
class="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow"
>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
class="euiToolTipAnchor"
>
<div
class="euiHealth c3 css-qn8ayk-euiHealth-s"
>
<div
class="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow"
>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
color="success"
data-euiicon-type="dot"
/>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
/>
</div>
</div>
</span>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero c4"
>
Untitled timeline
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<div />
</div>
</div>
</span>
</span>
</button>
</div>
</div>
</div>
<div
class="euiPanel euiPanel--plain c5 css-n9us4v-euiPanel-grow-m-plain-hasShadow"
>
<div
aria-label="You are in the timeline query area, which contains groups of data providers that query for events"
class="c6 drop-target-data-providers-container"
>
<div
class="c7 drop-target-data-providers"
data-test-subj="dataProviders"
>
<div
class="c8"
data-rbd-droppable-context-id="123"
data-rbd-droppable-id="123"
height="100%"
>
<div
class="c9 timeline-drop-area-empty"
data-test-subj="empty"
>
<div
class="c10"
>
<div
class="euiText c11 timeline-drop-area-empty__text css-czh9ev-euiText-s-euiTextColor-subdued"
>
Drop anything
</div>
<span
class="c12"
>
<span
class="euiBadge euiBadge--iconLeft c13 highlighted-drop-target"
style="background-color: rgb(211, 218, 230); color: rgb(0, 0, 0);"
title="highlighted"
>
<span
class="euiBadge__content"
>
<span
class="euiBadge__text"
>
highlighted
</span>
</span>
</span>
</span>
<div
class="euiText c11 timeline-drop-area-empty__text css-czh9ev-euiText-s-euiTextColor-subdued"
>
here to build an
</div>
<span
class="euiBadge euiBadge--hollow euiBadge--iconLeft c14"
data-test-subj="and-or-badge"
title="OR"
>
<span
class="euiBadge__content"
>
<span
class="euiBadge__text"
>
OR
</span>
</span>
</span>
<div
class="euiText c11 timeline-drop-area-empty__text css-czh9ev-euiText-s-euiTextColor-subdued"
>
query
</div>
</div>
<div
class="euiPopover euiPopover--anchorDownLeft"
id="addFieldsPopover"
>
<div
class="euiPopover__anchor"
>
<button
class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--small"
data-test-subj="addField"
type="button"
>
<span
class="euiButtonContent euiButtonContent--iconRight euiButtonEmpty__content"
>
<span
class="euiButtonEmpty__text"
>
<div
class="euiText css-1vkrgyt-euiText-s"
>
+ Add field
</div>
</span>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</DocumentFragment>
`;

View file

@ -5,9 +5,9 @@
* 2.0.
*/
import { mount, ReactWrapper } from 'enzyme';
import React from 'react';
import { waitFor } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { AddTimelineButton } from '.';
import { useKibana } from '../../../../common/lib/kibana';
@ -19,6 +19,7 @@ import {
} from '../../../../common/mock';
import { getAllTimeline, useGetAllTimeline } from '../../../containers/all';
import { mockHistory, Router } from '../../../../common/mock/router';
import * as i18n from '../../timeline/properties/translations';
jest.mock('../../open_timeline/use_timeline_status', () => {
const originalModule = jest.requireActual('../../open_timeline/use_timeline_status');
@ -50,20 +51,11 @@ jest.mock('../../../containers/all', () => {
});
jest.mock('../../timeline/properties/new_template_timeline', () => ({
NewTemplateTimeline: jest.fn(() => <div data-test-subj="create-template-btn" />),
NewTemplateTimeline: jest.fn(() => <div>{'Create new timeline template'}</div>),
}));
jest.mock('../../timeline/properties/helpers', () => ({
Description: jest.fn().mockReturnValue(<div data-test-subj="Description" />),
ExistingCase: jest.fn().mockReturnValue(<div data-test-subj="ExistingCase" />),
NewCase: jest.fn().mockReturnValue(<div data-test-subj="NewCase" />),
NewTimeline: jest.fn().mockReturnValue(<div data-test-subj="create-default-btn" />),
NotesButton: jest.fn().mockReturnValue(<div data-test-subj="NotesButton" />),
}));
jest.mock('../../../../common/components/inspect', () => ({
InspectButton: jest.fn().mockReturnValue(<div />),
InspectButtonContainer: jest.fn(({ children }) => <div>{children}</div>),
NewTimeline: jest.fn().mockReturnValue(<div>{'Create new timeline'}</div>),
}));
jest.mock('../../../../common/containers/source', () => ({
@ -71,7 +63,6 @@ jest.mock('../../../../common/containers/source', () => ({
}));
describe('AddTimelineButton', () => {
let wrapper: ReactWrapper;
const props = {
timelineId: TimelineId.active,
};
@ -89,36 +80,30 @@ describe('AddTimelineButton', () => {
},
},
});
wrapper = mount(<AddTimelineButton {...props} />);
render(<AddTimelineButton {...props} />);
});
afterEach(() => {
(useKibana as jest.Mock).mockReset();
});
test('it renders settings-plus-in-circle', () => {
expect(wrapper.find('[data-test-subj="settings-plus-in-circle"]').exists()).toBeTruthy();
test('it renders the add new timeline btn', () => {
expect(screen.getByLabelText(i18n.ADD_TIMELINE)).toBeInTheDocument();
});
test('it renders create timeline btn', async () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
await waitFor(() =>
expect(wrapper.find('[data-test-subj="create-default-btn"]').exists()).toBeTruthy()
);
userEvent.click(screen.getByLabelText(i18n.ADD_TIMELINE));
expect(screen.getByText(i18n.NEW_TIMELINE)).toBeInTheDocument();
});
test('it renders create timeline template btn', async () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
await waitFor(() =>
expect(wrapper.find('[data-test-subj="create-template-btn"]').exists()).toBeTruthy()
);
test('it renders create timeline template btn', () => {
userEvent.click(screen.getByLabelText(i18n.ADD_TIMELINE));
expect(screen.getByText(i18n.NEW_TEMPLATE_TIMELINE)).toBeInTheDocument();
});
test('it renders Open timeline btn', async () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
await waitFor(() =>
expect(wrapper.find('[data-test-subj="open-timeline-button"]').exists()).toBeTruthy()
);
test('it renders Open timeline btn', () => {
userEvent.click(screen.getByLabelText(i18n.ADD_TIMELINE));
expect(screen.getByTestId('open-timeline-button')).toBeInTheDocument();
});
});
@ -135,36 +120,30 @@ describe('AddTimelineButton', () => {
},
},
});
wrapper = mount(<AddTimelineButton {...props} />);
render(<AddTimelineButton {...props} />);
});
afterEach(() => {
(useKibana as jest.Mock).mockReset();
});
test('it renders settings-plus-in-circle', () => {
expect(wrapper.find('[data-test-subj="settings-plus-in-circle"]').exists()).toBeTruthy();
test('it renders the add new timeline btn', () => {
expect(screen.getByLabelText(i18n.ADD_TIMELINE)).toBeInTheDocument();
});
test('it renders create timeline btn', async () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
await waitFor(() =>
expect(wrapper.find('[data-test-subj="create-default-btn"]').exists()).toBeTruthy()
);
test('it renders create timeline btn', () => {
userEvent.click(screen.getByLabelText(i18n.ADD_TIMELINE));
expect(screen.getByText(i18n.NEW_TIMELINE)).toBeInTheDocument();
});
test('it renders create timeline template btn', async () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
await waitFor(() =>
expect(wrapper.find('[data-test-subj="create-template-btn"]').exists()).toBeTruthy()
);
test('it renders create timeline template btn', () => {
userEvent.click(screen.getByLabelText(i18n.ADD_TIMELINE));
expect(screen.getByText(i18n.NEW_TEMPLATE_TIMELINE)).toBeInTheDocument();
});
test('it renders Open timeline btn', async () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
await waitFor(() =>
expect(wrapper.find('[data-test-subj="open-timeline-button"]').exists()).toBeTruthy()
);
userEvent.click(screen.getByLabelText(i18n.ADD_TIMELINE));
expect(screen.getByTestId('open-timeline-button')).toBeInTheDocument();
});
});
@ -191,7 +170,7 @@ describe('AddTimelineButton', () => {
refetch: jest.fn(),
});
wrapper = mount(
render(
<TestProviders>
<Router history={mockHistory}>
<AddTimelineButton {...props} />
@ -204,29 +183,24 @@ describe('AddTimelineButton', () => {
(useKibana as jest.Mock).mockReset();
});
it('should render timelines table', async () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
await waitFor(() => {
expect(wrapper.find('[data-test-subj="open-timeline-button"]').exists()).toBeTruthy();
});
it('should render timelines table', () => {
userEvent.click(screen.getByLabelText(i18n.ADD_TIMELINE));
expect(screen.getByTestId('open-timeline-button')).toBeInTheDocument();
wrapper.find('[data-test-subj="open-timeline-button"]').first().simulate('click');
await waitFor(() => {
expect(wrapper.find('[data-test-subj="timelines-table"]').exists()).toBeTruthy();
});
userEvent.click(screen.getByTestId('open-timeline-button'));
expect(screen.getByTestId('timelines-table')).toBeInTheDocument();
});
it('should render correct actions', async () => {
wrapper.find('[data-test-subj="settings-plus-in-circle"]').last().simulate('click');
await waitFor(() =>
expect(wrapper.find('[data-test-subj="open-timeline-button"]').exists()).toBeTruthy()
);
it('should render correct actions', () => {
userEvent.click(screen.getByLabelText(i18n.ADD_TIMELINE));
expect(screen.getByTestId('open-timeline-button')).toBeInTheDocument();
wrapper.find('[data-test-subj="open-timeline-button"]').first().simulate('click');
await waitFor(() => {
expect(wrapper.find('[data-test-subj="open-duplicate"]').exists()).toBeTruthy();
expect(wrapper.find('[data-test-subj="create-from-template"]').exists()).toBeFalsy();
userEvent.click(screen.getByTestId('open-timeline-button'));
screen.queryAllByTestId('open-duplicate').forEach((element) => {
expect(element).toBeInTheDocument();
});
expect(screen.queryByTestId('create-from-template')).not.toBeInTheDocument();
});
});
});

View file

@ -6,7 +6,8 @@
*/
import React from 'react';
import { mount } from 'enzyme';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { useKibana } from '../../../../common/lib/kibana';
import { useDeepEqualSelector } from '../../../../common/hooks/use_selector';
@ -54,13 +55,13 @@ describe('AddToCaseButton', () => {
}
);
(useDeepEqualSelector as jest.Mock).mockReturnValue(mockTimelineModel);
const wrapper = mount(
render(
<TestProviders>
<AddToCaseButton timelineId={'timeline-1'} />
</TestProviders>
);
wrapper.find(`[data-test-subj="attach-timeline-case-button"]`).first().simulate('click');
wrapper.find(`[data-test-subj="attach-timeline-existing-case"]`).first().simulate('click');
userEvent.click(screen.getByTestId('attach-timeline-case-button'));
userEvent.click(screen.getByTestId('attach-timeline-existing-case'));
expect(navigateToApp).toHaveBeenCalledWith('securitySolutionUI', {
path: '/create',
@ -76,13 +77,13 @@ describe('AddToCaseButton', () => {
return <></>;
});
(useDeepEqualSelector as jest.Mock).mockReturnValue(mockTimelineModel);
const wrapper = mount(
render(
<TestProviders>
<AddToCaseButton timelineId={'timeline-1'} />
</TestProviders>
);
wrapper.find(`[data-test-subj="attach-timeline-case-button"]`).first().simulate('click');
wrapper.find(`[data-test-subj="attach-timeline-existing-case"]`).first().simulate('click');
userEvent.click(screen.getByTestId('attach-timeline-case-button'));
userEvent.click(screen.getByTestId('attach-timeline-existing-case'));
expect(navigateToApp).toHaveBeenCalledWith('securitySolutionUI', {
path: '/case-id',

View file

@ -5,8 +5,8 @@
* 2.0.
*/
import { mount } from 'enzyme';
import React from 'react';
import { render, screen } from '@testing-library/react';
import { TestProviders } from '../../../../common/mock/test_providers';
import { TimelineTabs } from '../../../../../common/types/timeline';
@ -14,7 +14,7 @@ import { FlyoutBottomBar } from '.';
describe('FlyoutBottomBar', () => {
test('it renders the expected bottom bar', () => {
const wrapper = mount(
render(
<TestProviders>
<FlyoutBottomBar
timelineId="test"
@ -24,11 +24,11 @@ describe('FlyoutBottomBar', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="flyoutBottomBar"]').exists()).toBeTruthy();
expect(screen.getByTestId('flyoutBottomBar')).toBeInTheDocument();
});
test('it renders the data providers drop target area', () => {
const wrapper = mount(
render(
<TestProviders>
<FlyoutBottomBar
timelineId="test"
@ -38,11 +38,11 @@ describe('FlyoutBottomBar', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="dataProviders"]').exists()).toBe(true);
expect(screen.getByTestId('dataProviders')).toBeInTheDocument();
});
test('it renders the flyout header panel', () => {
const wrapper = mount(
render(
<TestProviders>
<FlyoutBottomBar
timelineId="test"
@ -52,11 +52,11 @@ describe('FlyoutBottomBar', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="timeline-flyout-header-panel"]').exists()).toBe(true);
expect(screen.getByTestId('timeline-flyout-header-panel')).toBeInTheDocument();
});
test('it hides the data providers drop target area', () => {
const wrapper = mount(
render(
<TestProviders>
<FlyoutBottomBar
timelineId="test"
@ -66,11 +66,11 @@ describe('FlyoutBottomBar', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="dataProviders"]').exists()).toBe(false);
expect(screen.queryByTestId('dataProviders')).not.toBeInTheDocument();
});
test('it hides the flyout header panel', () => {
const wrapper = mount(
render(
<TestProviders>
<FlyoutBottomBar
timelineId="test"
@ -80,11 +80,11 @@ describe('FlyoutBottomBar', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="timeline-flyout-header-panel"]').exists()).toBe(false);
expect(screen.queryByTestId('timeline-flyout-header-panel')).not.toBeInTheDocument();
});
test('it renders the data providers drop target area when showDataproviders=false and tab is not query', () => {
const wrapper = mount(
render(
<TestProviders>
<FlyoutBottomBar
timelineId="test"
@ -94,6 +94,6 @@ describe('FlyoutBottomBar', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="dataProviders"]').exists()).toBe(true);
expect(screen.getByTestId('dataProviders')).toBeInTheDocument();
});
});

View file

@ -6,6 +6,7 @@
*/
import React from 'react';
import { render, screen } from '@testing-library/react';
import { useKibana, useGetUserCasesPermissions } from '../../../../common/lib/kibana';
import { TestProviders, mockIndexNames, mockIndexPattern } from '../../../../common/mock';
@ -14,7 +15,6 @@ import { useTimelineKpis } from '../../../containers/kpis';
import { FlyoutHeader } from '.';
import { useSourcererDataView } from '../../../../common/containers/sourcerer';
import { mockBrowserFields, mockDocValueFields } from '../../../../common/containers/source/mock';
import { useMountAppended } from '../../../../common/utils/use_mount_appended';
import { getEmptyValue } from '../../../../common/components/empty_value';
const mockUseSourcererDataView: jest.Mock = useSourcererDataView as jest.Mock;
@ -58,8 +58,6 @@ const defaultMocks = {
selectedPatterns: mockIndexNames,
};
describe('header', () => {
const mount = useMountAppended();
beforeEach(() => {
// Mocking these services is required for the header component to render.
mockUseSourcererDataView.mockImplementation(() => defaultMocks);
@ -86,13 +84,13 @@ describe('header', () => {
read: false,
});
const wrapper = mount(
render(
<TestProviders>
<FlyoutHeader timelineId={TimelineId.test} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="attach-timeline-case-button"]').exists()).toBeTruthy();
expect(screen.getByTestId('attach-timeline-case-button')).toBeInTheDocument();
});
it('does not render the button when the user does not have write permissions', () => {
@ -101,13 +99,13 @@ describe('header', () => {
read: false,
});
const wrapper = mount(
render(
<TestProviders>
<FlyoutHeader timelineId={TimelineId.test} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="attach-timeline-case-button"]').exists()).toBeFalsy();
expect(screen.queryByTestId('attach-timeline-case-button')).not.toBeInTheDocument();
});
});
@ -116,21 +114,17 @@ describe('header', () => {
beforeEach(() => {
mockUseTimelineKpis.mockReturnValue([false, mockUseTimelineKpiResponse]);
});
it('renders the component, labels and values successfully', async () => {
const wrapper = mount(
it('renders the component, labels and values successfully', () => {
render(
<TestProviders>
<FlyoutHeader timelineId={TimelineId.test} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="siem-timeline-kpis"]').exists()).toEqual(true);
expect(screen.getByTestId('siem-timeline-kpis')).toBeInTheDocument();
// label
expect(wrapper.find('[data-test-subj="siem-timeline-process-kpi"]').first().text()).toEqual(
expect.stringContaining('Processes')
);
expect(screen.getByText('Processes')).toBeInTheDocument();
// value
expect(wrapper.find('[data-test-subj="siem-timeline-process-kpi"]').first().text()).toEqual(
expect.stringContaining('1')
);
expect(screen.getByTestId('siem-timeline-process-kpi').textContent).toContain('1');
});
});
@ -139,14 +133,12 @@ describe('header', () => {
mockUseTimelineKpis.mockReturnValue([true, mockUseTimelineKpiResponse]);
});
it('renders a loading indicator for values', async () => {
const wrapper = mount(
render(
<TestProviders>
<FlyoutHeader timelineId={TimelineId.test} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="siem-timeline-process-kpi"]').first().text()).toEqual(
expect.stringContaining('--')
);
expect(screen.getAllByText('--')).not.toHaveLength(0);
});
});
@ -154,19 +146,14 @@ describe('header', () => {
beforeEach(() => {
mockUseTimelineKpis.mockReturnValue([false, null]);
});
it('renders labels and the default empty string', async () => {
const wrapper = mount(
it('renders labels and the default empty string', () => {
render(
<TestProviders>
<FlyoutHeader timelineId={TimelineId.test} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="siem-timeline-process-kpi"]').first().text()).toEqual(
expect.stringContaining('Processes')
);
expect(wrapper.find('[data-test-subj="siem-timeline-process-kpi"]').first().text()).toEqual(
expect.stringContaining(getEmptyValue())
);
expect(screen.getByText('Processes')).toBeInTheDocument();
expect(screen.getAllByText(getEmptyValue())).not.toHaveLength(0);
});
});
@ -174,24 +161,16 @@ describe('header', () => {
beforeEach(() => {
mockUseTimelineKpis.mockReturnValue([false, mockUseTimelineLargeKpiResponse]);
});
it('formats the numbers correctly', async () => {
const wrapper = mount(
it('formats the numbers correctly', () => {
render(
<TestProviders>
<FlyoutHeader timelineId={TimelineId.test} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="siem-timeline-process-kpi"]').first().text()).toEqual(
expect.stringContaining('1k')
);
expect(wrapper.find('[data-test-subj="siem-timeline-user-kpi"]').first().text()).toEqual(
expect.stringContaining('1m')
);
expect(
wrapper.find('[data-test-subj="siem-timeline-source-ip-kpi"]').first().text()
).toEqual(expect.stringContaining('1b'));
expect(wrapper.find('[data-test-subj="siem-timeline-host-kpi"]').first().text()).toEqual(
expect.stringContaining('999')
);
expect(screen.getByText('1k', { selector: '.euiTitle' })).toBeInTheDocument();
expect(screen.getByText('1m', { selector: '.euiTitle' })).toBeInTheDocument();
expect(screen.getByText('1b', { selector: '.euiTitle' })).toBeInTheDocument();
expect(screen.getByText('999', { selector: '.euiTitle' })).toBeInTheDocument();
});
});
});

View file

@ -5,20 +5,13 @@
* 2.0.
*/
import { mount, shallow } from 'enzyme';
import { set } from '@elastic/safer-lodash-set/fp';
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '../../../common/mock/react_beautiful_dnd';
import {
mockGlobalState,
TestProviders,
SUB_PLUGINS_REDUCER,
kibanaObservable,
createSecuritySolutionStorageMock,
} from '../../../common/mock';
import { TestProviders } from '../../../common/mock';
import { TimelineId } from '../../../../common/types/timeline';
import { createStore, State } from '../../../common/store';
import * as timelineActions from '../../store/timeline/actions';
import { Flyout } from '.';
@ -38,8 +31,6 @@ jest.mock('../timeline', () => ({
}));
describe('Flyout', () => {
const state: State = mockGlobalState;
const { storage } = createSecuritySolutionStorageMock();
const props = {
onAppLeave: jest.fn(),
timelineId: TimelineId.test,
@ -51,54 +42,32 @@ describe('Flyout', () => {
describe('rendering', () => {
test('it renders correctly against snapshot', () => {
const wrapper = shallow(
const { asFragment } = render(
<TestProviders>
<Flyout {...props} />
</TestProviders>
);
expect(wrapper.find('Flyout')).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('it renders the default flyout state as a bottom bar', () => {
const wrapper = mount(
render(
<TestProviders>
<Flyout {...props} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="flyoutBottomBar"]').first().text()).toContain(
'Untitled timeline'
);
});
test('it does NOT render the fly out bottom bar when its state is set to flyout is true', () => {
const stateShowIsTrue = set('timeline.timelineById.test.show', true, state);
const storeShowIsTrue = createStore(
stateShowIsTrue,
SUB_PLUGINS_REDUCER,
kibanaObservable,
storage
);
const wrapper = mount(
<TestProviders store={storeShowIsTrue}>
<Flyout {...props} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="flyout-button-not-ready-to-drop"]').exists()).toEqual(
false
);
expect(screen.getByText('Untitled timeline')).toBeInTheDocument();
});
test('should call the onOpen when the mouse is clicked for rendering', () => {
const wrapper = mount(
render(
<TestProviders>
<Flyout {...props} />
</TestProviders>
);
wrapper.find('[data-test-subj="flyoutOverlay"]').first().simulate('click');
userEvent.click(screen.getByTestId('flyoutOverlay'));
expect(mockDispatch).toBeCalledWith(timelineActions.showTimeline({ id: 'test', show: true }));
});

View file

@ -5,8 +5,8 @@
* 2.0.
*/
import React from 'react';
import { mount } from 'enzyme';
import { waitFor } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { FormattedIp } from '.';
import { TestProviders } from '../../../common/mock';
@ -76,13 +76,13 @@ describe('FormattedIp', () => {
toggleExpandedDetail.mockClear();
});
test('should render ip address', () => {
const wrapper = mount(
render(
<TestProviders>
<FormattedIp {...props} />
</TestProviders>
);
expect(wrapper.text()).toEqual(props.value);
expect(screen.getByText(props.value)).toBeInTheDocument();
});
test('should render DraggableWrapper if isDraggable is true', () => {
@ -90,37 +90,35 @@ describe('FormattedIp', () => {
...props,
isDraggable: true,
};
const wrapper = mount(
render(
<TestProviders>
<FormattedIp {...testProps} />
</TestProviders>
);
expect(wrapper.find('[data-test-subj="DraggableWrapper"]').exists()).toEqual(true);
expect(screen.getByTestId('DraggableWrapper')).toBeInTheDocument();
});
test('if not enableIpDetailsFlyout, should go to network details page', async () => {
const wrapper = mount(
test('if not enableIpDetailsFlyout, should go to network details page', () => {
render(
<TestProviders>
<FormattedIp {...props} />
</TestProviders>
);
wrapper.find('[data-test-subj="network-details"]').last().simulate('click');
await waitFor(() => {
expect(timelineActions.toggleDetailPanel).not.toHaveBeenCalled();
expect(toggleExpandedDetail).not.toHaveBeenCalled();
});
userEvent.click(screen.getByTestId('network-details'));
expect(timelineActions.toggleDetailPanel).not.toHaveBeenCalled();
expect(toggleExpandedDetail).not.toHaveBeenCalled();
});
test('if enableIpDetailsFlyout, should open NetworkDetailsSidePanel', async () => {
test('if enableIpDetailsFlyout, should open NetworkDetailsSidePanel', () => {
const context = {
enableHostDetailsFlyout: true,
enableIpDetailsFlyout: true,
timelineID: TimelineId.active,
tabType: TimelineTabs.query,
};
const wrapper = mount(
render(
<TestProviders>
<StatefulEventContext.Provider value={context}>
<FormattedIp {...props} />
@ -128,17 +126,15 @@ describe('FormattedIp', () => {
</TestProviders>
);
wrapper.find('[data-test-subj="network-details"]').last().simulate('click');
await waitFor(() => {
expect(timelineActions.toggleDetailPanel).toHaveBeenCalledWith({
panelView: 'networkDetail',
params: {
flowTarget: 'source',
ip: props.value,
},
tabType: context.tabType,
timelineId: context.timelineID,
});
userEvent.click(screen.getByTestId('network-details'));
expect(timelineActions.toggleDetailPanel).toHaveBeenCalledWith({
panelView: 'networkDetail',
params: {
flowTarget: 'source',
ip: props.value,
},
tabType: context.tabType,
timelineId: context.timelineID,
});
});
@ -149,7 +145,7 @@ describe('FormattedIp', () => {
timelineID: TimelineId.active,
tabType: TimelineTabs.query,
};
const wrapper = mount(
render(
<TestProviders>
<StatefulEventContext.Provider value={context}>
<FormattedIp {...props} />
@ -157,15 +153,13 @@ describe('FormattedIp', () => {
</TestProviders>
);
wrapper.find('[data-test-subj="network-details"]').last().simulate('click');
await waitFor(() => {
expect(toggleExpandedDetail).toHaveBeenCalledWith({
panelView: 'networkDetail',
params: {
flowTarget: 'source',
ip: props.value,
},
});
userEvent.click(screen.getByTestId('network-details'));
expect(toggleExpandedDetail).toHaveBeenCalledWith({
panelView: 'networkDetail',
params: {
flowTarget: 'source',
ip: props.value,
},
});
});
@ -176,7 +170,7 @@ describe('FormattedIp', () => {
timelineID: 'detection',
tabType: TimelineTabs.query,
};
const wrapper = mount(
render(
<TestProviders>
<StatefulEventContext.Provider value={context}>
<FormattedIp {...props} />
@ -184,18 +178,16 @@ describe('FormattedIp', () => {
</TestProviders>
);
wrapper.find('[data-test-subj="network-details"]').last().simulate('click');
await waitFor(() => {
expect(timelineActions.toggleDetailPanel).toHaveBeenCalledWith({
panelView: 'networkDetail',
params: {
flowTarget: 'source',
ip: props.value,
},
tabType: context.tabType,
timelineId: context.timelineID,
});
expect(toggleExpandedDetail).not.toHaveBeenCalled();
userEvent.click(screen.getByTestId('network-details'));
expect(timelineActions.toggleDetailPanel).toHaveBeenCalledWith({
panelView: 'networkDetail',
params: {
flowTarget: 'source',
ip: props.value,
},
tabType: context.tabType,
timelineId: context.timelineID,
});
expect(toggleExpandedDetail).not.toHaveBeenCalled();
});
});

View file

@ -6,21 +6,18 @@
*/
import React from 'react';
import { render, screen } from '@testing-library/react';
import { removeExternalLinkText } from '@kbn/securitysolution-io-ts-utils';
import { TestProviders } from '../../../common/mock';
import '../../../common/mock/match_media';
import { useMountAppended } from '../../../common/utils/use_mount_appended';
import { Ja3Fingerprint } from '.';
jest.mock('../../../common/lib/kibana');
describe('Ja3Fingerprint', () => {
const mount = useMountAppended();
test('renders the expected label', () => {
const wrapper = mount(
render(
<TestProviders>
<Ja3Fingerprint
eventId="KzNOvGkBqd-n62SwSPa4"
@ -31,11 +28,11 @@ describe('Ja3Fingerprint', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="ja3-fingerprint-label"]').first().text()).toEqual('ja3');
expect(screen.getByText('ja3')).toBeInTheDocument();
});
test('renders the fingerprint as text', () => {
const wrapper = mount(
render(
<TestProviders>
<Ja3Fingerprint
eventId="KzNOvGkBqd-n62SwSPa4"
@ -46,13 +43,11 @@ describe('Ja3Fingerprint', () => {
</TestProviders>
);
expect(
removeExternalLinkText(wrapper.find('[data-test-subj="ja3-fingerprint-link"]').first().text())
).toContain('fff799d91b7c01ae3fe6787cfc895552');
expect(screen.getByText('fff799d91b7c01ae3fe6787cfc895552')).toBeInTheDocument();
});
test('it renders a hyperlink to an external site to compare the fingerprint against a known set of signatures', () => {
const wrapper = mount(
render(
<TestProviders>
<Ja3Fingerprint
eventId="KzNOvGkBqd-n62SwSPa4"
@ -63,7 +58,8 @@ describe('Ja3Fingerprint', () => {
</TestProviders>
);
expect(wrapper.find('[data-test-subj="ja3-fingerprint-link"]').first().props().href).toEqual(
expect(screen.getByText('fff799d91b7c01ae3fe6787cfc895552')).toHaveAttribute(
'href',
'https://sslbl.abuse.ch/ja3-fingerprints/fff799d91b7c01ae3fe6787cfc895552'
);
});

View file

@ -44,9 +44,7 @@ export const Ja3Fingerprint = React.memo<{
isAggregatable={true}
fieldType="keyword"
>
<Ja3FingerprintLabel data-test-subj="ja3-fingerprint-label">
{i18n.JA3_FINGERPRINT_LABEL}
</Ja3FingerprintLabel>
<Ja3FingerprintLabel>{i18n.JA3_FINGERPRINT_LABEL}</Ja3FingerprintLabel>
<Ja3FingerprintLink data-test-subj="ja3-hash-link" ja3Fingerprint={value || ''} />
</DraggableBadge>
));

View file

@ -7,9 +7,8 @@
import { get } from 'lodash/fp';
import React from 'react';
import { shallow } from 'enzyme';
import { render, screen, within } from '@testing-library/react';
import { removeExternalLinkText } from '@kbn/securitysolution-io-ts-utils';
import { asArrayIfExists } from '../../../common/lib/helpers';
import '../../../common/mock/match_media';
import { TestProviders } from '../../../common/mock/test_providers';
@ -59,7 +58,6 @@ import {
NETWORK_PROTOCOL_FIELD_NAME,
NETWORK_TRANSPORT_FIELD_NAME,
} from '../../../network/components/source_destination/field_names';
import { useMountAppended } from '../../../common/utils/use_mount_appended';
import { getMockNetflowData } from '../../../common/mock/netflow';
jest.mock('../../../common/lib/kibana');
@ -136,300 +134,244 @@ const getNetflowInstance = () => (
jest.mock('../../../common/components/link_to');
describe('Netflow', () => {
const mount = useMountAppended();
test('renders correctly against snapshot', () => {
const wrapper = shallow(getNetflowInstance());
expect(wrapper).toMatchSnapshot();
const { asFragment } = render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(asFragment()).toMatchSnapshot();
});
test('it renders a destination label', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination-label"]').first().text()).toEqual(
i18n.DESTINATION
);
expect(screen.getByText(i18n.DESTINATION)).toBeInTheDocument();
});
test('it renders destination.bytes', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination-bytes"]').first().text()).toEqual('40B');
expect(screen.getByText('40B')).toBeInTheDocument();
});
test('it renders destination.geo.continent_name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
wrapper.find('[data-test-subj="destination.geo.continent_name"]').first().text()
).toEqual('North America');
expect(screen.getByTestId('draggable-content-destination.geo.continent_name').textContent).toBe(
'North America'
);
});
test('it renders destination.geo.country_name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination.geo.country_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-destination.geo.country_name').textContent).toBe(
'United States'
);
});
test('it renders destination.geo.country_iso_code', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
wrapper.find('[data-test-subj="destination.geo.country_iso_code"]').first().text()
).toEqual('US');
screen.getByTestId('draggable-content-destination.geo.country_iso_code').textContent
).toBe('US');
});
test('it renders destination.geo.region_name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination.geo.region_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-destination.geo.region_name').textContent).toBe(
'New York'
);
});
test('it renders destination.geo.city_name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination.geo.city_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-destination.geo.city_name').textContent).toBe(
'New York'
);
});
test('it renders the destination ip and port, separated with a colon', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
removeExternalLinkText(
wrapper.find('[data-test-subj="destination-ip-and-port"]').first().text()
)
).toContain('10.1.2.3:80');
expect(screen.getByTestId('destination-ip-badge').textContent).toContain('10.1.2.3:80');
});
test('it renders destination.packets', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="destination-packets"]').first().text()).toEqual('1 pkts');
expect(screen.getByText('1 pkts')).toBeInTheDocument();
});
test('it hyperlinks links destination.port to an external service that describes the purpose of the port', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
wrapper
.find('[data-test-subj="destination-ip-and-port"]')
.find('[data-test-subj="port-or-service-name-link"]')
.first()
.props().href
).toEqual(
within(screen.getByTestId('destination-ip-group')).getByTestId('port-or-service-name-link')
).toHaveAttribute(
'href',
'https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=80'
);
});
test('it renders event.duration', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="event-duration"]').first().text()).toEqual('1ms');
expect(screen.getByText('1ms')).toBeInTheDocument();
});
test('it renders event.end', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="event-end"]').first().text().length).toBeGreaterThan(0); // the format of this date will depend on the user's locale and settings
});
test('it renders event.start', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="event-start"]').first().text().length).toBeGreaterThan(0); // the format of this date will depend on the user's locale and settings
});
test('it renders network.bytes', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-bytes"]').first().text()).toEqual('100B');
});
test('it renders network.community_id', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-community-id"]').first().text()).toEqual(
'we.live.in.a'
expect(screen.getByTestId('draggable-content-event.end').textContent).toBe(
'Nov 12, 2018 @ 19:03:25.936'
);
});
test('it renders network.direction', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
test('it renders event.start', () => {
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-direction"]').first().text()).toEqual('outgoing');
expect(screen.getByTestId('draggable-content-event.start').textContent).toBe(
'Nov 12, 2018 @ 19:03:25.836'
);
});
test('it renders network.bytes', () => {
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(screen.getByText('100B')).toBeInTheDocument();
});
test('it renders network.community_id', () => {
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(screen.getByText('we.live.in.a')).toBeInTheDocument();
});
test('it renders network.direction', () => {
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(screen.getByText('outgoing')).toBeInTheDocument();
});
test('it renders network.packets', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-packets"]').first().text()).toEqual('3 pkts');
expect(screen.getByText('3 pkts')).toBeInTheDocument();
});
test('it renders network.protocol', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-protocol"]').first().text()).toEqual('http');
expect(screen.getByText('http')).toBeInTheDocument();
});
test('it renders process.name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="process-name"]').first().text()).toEqual('rat');
expect(screen.getByText('rat')).toBeInTheDocument();
});
test('it renders a source label', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source-label"]').first().text()).toEqual(i18n.SOURCE);
expect(screen.getByText(i18n.SOURCE)).toBeInTheDocument();
});
test('it renders source.bytes', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source-bytes"]').first().text()).toEqual('60B');
expect(screen.getByText('60B')).toBeInTheDocument();
});
test('it renders source.geo.continent_name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.continent_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.continent_name').textContent).toBe(
'North America'
);
});
test('it renders source.geo.country_name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.country_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.country_name').textContent).toBe(
'United States'
);
});
test('it renders source.geo.country_iso_code', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.country_iso_code"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.country_iso_code').textContent).toBe(
'US'
);
});
test('it renders source.geo.region_name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.region_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.region_name').textContent).toBe(
'Georgia'
);
});
test('it renders source.geo.city_name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source.geo.city_name"]').first().text()).toEqual(
expect(screen.getByTestId('draggable-content-source.geo.city_name').textContent).toBe(
'Atlanta'
);
});
test('it renders the source ip and port, separated with a colon', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
removeExternalLinkText(wrapper.find('[data-test-subj="source-ip-and-port"]').first().text())
).toContain('192.168.1.2:9987');
expect(screen.getByTestId('source-ip-badge').textContent).toContain('192.168.1.2:9987');
});
test('it renders source.packets', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="source-packets"]').first().text()).toEqual('2 pkts');
expect(screen.getByText('2 pkts')).toBeInTheDocument();
});
test('it hyperlinks tls.client_certificate.fingerprint.sha1 site to compare the fingerprint against a known set of signatures', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
wrapper
.find('[data-test-subj="client-certificate-fingerprint"]')
.find('[data-test-subj="certificate-fingerprint-link"]')
.first()
.props().href
).toEqual(
expect(screen.getByText('tls.client_certificate.fingerprint.sha1-value')).toHaveAttribute(
'href',
'https://sslbl.abuse.ch/ssl-certificates/sha1/tls.client_certificate.fingerprint.sha1-value'
);
});
test('renders tls.client_certificate.fingerprint.sha1 text', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
removeExternalLinkText(
wrapper
.find('[data-test-subj="client-certificate-fingerprint"]')
.find('[data-test-subj="certificate-fingerprint-link"]')
.first()
.text()
)
).toContain('tls.client_certificate.fingerprint.sha1-value');
});
test('it hyperlinks tls.fingerprints.ja3.hash site to compare the fingerprint against a known set of signatures', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="ja3-fingerprint-link"]').first().props().href).toEqual(
expect(screen.getByText('tls.fingerprints.ja3.hash-value')).toHaveAttribute(
'href',
'https://sslbl.abuse.ch/ja3-fingerprints/tls.fingerprints.ja3.hash-value'
);
});
test('renders tls.fingerprints.ja3.hash text', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
removeExternalLinkText(wrapper.find('[data-test-subj="ja3-fingerprint-link"]').first().text())
).toContain('tls.fingerprints.ja3.hash-value');
});
test('it hyperlinks tls.server_certificate.fingerprint.sha1 site to compare the fingerprint against a known set of signatures', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
wrapper
.find('[data-test-subj="server-certificate-fingerprint"]')
.find('[data-test-subj="certificate-fingerprint-link"]')
.first()
.props().href
).toEqual(
expect(screen.getByText('tls.server_certificate.fingerprint.sha1-value')).toHaveAttribute(
'href',
'https://sslbl.abuse.ch/ssl-certificates/sha1/tls.server_certificate.fingerprint.sha1-value'
);
});
test('renders tls.server_certificate.fingerprint.sha1 text', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(
removeExternalLinkText(
wrapper
.find('[data-test-subj="server-certificate-fingerprint"]')
.find('[data-test-subj="certificate-fingerprint-link"]')
.first()
.text()
)
).toContain('tls.server_certificate.fingerprint.sha1-value');
});
test('it renders network.transport', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="network-transport"]').first().text()).toEqual('tcp');
expect(screen.getByText('tcp')).toBeInTheDocument();
});
test('it renders user.name', () => {
const wrapper = mount(<TestProviders>{getNetflowInstance()}</TestProviders>);
render(<TestProviders>{getNetflowInstance()}</TestProviders>);
expect(wrapper.find('[data-test-subj="user-name"]').first().text()).toEqual('first.last');
expect(screen.getByText('first.last')).toBeInTheDocument();
});
});

View file

@ -51,7 +51,6 @@ export const DurationEventStartEnd = React.memo<{
? uniq(eventDuration).map((duration) => (
<EuiFlexItem grow={false} key={duration}>
<DefaultDraggable
data-test-subj="event-duration"
field={EVENT_DURATION_FIELD_NAME}
id={`duration-event-start-end-default-draggable-${contextId}-${eventId}-${EVENT_DURATION_FIELD_NAME}-${duration}`}
isDraggable={isDraggable}
@ -75,7 +74,6 @@ export const DurationEventStartEnd = React.memo<{
? uniq(eventStart).map((start) => (
<EuiFlexItem grow={false} key={start}>
<DefaultDraggable
data-test-subj="event-start"
field={EVENT_START_FIELD_NAME}
id={`duration-event-start-end-default-draggable-${contextId}-${eventId}-${EVENT_START_FIELD_NAME}-${start}`}
isDraggable={isDraggable}
@ -94,7 +92,6 @@ export const DurationEventStartEnd = React.memo<{
? uniq(eventEnd).map((end) => (
<EuiFlexItem grow={false} key={end}>
<DefaultDraggable
data-test-subj="event-end"
field={EVENT_END_FIELD_NAME}
id={`duration-event-start-end-default-draggable-${contextId}-${eventId}-${EVENT_END_FIELD_NAME}-${end}`}
isDraggable={isDraggable}

View file

@ -56,7 +56,6 @@ export const UserProcess = React.memo<{
<EuiFlexItem grow={false} key={process}>
<DraggableBadge
contextId={contextId}
data-test-subj="process-name"
eventId={eventId}
field={PROCESS_NAME_FIELD_NAME}
isDraggable={isDraggable}

View file

@ -5,13 +5,12 @@
* 2.0.
*/
import { shallow } from 'enzyme';
import React from 'react';
import { render, screen } from '@testing-library/react';
import '../../../../../../common/mock/match_media';
import { Ecs } from '../../../../../../../common/ecs';
import { getMockNetflowData, TestProviders } from '../../../../../../common/mock';
import { useMountAppended } from '../../../../../../common/utils/use_mount_appended';
import {
eventActionMatches,
@ -29,8 +28,6 @@ jest.mock('../../../../../../common/lib/kibana');
jest.mock('../../../../../../common/components/link_to');
describe('netflowRowRenderer', () => {
const mount = useMountAppended();
test('renders correctly against snapshot', () => {
const children = netflowRowRenderer.renderRow({
data: getMockNetflowData(),
@ -38,8 +35,8 @@ describe('netflowRowRenderer', () => {
timelineId: 'test',
});
const wrapper = shallow(<span>{children}</span>);
expect(wrapper).toMatchSnapshot();
const { asFragment } = render(<TestProviders>{children}</TestProviders>);
expect(asFragment()).toMatchSnapshot();
});
describe('#isInstance', () => {
@ -106,12 +103,12 @@ describe('netflowRowRenderer', () => {
isDraggable: true,
timelineId: 'test',
});
const wrapper = mount(
render(
<TestProviders>
<span>{children}</span>
</TestProviders>
);
expect(wrapper.find('[data-test-subj="destination-bytes"]').first().text()).toEqual('40B');
expect(screen.getByText('40B')).toBeInTheDocument();
});
});