Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15943,10 +15943,7 @@
"xpack.cases.caseView.syncAlertsLabel": "Alerts synchronisieren",
"xpack.cases.caseView.syncAlertsLowercaseLabel": "Alerts synchronisieren",
"xpack.cases.caseView.tabs.activity": "Aktivität",
"xpack.cases.caseView.tabs.alerts": "Alerts",
"xpack.cases.caseView.tabs.attachments": "Anhänge",
"xpack.cases.caseView.tabs.events": "Ereignisse",
"xpack.cases.caseView.tabs.files": "Dateien",
"xpack.cases.caseView.tabs.observables": "Beobachtungsdaten",
"xpack.cases.caseView.tabs.similar": "Ähnliche Tickets",
"xpack.cases.caseView.tags": "Tags",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15917,10 +15917,7 @@
"xpack.cases.caseView.syncAlertsLabel": "Synchroniser les alertes",
"xpack.cases.caseView.syncAlertsLowercaseLabel": "synchroniser les alertes",
"xpack.cases.caseView.tabs.activity": "Activité",
"xpack.cases.caseView.tabs.alerts": "Alertes",
"xpack.cases.caseView.tabs.attachments": "Pièces jointes",
"xpack.cases.caseView.tabs.events": "Événements",
"xpack.cases.caseView.tabs.files": "Fichiers",
"xpack.cases.caseView.tabs.observables": "Observables",
"xpack.cases.caseView.tabs.similar": "Cas similaires",
"xpack.cases.caseView.tags": "Balises",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15993,10 +15993,7 @@
"xpack.cases.caseView.syncAlertsLabel": "アラートの同期",
"xpack.cases.caseView.syncAlertsLowercaseLabel": "アラートの同期",
"xpack.cases.caseView.tabs.activity": "アクティビティ",
"xpack.cases.caseView.tabs.alerts": "アラート",
"xpack.cases.caseView.tabs.attachments": "添付ファイル",
"xpack.cases.caseView.tabs.events": "イベント",
"xpack.cases.caseView.tabs.files": "ファイル",
"xpack.cases.caseView.tabs.observables": "オブザーバブル",
"xpack.cases.caseView.tabs.similar": "類似したケース",
"xpack.cases.caseView.tags": "タグ",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15994,10 +15994,7 @@
"xpack.cases.caseView.syncAlertsLabel": "同步告警",
"xpack.cases.caseView.syncAlertsLowercaseLabel": "同步告警",
"xpack.cases.caseView.tabs.activity": "活动",
"xpack.cases.caseView.tabs.alerts": "告警",
"xpack.cases.caseView.tabs.attachments": "附件",
"xpack.cases.caseView.tabs.events": "事件",
"xpack.cases.caseView.tabs.files": "文件",
"xpack.cases.caseView.tabs.observables": "可观察对象",
"xpack.cases.caseView.tabs.similar": "类似案例",
"xpack.cases.caseView.tags": "标签",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { CASE_VIEW_PAGE_TABS } from '../../../common/types';
import { caseData, caseViewProps } from './mocks';
import type { CaseViewPageProps } from './types';
import { useCasesTitleBreadcrumbs } from '../use_breadcrumbs';
import { toUnifiedAttachmentType } from '../../../common/utils/attachments/migration_utils';
import { UnifiedAttachmentTypeRegistry } from '../../client/attachment_framework/unified_attachment_registry';

jest.mock('../../common/navigation/hooks');
Expand All @@ -31,14 +30,6 @@ jest.mock(
}),
{ virtual: true }
);
jest.mock('../../../common/utils/attachments/migration_utils', () => {
const actual = jest.requireActual('../../../common/utils/attachments/migration_utils');

return {
...actual,
toUnifiedAttachmentType: jest.fn(actual.toUnifiedAttachmentType),
};
});

jest.mock('../header_page', () => ({
HeaderPage: jest.fn(() => <div data-test-subj="test-case-view-header">{'Case view header'}</div>),
Expand All @@ -56,9 +47,9 @@ jest.mock('./components/case_view_activity', () => ({
)),
}));

jest.mock('./components/case_view_observables', () => ({
CaseViewObservables: jest.fn(() => (
<div data-test-subj="test-case-view-observables">{'Case view observables'}</div>
jest.mock('./components/case_view_attachments', () => ({
CaseViewAttachments: jest.fn(() => (
<div data-test-subj="test-case-view-attachments">{'Case view attachments'}</div>
)),
}));

Expand All @@ -70,9 +61,6 @@ jest.mock('./components/case_view_similar_cases', () => ({

const useUrlParamsMock = useUrlParams as jest.Mock;
const useCasesTitleBreadcrumbsMock = useCasesTitleBreadcrumbs as jest.Mock;
const toUnifiedAttachmentTypeMock = toUnifiedAttachmentType as jest.MockedFunction<
typeof toUnifiedAttachmentType
>;

const caseProps: CaseViewPageProps = {
...caseViewProps,
Expand All @@ -87,40 +75,6 @@ describe('CaseViewPage', () => {
jest.clearAllMocks();
useUrlParamsMock.mockReturnValue({});
unifiedAttachmentTypeRegistry = new UnifiedAttachmentTypeRegistry();
unifiedAttachmentTypeRegistry.register({
id: 'security.event',
displayName: 'Event',
icon: 'bell',
getAttachmentViewObject: () => ({ event: 'added an event' }),
getAttachmentTabViewObject: () => ({
children: () => (
<div data-test-subj="test-case-view-events-content">{'Events content'}</div>
),
}),
schemaValidator: () => {},
});
unifiedAttachmentTypeRegistry.register({
id: 'security.alert',
displayName: 'Alert',
icon: 'bell',
getAttachmentViewObject: () => ({ event: 'added an alert' }),
getAttachmentTabViewObject: () => ({
children: () => (
<div data-test-subj="test-case-view-alerts-content">{'Alerts content'}</div>
),
}),
schemaValidator: () => {},
});
unifiedAttachmentTypeRegistry.register({
id: 'file',
displayName: 'File',
icon: 'document',
getAttachmentViewObject: () => ({ event: 'added a file' }),
getAttachmentTabViewObject: () => ({
children: () => <div data-test-subj="test-case-view-files">{'Case view files'}</div>,
}),
schemaValidator: () => {},
});
});

it('shows the header section', async () => {
Expand Down Expand Up @@ -153,79 +107,19 @@ describe('CaseViewPage', () => {
});
});

it('resolves event type using the full case owner', () => {
const caseDataWithStringOwner = { ...caseProps.caseData, owner: 'securitySolution' };

renderWithTestingProviders(<CaseViewPage {...caseProps} caseData={caseDataWithStringOwner} />);

expect(toUnifiedAttachmentTypeMock).toHaveBeenCalledWith('event', 'securitySolution');
});

it('does not render the events tab content when events feature is disabled', () => {
useUrlParamsMock.mockReturnValue({
urlParams: { tabId: CASE_VIEW_PAGE_TABS.EVENTS },
});

renderWithTestingProviders(<CaseViewPage {...caseProps} />, {
wrapperProps: {
features: { events: { enabled: false } },
unifiedAttachmentTypeRegistry,
},
});

expect(screen.queryByTestId('test-case-view-events-content')).not.toBeInTheDocument();
});

it('renders the events tab content when events feature is enabled and type is registered', async () => {
useUrlParamsMock.mockReturnValue({
urlParams: { tabId: CASE_VIEW_PAGE_TABS.EVENTS },
});

renderWithTestingProviders(<CaseViewPage {...caseProps} />, {
wrapperProps: {
features: { events: { enabled: true } },
unifiedAttachmentTypeRegistry,
},
});

expect(await screen.findByTestId('test-case-view-events-content')).toBeInTheDocument();
});

it('resolves alert type using the full case owner', () => {
const caseDataWithStringOwner = { ...caseProps.caseData, owner: 'securitySolution' };

renderWithTestingProviders(<CaseViewPage {...caseProps} caseData={caseDataWithStringOwner} />);

expect(toUnifiedAttachmentTypeMock).toHaveBeenCalledWith('alert', 'securitySolution');
});

it('does not render the alerts tab content when alerts feature is disabled', () => {
useUrlParamsMock.mockReturnValue({
urlParams: { tabId: CASE_VIEW_PAGE_TABS.ALERTS },
});

renderWithTestingProviders(<CaseViewPage {...caseProps} />, {
wrapperProps: {
features: { alerts: { enabled: false } },
unifiedAttachmentTypeRegistry,
},
});

expect(screen.queryByTestId('test-case-view-alerts-content')).not.toBeInTheDocument();
});

it('renders the alerts tab content when alerts feature is enabled and type is registered', async () => {
useUrlParamsMock.mockReturnValue({
urlParams: { tabId: CASE_VIEW_PAGE_TABS.ALERTS },
});
it.each([
Comment thread
christineweng marked this conversation as resolved.
CASE_VIEW_PAGE_TABS.ATTACHMENTS,
CASE_VIEW_PAGE_TABS.ALERTS,
CASE_VIEW_PAGE_TABS.EVENTS,
CASE_VIEW_PAGE_TABS.FILES,
CASE_VIEW_PAGE_TABS.OBSERVABLES,
])('renders the consolidated attachments view for tabId=%s', async (tabId) => {
useUrlParamsMock.mockReturnValue({ urlParams: { tabId } });

renderWithTestingProviders(<CaseViewPage {...caseProps} />, {
wrapperProps: {
features: { alerts: { enabled: true } },
unifiedAttachmentTypeRegistry,
},
wrapperProps: { unifiedAttachmentTypeRegistry },
});

expect(await screen.findByTestId('test-case-view-alerts-content')).toBeInTheDocument();
expect(await screen.findByTestId('test-case-view-attachments')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,19 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { CASE_VIEW_PAGE_TABS } from '../../../common/types';
import { useUrlParams } from '../../common/navigation';
import { useCasesContext } from '../cases_context/use_cases_context';
import { CaseActionBar } from '../case_action_bar';
import { HeaderPage } from '../header_page';
import { EditableTitle } from '../header_page/editable_title';
import { useCasesTitleBreadcrumbs } from '../use_breadcrumbs';
import { CaseViewActivity } from './components/case_view_activity';
import { CaseViewObservables } from './components/case_view_observables';
import { CaseViewMetrics } from './metrics';
import type { CaseViewPageProps } from './types';
import { useRefreshCaseViewPage } from './use_on_refresh_case_view_page';
import { useOnUpdateField } from './use_on_update_field';
import { CaseViewSimilarCases } from './components/case_view_similar_cases';
import { CaseViewAttachments } from './components/case_view_attachments';
import { filterCaseAttachmentsBySearchTerm } from './components/helpers';
import { toUnifiedAttachmentType } from '../../../common/utils/attachments/migration_utils';
import { FILE_ATTACHMENT_TYPE } from '../../../common/constants';
import { ATTACHMENT_TAB_ALIASES } from './use_case_attachment_tabs';

const getActiveTabId = (tabId?: string) => {
if (tabId && Object.values(CASE_VIEW_PAGE_TABS).includes(tabId as CASE_VIEW_PAGE_TABS)) {
Expand All @@ -34,16 +31,8 @@ const getActiveTabId = (tabId?: string) => {
return CASE_VIEW_PAGE_TABS.ACTIVITY;
};

const ATTACHMENT_TABS = [
CASE_VIEW_PAGE_TABS.ALERTS,
CASE_VIEW_PAGE_TABS.EVENTS,
CASE_VIEW_PAGE_TABS.FILES,
CASE_VIEW_PAGE_TABS.OBSERVABLES,
];

export const CaseViewPage = React.memo<CaseViewPageProps>(
({ caseData, refreshRef, actionsNavigation }) => {
const { features, unifiedAttachmentTypeRegistry } = useCasesContext();
const { urlParams } = useUrlParams();
const refreshCaseViewPage = useRefreshCaseViewPage();

Expand Down Expand Up @@ -89,31 +78,6 @@ export const CaseViewPage = React.memo<CaseViewPageProps>(
}
}, [isLoading, refreshRef, refreshCaseViewPage]);

const owner = Array.isArray(caseData.owner) ? caseData.owner[0] : caseData.owner;
const EventTabComponent = useMemo(() => {
const eventType = toUnifiedAttachmentType('event', owner);
if (!unifiedAttachmentTypeRegistry.has(eventType)) {
return undefined;
}
return unifiedAttachmentTypeRegistry.get(eventType)?.getAttachmentTabViewObject?.()?.children;
}, [unifiedAttachmentTypeRegistry, owner]);

const AlertTabComponent = useMemo(() => {
const alertType = toUnifiedAttachmentType('alert', owner);
if (!unifiedAttachmentTypeRegistry.has(alertType)) {
return undefined;
}
return unifiedAttachmentTypeRegistry.get(alertType)?.getAttachmentTabViewObject?.()?.children;
}, [unifiedAttachmentTypeRegistry, owner]);

const FileTabComponent = useMemo(() => {
if (!unifiedAttachmentTypeRegistry.has(FILE_ATTACHMENT_TYPE)) {
return undefined;
}
return unifiedAttachmentTypeRegistry.get(FILE_ATTACHMENT_TYPE)?.getAttachmentTabViewObject?.()
?.children;
}, [unifiedAttachmentTypeRegistry]);

const onSubmitTitle = useCallback(
(newTitle: string) =>
onUpdateField({
Expand Down Expand Up @@ -159,43 +123,13 @@ export const CaseViewPage = React.memo<CaseViewPageProps>(
actionsNavigation={actionsNavigation}
/>
)}
{ATTACHMENT_TABS.includes(activeTabId as CASE_VIEW_PAGE_TABS) && (
{ATTACHMENT_TAB_ALIASES.has(activeTabId) && (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we going to update the activeTabId as more attachment types are added? Given the breakdown of alert => security.alert, should we create new ones for that so we can have a closer one to one mapping?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are params of old tabs, previously tab=alert will go to alert sub-tab. the tabs are dynamic now, so I'm collapsing them to go to attachment instead

We could... types are defined inside cases, but I also feel that this is redundant and create too much hard coded baggage. I need to think about this more and see what the design direction is heading..

<CaseViewAttachments
onSearch={onSearch}
searchTerm={searchTerm}
activeTab={activeTabId as CASE_VIEW_PAGE_TABS}
caseData={caseWithFilteredAttachments}
>
<>
{activeTabId === CASE_VIEW_PAGE_TABS.ALERTS &&
features.alerts.enabled &&
AlertTabComponent != null && (
<AlertTabComponent
key={caseWithFilteredAttachments.updatedAt}
caseData={caseWithFilteredAttachments}
/>
)}
{activeTabId === CASE_VIEW_PAGE_TABS.EVENTS &&
features.events.enabled &&
EventTabComponent != null && (
<EventTabComponent caseData={caseWithFilteredAttachments} />
)}
{activeTabId === CASE_VIEW_PAGE_TABS.FILES && FileTabComponent != null && (
<FileTabComponent
caseData={caseWithFilteredAttachments}
searchTerm={searchTerm}
/>
)}
{activeTabId === CASE_VIEW_PAGE_TABS.OBSERVABLES && (
<CaseViewObservables
isLoading={false}
caseData={caseWithFilteredAttachments}
searchTerm={searchTerm}
onUpdateField={onUpdateField}
/>
)}
</>
</CaseViewAttachments>
onUpdateField={onUpdateField}
/>
)}
{activeTabId === CASE_VIEW_PAGE_TABS.SIMILAR_CASES && (
<CaseViewSimilarCases caseData={caseWithFilteredAttachments} searchTerm={searchTerm} />
Expand Down
Loading
Loading