Skip to content

Commit

Permalink
[Investigations] Unskip dataproviders test (elastic#173183)
Browse files Browse the repository at this point in the history
## Summary

This PR unskips the tests for the timeline query builder dataProviders.
In this unskip a few things were tackled:

1. dataProviders were unskipped and the utilized tasks updated to work
with the new timeline ux
2. Two new tasks were added: `createTimelineOptionsPopoverBottomBar` and
`openTimelineByIdFromOpenTimelineModal`
3. All `force:true` were removed from the timeline tasks file
4. The `open_timeline`, `sourcerer_timeline`, and `query_tab` tests were
fixed against the new timeline ux as `force:true` was masking a bug in
how the cypress tests was written.

Resolves the following issues:

elastic#163622
elastic#164069
elastic#169396
elastic#156797

[Flaky Tests - Dec.
20](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4662)

---------

Co-authored-by: Jan Monschke <[email protected]>
  • Loading branch information
michaelolo24 and janmonschke authored Jan 17, 2024
1 parent a54e953 commit 9746bab
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
DEFAULT_INDEX_PATTERN,
} from '@kbn/security-solution-plugin/common/constants';

import { deleteTimelines } from '../../../../tasks/api_calls/common';
import { login } from '../../../../tasks/login';
import { visitWithTimeRange } from '../../../../tasks/navigation';

Expand Down Expand Up @@ -92,18 +93,15 @@ describe('Timeline scope', { tags: ['@ess', '@serverless', '@brokenInServerless'
});
});
describe('Alerts checkbox', () => {
before(() => {
beforeEach(() => {
login();
deleteTimelines();
createTimeline(getTimeline()).then((response) =>
cy.wrap(response.body.data.persistTimeline.timeline.savedObjectId).as('timelineId')
);
createTimeline(getTimelineModifiedSourcerer()).then((response) =>
cy.wrap(response.body.data.persistTimeline.timeline.savedObjectId).as('auditbeatTimelineId')
);
});

beforeEach(() => {
login();
visitWithTimeRange(TIMELINES_URL);
refreshUntilAlertsIndexExists();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,32 +22,27 @@ import {
updateDataProviderbyDraggingField,
addNameAndDescriptionToTimeline,
populateTimeline,
createNewTimeline,
createTimelineOptionsPopoverBottomBar,
updateDataProviderByFieldHoverAction,
saveTimeline,
} from '../../../tasks/timeline';
import { getTimeline } from '../../../objects/timeline';
import { hostsUrl } from '../../../urls/navigation';
import { scrollToBottom } from '../../../tasks/common';

// Failing in serverless
// FLAKY: https://github.com/elastic/kibana/issues/169396
describe.skip('timeline data providers', { tags: ['@ess', '@serverless'] }, () => {
describe('Timeline data providers', { tags: ['@ess', '@serverless'] }, () => {
beforeEach(() => {
login();
visitWithTimeRange(hostsUrl('allHosts'));
waitForAllHostsToBeLoaded();
scrollToBottom();
createNewTimeline();
createTimelineOptionsPopoverBottomBar();
addNameAndDescriptionToTimeline(getTimeline());
populateTimeline();
});

it('displays the data provider action menu when Enter is pressed', () => {
it('should display the data provider action menu when Enter is pressed', () => {
addDataProvider({ field: 'host.name', operator: 'exists' });

cy.get(TIMELINE_DATA_PROVIDERS_ACTION_MENU).should('not.exist');
cy.get(`${TIMELINE_FLYOUT_HEADER} ${TIMELINE_DROPPED_DATA_PROVIDERS}`).focus();
cy.get(`${TIMELINE_FLYOUT_HEADER} ${TIMELINE_DROPPED_DATA_PROVIDERS}`)
.first()
.parent()
Expand All @@ -56,22 +51,18 @@ describe.skip('timeline data providers', { tags: ['@ess', '@serverless'] }, () =
cy.get(TIMELINE_DATA_PROVIDERS_ACTION_MENU).should('exist');
});

it(
'persists timeline when data provider is updated by dragging a field from data grid',
{ tags: ['@brokenInServerless'] },
() => {
updateDataProviderbyDraggingField('host.name', 0);
saveTimeline();
cy.reload();
cy.get(`${GET_TIMELINE_GRID_CELL('host.name')}`)
.first()
.then((hostname) => {
cy.get(TIMELINE_DATA_PROVIDERS_CONTAINER).contains(`host.name: "${hostname.text()}"`);
});
}
);
it('should persist timeline when data provider is updated by dragging a field from data grid', () => {
updateDataProviderbyDraggingField('host.name', 0);
saveTimeline();
cy.reload();
cy.get(`${GET_TIMELINE_GRID_CELL('host.name')}`)
.first()
.then((hostname) => {
cy.get(TIMELINE_DATA_PROVIDERS_CONTAINER).contains(`host.name: "${hostname.text()}"`);
});
});

it('persists timeline when a field is added by hover action "Add To Timeline" in data provider ', () => {
it('should persist timeline when a field is added by hover action "Add To Timeline" in data provider ', () => {
addDataProvider({ field: 'host.name', operator: 'exists' });
saveTimeline();
updateDataProviderByFieldHoverAction('host.name', 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,17 @@ describe(
createNewTimeline();
// switch to old timeline
openTimelineFromSettings();
openTimelineById(timelineId);
cy.get(LOADING_INDICATOR).should('not.exist');
goToEsqlTab();
verifyDiscoverEsqlQuery(esqlQuery);
cy.get(GET_DISCOVER_DATA_GRID_CELL_HEADER(column1)).should('exist');
cy.get(GET_DISCOVER_DATA_GRID_CELL_HEADER(column2)).should('exist');
cy.get(GET_LOCAL_DATE_PICKER_START_DATE_POPOVER_BUTTON(DISCOVER_CONTAINER)).should(
'have.text',
INITIAL_START_DATE
);
openTimelineById(timelineId).then(() => {
cy.get(LOADING_INDICATOR).should('not.exist');
goToEsqlTab();
verifyDiscoverEsqlQuery(esqlQuery);
cy.get(GET_DISCOVER_DATA_GRID_CELL_HEADER(column1)).should('exist');
cy.get(GET_DISCOVER_DATA_GRID_CELL_HEADER(column2)).should('exist');
cy.get(GET_LOCAL_DATE_PICKER_START_DATE_POPOVER_BUTTON(DISCOVER_CONTAINER)).should(
'have.text',
INITIAL_START_DATE
);
});
});
});
it('should save/restore esql tab dataview/timerange/filter/query/columns when timeline is opened via url', () => {
Expand Down Expand Up @@ -164,10 +165,11 @@ describe(
createNewTimeline();
// switch to old timeline
openTimelineFromSettings();
openTimelineById(timelineId);
cy.get(LOADING_INDICATOR).should('not.exist');
goToEsqlTab();
cy.get(DISCOVER_DATA_VIEW_SWITCHER.BTN).should('not.exist');
openTimelineById(timelineId).then(() => {
cy.get(LOADING_INDICATOR).should('not.exist');
goToEsqlTab();
cy.get(DISCOVER_DATA_VIEW_SWITCHER.BTN).should('not.exist');
});
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,74 +14,57 @@ import {
TIMELINE_QUERY,
NOTE_CARD_CONTENT,
} from '../../../screens/timeline';
import { deleteTimelines } from '../../../tasks/api_calls/common';
import { addNoteToTimeline } from '../../../tasks/api_calls/notes';
import { createTimeline } from '../../../tasks/api_calls/timelines';

import { login } from '../../../tasks/login';
import { visit } from '../../../tasks/navigation';
import {
addFilter,
addNoteToFirstRowEvent,
openTimelineById,
pinFirstEvent,
refreshTimelinesUntilTimeLinePresent,
} from '../../../tasks/timeline';

import { TIMELINES_URL } from '../../../urls/navigation';

describe.skip('Timeline query tab', { tags: ['@ess', '@serverless'] }, () => {
before(() => {
const defaultTimeline = getTimeline();

describe('Timeline query tab', { tags: ['@ess', '@serverless'] }, () => {
beforeEach(() => {
login();
visit(TIMELINES_URL);
createTimeline(getTimeline())
deleteTimelines();
createTimeline(defaultTimeline)
.then((response) => response.body.data.persistTimeline.timeline.savedObjectId)
.then((timelineId: string) => {
refreshTimelinesUntilTimeLinePresent(timelineId)
// This cy.wait is here because we cannot do a pipe on a timeline as that will introduce multiple URL
// request responses and indeterminism since on clicks to activates URL's.
.then(() => cy.wrap(timelineId).as('timelineId'))
// eslint-disable-next-line cypress/no-unnecessary-waiting
.then(() => cy.wait(1000))
// TO-DO: Issue 163398
// .then(() =>
// addNoteToTimeline(getTimeline().notes, timelineId).should((response) =>
// expect(response.status).to.equal(200)
// )
// )
.then(() => openTimelineById(timelineId))
.then(() => pinFirstEvent())
// TO-DO: Issue 163398
// .then(() => persistNoteToFirstEvent('event note'))
.then(() => addFilter(getTimeline().filter));
cy.wrap(timelineId).as('timelineId');
addNoteToTimeline(defaultTimeline.notes, timelineId);
openTimelineById(timelineId);
pinFirstEvent();
addFilter(defaultTimeline.filter);
});
});

describe('Query tab', () => {
beforeEach(function () {
login();
visit(TIMELINES_URL);
openTimelineById(this.timelineId).then(() => addFilter(getTimeline().filter));
});

it('should contain the right query', () => {
cy.get(TIMELINE_QUERY).should('have.text', `${getTimeline().query}`);
});

// TO-DO: Issue 163398
it.skip('should be able to add event note', () => {
cy.get(NOTE_CARD_CONTENT).should('contain', 'event note');
});
it('should display the right query and filters', () => {
cy.get(TIMELINE_QUERY).should('have.text', `${defaultTimeline.query}`);
cy.get(TIMELINE_FILTER(defaultTimeline.filter)).should('exist');
});

it('should display timeline filter', () => {
cy.get(TIMELINE_FILTER(getTimeline().filter)).should('exist');
});
it('should be able to add event note', () => {
const note = 'event note';
addNoteToFirstRowEvent(note);
cy.get(NOTE_CARD_CONTENT).should('contain', 'event note');
});

it('should display pinned events', () => {
cy.get(PIN_EVENT)
.should('have.attr', 'aria-label')
.and('match', /Unpin the event in row 2/);
});
it('should display pinned events', () => {
cy.get(PIN_EVENT)
.should('have.attr', 'aria-label')
.and('match', /Unpin the event in row 2/);
});

it('should have an unlock icon', { tags: '@brokenInServerless' }, () => {
cy.get(UNLOCKED_ICON).should('be.visible');
});
it('should have an unlock icon', { tags: '@brokenInServerless' }, () => {
cy.get(UNLOCKED_ICON).should('be.visible');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export const LOCKED_ICON = '[data-test-subj="timeline-date-picker-lock-button"]'

export const UNLOCKED_ICON = '[data-test-subj="timeline-date-picker-unlock-button"]';

export const ROW_ADD_NOTES_BUTTON = '[data-test-subj="timeline-notes-button-small"]';

export const NOTE_CARD_CONTENT = '[data-test-subj="notes"]';

export const NOTE_DESCRIPTION = '[data-test-subj="note-preview-description"]';
Expand Down
36 changes: 22 additions & 14 deletions x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type { Timeline, TimelineFilter } from '../objects/timeline';

import { ALL_CASES_CREATE_NEW_CASE_TABLE_BTN } from '../screens/all_cases';
import { FIELDS_BROWSER_CHECKBOX } from '../screens/fields_browser';
import { LOADING_INDICATOR } from '../screens/security_header';
import { EQL_QUERY_VALIDATION_SPINNER } from '../screens/create_new_rule';

import {
Expand Down Expand Up @@ -65,7 +64,6 @@ import {
TIMELINE_COLLAPSED_ITEMS_BTN,
TIMELINE_TAB_CONTENT_EQL,
TIMESTAMP_HOVER_ACTION_OVERFLOW_BTN,
TIMELINE_DATA_PROVIDER_FIELD_INPUT,
ACTIVE_TIMELINE_BOTTOM_BAR,
EMPTY_DATA_PROVIDER_AREA,
EMPTY_DROPPABLE_DATA_PROVIDER_GROUP,
Expand All @@ -84,6 +82,8 @@ import {
TIMELINE_SEARCH_OR_FILTER,
TIMELINE_KQLMODE_FILTER,
TIMELINE_KQLMODE_SEARCH,
TIMELINE_DATA_PROVIDERS_CONTAINER,
ROW_ADD_NOTES_BUTTON,
TIMELINE_PANEL,
} from '../screens/timeline';

Expand Down Expand Up @@ -173,7 +173,6 @@ export const addNotesToTimeline = (notes: string) => {
.then((notesCount) => {
cy.get(NOTES_TEXT_AREA).type(notes, {
parseSpecialCharSequences: false,
force: true,
});

cy.get(ADD_NOTE_BUTTON).click();
Expand All @@ -183,6 +182,15 @@ export const addNotesToTimeline = (notes: string) => {
});
};

export const addNoteToFirstRowEvent = (notes: string) => {
cy.get(ROW_ADD_NOTES_BUTTON).first().click();
cy.get(NOTES_TEXT_AREA).type(notes, {
parseSpecialCharSequences: false,
});

cy.get(ADD_NOTE_BUTTON).click();
};

export const addEqlToTimeline = (eql: string) => {
goToCorrelationTab().then(() => {
cy.get(TIMELINE_CORRELATION_INPUT).type(eql);
Expand Down Expand Up @@ -217,19 +225,21 @@ export const changeTimelineQueryLanguage = (language: 'kuery' | 'lucene') => {
};

export const addDataProvider = (filter: TimelineFilter): Cypress.Chainable<JQuery<HTMLElement>> => {
cy.get(TOGGLE_DATA_PROVIDER_BTN).click();
cy.get(TIMELINE_DATA_PROVIDERS_CONTAINER).should('be.visible'); // Cypress doesn't properly wait for the data provider to finish expanding, so we wait for the animation to finish.
cy.get(TIMELINE_ADD_FIELD_BUTTON).click();
cy.get(LOADING_INDICATOR).should('not.exist');
cy.get('[data-popover-open]').should('exist');
cy.get(TIMELINE_DATA_PROVIDER_FIELD).click();
cy.get(TIMELINE_DATA_PROVIDER_FIELD)
.find(TIMELINE_DATA_PROVIDER_FIELD_INPUT)
.should('have.focus'); // make sure the focus is ready before start typing
cy.get(TIMELINE_DATA_PROVIDER_FIELD)
.find(COMBO_BOX_INPUT)
.type(`${filter.field}{downarrow}{enter}`);

cy.get(TIMELINE_DATA_PROVIDER_OPERATOR)
.find(`${COMBO_BOX_INPUT} input`)
.type(`{selectall}{backspace}{selectall}{backspace}`);

cy.get(TIMELINE_DATA_PROVIDER_OPERATOR)
.find(COMBO_BOX_INPUT)
.type(`${filter.operator}{downarrow}{enter}`);

if (filter.operator !== 'exists') {
cy.get(TIMELINE_DATA_PROVIDER_VALUE).type(`${filter.value}{enter}`);
}
Expand Down Expand Up @@ -260,7 +270,7 @@ export const updateDataProviderbyDraggingField = (fieldName: string, rowNumber:

export const updateDataProviderByFieldHoverAction = (fieldName: string, rowNumber: number) => {
const fieldSelector = GET_TIMELINE_GRID_CELL(fieldName);
cy.get(fieldSelector).eq(rowNumber).trigger('mouseover', { force: true });
cy.get(fieldSelector).eq(rowNumber).trigger('mouseover');
cy.get(HOVER_ACTIONS.ADD_TO_TIMELINE).should('be.visible');
recurse(
() => {
Expand Down Expand Up @@ -295,9 +305,7 @@ export const clickIdToggleField = () => {
clickIdHoverActionOverflowButton();
cy.get(ID_HEADER_FIELD).should('not.exist');

cy.get(ID_TOGGLE_FIELD).click({
force: true,
});
cy.get(ID_TOGGLE_FIELD).click();
};

export const closeTimeline = () => {
Expand All @@ -307,7 +315,7 @@ export const closeTimeline = () => {

export const createNewTimeline = () => {
cy.get(NEW_TIMELINE_ACTION).click();
cy.get(CREATE_NEW_TIMELINE).first().click();
cy.get(CREATE_NEW_TIMELINE).eq(0).click();
};

export const openCreateTimelineOptionsPopover = () => {
Expand Down

0 comments on commit 9746bab

Please sign in to comment.