adds import Timeline test (#114703) (#116655)

Co-authored-by: Gloria Hornero <snootchie.boochies@gmail.com>
This commit is contained in:
Kibana Machine 2021-11-01 21:20:45 -04:00 committed by GitHub
parent bd3ec381d9
commit 8402a88c53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 303 additions and 2 deletions

View file

@ -667,6 +667,7 @@
"cypress": "^8.5.0",
"cypress-axe": "^0.13.0",
"cypress-cucumber-preprocessor": "^2.5.2",
"cypress-file-upload": "^5.0.8",
"cypress-multi-reporters": "^1.5.0",
"cypress-pipe": "^2.0.0",
"cypress-real-events": "^1.5.1",

View file

@ -0,0 +1 @@
{"savedObjectId":"53f99cf0-2b48-11ec-abd7-4702b60533ad","version":"WzExNDEyMSwxXQ==","columns":[{"columnHeaderType":"not-filtered","id":"@timestamp","type":"number"},{"columnHeaderType":"not-filtered","id":"message"},{"columnHeaderType":"not-filtered","id":"event.category"},{"columnHeaderType":"not-filtered","id":"event.action"},{"columnHeaderType":"not-filtered","id":"host.name"},{"columnHeaderType":"not-filtered","id":"source.ip"},{"columnHeaderType":"not-filtered","id":"destination.ip"},{"columnHeaderType":"not-filtered","id":"user.name"}],"dataProviders":[{"excluded":false,"and":[],"kqlQuery":"","name":"source.ip: 127.0.0.1","queryMatch":{"field":"source.ip","value":"127.0.0.1","operator":":"},"id":"formatted-ip-data-provider-plain-column-renderer-formatted-field-value-timeline-1-query-source_ip-127_0_0_1-df246068f5258a4168f6dd37eecf8c8575d4821ce459d7060ab7be66e6768d52","enabled":true}],"description":"This a timeline created on 7.15 version","eventType":"all","filters":[],"kqlMode":"filter","timelineType":"default","kqlQuery":{"filterQuery":{"serializedQuery":"{\"bool\":{\"should\":[{\"match_phrase\":{\"host.name\":\"security-solution.local\"}}],\"minimum_should_match\":1}}","kuery":{"expression":"host.name:\"security-solution.local\" ","kind":"kuery"}}},"title":"7.15 Timeline","sort":[{"columnType":"number","sortDirection":"desc","columnId":"@timestamp"}],"templateTimelineId":null,"templateTimelineVersion":null,"dateRange":{"start":"2020-10-10T22:00:00.000Z","end":"2030-10-11T15:13:15.851Z"},"indexNames":["auditbeat-*",".siem-signals-default"],"eqlOptions":{"tiebreakerField":"","size":100,"query":"","eventCategoryField":"event.category","timestampField":"@timestamp"},"savedQueryId":null,"favorite":[{"favoriteDate":1633965242498,"keySearch":"MTY3Mzk5OTM3OQ==","fullName":"glo@email.com","userName":"1673999379"}],"created":1634035018815,"createdBy":"elastic","updated":1634035018815,"updatedBy":"elastic","eventNotes":[],"globalNotes":[{"noteId":"7aa03750-2b49-11ec-abd7-4702b60533ad","version":"WzExNDI3NiwxXQ==","note":"This is a note","timelineId":"53f99cf0-2b48-11ec-abd7-4702b60533ad","created":1634035513157,"createdBy":"1673999379","updated":1634035513157,"updatedBy":"1673999379"}],"pinnedEventIds":["df246068f5258a4168f6dd37eecf8c8575d4821ce459d7060ab7be66e6768d52"]}

View file

@ -24,6 +24,8 @@ export const CASE = (id: string) => {
return `[data-test-subj="cases-table-row-${id}"]`;
};
export const CELL = '[data-test-subj="statefulCell"]';
export const CLOSE_TIMELINE_BTN = '[data-test-subj="close-timeline"]';
export const COMBO_BOX = '.euiComboBoxOption__content';
@ -34,13 +36,29 @@ export const CREATE_NEW_TIMELINE = '[data-test-subj="timeline-new"]';
export const CREATE_NEW_TIMELINE_TEMPLATE = '[data-test-subj="template-timeline-new"]';
export const DATA_PROVIDERS = '.field-value';
export const DATAGRID_HEADERS =
'[data-test-subj="events-viewer-panel"] [data-test-subj^="dataGridHeaderCell-"]';
export const DATE_PICKER_END = '[data-test-subj="superDatePickerendDatePopoverButton"]';
export const DATE_PICKER_START = '[data-test-subj="superDatePickerstartDatePopoverButton"]';
export const DELETE_TIMELINE_BTN = '[data-test-subj="delete-timeline"]';
export const DELETION_CONFIRMATION = '[data-test-subj="confirmModalConfirmButton"]';
export const DESTINATION_IP_KPI = '[data-test-subj="siem-timeline-destination-ip-kpi"]';
export const FAVORITE_TIMELINE = '[data-test-subj="timeline-favorite-filled-star"]';
export const FIELD_BROWSER = '[data-test-subj="show-field-browser"]';
export const GRAPH_TAB_BUTTON = '[data-test-subj="timelineTabs-graph"]';
export const HOST_KPI = '[data-test-subj="siem-timeline-host-kpi"]';
export const ID_HEADER_FIELD = '[data-test-subj="timeline"] [data-test-subj="header-text-_id"]';
export const ID_TOGGLE_FIELD = '[data-test-subj="toggle-field-_id"]';
@ -57,6 +75,10 @@ export const NOTE_CARD_CONTENT = '[data-test-subj="notes"]';
export const EVENT_NOTE = '[data-test-subj="timeline-notes-button-small"]';
export const NOTE_DESCRIPTION = '[data-test-subj="note-preview-description"]';
export const NOTE_PREVIEW = '[data-test-subj^="note-preview"]';
export const NOTES_TEXT_AREA = '[data-test-subj="add-a-note"] textarea';
export const NOTES_TAB_BUTTON = '[data-test-subj="timelineTabs-notes"]';
@ -82,6 +104,10 @@ export const OPEN_TIMELINE_TEMPLATE_ICON =
export const PIN_EVENT = '[data-test-subj="pin"]';
export const PINNED_TAB_BUTTON = '[data-test-subj="timelineTabs-pinned"]';
export const PROCESS_KPI = '[data-test-subj="siem-timeline-process-kpi"';
export const PROVIDER_BADGE = '[data-test-subj="providerBadge"]';
export const RESET_FIELDS =
@ -98,6 +124,8 @@ export const QUERY_TAB_BUTTON = '[data-test-subj="timelineTabs-query"]';
export const SERVER_SIDE_EVENT_COUNT = '[data-test-subj="server-side-event-count"]';
export const SOURCE_IP_KPI = '[data-test-subj="siem-timeline-source-ip-kpi"]';
export const STAR_ICON = '[data-test-subj="timeline-favorite-empty-star"]';
export const TIMELINE_CHANGES_IN_PROGRESS = '[data-test-subj="timeline"] .euiProgress';
@ -227,3 +255,5 @@ export const TIMELINE_TAB_CONTENT_GRAPHS_NOTES =
'[data-test-subj="timeline-tab-content-graph-notes"]';
export const TIMESTAMP_HOVER_ACTION_OVERFLOW_BTN = '[data-test-subj="more-actions-@timestamp"]';
export const USER_KPI = '[data-test-subj="siem-timeline-user-kpi"]';

View file

@ -7,8 +7,20 @@
export const BULK_ACTIONS = '[data-test-subj="utility-bar-action-button"]';
export const EXPAND_NOTES_BTN = '[data-test-subj="expand-notes"]';
export const EXPORT_TIMELINE_ACTION = '[data-test-subj="export-timeline-action"]';
export const IMPORT_BTN = '.euiButton__text';
export const IMPORT_BTN_POSITION = 8;
export const IMPORT_TIMELINE_BTN = '[data-test-subj="open-import-data-modal-btn"]';
export const INPUT_FILE = 'input[type=file]';
export const NOTE = '[data-test-subj^="note-preview-"]';
export const TIMELINE = (id: string | undefined) => {
if (id == null) {
throw new TypeError('id should never be null or undefined');
@ -20,6 +32,8 @@ export const TIMELINE_CHECKBOX = (id: string) => {
return `[data-test-subj="checkboxSelectRow-${id}"]`;
};
export const TIMELINE_NAME = '[data-test-subj^=title]';
export const TIMELINES_FAVORITE = '[data-test-subj="favorite-starFilled-star"]';
export const TIMELINES_DESCRIPTION = '[data-test-subj="description"]';
@ -30,4 +44,6 @@ export const TIMELINES_PINNED_EVENT_COUNT = '[data-test-subj="pinned-event-count
export const TIMELINES_TABLE = '[data-test-subj="timelines-table"]';
export const TIMELINES_USERNAME = '[data-test-subj="username"]';
export const REFRESH_BUTTON = '[data-test-subj="refreshButton-linkIcon"]';

View file

@ -31,6 +31,8 @@
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
import 'cypress-file-upload';
Cypress.Commands.add(
'attachFile',
{

View file

@ -22,6 +22,8 @@ import {
COMBO_BOX,
COMBO_BOX_INPUT,
CREATE_NEW_TIMELINE,
DELETE_TIMELINE_BTN,
DELETION_CONFIRMATION,
FIELD_BROWSER,
ID_HEADER_FIELD,
ID_TOGGLE_FIELD,
@ -66,6 +68,7 @@ import {
TIMELINE_COLLAPSED_ITEMS_BTN,
TIMELINE_TAB_CONTENT_EQL,
TIMESTAMP_HOVER_ACTION_OVERFLOW_BTN,
PINNED_TAB_BUTTON,
} from '../screens/timeline';
import { REFRESH_BUTTON, TIMELINE } from '../screens/timelines';
@ -128,6 +131,15 @@ export const goToQueryTab = () => {
.should('have.class', 'euiTab-isSelected');
};
export const goToPinnedTab = () => {
cy.root()
.pipe(($el) => {
$el.find(PINNED_TAB_BUTTON).trigger('click');
return $el.find(PINNED_TAB_BUTTON);
})
.should('have.class', 'euiTab-isSelected');
};
export const addNotesToTimeline = (notes: string) => {
goToNotesTab().then(() => {
cy.get(NOTES_TAB_BUTTON)
@ -243,6 +255,12 @@ export const expandFirstTimelineEventDetails = () => {
cy.get(TOGGLE_TIMELINE_EXPAND_EVENT).first().click({ force: true });
};
export const deleteTimeline = () => {
cy.get(TIMELINE_COLLAPSED_ITEMS_BTN).click();
cy.get(DELETE_TIMELINE_BTN).click();
cy.get(DELETION_CONFIRMATION).click();
};
export const markAsFavorite = () => {
const click = ($el: Cypress.ObjectLike) => cy.wrap($el).click();
cy.get(STAR_ICON).should('be.visible').pipe(click);

View file

@ -9,20 +9,42 @@ import { LOADING_INDICATOR } from '../screens/security_header';
import {
TIMELINE_CHECKBOX,
BULK_ACTIONS,
EXPAND_NOTES_BTN,
EXPORT_TIMELINE_ACTION,
IMPORT_BTN,
IMPORT_BTN_POSITION,
IMPORT_TIMELINE_BTN,
INPUT_FILE,
TIMELINES_TABLE,
TIMELINE,
TIMELINE_NAME,
} from '../screens/timelines';
export const expandNotes = () => {
cy.get(EXPAND_NOTES_BTN).click();
};
export const exportTimeline = (timelineId: string) => {
cy.get(TIMELINE_CHECKBOX(timelineId)).click({ force: true });
cy.get(BULK_ACTIONS).click({ force: true });
cy.get(EXPORT_TIMELINE_ACTION).click();
};
export const openTimeline = (id: string) => {
export const importTimeline = (timeline: string) => {
cy.get(IMPORT_TIMELINE_BTN).click();
cy.get(INPUT_FILE).should('exist');
cy.get(INPUT_FILE).trigger('click', { force: true }).attachFile(timeline).trigger('change');
cy.get(IMPORT_BTN).eq(IMPORT_BTN_POSITION).click({ force: true });
cy.get(INPUT_FILE).should('not.exist');
};
export const openTimeline = (id?: string) => {
const click = ($el: Cypress.ObjectLike) => cy.wrap($el).click();
cy.get(TIMELINE(id)).should('be.visible').pipe(click);
if (id) {
cy.get(TIMELINE(id)).should('be.visible').pipe(click);
} else {
cy.get(TIMELINE_NAME).should('be.visible').pipe(click);
}
};
export const waitForTimelinesPanelToBeLoaded = () => {

View file

@ -12,6 +12,7 @@
"outDir": "target/types",
"types": [
"cypress",
"cypress-file-upload",
"cypress-pipe",
"node",
"resize-observer-polyfill",

View file

@ -0,0 +1,205 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import {
CELL,
DATA_PROVIDERS,
DATE_PICKER_END,
DATE_PICKER_START,
DESTINATION_IP_KPI,
GRAPH_TAB_BUTTON,
HOST_KPI,
QUERY_TAB_BUTTON,
NOTE_DESCRIPTION,
NOTE_PREVIEW,
NOTES_TAB_BUTTON,
PINNED_TAB_BUTTON,
PROCESS_KPI,
SOURCE_IP_KPI,
TIMELINE_CORRELATION_TAB,
TIMELINE_CORRELATION_INPUT,
TIMELINE_DESCRIPTION,
TIMELINE_QUERY,
TIMELINE_TITLE,
USER_KPI,
} from '../screens/timeline';
import {
NOTE,
TIMELINES_USERNAME,
TIMELINE_NAME,
TIMELINES_DESCRIPTION,
TIMELINES_NOTES_COUNT,
TIMELINES_PINNED_EVENT_COUNT,
} from '../screens/timelines';
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
import {
closeTimeline,
deleteTimeline,
goToCorrelationTab,
goToNotesTab,
goToPinnedTab,
} from '../tasks/timeline';
import { expandNotes, importTimeline, openTimeline } from '../tasks/timelines';
import { TIMELINES_URL } from '../urls/navigation';
const timeline = '7_15_timeline.ndjson';
const username = 'elastic';
const timelineDetails = {
dateStart: 'Oct 11, 2020 @ 00:00:00.000',
dateEnd: 'Oct 11, 2030 @ 17:13:15.851',
queryTab: 'Query2',
correlationTab: 'Correlation',
analyzerTab: 'Analyzer',
notesTab: 'Notes2',
pinnedTab: 'Pinned1',
};
const detectionAlert = {
timestamp: 'Oct 7, 2021 @ 11:14:10.888',
message: '—',
eventCategory: 'file',
eventAction: 'initial_scan',
hostName: 'security-solution.local',
sourceIp: '127.0.0.1',
destinationIp: '127.0.0.2',
userName: 'Security Solution',
};
const event = {
timestamp: 'Oct 6, 2021 @ 17:09:29.438',
message: '—',
eventCategory: 'file',
eventAction: 'initial_scan',
hostName: 'security-solution.local',
sourceIp: '127.0.0.1',
destinationIp: '127.0.0.2',
userName: 'Security Solution',
};
describe('Import timeline after upgrade', () => {
before(() => {
loginAndWaitForPageWithoutDateRange(TIMELINES_URL);
importTimeline(timeline);
});
after(() => {
closeTimeline();
deleteTimeline();
});
it('Displays the correct timeline details on the timelines page', () => {
cy.readFile(`cypress/fixtures/${timeline}`).then((file) => {
const timelineJson = JSON.parse(file);
const regex = new RegExp(
`\\S${timelineJson.globalNotes[0].createdBy}added a note\\d* \\w* ago${timelineJson.globalNotes[0].createdBy} added a note${timelineJson.globalNotes[0].note}`
);
cy.get(TIMELINE_NAME).should('have.text', timelineJson.title);
cy.get(TIMELINES_DESCRIPTION).should('have.text', timelineJson.description);
cy.get(TIMELINES_USERNAME).should('have.text', username);
cy.get(TIMELINES_NOTES_COUNT).should('have.text', timelineJson.globalNotes.length.toString());
cy.get(TIMELINES_PINNED_EVENT_COUNT).should(
'have.text',
timelineJson.pinnedEventIds.length.toString()
);
expandNotes();
cy.get(NOTE).invoke('text').should('match', regex);
});
});
it('Displays the correct timeline details inside the query tab', () => {
openTimeline();
cy.readFile(`cypress/fixtures/${timeline}`).then((file) => {
const timelineJson = JSON.parse(file);
cy.get(TIMELINE_TITLE).should('have.text', timelineJson.title);
cy.get(TIMELINE_DESCRIPTION).should('have.text', timelineJson.description);
cy.get(DATA_PROVIDERS).should('have.length', timelineJson.dataProviders.length.toString());
cy.get(DATA_PROVIDERS)
.invoke('text')
.then((value) => {
expect(value.replace(/"/g, '')).to.eq(timelineJson.dataProviders[0].name);
});
cy.get(PROCESS_KPI).should('contain', '0');
cy.get(USER_KPI).should('contain', '0');
cy.get(HOST_KPI).should('contain', '1');
cy.get(SOURCE_IP_KPI).should('contain', '1');
cy.get(DESTINATION_IP_KPI).should('contain', '1');
cy.get(DATE_PICKER_START).should('contain', timelineDetails.dateStart);
cy.get(DATE_PICKER_END).should('contain', timelineDetails.dateEnd);
cy.get(TIMELINE_QUERY).should(
'have.text',
timelineJson.kqlQuery.filterQuery.kuery.expression
);
cy.get(QUERY_TAB_BUTTON).should('have.text', timelineDetails.queryTab);
cy.get(TIMELINE_CORRELATION_TAB).should('have.text', timelineDetails.correlationTab);
cy.get(GRAPH_TAB_BUTTON).should('have.text', timelineDetails.analyzerTab).and('be.disabled');
cy.get(NOTES_TAB_BUTTON).should('have.text', timelineDetails.notesTab);
cy.get(PINNED_TAB_BUTTON).should('have.text', timelineDetails.pinnedTab);
cy.get(CELL).eq(0).should('contain', detectionAlert.timestamp);
cy.get(CELL).eq(1).should('contain', detectionAlert.message);
cy.get(CELL).eq(2).should('contain', detectionAlert.eventCategory);
cy.get(CELL).eq(3).should('contain', detectionAlert.eventAction);
cy.get(CELL).eq(4).should('contain', detectionAlert.hostName);
cy.get(CELL).eq(5).should('contain', detectionAlert.sourceIp);
cy.get(CELL).eq(6).should('contain', detectionAlert.destinationIp);
cy.get(CELL).eq(7).should('contain', detectionAlert.userName);
cy.get(CELL).eq(8).should('contain', event.timestamp);
cy.get(CELL).eq(9).should('contain', event.message);
cy.get(CELL).eq(10).should('contain', event.eventCategory);
cy.get(CELL).eq(11).should('contain', event.eventAction);
cy.get(CELL).eq(12).should('contain', event.hostName);
cy.get(CELL).eq(13).should('contain', event.sourceIp);
cy.get(CELL).eq(14).should('contain', event.destinationIp);
cy.get(CELL).eq(15).should('contain', event.userName);
});
});
it('Displays the correct timeline details inside the query tab', () => {
goToCorrelationTab();
cy.get(TIMELINE_CORRELATION_INPUT).should('be.empty');
});
it('Displays the correct timeline details inside the notes tab', () => {
goToNotesTab();
cy.readFile(`cypress/fixtures/${timeline}`).then((file) => {
const timelineJson = JSON.parse(file);
const descriptionRegex = new RegExp(
`\\S${username}added description\\d* \\w* ago${timelineJson.description}`
);
const noteRegex = new RegExp(
`\\S${timelineJson.globalNotes[0].createdBy}added a note\\d* \\w* ago${timelineJson.globalNotes[0].createdBy} added a note${timelineJson.globalNotes[0].note}`
);
cy.get(NOTE_DESCRIPTION).invoke('text').should('match', descriptionRegex);
cy.get(NOTE_PREVIEW).invoke('text').should('match', noteRegex);
});
});
it('Displays the correct timeline details inside the pinned tab', () => {
goToPinnedTab();
cy.get(CELL).eq(0).should('contain', detectionAlert.timestamp);
cy.get(CELL).eq(1).should('contain', detectionAlert.message);
cy.get(CELL).eq(2).should('contain', detectionAlert.eventCategory);
cy.get(CELL).eq(3).should('contain', detectionAlert.eventAction);
cy.get(CELL).eq(4).should('contain', detectionAlert.hostName);
cy.get(CELL).eq(5).should('contain', detectionAlert.sourceIp);
cy.get(CELL).eq(6).should('contain', detectionAlert.destinationIp);
cy.get(CELL).eq(7).should('contain', detectionAlert.userName);
});
});

View file

@ -11794,6 +11794,11 @@ cypress-cucumber-preprocessor@^2.5.2:
minimist "^1.2.0"
through "^2.3.8"
cypress-file-upload@^5.0.8:
version "5.0.8"
resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-5.0.8.tgz#d8824cbeaab798e44be8009769f9a6c9daa1b4a1"
integrity sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g==
cypress-multi-reporters@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/cypress-multi-reporters/-/cypress-multi-reporters-1.5.0.tgz#fff2758c082b49e8b91fed39f9650c70bc06de0d"