mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* adds "Creates timeline" test * deletes timeline events spec * completes assertions * comments assertion * fixes typecheck error * waits for all the changes in the timeline to be performed before creating a new timeline and closing the toggle * fixes failing problem * fixes loop script * makes test realiable on visual mode * fixes merge issue * makes test more reliable * fixes typecheck issue * fixes typecheck * opens timeline from timeline settings Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
e04438a5f8
commit
ea360ecd78
27 changed files with 307 additions and 95 deletions
|
@ -151,6 +151,7 @@
|
|||
"color": "1.0.3",
|
||||
"commander": "3.0.2",
|
||||
"core-js": "^3.6.4",
|
||||
"cypress-promise": "^1.1.0",
|
||||
"deep-freeze-strict": "^1.1.1",
|
||||
"del": "^5.1.0",
|
||||
"elastic-apm-node": "^3.7.0",
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
"cronstrue": "^1.51.0",
|
||||
"cypress": "5.0.0",
|
||||
"cypress-multi-reporters": "^1.2.3",
|
||||
"cypress-promise": "^1.1.0",
|
||||
"d3": "3.5.17",
|
||||
"d3-scale": "1.0.7",
|
||||
"dragselect": "1.13.1",
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
"plugins": ["cypress"],
|
||||
"env": {
|
||||
"cypress/globals": true
|
||||
},
|
||||
"rules": {
|
||||
"import/no-extraneous-dependencies": "off"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import {
|
|||
resetFields,
|
||||
} from '../tasks/fields_browser';
|
||||
import { loginAndWaitForPage } from '../tasks/login';
|
||||
import { openTimeline } from '../tasks/security_main';
|
||||
import { openTimelineUsingToggle } from '../tasks/security_main';
|
||||
import { openTimelineFieldsBrowser, populateTimeline } from '../tasks/timeline';
|
||||
|
||||
import { HOSTS_URL } from '../urls/navigation';
|
||||
|
@ -48,7 +48,7 @@ describe('Fields Browser', () => {
|
|||
context('Fields Browser rendering', () => {
|
||||
before(() => {
|
||||
loginAndWaitForPage(HOSTS_URL);
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
populateTimeline();
|
||||
openTimelineFieldsBrowser();
|
||||
});
|
||||
|
@ -111,7 +111,7 @@ describe('Fields Browser', () => {
|
|||
context('Editing the timeline', () => {
|
||||
before(() => {
|
||||
loginAndWaitForPage(HOSTS_URL);
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
populateTimeline();
|
||||
openTimelineFieldsBrowser();
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
|
||||
import { closesModal, openStatsAndTables } from '../tasks/inspect';
|
||||
import { loginAndWaitForPage } from '../tasks/login';
|
||||
import { openTimeline } from '../tasks/security_main';
|
||||
import { openTimelineUsingToggle } from '../tasks/security_main';
|
||||
import {
|
||||
executeTimelineKQL,
|
||||
openTimelineInspectButton,
|
||||
|
@ -58,7 +58,7 @@ describe('Inspect', () => {
|
|||
it('inspects the timeline', () => {
|
||||
const hostExistsQuery = 'host.name: *';
|
||||
loginAndWaitForPage(HOSTS_URL);
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
executeTimelineKQL(hostExistsQuery);
|
||||
openTimelineSettings();
|
||||
openTimelineInspectButton();
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { timeline } from '../objects/timeline';
|
||||
|
||||
import {
|
||||
FAVORITE_TIMELINE,
|
||||
LOCKED_ICON,
|
||||
NOTES,
|
||||
NOTES_BUTTON,
|
||||
NOTES_COUNT,
|
||||
NOTES_TEXT_AREA,
|
||||
PIN_EVENT,
|
||||
TIMELINE_DESCRIPTION,
|
||||
// TIMELINE_FILTER,
|
||||
TIMELINE_QUERY,
|
||||
TIMELINE_TITLE,
|
||||
} from '../screens/timeline';
|
||||
import {
|
||||
TIMELINES_DESCRIPTION,
|
||||
TIMELINES_PINNED_EVENT_COUNT,
|
||||
TIMELINES_NOTES_COUNT,
|
||||
TIMELINES_FAVORITE,
|
||||
} from '../screens/timelines';
|
||||
|
||||
import { loginAndWaitForPage } from '../tasks/login';
|
||||
import { openTimelineUsingToggle } from '../tasks/security_main';
|
||||
import {
|
||||
addDescriptionToTimeline,
|
||||
addFilter,
|
||||
addNameToTimeline,
|
||||
addNotesToTimeline,
|
||||
closeNotes,
|
||||
closeTimeline,
|
||||
createNewTimeline,
|
||||
markAsFavorite,
|
||||
openTimelineFromSettings,
|
||||
pinFirstEvent,
|
||||
populateTimeline,
|
||||
waitForTimelineChanges,
|
||||
} from '../tasks/timeline';
|
||||
import { openTimeline } from '../tasks/timelines';
|
||||
|
||||
import { OVERVIEW_URL } from '../urls/navigation';
|
||||
|
||||
describe('Timelines', () => {
|
||||
before(() => {
|
||||
cy.server();
|
||||
cy.route('PATCH', '**/api/timeline').as('timeline');
|
||||
});
|
||||
|
||||
it('Creates a timeline', async () => {
|
||||
loginAndWaitForPage(OVERVIEW_URL);
|
||||
openTimelineUsingToggle();
|
||||
populateTimeline();
|
||||
addFilter(timeline.filter);
|
||||
pinFirstEvent();
|
||||
|
||||
cy.get(PIN_EVENT).should('have.attr', 'aria-label', 'Pinned event');
|
||||
cy.get(LOCKED_ICON).should('be.visible');
|
||||
|
||||
addNameToTimeline(timeline.title);
|
||||
|
||||
const response = await cy.wait('@timeline').promisify();
|
||||
const timelineId = JSON.parse(response.xhr.responseText).data.persistTimeline.timeline
|
||||
.savedObjectId;
|
||||
|
||||
addDescriptionToTimeline(timeline.description);
|
||||
addNotesToTimeline(timeline.notes);
|
||||
closeNotes();
|
||||
markAsFavorite();
|
||||
waitForTimelineChanges();
|
||||
createNewTimeline();
|
||||
closeTimeline();
|
||||
openTimelineFromSettings();
|
||||
|
||||
cy.contains(timeline.title).should('exist');
|
||||
cy.get(TIMELINES_DESCRIPTION).first().should('have.text', timeline.description);
|
||||
cy.get(TIMELINES_PINNED_EVENT_COUNT).first().should('have.text', '1');
|
||||
cy.get(TIMELINES_NOTES_COUNT).first().should('have.text', '1');
|
||||
cy.get(TIMELINES_FAVORITE).first().should('exist');
|
||||
|
||||
openTimeline(timelineId);
|
||||
|
||||
cy.get(FAVORITE_TIMELINE).should('exist');
|
||||
cy.get(TIMELINE_TITLE).should('have.attr', 'value', timeline.title);
|
||||
cy.get(TIMELINE_DESCRIPTION).should('have.attr', 'value', timeline.description);
|
||||
cy.get(TIMELINE_QUERY).should('have.text', timeline.query);
|
||||
// Comments this assertion until we agreed what to do with the filters.
|
||||
// cy.get(TIMELINE_FILTER(timeline.filter)).should('exist');
|
||||
cy.get(NOTES_COUNT).should('have.text', '1');
|
||||
cy.get(PIN_EVENT).should('have.attr', 'aria-label', 'Pinned event');
|
||||
cy.get(NOTES_BUTTON).click();
|
||||
cy.get(NOTES_TEXT_AREA).should('have.attr', 'placeholder', 'Add a Note');
|
||||
cy.get(NOTES).should('have.text', timeline.notes);
|
||||
});
|
||||
});
|
|
@ -19,7 +19,7 @@ import {
|
|||
} from '../tasks/hosts/all_hosts';
|
||||
|
||||
import { loginAndWaitForPage } from '../tasks/login';
|
||||
import { openTimeline } from '../tasks/security_main';
|
||||
import { openTimelineUsingToggle } from '../tasks/security_main';
|
||||
import { createNewTimeline } from '../tasks/timeline';
|
||||
|
||||
import { HOSTS_URL } from '../urls/navigation';
|
||||
|
@ -31,7 +31,7 @@ describe('timeline data providers', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { PIN_EVENT } from '../screens/timeline';
|
||||
|
||||
import { loginAndWaitForPage } from '../tasks/login';
|
||||
import { openTimeline } from '../tasks/security_main';
|
||||
import { pinFirstEvent, populateTimeline, unpinFirstEvent } from '../tasks/timeline';
|
||||
|
||||
import { HOSTS_URL } from '../urls/navigation';
|
||||
|
||||
describe('timeline events', () => {
|
||||
before(() => {
|
||||
loginAndWaitForPage(HOSTS_URL);
|
||||
openTimeline();
|
||||
populateTimeline();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
unpinFirstEvent();
|
||||
});
|
||||
|
||||
it('pins the first event to the timeline', () => {
|
||||
cy.server();
|
||||
cy.route('POST', '**/api/solutions/security/graphql').as('persistTimeline');
|
||||
|
||||
pinFirstEvent();
|
||||
|
||||
cy.wait('@persistTimeline', { timeout: 10000 }).then((response) => {
|
||||
cy.wrap(response.status).should('eql', 200);
|
||||
cy.wrap(response.xhr.responseText).should('include', 'persistPinnedEventOnTimeline');
|
||||
});
|
||||
|
||||
cy.get(PIN_EVENT).should('have.attr', 'aria-label', 'Pinned event');
|
||||
});
|
||||
});
|
|
@ -8,7 +8,7 @@ import { TIMELINE_FLYOUT_HEADER, TIMELINE_NOT_READY_TO_DROP_BUTTON } from '../sc
|
|||
|
||||
import { dragFirstHostToTimeline, waitForAllHostsToBeLoaded } from '../tasks/hosts/all_hosts';
|
||||
import { loginAndWaitForPage } from '../tasks/login';
|
||||
import { openTimeline, openTimelineIfClosed } from '../tasks/security_main';
|
||||
import { openTimelineUsingToggle, openTimelineIfClosed } from '../tasks/security_main';
|
||||
import { createNewTimeline } from '../tasks/timeline';
|
||||
|
||||
import { HOSTS_URL } from '../urls/navigation';
|
||||
|
@ -25,7 +25,7 @@ describe('timeline flyout button', () => {
|
|||
});
|
||||
|
||||
it('toggles open the timeline', () => {
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
cy.get(TIMELINE_FLYOUT_HEADER).should('have.css', 'visibility', 'visible');
|
||||
});
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { SERVER_SIDE_EVENT_COUNT } from '../screens/timeline';
|
||||
|
||||
import { loginAndWaitForPage } from '../tasks/login';
|
||||
import { openTimeline } from '../tasks/security_main';
|
||||
import { openTimelineUsingToggle } from '../tasks/security_main';
|
||||
import { executeTimelineKQL } from '../tasks/timeline';
|
||||
|
||||
import { HOSTS_URL } from '../urls/navigation';
|
||||
|
@ -19,7 +19,7 @@ describe('timeline search or filter KQL bar', () => {
|
|||
|
||||
it('executes a KQL query', () => {
|
||||
const hostExistsQuery = 'host.name: *';
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
executeTimelineKQL(hostExistsQuery);
|
||||
|
||||
cy.get(SERVER_SIDE_EVENT_COUNT)
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
} from '../screens/timeline';
|
||||
|
||||
import { loginAndWaitForPage } from '../tasks/login';
|
||||
import { openTimeline } from '../tasks/security_main';
|
||||
import { openTimelineUsingToggle } from '../tasks/security_main';
|
||||
import {
|
||||
checkIdToggleField,
|
||||
createNewTimeline,
|
||||
|
@ -30,7 +30,7 @@ describe('toggle column in timeline', () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
populateTimeline();
|
||||
});
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { exportTimeline, waitForTimelinesPanelToBeLoaded } from '../tasks/timeline';
|
||||
import { exportTimeline, waitForTimelinesPanelToBeLoaded } from '../tasks/timelines';
|
||||
import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver';
|
||||
import { loginAndWaitForPageWithoutDateRange } from '../tasks/login';
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import { openAllHosts } from '../tasks/hosts/main';
|
|||
|
||||
import { waitForIpsTableToBeLoaded } from '../tasks/network/flows';
|
||||
import { clearSearchBar, kqlSearch, navigateFromHeaderTo } from '../tasks/security_header';
|
||||
import { openTimeline } from '../tasks/security_main';
|
||||
import { openTimelineUsingToggle } from '../tasks/security_main';
|
||||
import {
|
||||
addDescriptionToTimeline,
|
||||
addNameToTimeline,
|
||||
|
@ -82,7 +82,7 @@ describe('url state', () => {
|
|||
|
||||
it('sets the timeline start and end dates from the url when locked to global time', () => {
|
||||
loginAndWaitForPageWithoutDateRange(ABSOLUTE_DATE_RANGE.url);
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
|
||||
cy.get(DATE_PICKER_START_DATE_POPOVER_BUTTON_TIMELINE).should(
|
||||
'have.attr',
|
||||
|
@ -105,7 +105,7 @@ describe('url state', () => {
|
|||
);
|
||||
cy.get(DATE_PICKER_END_DATE_POPOVER_BUTTON).should('have.attr', 'title', ABSOLUTE_DATE.endTime);
|
||||
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
|
||||
cy.get(DATE_PICKER_START_DATE_POPOVER_BUTTON_TIMELINE).should(
|
||||
'have.attr',
|
||||
|
@ -121,7 +121,7 @@ describe('url state', () => {
|
|||
|
||||
it('sets the url state when timeline/global date pickers are unlinked and timeline start and end date are set', () => {
|
||||
loginAndWaitForPageWithoutDateRange(ABSOLUTE_DATE_RANGE.urlUnlinked);
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
setTimelineStartDate(ABSOLUTE_DATE.newStartTimeTyped);
|
||||
updateTimelineDates();
|
||||
setTimelineEndDate(ABSOLUTE_DATE.newEndTimeTyped);
|
||||
|
@ -220,7 +220,7 @@ describe('url state', () => {
|
|||
|
||||
it('sets and reads the url state for timeline by id', () => {
|
||||
loginAndWaitForPage(HOSTS_URL);
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
executeTimelineKQL('host.name: *');
|
||||
|
||||
cy.get(SERVER_SIDE_EVENT_COUNT)
|
||||
|
|
|
@ -10,6 +10,30 @@ export interface Timeline {
|
|||
query: string;
|
||||
}
|
||||
|
||||
export interface CompleteTimeline extends Timeline {
|
||||
notes: string;
|
||||
filter: TimelineFilter;
|
||||
}
|
||||
|
||||
export interface TimelineFilter {
|
||||
field: string;
|
||||
operator: string;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export interface TimelineWithId extends Timeline {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export const filter: TimelineFilter = {
|
||||
field: 'host.name',
|
||||
operator: 'exists',
|
||||
};
|
||||
|
||||
export const timeline: CompleteTimeline = {
|
||||
title: 'Security Timeline',
|
||||
description: 'This is the best timeline',
|
||||
query: 'host.name: * ',
|
||||
notes: 'Yes, the best timeline',
|
||||
filter,
|
||||
};
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { TimelineFilter } from '../objects/timeline';
|
||||
|
||||
export const ADD_NOTE_BUTTON = '[data-test-subj="add-note"]';
|
||||
|
||||
export const ADD_FILTER = '[data-test-subj="timeline"] [data-test-subj="addFilter"]';
|
||||
|
||||
export const ATTACH_TIMELINE_TO_NEW_CASE_ICON = '[data-test-subj="attach-timeline-case"]';
|
||||
|
||||
export const ATTACH_TIMELINE_TO_EXISTING_CASE_ICON =
|
||||
|
@ -15,14 +21,18 @@ export const CASE = (id: string) => {
|
|||
return `[data-test-subj="cases-table-row-${id}"]`;
|
||||
};
|
||||
|
||||
export const CLOSE_NOTES_BTN = '[data-test-subj="notesModal"] .euiButtonIcon';
|
||||
|
||||
export const CLOSE_TIMELINE_BTN = '[data-test-subj="close-timeline"]';
|
||||
|
||||
export const COMBO_BOX = '.euiComboBoxOption__content';
|
||||
|
||||
export const CREATE_NEW_TIMELINE = '[data-test-subj="timeline-new"]';
|
||||
|
||||
export const DRAGGABLE_HEADER =
|
||||
'[data-test-subj="events-viewer-panel"] [data-test-subj="headers-group"] [data-test-subj="draggable-header"]';
|
||||
|
||||
export const EXPORT_TIMELINE_ACTION = '[data-test-subj="export-timeline-action"]';
|
||||
export const FAVORITE_TIMELINE = '[data-test-subj="timeline-favorite-filled-star"]';
|
||||
|
||||
export const HEADER = '[data-test-subj="header"]';
|
||||
|
||||
|
@ -34,6 +44,16 @@ export const ID_FIELD = '[data-test-subj="timeline"] [data-test-subj="field-name
|
|||
|
||||
export const ID_TOGGLE_FIELD = '[data-test-subj="toggle-field-_id"]';
|
||||
|
||||
export const LOCKED_ICON = '[data-test-subj="timeline-date-picker-lock-button"]';
|
||||
|
||||
export const NOTES = '[data-test-subj="markdown-root"]';
|
||||
|
||||
export const NOTES_TEXT_AREA = '[data-test-subj="add-a-note"]';
|
||||
|
||||
export const NOTES_BUTTON = '[data-test-subj="timeline-notes-button-large"]';
|
||||
|
||||
export const NOTES_COUNT = '[data-test-subj="timeline-notes-count"]';
|
||||
|
||||
export const OPEN_TIMELINE_ICON = '[data-test-subj="open-timeline-button"]';
|
||||
|
||||
export const PIN_EVENT = '[data-test-subj="pin"]';
|
||||
|
@ -45,21 +65,17 @@ export const REMOVE_COLUMN = '[data-test-subj="remove-column"]';
|
|||
export const RESET_FIELDS =
|
||||
'[data-test-subj="events-viewer-panel"] [data-test-subj="reset-fields"]';
|
||||
|
||||
export const SAVE_FILTER_BTN = '[data-test-subj="saveFilter"]';
|
||||
|
||||
export const SEARCH_OR_FILTER_CONTAINER =
|
||||
'[data-test-subj="timeline-search-or-filter-search-container"]';
|
||||
|
||||
export const SERVER_SIDE_EVENT_COUNT = '[data-test-subj="server-side-event-count"]';
|
||||
|
||||
export const TIMELINE = (id: string) => {
|
||||
return `[data-test-subj="title-${id}"]`;
|
||||
};
|
||||
export const STAR_ICON = '[data-test-subj="timeline-favorite-empty-star"]';
|
||||
|
||||
export const TIMELINE_CHANGES_IN_PROGRESS = '[data-test-subj="timeline"] .euiProgress';
|
||||
|
||||
export const TIMELINE_CHECKBOX = (id: string) => {
|
||||
return `[data-test-subj="checkboxSelectRow-${id}"]`;
|
||||
};
|
||||
|
||||
export const TIMELINE_COLUMN_SPINNER = '[data-test-subj="timeline-loading-spinner"]';
|
||||
|
||||
export const TIMELINE_DATA_PROVIDERS = '[data-test-subj="dataProviders"]';
|
||||
|
@ -74,6 +90,17 @@ export const TIMELINE_DROPPED_DATA_PROVIDERS = '[data-test-subj="providerContain
|
|||
export const TIMELINE_FIELDS_BUTTON =
|
||||
'[data-test-subj="timeline"] [data-test-subj="show-field-browser"]';
|
||||
|
||||
export const TIMELINE_FILTER = (filter: TimelineFilter) => {
|
||||
return `[data-test-subj="filter filter-enabled filter-key-${filter.field} filter-value-${filter.value} filter-unpinned"]`;
|
||||
};
|
||||
|
||||
export const TIMELINE_FILTER_FIELD = '[data-test-subj="filterFieldSuggestionList"]';
|
||||
|
||||
export const TIMELINE_FILTER_OPERATOR = '[data-test-subj="filterOperatorList"]';
|
||||
|
||||
export const TIMELINE_FILTER_VALUE =
|
||||
'[data-test-subj="filterParamsComboBox phraseParamsComboxBox"]';
|
||||
|
||||
export const TIMELINE_FLYOUT_HEADER = '[data-test-subj="eui-flyout-header"]';
|
||||
|
||||
export const TIMELINE_FLYOUT_BODY = '[data-test-subj="eui-flyout-body"]';
|
||||
|
@ -89,8 +116,6 @@ export const TIMELINE_SETTINGS_ICON = '[data-test-subj="settings-gear"]';
|
|||
|
||||
export const TIMELINE_TITLE = '[data-test-subj="timeline-title"]';
|
||||
|
||||
export const TIMELINES_TABLE = '[data-test-subj="timelines-table"]';
|
||||
|
||||
export const TIMESTAMP_HEADER_FIELD = '[data-test-subj="header-text-@timestamp"]';
|
||||
|
||||
export const TIMESTAMP_TOGGLE_FIELD = '[data-test-subj="toggle-field-@timestamp"]';
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const BULK_ACTIONS = '[data-test-subj="utility-bar-action-button"]';
|
||||
|
||||
export const EXPORT_TIMELINE_ACTION = '[data-test-subj="export-timeline-action"]';
|
||||
|
||||
export const TIMELINE = (id: string) => {
|
||||
return `[data-test-subj="title-${id}"]`;
|
||||
};
|
||||
|
||||
export const TIMELINE_CHECKBOX = (id: string) => {
|
||||
return `[data-test-subj="checkboxSelectRow-${id}"]`;
|
||||
};
|
||||
|
||||
export const TIMELINES_FAVORITE = '[data-test-subj="favorite-starFilled-star"]';
|
||||
|
||||
export const TIMELINES_DESCRIPTION = '[data-test-subj="description"]';
|
||||
|
||||
export const TIMELINES_NOTES_COUNT = '[data-test-subj="notes-count"]';
|
||||
|
||||
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"]';
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
declare namespace Cypress {
|
||||
interface Chainable<Subject> {
|
||||
promisify(): Promise<Subject>;
|
||||
stubSecurityApi(dataFileName: string): Chainable<Subject>;
|
||||
stubSearchStrategyApi(dataFileName: string): Chainable<Subject>;
|
||||
attachFile(fileName: string, fileType?: string): Chainable<JQuery>;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
import 'cypress-promise/register';
|
||||
|
||||
Cypress.Cookies.defaults({
|
||||
preserve: 'sid',
|
||||
|
|
|
@ -55,7 +55,7 @@ import {
|
|||
EQL_TYPE,
|
||||
EQL_QUERY_INPUT,
|
||||
} from '../screens/create_new_rule';
|
||||
import { TIMELINE } from '../screens/timeline';
|
||||
import { TIMELINE } from '../screens/timelines';
|
||||
|
||||
export const createAndActivateRule = () => {
|
||||
cy.get(SCHEDULE_CONTINUE_BUTTON).click({ force: true });
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
|
||||
import { MAIN_PAGE, TIMELINE_TOGGLE_BUTTON } from '../screens/security_main';
|
||||
|
||||
export const openTimeline = () => {
|
||||
export const openTimelineUsingToggle = () => {
|
||||
cy.get(TIMELINE_TOGGLE_BUTTON).click();
|
||||
};
|
||||
|
||||
export const openTimelineIfClosed = () => {
|
||||
cy.get(MAIN_PAGE).then(($page) => {
|
||||
if ($page.find(TIMELINE_TOGGLE_BUTTON).length === 1) {
|
||||
openTimeline();
|
||||
openTimelineUsingToggle();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -4,36 +4,47 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { TimelineFilter } from '../objects/timeline';
|
||||
|
||||
import { ALL_CASES_CREATE_NEW_CASE_TABLE_BTN } from '../screens/all_cases';
|
||||
|
||||
import {
|
||||
BULK_ACTIONS,
|
||||
ADD_FILTER,
|
||||
ADD_NOTE_BUTTON,
|
||||
ATTACH_TIMELINE_TO_EXISTING_CASE_ICON,
|
||||
ATTACH_TIMELINE_TO_NEW_CASE_ICON,
|
||||
CASE,
|
||||
CLOSE_TIMELINE_BTN,
|
||||
CLOSE_NOTES_BTN,
|
||||
COMBO_BOX,
|
||||
CREATE_NEW_TIMELINE,
|
||||
EXPORT_TIMELINE_ACTION,
|
||||
TIMELINE_CHECKBOX,
|
||||
HEADER,
|
||||
ID_FIELD,
|
||||
ID_HEADER_FIELD,
|
||||
ID_TOGGLE_FIELD,
|
||||
NOTES_BUTTON,
|
||||
NOTES_TEXT_AREA,
|
||||
OPEN_TIMELINE_ICON,
|
||||
PIN_EVENT,
|
||||
REMOVE_COLUMN,
|
||||
RESET_FIELDS,
|
||||
SAVE_FILTER_BTN,
|
||||
SEARCH_OR_FILTER_CONTAINER,
|
||||
SERVER_SIDE_EVENT_COUNT,
|
||||
STAR_ICON,
|
||||
TIMELINE_CHANGES_IN_PROGRESS,
|
||||
TIMELINE_DESCRIPTION,
|
||||
TIMELINE_FIELDS_BUTTON,
|
||||
TIMELINE_FILTER_FIELD,
|
||||
TIMELINE_FILTER_OPERATOR,
|
||||
TIMELINE_FILTER_VALUE,
|
||||
TIMELINE_INSPECT_BUTTON,
|
||||
TIMELINE_SETTINGS_ICON,
|
||||
TIMELINE_TITLE,
|
||||
TIMELINES_TABLE,
|
||||
TIMESTAMP_TOGGLE_FIELD,
|
||||
TOGGLE_TIMELINE_EXPAND_EVENT,
|
||||
REMOVE_COLUMN,
|
||||
RESET_FIELDS,
|
||||
ATTACH_TIMELINE_TO_NEW_CASE_ICON,
|
||||
OPEN_TIMELINE_ICON,
|
||||
ATTACH_TIMELINE_TO_EXISTING_CASE_ICON,
|
||||
CASE,
|
||||
} from '../screens/timeline';
|
||||
import { TIMELINES_TABLE } from '../screens/timelines';
|
||||
|
||||
import { drag, drop } from '../tasks/common';
|
||||
|
||||
|
@ -49,6 +60,24 @@ export const addNameToTimeline = (name: string) => {
|
|||
cy.get(TIMELINE_TITLE).should('have.attr', 'value', name);
|
||||
};
|
||||
|
||||
export const addNotesToTimeline = (notes: string) => {
|
||||
cy.get(NOTES_BUTTON).click();
|
||||
cy.get(NOTES_TEXT_AREA).type(notes);
|
||||
cy.get(ADD_NOTE_BUTTON).click();
|
||||
};
|
||||
|
||||
export const addFilter = (filter: TimelineFilter) => {
|
||||
cy.get(ADD_FILTER).click();
|
||||
cy.get(TIMELINE_FILTER_FIELD).type(filter.field);
|
||||
cy.get(COMBO_BOX).contains(filter.field).click();
|
||||
cy.get(TIMELINE_FILTER_OPERATOR).type(filter.operator);
|
||||
cy.get(COMBO_BOX).contains(filter.operator).click();
|
||||
if (filter.operator !== 'exists') {
|
||||
cy.get(TIMELINE_FILTER_VALUE).type(`${filter.value}{enter}`);
|
||||
}
|
||||
cy.get(SAVE_FILTER_BTN).click();
|
||||
};
|
||||
|
||||
export const addNewCase = () => {
|
||||
cy.get(ALL_CASES_CREATE_NEW_CASE_TABLE_BTN).click();
|
||||
};
|
||||
|
@ -71,6 +100,10 @@ export const checkIdToggleField = () => {
|
|||
});
|
||||
};
|
||||
|
||||
export const closeNotes = () => {
|
||||
cy.get(CLOSE_NOTES_BTN).click();
|
||||
};
|
||||
|
||||
export const closeTimeline = () => {
|
||||
cy.get(CLOSE_TIMELINE_BTN).click({ force: true });
|
||||
};
|
||||
|
@ -89,10 +122,8 @@ export const expandFirstTimelineEventDetails = () => {
|
|||
cy.get(TOGGLE_TIMELINE_EXPAND_EVENT).first().click({ force: true });
|
||||
};
|
||||
|
||||
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 markAsFavorite = () => {
|
||||
cy.get(STAR_ICON).click();
|
||||
};
|
||||
|
||||
export const openTimelineFieldsBrowser = () => {
|
||||
|
@ -160,11 +191,11 @@ export const selectCase = (caseId: string) => {
|
|||
cy.get(CASE(caseId)).click();
|
||||
};
|
||||
|
||||
export const waitForTimelinesPanelToBeLoaded = () => {
|
||||
cy.get(TIMELINES_TABLE).should('exist');
|
||||
};
|
||||
|
||||
export const waitForTimelineChanges = () => {
|
||||
cy.get(TIMELINE_CHANGES_IN_PROGRESS).should('exist');
|
||||
cy.get(TIMELINE_CHANGES_IN_PROGRESS).should('not.exist');
|
||||
};
|
||||
|
||||
export const waitForTimelinesPanelToBeLoaded = () => {
|
||||
cy.get(TIMELINES_TABLE).should('exist');
|
||||
};
|
||||
|
|
27
x-pack/plugins/security_solution/cypress/tasks/timelines.ts
Normal file
27
x-pack/plugins/security_solution/cypress/tasks/timelines.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
TIMELINE_CHECKBOX,
|
||||
BULK_ACTIONS,
|
||||
EXPORT_TIMELINE_ACTION,
|
||||
TIMELINES_TABLE,
|
||||
TIMELINE,
|
||||
} from '../screens/timelines';
|
||||
|
||||
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) => {
|
||||
cy.get(TIMELINE(id)).click();
|
||||
};
|
||||
|
||||
export const waitForTimelinesPanelToBeLoaded = () => {
|
||||
cy.get(TIMELINES_TABLE).should('exist');
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
{
|
||||
"author": "Elastic",
|
||||
"name": "security_solution",
|
||||
"version": "8.0.0",
|
||||
|
|
|
@ -146,7 +146,7 @@ const AddDataProviderPopoverComponent: React.FC<AddDataProviderPopoverProps> = (
|
|||
<EuiButton
|
||||
size="s"
|
||||
onClick={handleOpenPopover}
|
||||
data-test-subj="addFilter"
|
||||
data-test-subj="addField"
|
||||
iconType="arrowDown"
|
||||
fill
|
||||
iconSide="right"
|
||||
|
@ -160,7 +160,7 @@ const AddDataProviderPopoverComponent: React.FC<AddDataProviderPopoverProps> = (
|
|||
<EuiButtonEmpty
|
||||
size="s"
|
||||
onClick={handleOpenPopover}
|
||||
data-test-subj="addFilter"
|
||||
data-test-subj="addField"
|
||||
iconSide="right"
|
||||
>
|
||||
<EuiText size="s">{`+ ${ADD_FIELD_LABEL}`}</EuiText>
|
||||
|
|
|
@ -376,7 +376,11 @@ const NotesButtonComponent = React.memo<NotesButtonProps>(
|
|||
)}
|
||||
{size === 'l' && showNotes ? (
|
||||
<EuiOverlayMask>
|
||||
<EuiModal maxWidth={NOTES_PANEL_WIDTH} onClose={toggleShowNotes}>
|
||||
<EuiModal
|
||||
data-test-subj="notesModal"
|
||||
maxWidth={NOTES_PANEL_WIDTH}
|
||||
onClose={toggleShowNotes}
|
||||
>
|
||||
<Notes
|
||||
associateNote={associateNote}
|
||||
getNewNoteId={getNewNoteId}
|
||||
|
|
|
@ -34,7 +34,7 @@ const exitIfIncorrectWorkingDir = () => {
|
|||
const exitIfTimesToRunIsInvalid = (timesToRun) => {
|
||||
if (!timesToRun > 0) {
|
||||
console.error(
|
||||
'\nERROR: You must specify a valid number of times to run the SIEM Cypress tests.'
|
||||
'\nERROR: You must specify a valid number of times to run the Security Solution Cypress tests.'
|
||||
);
|
||||
showUsage();
|
||||
process.exit(1);
|
||||
|
@ -44,7 +44,7 @@ const spawnChild = async () => {
|
|||
const child = spawn('node', [
|
||||
'scripts/functional_tests',
|
||||
'--config',
|
||||
'x-pack/test/security_solution_cypress/config.ts',
|
||||
'x-pack/test/security_solution_cypress/cli_config.ts',
|
||||
]);
|
||||
for await (const chunk of child.stdout) {
|
||||
console.log(chunk.toString());
|
||||
|
|
|
@ -9978,6 +9978,11 @@ cypress-multi-reporters@^1.2.3:
|
|||
debug "^4.1.1"
|
||||
lodash "^4.17.11"
|
||||
|
||||
cypress-promise@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cypress-promise/-/cypress-promise-1.1.0.tgz#f2d66965945fe198431aaf692d5157cea9d47b25"
|
||||
integrity sha512-DhIf5PJ/a0iY+Yii6n7Rbwq+9TJxU4pupXYzf9mZd8nPG0AzQrj9i+pqINv4xbI2EV1p+PKW3maCkR7oPG4GrA==
|
||||
|
||||
cypress@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-5.0.0.tgz#6957e299b790af8b1cd7bea68261b8935646f72e"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue