Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix circle deps #4

Closed
Show file tree
Hide file tree
Changes from all commits
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 @@ -418,7 +418,10 @@ export class StatefulOpenTimelineComponent extends React.PureComponent<
? {}
: timelineModel.pinnedEventsSaveObject != null
? timelineModel.pinnedEventsSaveObject.reduce(
(acc, pinnedEvent) => ({ ...acc, [pinnedEvent.pinnedEventId]: pinnedEvent }),
(acc, pinnedEvent) => ({
...acc,
...(pinnedEvent.eventId != null ? { [pinnedEvent.eventId]: pinnedEvent } : {}),
}),
{}
)
: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { debounce } from 'lodash/fp';
import { mount } from 'enzyme';
import * as React from 'react';

Expand All @@ -12,6 +12,8 @@ import { ACTIONS_COLUMN_WIDTH } from '../helpers';

import { Actions } from '.';

jest.mock('lodash/fp');

describe('Actions', () => {
test('it renders a checkbox for selecting the event when `showCheckboxes` is `true`', () => {
const wrapper = mount(
Expand Down Expand Up @@ -124,39 +126,6 @@ describe('Actions', () => {
expect(onEventToggled).toBeCalled();
});

test('it invokes onPinClicked when the button for pinning events is clicked', () => {
const onPinClicked = jest.fn();

const wrapper = mount(
<TestProviders>
<Actions
actionsColumnWidth={ACTIONS_COLUMN_WIDTH}
associateNote={jest.fn()}
checked={false}
expanded={false}
eventId="abc"
eventIsPinned={false}
getNotesByIds={jest.fn()}
loading={false}
noteIds={[]}
onEventToggled={jest.fn()}
onPinClicked={onPinClicked}
showCheckboxes={false}
showNotes={false}
toggleShowNotes={jest.fn()}
updateNote={jest.fn()}
/>
</TestProviders>
);

wrapper
.find('[data-test-subj="pin"]')
.first()
.simulate('click');

expect(onPinClicked).toBeCalled();
});

test('it invokes toggleShowNotes when the button for adding notes is clicked', () => {
const toggleShowNotes = jest.fn();

Expand Down Expand Up @@ -189,4 +158,48 @@ describe('Actions', () => {

expect(toggleShowNotes).toBeCalled();
});
describe('mock debounce from lodash/fp', () => {
beforeEach(() => {
// @ts-ignore property mockImplementation does not exists
debounce.mockImplementation((time: number, fn: () => void) => {
return fn();
});
});
afterEach(() => {
jest.resetAllMocks();
});

test('it invokes onPinClicked when the button for pinning events is clicked', () => {
const onPinClicked = jest.fn();

const wrapper = mount(
<TestProviders>
<Actions
actionsColumnWidth={ACTIONS_COLUMN_WIDTH}
associateNote={jest.fn()}
checked={false}
expanded={false}
eventId="abc"
eventIsPinned={false}
getNotesByIds={jest.fn()}
loading={false}
noteIds={[]}
onEventToggled={jest.fn()}
onPinClicked={onPinClicked}
showCheckboxes={false}
showNotes={false}
toggleShowNotes={jest.fn()}
updateNote={jest.fn()}
/>
</TestProviders>
);

wrapper
.find('[data-test-subj="pin"]')
.first()
.simulate('click');

expect(onPinClicked).toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
EuiLoadingSpinner,
EuiToolTip,
} from '@elastic/eui';
import { noop } from 'lodash/fp';
import { noop, debounce } from 'lodash/fp';
import * as React from 'react';
import styled from 'styled-components';

Expand Down Expand Up @@ -157,7 +157,7 @@ export const Actions = React.memo<Props>(
allowUnpinning={!eventHasNotes(noteIds)}
pinned={eventIsPinned}
data-test-subj="pin-event"
onClick={onPinClicked}
onClick={debounce(300, onPinClicked)}
/>
</PinContainer>
</EuiToolTip>
Expand Down
28 changes: 8 additions & 20 deletions x-pack/legacy/plugins/siem/public/store/timeline/epic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ import { isNotNull } from './helpers';
import { dispatcherTimelinePersistQueue } from './epic_dispatcher_timeline_persistence_queue';
import { refetchQueries } from './refetch_queries';
import { myEpicTimelineId } from './my_epic_timeline_id';
import { TimelineById } from './types';
import { TimelineById, ActionTimeline } from './types';

interface TimelineEpicDependencies<State> {
timelineByIdSelector: (state: State) => TimelineById;
Expand All @@ -75,15 +75,6 @@ interface TimelineEpicDependencies<State> {
apolloClient$: Observable<AppApolloClient>;
}

export interface ActionTimeline {
type: string;
payload: {
id: string;
eventId: string;
noteId: string;
};
}

const timelineActionsType = [
applyKqlFilterQuery.type,
addProvider.type,
Expand Down Expand Up @@ -158,7 +149,7 @@ export const createTimelineEpic = <State>(): Epic<
delay(500),
withLatestFrom(timeline$, apolloClient$, notes$, timelineTimeRange$),
concatMap(([objAction, timeline, apolloClient, notes, timelineTimeRange]) => {
const action: Action = get('action', objAction);
const action: ActionTimeline = get('action', objAction);
const timelineId = myEpicTimelineId.getTimelineId();
const version = myEpicTimelineId.getTimelineVersion();

Expand All @@ -179,28 +170,25 @@ export const createTimelineEpic = <State>(): Epic<
variables: {
timelineId,
version,
timeline: convertTimelineAsInput(
timeline[get('payload.id', action)],
timelineTimeRange
),
timeline: convertTimelineAsInput(timeline[action.payload.id], timelineTimeRange),
},
refetchQueries,
})
).pipe(
withLatestFrom(timeline$),
mergeMap(([result, recentTimeline]) => {
const savedTimeline = recentTimeline[get('payload.id', action)];
const savedTimeline = recentTimeline[action.payload.id];
const response: ResponseTimeline = get('data.persistTimeline', result);
const callOutMsg = response.code === 403 ? [showCallOutUnauthorizedMsg()] : [];

return [
response.code === 409
? updateAutoSaveMsg({
timelineId: get('payload.id', action),
timelineId: action.payload.id,
newTimelineModel: omitTypenameInTimeline(savedTimeline, response.timeline),
})
: updateTimeline({
id: get('payload.id', action),
id: action.payload.id,
timeline: {
...savedTimeline,
savedObjectId: response.timeline.savedObjectId,
Expand All @@ -210,11 +198,11 @@ export const createTimelineEpic = <State>(): Epic<
}),
...callOutMsg,
endTimelineSaving({
id: get('payload.id', action),
id: action.payload.id,
}),
];
}),
startWith(startTimelineSaving({ id: get('payload.id', action) })),
startWith(startTimelineSaving({ id: action.payload.id })),
takeUntil(
action$.pipe(
withLatestFrom(timeline$),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ import {
import { dispatcherTimelinePersistQueue } from './epic_dispatcher_timeline_persistence_queue';
import { refetchQueries } from './refetch_queries';
import { myEpicTimelineId } from './my_epic_timeline_id';
import { TimelineById } from './types';
import { TimelineById, ActionTimeline } from './types';

export const timelineFavoriteActionsType = [updateIsFavorite.type];

export const epicPersistTimelineFavorite = (
apolloClient: ApolloClient<NormalizedCacheObject>,
action: Action,
action: ActionTimeline,
timeline: TimelineById,
action$: Observable<Action>,
timeline$: Observable<TimelineById>
Expand All @@ -52,14 +52,14 @@ export const epicPersistTimelineFavorite = (
).pipe(
withLatestFrom(timeline$),
mergeMap(([result, recentTimelines]) => {
const savedTimeline = recentTimelines[get('payload.id', action)];
const savedTimeline = recentTimelines[action.payload.id];
const response: ResponseFavoriteTimeline = get('data.persistFavorite', result);
const callOutMsg = response.code === 403 ? [showCallOutUnauthorizedMsg()] : [];

return [
...callOutMsg,
updateTimeline({
id: get('payload.id', action),
id: action.payload.id,
timeline: {
...savedTimeline,
isFavorite: response.favorite != null && response.favorite.length > 0,
Expand All @@ -68,11 +68,11 @@ export const epicPersistTimelineFavorite = (
},
}),
endTimelineSaving({
id: get('payload.id', action),
id: action.payload.id,
}),
];
}),
startWith(startTimelineSaving({ id: get('payload.id', action) })),
startWith(startTimelineSaving({ id: action.payload.id })),
takeUntil(
action$.pipe(
withLatestFrom(timeline$),
Expand Down
20 changes: 10 additions & 10 deletions x-pack/legacy/plugins/siem/public/store/timeline/epic_note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ import {
import { myEpicTimelineId } from './my_epic_timeline_id';
import { refetchQueries } from './refetch_queries';
import { dispatcherTimelinePersistQueue } from './epic_dispatcher_timeline_persistence_queue';
import { TimelineById } from './types';
import { TimelineById, ActionTimeline } from './types';
export const timelineNoteActionsType = [addNote.type, addNoteToEvent.type];

export const epicPersistNote = (
apolloClient: ApolloClient<NormalizedCacheObject>,
action: Action,
action: ActionTimeline,
timeline: TimelineById,
notes: NotesById,
action$: Observable<Action>,
Expand All @@ -52,8 +52,8 @@ export const epicPersistNote = (
noteId: null,
version: null,
note: {
eventId: get('payload.eventId', action),
note: getNote(get('payload.noteId', action), notes),
eventId: action.payload.eventId,
note: getNote(action.payload.noteId, notes),
timelineId: myEpicTimelineId.getTimelineId(),
},
},
Expand All @@ -62,17 +62,17 @@ export const epicPersistNote = (
).pipe(
withLatestFrom(timeline$, notes$),
mergeMap(([result, recentTimeline, recentNotes]) => {
const noteIdRedux = get('payload.noteId', action);
const noteIdRedux = action.payload.noteId;
const response: ResponseNote = get('data.persistNote', result);
const callOutMsg = response.code === 403 ? [showCallOutUnauthorizedMsg()] : [];

return [
...callOutMsg,
recentTimeline[get('payload.id', action)].savedObjectId == null
recentTimeline[action.payload.id].savedObjectId == null
? updateTimeline({
id: get('payload.id', action),
id: action.payload.id,
timeline: {
...recentTimeline[get('payload.id', action)],
...recentTimeline[action.payload.id],
savedObjectId: response.note.timelineId || null,
version: response.note.timelineVersion || null,
},
Expand All @@ -94,11 +94,11 @@ export const epicPersistNote = (
},
}),
endTimelineSaving({
id: get('payload.id', action),
id: action.payload.id,
}),
].filter(item => item != null);
}),
startWith(startTimelineSaving({ id: get('payload.id', action) })),
startWith(startTimelineSaving({ id: action.payload.id })),
takeUntil(
action$.pipe(
withLatestFrom(timeline$),
Expand Down
Loading