Skip to content

Commit

Permalink
email and case closed complete
Browse files Browse the repository at this point in the history
  • Loading branch information
stephmilovic committed Mar 18, 2020
1 parent 8244481 commit 781ccbd
Show file tree
Hide file tree
Showing 12 changed files with 234 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const useGetCasesMockState: UseGetCasesState = {
countOpenCases: 0,
cases: [
{
closedAt: null,
closedBy: null,
id: '3c4ddcc0-4e99-11ea-9290-35d05cb55c15',
createdAt: '2020-02-13T19:44:23.627Z',
createdBy: { username: 'elastic' },
Expand All @@ -27,6 +29,8 @@ export const useGetCasesMockState: UseGetCasesState = {
version: 'WzQ3LDFd',
},
{
closedAt: null,
closedBy: null,
id: '362a5c10-4e99-11ea-9290-35d05cb55c15',
createdAt: '2020-02-13T19:44:13.328Z',
createdBy: { username: 'elastic' },
Expand All @@ -41,6 +45,8 @@ export const useGetCasesMockState: UseGetCasesState = {
version: 'WzQ3LDFd',
},
{
closedAt: null,
closedBy: null,
id: '34f8b9e0-4e99-11ea-9290-35d05cb55c15',
createdAt: '2020-02-13T19:44:11.328Z',
createdBy: { username: 'elastic' },
Expand All @@ -55,6 +61,8 @@ export const useGetCasesMockState: UseGetCasesState = {
version: 'WzQ3LDFd',
},
{
closedAt: '2020-02-13T19:44:13.328Z',
closedBy: { username: 'elastic' },
id: '31890e90-4e99-11ea-9290-35d05cb55c15',
createdAt: '2020-02-13T19:44:05.563Z',
createdBy: { username: 'elastic' },
Expand All @@ -64,11 +72,13 @@ export const useGetCasesMockState: UseGetCasesState = {
status: 'closed',
tags: ['phishing'],
title: 'Uh oh',
updatedAt: null,
updatedBy: null,
updatedAt: '2020-02-13T19:44:13.328Z',
updatedBy: { username: 'elastic' },
version: 'WzQ3LDFd',
},
{
closedAt: null,
closedBy: null,
id: '2f5b3210-4e99-11ea-9290-35d05cb55c15',
createdAt: '2020-02-13T19:44:01.901Z',
createdBy: { username: 'elastic' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ const Spacer = styled.span`
const renderStringField = (field: string, dataTestSubj: string) =>
field != null ? <span data-test-subj={dataTestSubj}>{field}</span> : getEmptyTagValue();
export const getCasesColumns = (
actions: Array<DefaultItemIconButtonAction<Case>>
actions: Array<DefaultItemIconButtonAction<Case>>,
filterStatus: string
): CasesColumns[] => [
{
name: i18n.NAME,
Expand Down Expand Up @@ -113,22 +114,39 @@ export const getCasesColumns = (
render: (comments: Case['commentIds']) =>
renderStringField(`${comments.length}`, `case-table-column-commentCount`),
},
{
field: 'createdAt',
name: i18n.OPENED_ON,
sortable: true,
render: (createdAt: Case['createdAt']) => {
if (createdAt != null) {
return (
<FormattedRelativePreferenceDate
value={createdAt}
data-test-subj={`case-table-column-createdAt`}
/>
);
filterStatus === 'open'
? {
field: 'createdAt',
name: i18n.OPENED_ON,
sortable: true,
render: (createdAt: Case['createdAt']) => {
if (createdAt != null) {
return (
<FormattedRelativePreferenceDate
value={createdAt}
data-test-subj={`case-table-column-createdAt`}
/>
);
}
return getEmptyTagValue();
},
}
return getEmptyTagValue();
},
},
: {
field: 'closedAt',
name: i18n.CLOSED_ON,
sortable: true,
render: (closedAt: Case['closedAt']) => {
if (closedAt != null) {
return (
<FormattedRelativePreferenceDate
value={closedAt}
data-test-subj={`case-table-column-closedAt`}
/>
);
}
return getEmptyTagValue();
},
},
{
name: 'Actions',
actions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,17 +206,25 @@ export const AllCases = React.memo(() => {
}
setQueryParams(newQueryParams);
},
[setQueryParams, queryParams]
[queryParams]
);

const onFilterChangedCallback = useCallback(
(newFilterOptions: Partial<FilterOptions>) => {
if (newFilterOptions.status && newFilterOptions.status === 'closed') {
setQueryParams({ ...queryParams, sortField: SortFieldCase.closedAt });
} else if (newFilterOptions.status && newFilterOptions.status === 'open') {
setQueryParams({ ...queryParams, sortField: SortFieldCase.createdAt });
}
setFilters({ ...filterOptions, ...newFilterOptions });
},
[filterOptions, setFilters]
[filterOptions, queryParams]
);

const memoizedGetCasesColumns = useMemo(() => getCasesColumns(actions), [actions]);
const memoizedGetCasesColumns = useMemo(() => getCasesColumns(actions, filterOptions.status), [
actions,
filterOptions.status,
]);
const memoizedPagination = useMemo(
() => ({
pageIndex: queryParams.page - 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,38 +44,22 @@ export const caseProps: CaseProps = {
version: 'WzQ3LDFd',
},
};

export const data: Case = {
closedAt: null,
closedBy: null,
id: '3c4ddcc0-4e99-11ea-9290-35d05cb55c15',
commentIds: ['a357c6a0-5435-11ea-b427-fb51a1fcb7b8'],
comments: [
{
comment: 'Solve this fast!',
id: 'a357c6a0-5435-11ea-b427-fb51a1fcb7b8',
createdAt: '2020-02-20T23:06:33.798Z',
createdBy: {
fullName: 'Steph Milovic',
username: 'smilovic',
email: 'notmyrealemailfool@elastic.co',
},
updatedAt: '2020-02-20T23:06:33.798Z',
updatedBy: {
username: 'elastic',
},
version: 'WzQ3LDFd',
export const caseClosedProps: CaseProps = {
...caseProps,
initialData: {
...caseProps.initialData,
closedAt: '2020-02-20T23:06:33.798Z',
closedBy: {
username: 'elastic',
},
],
createdAt: '2020-02-13T19:44:23.627Z',
createdBy: { fullName: null, email: 'testemail@elastic.co', username: 'elastic' },
description: 'Security banana Issue',
status: 'open',
tags: ['defacement'],
title: 'Another horrible breach!!',
updatedAt: '2020-02-19T15:02:57.995Z',
updatedBy: {
username: 'elastic',
status: 'closed',
},
version: 'WzQ3LDFd',
};

export const data: Case = {
...caseProps.initialData,
};

export const dataClosed: Case = {
...caseClosedProps.initialData,
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,26 @@
import React from 'react';
import { mount } from 'enzyme';
import { CaseComponent } from './';
import * as apiHook from '../../../../containers/case/use_update_case';
import { caseProps, data } from './__mock__';
import { caseProps, caseClosedProps, data, dataClosed } from './__mock__';
import { TestProviders } from '../../../../mock';
import { useUpdateCase } from '../../../../containers/case/use_update_case';
jest.mock('../../../../containers/case/use_update_case');
const useUpdateCaseMock = useUpdateCase as jest.Mock;

describe('CaseView ', () => {
const updateCaseProperty = jest.fn();

const defaultUpdateCaseState = {
caseData: data,
isLoading: false,
isError: false,
updateKey: null,
updateCaseProperty,
};

beforeEach(() => {
jest.resetAllMocks();
jest.spyOn(apiHook, 'useUpdateCase').mockReturnValue({
caseData: data,
isLoading: false,
isError: false,
updateKey: null,
updateCaseProperty,
});
useUpdateCaseMock.mockImplementation(() => defaultUpdateCaseState);
});

it('should render CaseComponent', () => {
Expand Down Expand Up @@ -55,6 +59,7 @@ describe('CaseView ', () => {
.first()
.text()
).toEqual(data.createdBy.username);
expect(wrapper.contains(`[data-test-subj="case-view-closedAt"]`)).toBe(false);
expect(
wrapper
.find(`[data-test-subj="case-view-createdAt"]`)
Expand All @@ -68,6 +73,30 @@ describe('CaseView ', () => {
.prop('raw')
).toEqual(data.description);
});
it('should show closed indicators in header when case is closed', () => {
useUpdateCaseMock.mockImplementation(() => ({
...defaultUpdateCaseState,
caseData: dataClosed,
}));
const wrapper = mount(
<TestProviders>
<CaseComponent {...caseClosedProps} />
</TestProviders>
);
expect(wrapper.contains(`[data-test-subj="case-view-createdAt"]`)).toBe(false);
expect(
wrapper
.find(`[data-test-subj="case-view-closedAt"]`)
.first()
.prop('value')
).toEqual(dataClosed.closedAt);
expect(
wrapper
.find(`[data-test-subj="case-view-status"]`)
.first()
.text()
).toEqual(dataClosed.status);
});

it('should dispatch update state when button is toggled', () => {
const wrapper = mount(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { WhitePageWrapper } from '../wrappers';
import { useDeleteCases } from '../../../../containers/case/use_delete_cases';
import { SiemPageName } from '../../../home/types';
import { ConfirmDeleteCaseModal } from '../confirm_delete_case';
import { useBasePath } from '../../../../lib/kibana';

interface Props {
caseId: string;
Expand Down Expand Up @@ -64,6 +65,8 @@ export interface CaseProps {
}

export const CaseComponent = React.memo<CaseProps>(({ caseId, initialData }) => {
const basePath = window.location.origin + useBasePath();
const caseLink = `${basePath}/app/siem#/case/${caseId}`;
const { caseData, isLoading, updateKey, updateCaseProperty } = useUpdateCase(caseId, initialData);

// Update Fields
Expand Down Expand Up @@ -140,7 +143,7 @@ export const CaseComponent = React.memo<CaseProps>(({ caseId, initialData }) =>
const propertyActions = [
{
iconType: 'trash',
label: 'Delete case',
label: i18n.DELETE_CASE,
onClick: handleToggleModal,
},
{
Expand Down Expand Up @@ -192,15 +195,27 @@ export const CaseComponent = React.memo<CaseProps>(({ caseId, initialData }) =>
</EuiBadge>
</EuiDescriptionListDescription>
</EuiFlexItem>
<EuiFlexItem>
<EuiDescriptionListTitle>{i18n.CASE_OPENED}</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedRelativePreferenceDate
data-test-subj="case-view-createdAt"
value={caseData.createdAt}
/>
</EuiDescriptionListDescription>
</EuiFlexItem>
{caseData.status === 'open' ? (
<EuiFlexItem>
<EuiDescriptionListTitle>{i18n.CASE_OPENED}</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedRelativePreferenceDate
data-test-subj="case-view-createdAt"
value={caseData.createdAt}
/>
</EuiDescriptionListDescription>
</EuiFlexItem>
) : (
<EuiFlexItem>
<EuiDescriptionListTitle>{i18n.CASE_CLOSEED}</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedRelativePreferenceDate
data-test-subj="case-view-closedAt"
value={caseData.closedAt}
/>
</EuiDescriptionListDescription>
</EuiFlexItem>
)}
</EuiFlexGroup>
</MyDescriptionList>
</EuiFlexItem>
Expand Down Expand Up @@ -237,6 +252,10 @@ export const CaseComponent = React.memo<CaseProps>(({ caseId, initialData }) =>
<EuiFlexItem grow={2}>
<UserList
data-test-subj="case-view-user-list"
email={{
subject: i18n.EMAIL_SUBJECT(caseData.title),
body: i18n.EMAIL_BODY(caseLink),
}}
headline={i18n.REPORTER}
users={[caseData.createdBy]}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,19 @@ export const STATUS = i18n.translate('xpack.siem.case.caseView.statusLabel', {
export const CASE_OPENED = i18n.translate('xpack.siem.case.caseView.caseOpened', {
defaultMessage: 'Case opened',
});

export const CASE_CLOSEED = i18n.translate('xpack.siem.case.caseView.caseClosed', {
defaultMessage: 'Case closed',
});

export const EMAIL_SUBJECT = (caseTitle: string) =>
i18n.translate('xpack.siem.case.caseView.emailSubject', {
values: { caseTitle },
defaultMessage: 'SIEM Case - {caseTitle}',
});

export const EMAIL_BODY = (caseUrl: string) =>
i18n.translate('xpack.siem.case.caseView.emailBody', {
values: { caseUrl },
defaultMessage: 'Case reference: {caseUrl}',
});
Loading

0 comments on commit 781ccbd

Please sign in to comment.