Skip to content

Commit

Permalink
fix bug by doing cypress test
Browse files Browse the repository at this point in the history
  • Loading branch information
XavierM committed Sep 4, 2019
1 parent 8dce645 commit 7bb962a
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ export const ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS = `${ALL_HOSTS_WIDGET} ${ALL_HOSTS

/** Clicking this button displays the `Events` tab */
export const EVENTS_TAB_BUTTON = '[data-test-subj="navigation-events"]';

export const NAVIGATION_HOSTS_ALL_HOSTS = '[data-test-subj="navigation-link-allHosts"]';

export const NAVIGATION_HOSTS_ANOMALIES = '[data-test-subj="navigation-link-anomalies"]';
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ export const ABSOLUTE_DATE_RANGE = {
'/app/siem#/network/?kqlQuery=(filterQuery:!n,queryLocation:network.page)&timerange=(global:(linkTo:!(),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(),timerange:(from:1564776209186,kind:absolute,to:1564779809186)))',
urlKqlNetworkNetwork: `/app/siem#/network/?_g=()&kqlQuery=(filterQuery:(expression:'source.ip:%20"10.142.0.9"',kind:kuery),queryLocation:network.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))`,
urlKqlNetworkHosts: `/app/siem#/network/?_g=()&kqlQuery=(filterQuery:(expression:'source.ip:%20"10.142.0.9"',kind:kuery),queryLocation:hosts.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))`,
urlKqlHostsNetwork: `/app/siem#/hosts/?_g=()&kqlQuery=(filterQuery:(expression:'source.ip:%20"10.142.0.9"',kind:kuery),queryLocation:network.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))`,
urlKqlHostsHosts: `/app/siem#/hosts/?_g=()&kqlQuery=(filterQuery:(expression:'source.ip:%20"10.142.0.9"',kind:kuery),queryLocation:hosts.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))`,
urlKqlHostsNetwork: `/app/siem#/hosts/allHosts?_g=()&kqlQuery=(filterQuery:(expression:'source.ip:%20"10.142.0.9"',kind:kuery),queryLocation:network.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))`,
urlKqlHostsHosts: `/app/siem#/hosts/allHosts?_g=()&kqlQuery=(filterQuery:(expression:'source.ip:%20"10.142.0.9"',kind:kuery),queryLocation:hosts.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))`,
urlHost:
'/app/siem#/hosts/authentications?timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))',
};
export const DATE_PICKER_START_DATE_POPOVER_BUTTON =
'[data-test-subj="globalDatePicker"] [data-test-subj="superDatePickerstartDatePopoverButton"]';
'div[data-test-subj="globalDatePicker"] button[data-test-subj="superDatePickerstartDatePopoverButton"]';
export const DATE_PICKER_END_DATE_POPOVER_BUTTON =
'[data-test-subj="globalDatePicker"] [data-test-subj="superDatePickerendDatePopoverButton"]';
export const DATE_PICKER_START_DATE_POPOVER_BUTTON_TIMELINE =
Expand All @@ -56,3 +58,6 @@ export const DATE_PICKER_APPLY_BUTTON_TIMELINE =
export const DATE_PICKER_ABSOLUTE_INPUT = '[data-test-subj="superDatePickerAbsoluteDateInput"]';
export const KQL_INPUT = '[data-test-subj="kqlInput"]';
export const TIMELINE_TITLE = '[data-test-subj="timeline-title"]';

export const HOST_DETAIL_SIEM_KIBANA = '[data-test-subj="all-hosts"] a.euiLink';
export const BREADCRUMBS = '[data-test-subj="breadcrumbs"] a';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

/** The SIEM app's Hosts page */
export const HOSTS_PAGE = '/app/siem#/hosts';
export const HOSTS_PAGE = '/app/siem#/hosts/allHosts';

/** Kibana's login page */
export const LOGIN_PAGE = '/login';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { login } from '../login/helpers';

/** The default time in ms to wait for a Cypress command to complete */
export const DEFAULT_TIMEOUT = 30 * 1000;
export const DEFAULT_TIMEOUT = 50 * 1000;

/**
* Authenticates with Kibana, visits the specified `url`, and waits for the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
DATE_PICKER_START_DATE_POPOVER_BUTTON_TIMELINE,
KQL_INPUT,
TIMELINE_TITLE,
HOST_DETAIL_SIEM_KIBANA,
BREADCRUMBS,
} from '../../lib/url_state';
import { DEFAULT_TIMEOUT, loginAndWaitForPage } from '../../lib/util/helpers';
import {
Expand All @@ -25,8 +27,10 @@ import {
hostExistsQuery,
toggleTimelineVisibility,
} from '../../lib/timeline/helpers';
import { NAVIGATION_NETWORK } from '../../lib/navigation/selectors';
import { NAVIGATION_NETWORK, NAVIGATION_HOSTS } from '../../lib/navigation/selectors';
import { HOSTS_PAGE } from '../../lib/urls';
import { waitForAllHostsWidget } from '../../lib/hosts/helpers';
import { NAVIGATION_HOSTS_ALL_HOSTS, NAVIGATION_HOSTS_ANOMALIES } from '../../lib/hosts/selectors';

describe('url state', () => {
afterEach(() => {
Expand Down Expand Up @@ -190,6 +194,65 @@ describe('url state', () => {
);
});

it('sets the url state when kql is set and check if href reflect this change', () => {
loginAndWaitForPage(ABSOLUTE_DATE_RANGE.url);
cy.get(KQL_INPUT, { timeout: 5000 }).type('source.ip: "10.142.0.9" {enter}');
cy.get(NAVIGATION_HOSTS)
.first()
.click({ force: true });
cy.get(NAVIGATION_NETWORK).should(
'have.attr',
'href',
"#/link-to/network?kqlQuery=(filterQuery:(expression:'source.ip:%20%2210.142.0.9%22%20',kind:kuery),queryLocation:network.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))"
);
});

it('sets KQL in host page and detail page and check if href match on breadcrumb, tabs and subTabs', () => {
loginAndWaitForPage(ABSOLUTE_DATE_RANGE.urlHost);
cy.get(KQL_INPUT, { timeout: 5000 }).type('host.name: "siem-kibana" {enter}');
cy.get(NAVIGATION_HOSTS_ALL_HOSTS)
.first()
.click({ force: true });
waitForAllHostsWidget();
cy.get(HOST_DETAIL_SIEM_KIBANA, { timeout: 5000 })
.first()
.invoke('text')
.should('eq', 'siem-kibana');
cy.get(HOST_DETAIL_SIEM_KIBANA)
.first()
.click({ force: true });
cy.get(KQL_INPUT, { timeout: 5000 }).type('agent.type: "auditbeat" {enter}');
cy.get(NAVIGATION_HOSTS).should(
'have.attr',
'href',
"#/link-to/hosts?kqlQuery=(filterQuery:(expression:'host.name:%20%22siem-kibana%22%20',kind:kuery),queryLocation:hosts.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))"
);
cy.get(NAVIGATION_NETWORK).should(
'have.attr',
'href',
'#/link-to/network?timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))'
);
cy.get(NAVIGATION_HOSTS_ANOMALIES).should(
'have.attr',
'href',
"#/hosts/siem-kibana/anomalies?kqlQuery=(filterQuery:(expression:'agent.type:%20%22auditbeat%22%20',kind:kuery),queryLocation:hosts.details)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))"
);
cy.get(BREADCRUMBS)
.eq(1)
.should(
'have.attr',
'href',
"#/link-to/hosts?kqlQuery=(filterQuery:(expression:'host.name:%20%22siem-kibana%22%20',kind:kuery),queryLocation:hosts.page)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))"
);
cy.get(BREADCRUMBS)
.eq(2)
.should(
'have.attr',
'href',
"#/link-to/hosts/siem-kibana?kqlQuery=(filterQuery:(expression:'agent.type:%20%22auditbeat%22%20',kind:kuery),queryLocation:hosts.details)&timerange=(global:(linkTo:!(timeline),timerange:(from:1564689809186,kind:absolute,to:1564691609186)),timeline:(linkTo:!(global),timerange:(from:1564689809186,kind:absolute,to:1564691609186)))"
);
});

it('clears kql when navigating to a new page', () => {
loginAndWaitForPage(ABSOLUTE_DATE_RANGE.urlKqlHostsHosts);
cy.get(NAVIGATION_NETWORK).click({ force: true });
Expand All @@ -202,17 +265,10 @@ describe('url state', () => {
executeKQL(hostExistsQuery);
assertAtLeastOneEventMatchesSearch();
const bestTimelineName = 'The Best Timeline';
cy.get(TIMELINE_TITLE).type(bestTimelineName);
cy.hash().then(hash => {
const matched = hash.match(/(?<=timelineId=\').+?(?=\')/g);
const newTimelineId = matched && matched.length > 0 ? matched[0] : 'null';
expect(matched).to.have.lengthOf(1);
cy.log('hash', hash);
cy.log('matched', matched);
cy.log('newTimelineId', newTimelineId);
cy.visit(
`/app/siem#/timelines?timelineId='${newTimelineId}'&timerange=(global:(linkTo:!(),timerange:(from:1565274377369,kind:absolute,to:1565360777369)),timeline:(linkTo:!(),timerange:(from:1565274377369,kind:absolute,to:1565360777369)))`
).then(() => cy.get(TIMELINE_TITLE).should('have.attr', 'value', bestTimelineName));
});
cy.get(TIMELINE_TITLE, { timeout: 5000 }).type(bestTimelineName);
cy.url().should('include', 'timelineId=');
cy.visit(
`/app/siem#/timelines?timerange=(global:(linkTo:!(),timerange:(from:1565274377369,kind:absolute,to:1565360777369)),timeline:(linkTo:!(),timerange:(from:1565274377369,kind:absolute,to:1565360777369)))`
).then(() => cy.get(TIMELINE_TITLE).should('have.attr', 'value', bestTimelineName));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const RedirectToNetworkPage = ({
},
location: { search },
}: NetworkComponentProps) => (
<RedirectWrapper to={detailName ? `/network/ip/${detailName}${search}` : `/network/${search}`} />
<RedirectWrapper to={detailName ? `/network/ip/${detailName}${search}` : `/network${search}`} />
);

export const getNetworkUrl = () => '#/link-to/network';
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export const UrlStateContainer = React.memo<UrlStateContainerPropTypes>(
return null;
},
(prevProps, nextProps) =>
prevProps.pathName === nextProps.pathName && isEqual(prevProps.urlState, nextProps.urlState)
prevProps.pageName === nextProps.pageName &&
prevProps.pathName === nextProps.pathName &&
isEqual(prevProps.urlState, nextProps.urlState)
);

UrlStateContainer.displayName = 'UrlStateContainer';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ export const useUrlStateHooks = ({
search,
state: '',
};

if (isInitializing && pageName != null && pageName !== '') {
handleInitialize(location, type);
setIsInitializing(false);
Expand Down
2 changes: 1 addition & 1 deletion x-pack/legacy/plugins/siem/public/pages/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export const HomePage = pure(() => (
</EuiFlexGroup>
</NavGlobal>
<Switch>
<Redirect from="/" exact={true} to="/:pageName(overview)" />
<Redirect from="/" exact={true} to="/overview" />
<Route path="/:pageName(overview)" render={() => <Overview />} />
<Route path="/:pageName(hosts)" component={HostsContainer} />
<Route path="/:pageName(network)" component={NetworkContainer} />
Expand Down
23 changes: 23 additions & 0 deletions x-pack/legacy/plugins/siem/public/pages/home/translations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 { i18n } from '@kbn/i18n';

export const OVERVIEW = i18n.translate('xpack.siem.navigation.overview', {
defaultMessage: 'Overview',
});

export const HOSTS = i18n.translate('xpack.siem.navigation.hosts', {
defaultMessage: 'Hosts',
});

export const NETWORK = i18n.translate('xpack.siem.navigation.network', {
defaultMessage: 'Network',
});

export const TIMELINES = i18n.translate('xpack.siem.navigation.timelines', {
defaultMessage: 'Timelines',
});
21 changes: 12 additions & 9 deletions x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,17 @@ export const HostsContainer = pure<HostComponentProps>(({ match }) => (
<Route
path={hostsPagePath}
render={() => (
<HostsBody
from={from}
to={to}
setQuery={setQuery}
isInitializing={isInitializing}
{...props}
children={HostsQueryTabBody}
/>
<>
<Hosts from={from} to={to} setQuery={setQuery} isInitializing={isInitializing} />
<HostsBody
from={from}
to={to}
setQuery={setQuery}
isInitializing={isInitializing}
{...props}
children={HostsQueryTabBody}
/>
</>
)}
/>
)}
Expand Down Expand Up @@ -224,7 +227,7 @@ export const HostsContainer = pure<HostComponentProps>(({ match }) => (
from={`${match.url}/:detailName`}
to={`${match.url}/:detailName/${HostsTableType.authentications}`}
/>
<Redirect from="/hosts/" to="/hosts" />
<Redirect from="/hosts/" to={`/hosts/${HostsTableType.hosts}`} />
</Switch>
)}
</GlobalTime>
Expand Down
76 changes: 61 additions & 15 deletions x-pack/legacy/plugins/siem/public/utils/route/spy_routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@
*/

import * as H from 'history';
import React, { createContext, memo, useContext, useEffect, Dispatch, useReducer } from 'react';
import React, {
createContext,
memo,
useContext,
useEffect,
Dispatch,
useReducer,
useState,
} from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';
import { noop } from 'redux-saga/utils';
import { isEqual } from 'lodash/fp';
Expand All @@ -28,10 +36,19 @@ const initRouteSpy: RouteSpyState = {
pathName: '/',
};

export interface RouteSpyAction {
type: 'updateRoute';
route: RouteSpyState;
}
export type RouteSpyAction =
| {
type: 'updateSearch';
search: string;
}
| {
type: 'updateRouteWithOutSearch';
route: Pick<RouteSpyState, 'pageName' & 'detailName' & 'tabName' & 'pathName' & 'history'>;
}
| {
type: 'updateRoute';
route: RouteSpyState;
};

export const RouterSpyStateContext = createContext<[RouteSpyState, Dispatch<RouteSpyAction>]>([
initRouteSpy,
Expand All @@ -49,6 +66,10 @@ export const ManageRoutesSpy = ({ children }: ManageRoutesSpyProps) => {
switch (action.type) {
case 'updateRoute':
return action.route;
case 'updateRouteWithOutSearch':
return { ...state, ...action.route };
case 'updateSearch':
return { ...state, search: action.search };
default:
return state;
}
Expand Down Expand Up @@ -76,20 +97,45 @@ const SpyRouteComponent = memo<SpyRouteProps & { location: Location }>(
params: { pageName, detailName, tabName },
},
}) => {
const [isInitializing, setIsnitializing] = useState(true);
const [route, dispatch] = useRouteSpy();

useEffect(() => {
if (pageName && !isEqual(route.pathName, pathname)) {
if (isInitializing && search !== '') {
dispatch({
type: 'updateRoute',
route: {
pageName,
detailName,
tabName,
search,
pathName: pathname,
history,
},
type: 'updateSearch',
search,
});
setIsnitializing(false);
}
}, [search]);
useEffect(() => {
if (pageName && !isEqual(route.pathName, pathname)) {
if (isInitializing) {
dispatch({
type: 'updateRouteWithOutSearch',
route: {
pageName,
detailName,
tabName,
pathName: pathname,
history,
},
});
setIsnitializing(false);
} else {
dispatch({
type: 'updateRoute',
route: {
pageName,
detailName,
tabName,
search,
pathName: pathname,
history,
},
});
}
}
}, [pathname, search, pageName, detailName, tabName]);
return null;
Expand Down

0 comments on commit 7bb962a

Please sign in to comment.