Skip to content

Commit

Permalink
Merge branch 'main' into osquery-fix-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Aug 4, 2022
2 parents 0bc2695 + bd2361d commit 99f869f
Show file tree
Hide file tree
Showing 40 changed files with 644 additions and 152 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { mountWithIntl } from '@kbn/test-jest-helpers';
import { waitFor } from '@testing-library/react';
import { setHeaderActionMenuMounter } from '../../kibana_services';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { discoverServiceMock } from '../../__mocks__/services';
import { DiscoverMainRoute } from './discover_main_route';
import { MemoryRouter } from 'react-router-dom';
import { dataViewMock } from '../../__mocks__/data_view';
import { SavedObject } from '@kbn/core/public';
import { DataViewSavedObjectAttrs } from '@kbn/data-views-plugin/common';
import { DiscoverMainApp } from './discover_main_app';
import { SearchSource } from '@kbn/data-plugin/common';
import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks';
import { findTestSubject } from '@elastic/eui/lib/test';
jest.mock('./discover_main_app', () => {
return {
DiscoverMainApp: jest.fn(),
};
});

describe('DiscoverMainRoute', () => {
test('renders the main app when hasESData=true & hasUserDataView=true ', async () => {
const component = mountComponent(true, true);

await waitFor(() => {
component.update();
expect(component.find(DiscoverMainApp).exists()).toBe(true);
});
});

test('renders no data page when hasESData=false & hasUserDataView=false', async () => {
const component = mountComponent(false, false);

await waitFor(() => {
component.update();
expect(findTestSubject(component, 'kbnNoDataPage').length).toBe(1);
});
});
test('renders no data view when hasESData=true & hasUserDataView=false', async () => {
const component = mountComponent(true, false);

await waitFor(() => {
component.update();
expect(findTestSubject(component, 'noDataViewsPrompt').length).toBe(1);
});
});
// skipped because this is the case that never ever should happen, it happened once and was fixed in
// https://github.com/elastic/kibana/pull/137824
test.skip('renders no data page when hasESData=false & hasUserDataView=true', async () => {
const component = mountComponent(false, true);

await waitFor(() => {
component.update();
expect(findTestSubject(component, 'kbnNoDataPage').length).toBe(1);
});
});
});
const mountComponent = (hasESData = true, hasUserDataView = true) => {
const props = {
isDev: false,
};

return mountWithIntl(
<MemoryRouter>
<KibanaContextProvider services={getServicesMock(hasESData, hasUserDataView)}>
<DiscoverMainRoute {...props} />
</KibanaContextProvider>
</MemoryRouter>
);
};
function getServicesMock(hasESData = true, hasUserDataView = true) {
const dataViewsMock = discoverServiceMock.data.dataViews;
dataViewsMock.getCache = jest.fn(() => {
return Promise.resolve([dataViewMock as unknown as SavedObject<DataViewSavedObjectAttrs>]);
});
dataViewsMock.get = jest.fn(() => Promise.resolve(dataViewMock));
dataViewsMock.getDefaultDataView = jest.fn(() => Promise.resolve(dataViewMock));
dataViewsMock.hasData = {
hasESData: jest.fn(() => Promise.resolve(hasESData)),
hasUserDataView: jest.fn(() => Promise.resolve(hasUserDataView)),
hasDataView: jest.fn(() => Promise.resolve(true)),
};
dataViewsMock.refreshFields = jest.fn();

discoverServiceMock.data.search.searchSource.createEmpty = jest.fn(() => {
const fields: Record<string, unknown> = {};
const empty = {
...searchSourceInstanceMock,
setField: (key: string, value: unknown) => (fields[key] = value),
getField: (key: string) => fields[key],
};
return empty as unknown as SearchSource;
});
return discoverServiceMock;
}

setHeaderActionMenuMounter(jest.fn());
46 changes: 25 additions & 21 deletions x-pack/plugins/cases/public/client/helpers/group_alerts_by_rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { CommentRequestAlertType } from '../../../common/api';
import { CommentType, Ecs } from '../../../common';
import { getRuleIdFromEvent } from './get_rule_id_from_event';
import { CaseAttachments } from '../../types';
import { CaseAttachmentsWithoutOwner } from '../../types';

type Maybe<T> = T | null;
interface Event {
Expand All @@ -20,25 +20,29 @@ interface EventNonEcsData {
value?: Maybe<string[]>;
}

export const groupAlertsByRule = (items: Event[], owner: string): CaseAttachments => {
const attachmentsByRule = items.reduce<Record<string, CommentRequestAlertType>>((acc, item) => {
const rule = getRuleIdFromEvent(item);
if (!acc[rule.id]) {
acc[rule.id] = {
alertId: [],
index: [],
owner,
type: CommentType.alert as const,
rule,
};
}
const alerts = acc[rule.id].alertId;
const indexes = acc[rule.id].index;
if (Array.isArray(alerts) && Array.isArray(indexes)) {
alerts.push(item.ecs._id ?? '');
indexes.push(item.ecs._index ?? '');
}
return acc;
}, {});
type CommentRequestAlertTypeWithoutOwner = Omit<CommentRequestAlertType, 'owner'>;

export const groupAlertsByRule = (items: Event[]): CaseAttachmentsWithoutOwner => {
const attachmentsByRule = items.reduce<Record<string, CommentRequestAlertTypeWithoutOwner>>(
(acc, item) => {
const rule = getRuleIdFromEvent(item);
if (!acc[rule.id]) {
acc[rule.id] = {
alertId: [],
index: [],
type: CommentType.alert as const,
rule,
};
}
const alerts = acc[rule.id].alertId;
const indexes = acc[rule.id].index;
if (Array.isArray(alerts) && Array.isArray(indexes)) {
alerts.push(item.ecs._id ?? '');
indexes.push(item.ecs._index ?? '');
}
return acc;
},
{}
);
return Object.values(attachmentsByRule);
};
10 changes: 5 additions & 5 deletions x-pack/plugins/cases/public/common/use_cases_toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { Case, CommentType } from '../../common';
import { useToasts } from './lib/kibana';
import { useCaseViewNavigation } from './navigation';
import { CaseAttachments } from '../types';
import { CaseAttachmentsWithoutOwner } from '../types';
import {
CASE_ALERT_SUCCESS_SYNC_TEXT,
CASE_ALERT_SUCCESS_TOAST,
Expand All @@ -34,7 +34,7 @@ const EuiTextStyled = styled(EuiText)`
`}
`;

function getAlertsCount(attachments: CaseAttachments): number {
function getAlertsCount(attachments: CaseAttachmentsWithoutOwner): number {
let alertsCount = 0;
for (const attachment of attachments) {
if (attachment.type === CommentType.alert) {
Expand All @@ -57,7 +57,7 @@ function getToastTitle({
}: {
theCase: Case;
title?: string;
attachments?: CaseAttachments;
attachments?: CaseAttachmentsWithoutOwner;
}): string {
if (title !== undefined) {
return title;
Expand All @@ -78,7 +78,7 @@ function getToastContent({
}: {
theCase: Case;
content?: string;
attachments?: CaseAttachments;
attachments?: CaseAttachmentsWithoutOwner;
}): string | undefined {
if (content !== undefined) {
return content;
Expand Down Expand Up @@ -106,7 +106,7 @@ export const useCasesToast = () => {
content,
}: {
theCase: Case;
attachments?: CaseAttachments;
attachments?: CaseAttachmentsWithoutOwner;
title?: string;
content?: string;
}) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import { noop } from 'lodash/fp';

import { noCreateCasesPermissions, TestProviders } from '../../common/mock';

import { CommentRequest, CommentType } from '../../../common/api';
import { CommentType } from '../../../common/api';
import { SECURITY_SOLUTION_OWNER } from '../../../common/constants';
import { useCreateAttachments } from '../../containers/use_create_attachments';
import { AddComment, AddCommentProps, AddCommentRefObject } from '.';
import { CasesTimelineIntegrationProvider } from '../timeline_context';
import { timelineIntegrationMock } from '../__mock__/timeline';
import { CaseAttachmentWithoutOwner } from '../../types';

jest.mock('../../containers/use_create_attachments');

Expand All @@ -41,10 +42,9 @@ const defaultResponse = {
createAttachments,
};

const sampleData: CommentRequest = {
const sampleData: CaseAttachmentWithoutOwner = {
comment: 'what a cool comment',
type: CommentType.user,
owner: SECURITY_SOLUTION_OWNER,
type: CommentType.user as const,
};

describe('AddComment ', () => {
Expand Down Expand Up @@ -73,6 +73,7 @@ describe('AddComment ', () => {
expect(onCommentSaving).toBeCalled();
expect(createAttachments).toBeCalledWith({
caseId: addCommentProps.caseId,
caseOwner: SECURITY_SOLUTION_OWNER,
data: [sampleData],
updateCase: onCommentPosted,
});
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/cases/public/components/add_comment/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ export const AddComment = React.memo(
}
createAttachments({
caseId,
data: [{ ...data, type: CommentType.user, owner: owner[0] }],
caseOwner: owner[0],
data: [{ ...data, type: CommentType.user }],
updateCase: onCommentPosted,
});
reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const AllCasesList = React.memo<AllCasesListProps>(
const firstAvailableStatus = head(difference(caseStatuses, hiddenStatuses));
const initialFilterOptions = {
...(!isEmpty(hiddenStatuses) && firstAvailableStatus && { status: firstAvailableStatus }),
owner: hasOwner ? owner : availableSolutions,
owner: hasOwner ? owner : [],
};
const [filterOptions, setFilterOptions] = useState<FilterOptions>({
...DEFAULT_FILTER_OPTIONS,
Expand Down
7 changes: 6 additions & 1 deletion x-pack/plugins/cases/public/components/all_cases/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,12 @@ export const useCasesColumns = ({
render: (caseOwner: CasesOwners) => {
const ownerInfo = OWNER_INFO[caseOwner];
return ownerInfo ? (
<EuiIcon size="s" type={ownerInfo.iconType} title={ownerInfo.label} />
<EuiIcon
size="m"
type={ownerInfo.iconType}
title={ownerInfo.label}
data-test-subj={`case-table-column-owner-icon-${caseOwner}`}
/>
) : (
getEmptyTagValue()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Case } from '../../../containers/types';
import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer';
import { useCasesContext } from '../../cases_context/use_cases_context';
import { useCasesAddToNewCaseFlyout } from '../../create/flyout/use_cases_add_to_new_case_flyout';
import { CaseAttachments } from '../../../types';
import { CaseAttachmentsWithoutOwner } from '../../../types';
import { useCreateAttachments } from '../../../containers/use_create_attachments';

type AddToExistingFlyoutProps = AllCasesSelectorModalProps & {
Expand Down Expand Up @@ -51,7 +51,7 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingFlyoutProps =
}, [dispatch]);

const handleOnRowClick = useCallback(
async (theCase: Case | undefined, attachments: CaseAttachments) => {
async (theCase: Case | undefined, attachments: CaseAttachmentsWithoutOwner) => {
// when the case is undefined in the modal
// the user clicked "create new case"
if (theCase === undefined) {
Expand All @@ -65,6 +65,7 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingFlyoutProps =
if (attachments !== undefined && attachments.length > 0) {
await createAttachments({
caseId: theCase.id,
caseOwner: theCase.owner,
data: attachments,
throwOnError: true,
});
Expand All @@ -89,7 +90,7 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingFlyoutProps =
);

const openModal = useCallback(
({ attachments }: { attachments?: CaseAttachments } = {}) => {
({ attachments }: { attachments?: CaseAttachmentsWithoutOwner } = {}) => {
dispatch({
type: CasesContextStoreActionsList.OPEN_ADD_TO_CASE_MODAL,
payload: {
Expand Down
Loading

0 comments on commit 99f869f

Please sign in to comment.