Merge remote-tracking branch 'origin/master' into feature/merge-code
This commit is contained in:
commit
2bba2bbd38
|
@ -463,7 +463,7 @@ To include your change in the Release Notes:
|
||||||
* For a new feature or functionality, use `release_note:enhancement`.
|
* For a new feature or functionality, use `release_note:enhancement`.
|
||||||
* For an external-facing fix, use `release_note:fix`. Exception: docs, build, and test fixes do not go in the Release Notes.
|
* For an external-facing fix, use `release_note:fix`. Exception: docs, build, and test fixes do not go in the Release Notes.
|
||||||
* For a deprecated feature, use `release_note:deprecation`.
|
* For a deprecated feature, use `release_note:deprecation`.
|
||||||
* For a breaking change, use `release-breaking:note`.
|
* For a breaking change, use `release_note:breaking`.
|
||||||
|
|
||||||
To NOT include your changes in the Release Notes, please use label`non-issue`. PRs with the following labels also won't be included in the Release Notes:
|
To NOT include your changes in the Release Notes, please use label`non-issue`. PRs with the following labels also won't be included in the Release Notes:
|
||||||
`build`, `docs`, `test`, `non-issue`, `jenkins`, `backport`, and `chore`.
|
`build`, `docs`, `test`, `non-issue`, `jenkins`, `backport`, and `chore`.
|
||||||
|
|
|
@ -38,10 +38,13 @@ continue by reindexing fewer indices at a time.
|
||||||
|
|
||||||
Additional considerations:
|
Additional considerations:
|
||||||
|
|
||||||
* During a reindex of a Watcher (`.watches`) index, the Watcher process
|
* If you use {alert-features}, when you reindex the internal indices
|
||||||
pauses and no alerts are triggered.
|
(`.watches`), the {watcher} process pauses and no alerts are triggered.
|
||||||
|
|
||||||
* During a reindex of a Machine Learning (`.ml-state`) index, the Machine
|
|
||||||
Learning job pauses and models are not trained or updated.
|
|
||||||
|
|
||||||
|
* If you use {ml-features}, when you reindex the internal indices (`.ml-state`),
|
||||||
|
the {ml} jobs pause and models are not trained or updated.
|
||||||
|
|
||||||
|
* If you use {security-features}, before you reindex the internal indices
|
||||||
|
(`.security*`), it is a good idea to create a temporary superuser account in the
|
||||||
|
`file` realm. For more information, see
|
||||||
|
{ref}/configuring-file-realm.html[Configuring a file realm].
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elastic/datemath": "5.0.2",
|
"@elastic/datemath": "5.0.2",
|
||||||
"@elastic/eui": "9.2.1",
|
"@elastic/eui": "9.4.0",
|
||||||
"@elastic/filesaver": "1.1.2",
|
"@elastic/filesaver": "1.1.2",
|
||||||
"@elastic/good": "8.1.1-kibana2",
|
"@elastic/good": "8.1.1-kibana2",
|
||||||
"@elastic/numeral": "2.3.2",
|
"@elastic/numeral": "2.3.2",
|
||||||
|
|
|
@ -82,7 +82,7 @@ It allows you to monitor the performance of thousands of applications in real ti
|
||||||
'{config.docs.base_url}guide/en/apm/get-started/{config.docs.version}/index.html',
|
'{config.docs.base_url}guide/en/apm/get-started/{config.docs.version}/index.html',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
euiIconType: 'apmApp',
|
euiIconType: 'logoAPM',
|
||||||
artifacts: artifacts,
|
artifacts: artifacts,
|
||||||
onPrem: onPremInstructions(config),
|
onPrem: onPremInstructions(config),
|
||||||
elasticCloud: createElasticCloudInstructions(config),
|
elasticCloud: createElasticCloudInstructions(config),
|
||||||
|
|
|
@ -43,7 +43,7 @@ export function natsLogsSpecProvider(server, context) {
|
||||||
learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-nats.html',
|
learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-nats.html',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
euiIconType: 'logoNats',
|
// euiIconType: 'logoNats',
|
||||||
artifacts: {
|
artifacts: {
|
||||||
dashboards: [
|
dashboards: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,7 @@ export function natsMetricsSpecProvider(server, context) {
|
||||||
learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-nats.html',
|
learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-nats.html',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
euiIconType: 'logoNats',
|
// euiIconType: 'logoNats',
|
||||||
artifacts: {
|
artifacts: {
|
||||||
dashboards: [
|
dashboards: [
|
||||||
{
|
{
|
||||||
|
|
1
src/legacy/ui/public/chrome/api/nav.d.ts
vendored
1
src/legacy/ui/public/chrome/api/nav.d.ts
vendored
|
@ -28,6 +28,7 @@ export interface NavLink {
|
||||||
subUrlBase: string;
|
subUrlBase: string;
|
||||||
id: string;
|
id: string;
|
||||||
euiIconType: IconType;
|
euiIconType: IconType;
|
||||||
|
icon?: string;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
lastSubUrl?: string;
|
lastSubUrl?: string;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
|
|
||||||
import Url from 'url';
|
import Url from 'url';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import React, { Component, createRef, Fragment } from 'react';
|
||||||
import React, { Component, Fragment } from 'react';
|
|
||||||
import * as Rx from 'rxjs';
|
import * as Rx from 'rxjs';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -39,16 +38,14 @@ import {
|
||||||
EuiHideFor,
|
EuiHideFor,
|
||||||
EuiHorizontalRule,
|
EuiHorizontalRule,
|
||||||
EuiIcon,
|
EuiIcon,
|
||||||
EuiListGroup,
|
// @ts-ignore
|
||||||
|
EuiImage,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
EuiListGroupItem,
|
EuiListGroupItem,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
EuiNavDrawer,
|
EuiNavDrawer,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
EuiNavDrawerFlyout,
|
EuiNavDrawerGroup,
|
||||||
// @ts-ignore
|
|
||||||
EuiNavDrawerMenu,
|
|
||||||
EuiOutsideClickDetector,
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
EuiShowFor,
|
EuiShowFor,
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
|
@ -79,6 +76,11 @@ interface Props {
|
||||||
intl: InjectedIntl;
|
intl: InjectedIntl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Providing a buffer between the limit and the cut off index
|
||||||
|
// protects from truncating just the last couple (6) characters
|
||||||
|
const TRUNCATE_LIMIT: number = 64;
|
||||||
|
const TRUNCATE_AT: number = 58;
|
||||||
|
|
||||||
function extendRecentlyAccessedHistoryItem(
|
function extendRecentlyAccessedHistoryItem(
|
||||||
navLinks: NavLink[],
|
navLinks: NavLink[],
|
||||||
recentlyAccessed: RecentlyAccessedHistoryItem
|
recentlyAccessed: RecentlyAccessedHistoryItem
|
||||||
|
@ -115,16 +117,15 @@ function findClosestAnchor(element: HTMLElement): HTMLAnchorElement | void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function truncateRecentItemLabel(label: string): string {
|
||||||
|
if (label.length > TRUNCATE_LIMIT) {
|
||||||
|
label = `${label.substring(0, TRUNCATE_AT)}…`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
isCollapsed: boolean;
|
|
||||||
flyoutIsCollapsed: boolean;
|
|
||||||
flyoutIsAnimating: boolean;
|
|
||||||
navFlyoutTitle: string;
|
|
||||||
navFlyoutContent: [];
|
|
||||||
mobileIsHidden: boolean;
|
|
||||||
showScrollbar: boolean;
|
|
||||||
outsideClickDisabled: boolean;
|
|
||||||
isManagingFocus: boolean;
|
|
||||||
navLinks: Array<ReturnType<typeof extendNavLink>>;
|
navLinks: Array<ReturnType<typeof extendNavLink>>;
|
||||||
recentlyAccessed: Array<ReturnType<typeof extendRecentlyAccessedHistoryItem>>;
|
recentlyAccessed: Array<ReturnType<typeof extendRecentlyAccessedHistoryItem>>;
|
||||||
forceNavigation: boolean;
|
forceNavigation: boolean;
|
||||||
|
@ -132,23 +133,12 @@ interface State {
|
||||||
|
|
||||||
class HeaderUI extends Component<Props, State> {
|
class HeaderUI extends Component<Props, State> {
|
||||||
private subscription?: Rx.Subscription;
|
private subscription?: Rx.Subscription;
|
||||||
private timeoutID?: ReturnType<typeof setTimeout>;
|
private navDrawerRef = createRef<EuiNavDrawer>();
|
||||||
private timeoutExpand?: ReturnType<typeof setTimeout>;
|
|
||||||
private timeoutScrollbar?: ReturnType<typeof setTimeout>;
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isCollapsed: true,
|
|
||||||
flyoutIsCollapsed: true,
|
|
||||||
flyoutIsAnimating: false,
|
|
||||||
navFlyoutTitle: '',
|
|
||||||
navFlyoutContent: [],
|
|
||||||
mobileIsHidden: true,
|
|
||||||
showScrollbar: false,
|
|
||||||
outsideClickDisabled: true,
|
|
||||||
isManagingFocus: false,
|
|
||||||
navLinks: [],
|
navLinks: [],
|
||||||
recentlyAccessed: [],
|
recentlyAccessed: [],
|
||||||
forceNavigation: false,
|
forceNavigation: false,
|
||||||
|
@ -197,14 +187,17 @@ class HeaderUI extends Component<Props, State> {
|
||||||
|
|
||||||
public renderMenuTrigger() {
|
public renderMenuTrigger() {
|
||||||
return (
|
return (
|
||||||
<EuiHeaderSectionItemButton aria-label="Toggle side navigation" onClick={this.toggleOpen}>
|
<EuiHeaderSectionItemButton
|
||||||
|
aria-label="Toggle side navigation"
|
||||||
|
onClick={() => this.navDrawerRef.current.toggleOpen()}
|
||||||
|
>
|
||||||
<EuiIcon type="apps" size="m" />
|
<EuiIcon type="apps" size="m" />
|
||||||
</EuiHeaderSectionItemButton>
|
</EuiHeaderSectionItemButton>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { appTitle, breadcrumbs$, isVisible, navControls, helpExtension$ } = this.props;
|
const { appTitle, breadcrumbs$, isVisible, navControls, helpExtension$, intl } = this.props;
|
||||||
const { navLinks, recentlyAccessed } = this.state;
|
const { navLinks, recentlyAccessed } = this.state;
|
||||||
|
|
||||||
if (!isVisible) {
|
if (!isVisible) {
|
||||||
|
@ -214,6 +207,52 @@ class HeaderUI extends Component<Props, State> {
|
||||||
const leftNavControls = navControls.bySide[NavControlSide.Left];
|
const leftNavControls = navControls.bySide[NavControlSide.Left];
|
||||||
const rightNavControls = navControls.bySide[NavControlSide.Right];
|
const rightNavControls = navControls.bySide[NavControlSide.Right];
|
||||||
|
|
||||||
|
let navLinksArray = navLinks.map(navLink =>
|
||||||
|
navLink.hidden
|
||||||
|
? null
|
||||||
|
: {
|
||||||
|
key: navLink.id,
|
||||||
|
label: navLink.title,
|
||||||
|
href: navLink.href,
|
||||||
|
iconType: navLink.euiIconType,
|
||||||
|
icon:
|
||||||
|
!navLink.euiIconType && navLink.icon ? (
|
||||||
|
<EuiImage size="s" alt="" aria-hidden={true} url={`/${navLink.icon}`} />
|
||||||
|
) : (
|
||||||
|
undefined
|
||||||
|
),
|
||||||
|
isActive: navLink.active,
|
||||||
|
'data-test-subj': 'navDrawerAppsMenuLink',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// filter out the null items
|
||||||
|
navLinksArray = navLinksArray.filter(item => item !== null);
|
||||||
|
|
||||||
|
const recentLinksArray = [
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'common.ui.chrome.sideGlobalNav.viewRecentItemsLabel',
|
||||||
|
defaultMessage: 'Recently viewed',
|
||||||
|
}),
|
||||||
|
iconType: 'clock',
|
||||||
|
isDisabled: recentlyAccessed.length > 0 ? false : true,
|
||||||
|
flyoutMenu: {
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'common.ui.chrome.sideGlobalNav.viewRecentItemsFlyoutTitle',
|
||||||
|
defaultMessage: 'Recent items',
|
||||||
|
}),
|
||||||
|
listItems: recentlyAccessed.map(item => ({
|
||||||
|
label: truncateRecentItemLabel(item.label),
|
||||||
|
// TODO: Add what type of app/saved object to title attr
|
||||||
|
title: `${item.label}`,
|
||||||
|
'aria-label': item.label,
|
||||||
|
href: item.href,
|
||||||
|
iconType: item.euiIconType,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<EuiHeader>
|
<EuiHeader>
|
||||||
|
@ -238,85 +277,11 @@ class HeaderUI extends Component<Props, State> {
|
||||||
</EuiHeaderSection>
|
</EuiHeaderSection>
|
||||||
</EuiHeader>
|
</EuiHeader>
|
||||||
|
|
||||||
<EuiOutsideClickDetector
|
<EuiNavDrawer ref={this.navDrawerRef} data-test-subj="navDrawer">
|
||||||
onOutsideClick={() => this.collapseDrawer()}
|
<EuiNavDrawerGroup listItems={recentLinksArray} />
|
||||||
isDisabled={this.state.outsideClickDisabled}
|
<EuiHorizontalRule margin="none" />
|
||||||
>
|
<EuiNavDrawerGroup data-test-subj="navDrawerAppsMenu" listItems={navLinksArray} />
|
||||||
<EuiNavDrawer
|
</EuiNavDrawer>
|
||||||
isCollapsed={this.state.isCollapsed}
|
|
||||||
flyoutIsCollapsed={this.state.flyoutIsCollapsed}
|
|
||||||
flyoutIsAnimating={this.state.flyoutIsAnimating}
|
|
||||||
onMouseEnter={this.expandDrawer}
|
|
||||||
onFocus={this.expandDrawer}
|
|
||||||
onBlur={this.focusOut}
|
|
||||||
onMouseLeave={this.collapseDrawer}
|
|
||||||
mobileIsHidden={this.state.mobileIsHidden}
|
|
||||||
showScrollbar={this.state.showScrollbar}
|
|
||||||
data-test-subj={classNames(
|
|
||||||
'navDrawer',
|
|
||||||
this.state.flyoutIsAnimating
|
|
||||||
? null
|
|
||||||
: this.state.isCollapsed
|
|
||||||
? 'collapsed'
|
|
||||||
: 'expanded'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<EuiNavDrawerMenu id="navDrawerMenu" onClick={this.onNavClick}>
|
|
||||||
<EuiListGroup>
|
|
||||||
<EuiListGroupItem
|
|
||||||
label="Recently viewed"
|
|
||||||
iconType="clock"
|
|
||||||
size="s"
|
|
||||||
style={{ color: 'inherit' }}
|
|
||||||
aria-label="Recently viewed items"
|
|
||||||
onClick={() => this.expandFlyout()}
|
|
||||||
isDisabled={recentlyAccessed.length > 0 ? false : true}
|
|
||||||
extraAction={{
|
|
||||||
color: 'subdued',
|
|
||||||
iconType: 'arrowRight',
|
|
||||||
iconSize: 's',
|
|
||||||
'aria-label': 'Expand to view recent apps and objects',
|
|
||||||
onClick: () => this.expandFlyout(),
|
|
||||||
alwaysShow: true,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</EuiListGroup>
|
|
||||||
<EuiHorizontalRule margin="none" />
|
|
||||||
<EuiListGroup data-test-subj="appsMenu">
|
|
||||||
{navLinks.map(navLink =>
|
|
||||||
navLink.hidden ? null : (
|
|
||||||
<EuiListGroupItem
|
|
||||||
key={navLink.id}
|
|
||||||
label={navLink.title}
|
|
||||||
href={navLink.href}
|
|
||||||
iconType={navLink.euiIconType}
|
|
||||||
size="s"
|
|
||||||
style={{ color: 'inherit' }}
|
|
||||||
aria-label={navLink.title}
|
|
||||||
isActive={navLink.active}
|
|
||||||
data-test-subj="appLink"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</EuiListGroup>
|
|
||||||
</EuiNavDrawerMenu>
|
|
||||||
<EuiNavDrawerFlyout
|
|
||||||
id="navDrawerFlyout"
|
|
||||||
title="Recent items"
|
|
||||||
isCollapsed={this.state.flyoutIsCollapsed}
|
|
||||||
listItems={recentlyAccessed.map(item => ({
|
|
||||||
label: item.label,
|
|
||||||
href: item.href,
|
|
||||||
iconType: item.euiIconType,
|
|
||||||
size: 's',
|
|
||||||
style: { color: 'inherit' },
|
|
||||||
'aria-label': item.label,
|
|
||||||
}))}
|
|
||||||
onMouseLeave={this.collapseFlyout}
|
|
||||||
wrapText={true}
|
|
||||||
/>
|
|
||||||
</EuiNavDrawer>
|
|
||||||
</EuiOutsideClickDetector>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -361,120 +326,6 @@ class HeaderUI extends Component<Props, State> {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private toggleOpen = () => {
|
|
||||||
this.setState({
|
|
||||||
mobileIsHidden: !this.state.mobileIsHidden,
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({
|
|
||||||
outsideClickDisabled: this.state.mobileIsHidden ? true : false,
|
|
||||||
});
|
|
||||||
}, this.getTimeoutMs(350));
|
|
||||||
};
|
|
||||||
|
|
||||||
private expandDrawer = () => {
|
|
||||||
this.timeoutExpand = setTimeout(() => {
|
|
||||||
this.setState({
|
|
||||||
isCollapsed: false,
|
|
||||||
});
|
|
||||||
}, this.getTimeoutMs(750));
|
|
||||||
|
|
||||||
this.timeoutScrollbar = setTimeout(() => {
|
|
||||||
this.setState({
|
|
||||||
showScrollbar: true,
|
|
||||||
});
|
|
||||||
}, this.getTimeoutMs(1200));
|
|
||||||
|
|
||||||
// This prevents the drawer from collapsing when tabbing through children
|
|
||||||
// by clearing the timeout thus cancelling the onBlur event (see focusOut).
|
|
||||||
// This means isManagingFocus remains true as long as a child element
|
|
||||||
// has focus. This is the case since React bubbles up onFocus and onBlur
|
|
||||||
// events from the child elements.
|
|
||||||
|
|
||||||
if (this.timeoutID) {
|
|
||||||
clearTimeout(this.timeoutID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.state.isManagingFocus) {
|
|
||||||
this.setState({
|
|
||||||
isManagingFocus: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private collapseDrawer = () => {
|
|
||||||
// Stop the expand animation
|
|
||||||
if (this.timeoutExpand) {
|
|
||||||
clearTimeout(this.timeoutExpand);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.timeoutScrollbar) {
|
|
||||||
clearTimeout(this.timeoutScrollbar);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
flyoutIsAnimating: false,
|
|
||||||
isCollapsed: true,
|
|
||||||
flyoutIsCollapsed: true,
|
|
||||||
mobileIsHidden: true,
|
|
||||||
showScrollbar: false,
|
|
||||||
outsideClickDisabled: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Scrolls the menu and flyout back to top when the nav drawer collapses
|
|
||||||
const menuEl = document.getElementById('navDrawerMenu');
|
|
||||||
if (menuEl) {
|
|
||||||
menuEl.scrollTop = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const flyoutEl = document.getElementById('navDrawerFlyout');
|
|
||||||
if (flyoutEl) {
|
|
||||||
flyoutEl.scrollTop = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private focusOut = () => {
|
|
||||||
// This collapses the drawer when no children have focus (i.e. tabbed out).
|
|
||||||
// In other words, if focus does not bubble up from a child element, then
|
|
||||||
// the drawer will collapse. See the corresponding block in expandDrawer
|
|
||||||
// (called by onFocus) which cancels this operation via clearTimeout.
|
|
||||||
this.timeoutID = setTimeout(() => {
|
|
||||||
if (this.state.isManagingFocus) {
|
|
||||||
this.setState({
|
|
||||||
isManagingFocus: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.collapseDrawer();
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
private expandFlyout = () => {
|
|
||||||
this.setState(() => ({
|
|
||||||
flyoutIsCollapsed: !this.state.flyoutIsCollapsed,
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
flyoutIsAnimating: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
private collapseFlyout = () => {
|
|
||||||
this.setState({ flyoutIsAnimating: true });
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({
|
|
||||||
flyoutIsCollapsed: true,
|
|
||||||
});
|
|
||||||
}, this.getTimeoutMs(250));
|
|
||||||
};
|
|
||||||
|
|
||||||
private getTimeoutMs = (defaultTimeout: number) => {
|
|
||||||
const uiSettings = chrome.getUiSettingsClient();
|
|
||||||
return uiSettings.get('accessibility:disableAnimations') ? 0 : defaultTimeout;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Header = injectI18n(HeaderUI);
|
export const Header = injectI18n(HeaderUI);
|
||||||
|
|
|
@ -283,7 +283,7 @@ export default function ({ getService, getPageObjects }) {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await pieChart.expectPieSliceCount(5);
|
await pieChart.expectPieSliceCount(5);
|
||||||
|
|
||||||
await PageObjects.visualize.saveVisualization('Rendering Test: animal sounds pie');
|
await PageObjects.visualize.saveVisualizationExpectSuccess('Rendering Test: animal sounds pie');
|
||||||
await PageObjects.header.clickDashboard();
|
await PageObjects.header.clickDashboard();
|
||||||
|
|
||||||
await pieChart.expectPieSliceCount(5);
|
await pieChart.expectPieSliceCount(5);
|
||||||
|
|
|
@ -22,22 +22,19 @@ import { FtrProviderContext } from '../ftr_provider_context';
|
||||||
export function AppsMenuProvider({ getService }: FtrProviderContext) {
|
export function AppsMenuProvider({ getService }: FtrProviderContext) {
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const log = getService('log');
|
const log = getService('log');
|
||||||
const retry = getService('retry');
|
|
||||||
const globalNav = getService('globalNav');
|
|
||||||
|
|
||||||
return new class AppsMenu {
|
return new class AppsMenu {
|
||||||
/**
|
/**
|
||||||
* Get the text and href from each of the links in the apps menu
|
* Get the text and href from each of the links in the apps menu
|
||||||
*/
|
*/
|
||||||
public async readLinks() {
|
public async readLinks() {
|
||||||
await this.ensureMenuOpen();
|
const appMenu = await testSubjects.find('navDrawer');
|
||||||
const appMenu = await testSubjects.find('navDrawer&expanded appsMenu');
|
|
||||||
const $ = await appMenu.parseDomContent();
|
const $ = await appMenu.parseDomContent();
|
||||||
|
|
||||||
const links: Array<{
|
const links: Array<{
|
||||||
text: string;
|
text: string;
|
||||||
href: string;
|
href: string;
|
||||||
}> = $.findTestSubjects('appLink')
|
}> = $.findTestSubjects('navDrawerAppsMenuLink')
|
||||||
.toArray()
|
.toArray()
|
||||||
.map((link: any) => {
|
.map((link: any) => {
|
||||||
return {
|
return {
|
||||||
|
@ -46,7 +43,6 @@ export function AppsMenuProvider({ getService }: FtrProviderContext) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.ensureMenuClosed();
|
|
||||||
return links;
|
return links;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,30 +61,12 @@ export function AppsMenuProvider({ getService }: FtrProviderContext) {
|
||||||
public async clickLink(name: string) {
|
public async clickLink(name: string) {
|
||||||
try {
|
try {
|
||||||
log.debug(`click "${name}" app link`);
|
log.debug(`click "${name}" app link`);
|
||||||
await this.ensureMenuOpen();
|
const container = await testSubjects.find('navDrawer');
|
||||||
const container = await testSubjects.find('navDrawer&expanded appsMenu');
|
// Text content is not visible or selectable (0px width) so we use an attr with th same value
|
||||||
const link = await container.findByPartialLinkText(name);
|
const link = await container.findByCssSelector(`[aria-label='${name}']`);
|
||||||
await link.click();
|
await link.click();
|
||||||
} finally {
|
} finally {
|
||||||
await this.ensureMenuClosed();
|
// Intentionally empty
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ensureMenuClosed() {
|
|
||||||
await globalNav.moveMouseToLogo();
|
|
||||||
await retry.waitFor(
|
|
||||||
'apps drawer closed',
|
|
||||||
async () => await testSubjects.exists('navDrawer&collapsed')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async ensureMenuOpen() {
|
|
||||||
if (!(await testSubjects.exists('navDrawer&expanded'))) {
|
|
||||||
await testSubjects.moveMouseTo('navDrawer');
|
|
||||||
await retry.waitFor(
|
|
||||||
'apps drawer open',
|
|
||||||
async () => await testSubjects.exists('navDrawer&expanded')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elastic/eui": "5.0.0",
|
"@elastic/eui": "9.4.0",
|
||||||
"react": "^16.3.0"
|
"react": "^16.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elastic/eui": "5.0.0",
|
"@elastic/eui": "9.4.0",
|
||||||
"react": "^16.3.0"
|
"react": "^16.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elastic/eui": "5.0.0",
|
"@elastic/eui": "9.4.0",
|
||||||
"react": "^16.3.0",
|
"react": "^16.8.0",
|
||||||
"react-dom": "^16.3.0"
|
"react-dom": "^16.8.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ export default function ({ getService, getPageObjects }) {
|
||||||
await PageObjects.common.navigateToApp('settings');
|
await PageObjects.common.navigateToApp('settings');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should should nav link that navigates to the app', async () => {
|
it('should show nav link that navigates to the app', async () => {
|
||||||
await appsMenu.clickLink('Test Plugin App');
|
await appsMenu.clickLink('Test Plugin App');
|
||||||
const pluginContent = await testSubjects.find('pluginContent');
|
const pluginContent = await testSubjects.find('pluginContent');
|
||||||
expect(await pluginContent.getVisibleText()).to.be('Super simple app plugin');
|
expect(await pluginContent.getVisibleText()).to.be('Super simple app plugin');
|
||||||
|
|
|
@ -154,7 +154,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elastic/datemath": "5.0.2",
|
"@elastic/datemath": "5.0.2",
|
||||||
"@elastic/eui": "9.2.1",
|
"@elastic/eui": "9.4.0",
|
||||||
"@elastic/javascript-typescript-langserver": "^0.1.17",
|
"@elastic/javascript-typescript-langserver": "^0.1.17",
|
||||||
"@elastic/lsp-extension": "^0.1.1",
|
"@elastic/lsp-extension": "^0.1.1",
|
||||||
"@elastic/node-crypto": "0.1.2",
|
"@elastic/node-crypto": "0.1.2",
|
||||||
|
|
|
@ -18,7 +18,7 @@ function getAllFetchParams(searchRequests, Promise) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function serializeAllFetchParams(fetchParams, searchRequests) {
|
function serializeAllFetchParams(fetchParams, searchRequests) {
|
||||||
const searchRequestsWithFetchParams = [];
|
const searchRequestsWithFetchParams = [];
|
||||||
const failedSearchRequests = [];
|
const failedSearchRequests = [];
|
||||||
|
|
||||||
|
|
|
@ -53,12 +53,12 @@ export function mergeJobConfigurations(jobs = []) {
|
||||||
const aggName = agg.agg;
|
const aggName = agg.agg;
|
||||||
const aggDoesntExist = !allAggs[aggName];
|
const aggDoesntExist = !allAggs[aggName];
|
||||||
const fieldDoesntExist = allAggs[aggName] && !allAggs[aggName][fieldName];
|
const fieldDoesntExist = allAggs[aggName] && !allAggs[aggName][fieldName];
|
||||||
const aggIsntDateHistogram = aggName !== 'date_histogram';
|
const isDateHistogramAgg = aggName === 'date_histogram';
|
||||||
|
|
||||||
// If we currently don't have this aggregation, add it.
|
// If we currently don't have this aggregation, add it.
|
||||||
// Special case for date histogram, since there can only be one
|
// Special case for date histogram, since there can only be one
|
||||||
// date histogram field.
|
// date histogram field.
|
||||||
if(aggDoesntExist || (fieldDoesntExist && aggIsntDateHistogram)) {
|
if(aggDoesntExist || (fieldDoesntExist && !isDateHistogramAgg)) {
|
||||||
allAggs[aggName] = allAggs[aggName] || {};
|
allAggs[aggName] = allAggs[aggName] || {};
|
||||||
allAggs[aggName][fieldName] = { ...agg };
|
allAggs[aggName][fieldName] = { ...agg };
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const API_BASE_PATH = '/api/rollup';
|
export const API_BASE_PATH = '/api/rollup';
|
||||||
|
export const INDEX_PATTERNS_EXTENSION_BASE_PATH = '/api/index_patterns/rollup';
|
||||||
export const ROLLUP_INDEX_NAME = 'rollup_index';
|
export const ROLLUP_INDEX_NAME = 'rollup_index';
|
||||||
export const INDEX_TO_ROLLUP_MAPPINGS = {
|
export const INDEX_TO_ROLLUP_MAPPINGS = {
|
||||||
properties: {
|
properties: {
|
||||||
testTotalField: { 'type': 'long' },
|
testTotalField: { type: 'long' },
|
||||||
testTagField: { 'type': 'keyword' },
|
testTagField: { type: 'keyword' },
|
||||||
testCreatedField: { 'type': 'date' },
|
testCreatedField: { type: 'date' },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,5 +7,7 @@
|
||||||
export default function ({ loadTestFile }) {
|
export default function ({ loadTestFile }) {
|
||||||
describe('rollup', () => {
|
describe('rollup', () => {
|
||||||
loadTestFile(require.resolve('./rollup'));
|
loadTestFile(require.resolve('./rollup'));
|
||||||
|
loadTestFile(require.resolve('./index_patterns_extensions'));
|
||||||
|
loadTestFile(require.resolve('./rollup_search'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* 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 expect from 'expect.js';
|
||||||
|
import querystring from 'querystring';
|
||||||
|
|
||||||
|
import { registerHelpers } from './rollup.test_helpers';
|
||||||
|
import { INDEX_TO_ROLLUP_MAPPINGS, INDEX_PATTERNS_EXTENSION_BASE_PATH } from './constants';
|
||||||
|
import { getRandomString } from './lib';
|
||||||
|
|
||||||
|
export default function ({ getService }) {
|
||||||
|
const supertest = getService('supertest');
|
||||||
|
const es = getService('es');
|
||||||
|
|
||||||
|
const {
|
||||||
|
createIndexWithMappings,
|
||||||
|
getJobPayload,
|
||||||
|
createJob,
|
||||||
|
cleanUp,
|
||||||
|
} = registerHelpers({ supertest, es });
|
||||||
|
|
||||||
|
describe('index patterns extension', () => {
|
||||||
|
describe('Fields for wildcards', () => {
|
||||||
|
const BASE_URI = `${INDEX_PATTERNS_EXTENSION_BASE_PATH}/_fields_for_wildcard`;
|
||||||
|
|
||||||
|
describe('query params validation', () => {
|
||||||
|
let uri;
|
||||||
|
let body;
|
||||||
|
let params;
|
||||||
|
|
||||||
|
it('"pattern" is required', async () => {
|
||||||
|
uri = `${BASE_URI}`;
|
||||||
|
({ body } = await supertest.get(uri).expect(400));
|
||||||
|
expect(body.message).to.contain('"pattern" is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"params" is required', async () => {
|
||||||
|
params = { pattern: 'foo' };
|
||||||
|
uri = `${BASE_URI}?${querystring.stringify(params)}`;
|
||||||
|
({ body } = await supertest.get(uri).expect(400));
|
||||||
|
expect(body.message).to.contain('"params" is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"params" must be an object', async () => {
|
||||||
|
params = { pattern: 'foo', params: 'bar' };
|
||||||
|
uri = `${BASE_URI}?${querystring.stringify(params)}`;
|
||||||
|
({ body } = await supertest.get(uri).expect(400));
|
||||||
|
expect(body.message).to.contain('"params" must be an object');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"params" must be an object that only accepts a "rollup_index" property', async () => {
|
||||||
|
params = { pattern: 'foo', params: JSON.stringify({ someProp: 'bar' }) };
|
||||||
|
uri = `${BASE_URI}?${querystring.stringify(params)}`;
|
||||||
|
({ body } = await supertest.get(uri).expect(400));
|
||||||
|
expect(body.message).to.contain('"someProp" is not allowed');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('"meta_fields" must be an Array', async () => {
|
||||||
|
params = {
|
||||||
|
pattern: 'foo',
|
||||||
|
params: JSON.stringify({ rollup_index: 'bar' }),
|
||||||
|
meta_fields: 'stringValue'
|
||||||
|
};
|
||||||
|
uri = `${BASE_URI}?${querystring.stringify(params)}`;
|
||||||
|
({ body } = await supertest.get(uri).expect(400));
|
||||||
|
expect(body.message).to.contain('"meta_fields" must be an array');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return 404 the rollup index to query does not exist', async () => {
|
||||||
|
uri = `${BASE_URI}?${querystring.stringify({ pattern: 'foo', params: JSON.stringify({ rollup_index: 'bar' }) })}`;
|
||||||
|
({ body } = await supertest.get(uri).expect(404));
|
||||||
|
expect(body.message).to.contain('no such index [bar]');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the correct fields', async () => {
|
||||||
|
// Create a Rollup job on an index with the INDEX_TO_ROLLUP_MAPPINGS
|
||||||
|
const indexName = await createIndexWithMappings();
|
||||||
|
const rollupIndex = getRandomString();
|
||||||
|
const payload = getJobPayload(indexName, undefined, rollupIndex);
|
||||||
|
await createJob(payload);
|
||||||
|
|
||||||
|
// Query for wildcard
|
||||||
|
const params = {
|
||||||
|
pattern: indexName,
|
||||||
|
params: JSON.stringify({ rollup_index: rollupIndex })
|
||||||
|
};
|
||||||
|
const uri = `${BASE_URI}?${querystring.stringify(params)}`;
|
||||||
|
const { body } = await supertest.get(uri).expect(200);
|
||||||
|
|
||||||
|
// Verify that the fields for wildcard correspond to our declared mappings
|
||||||
|
const propertiesWithMappings = Object.keys(INDEX_TO_ROLLUP_MAPPINGS.properties);
|
||||||
|
const fieldsForWildcard = body.fields.map(field => field.name);
|
||||||
|
expect(fieldsForWildcard.sort()).eql(propertiesWithMappings.sort());
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
await cleanUp();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -11,3 +11,7 @@ export {
|
||||||
export {
|
export {
|
||||||
getRandomString,
|
getRandomString,
|
||||||
} from './random';
|
} from './random';
|
||||||
|
|
||||||
|
export {
|
||||||
|
wait
|
||||||
|
} from './utils';
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* 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 wait = (time = 1000) => (
|
||||||
|
new Promise((resolve) => (
|
||||||
|
setTimeout(resolve, time)
|
||||||
|
))
|
||||||
|
);
|
|
@ -23,10 +23,10 @@ export default function ({ getService }) {
|
||||||
cleanUp,
|
cleanUp,
|
||||||
} = registerHelpers({ supertest, es });
|
} = registerHelpers({ supertest, es });
|
||||||
|
|
||||||
describe('Rollup jobs', () => {
|
describe('jobs', () => {
|
||||||
after(() => cleanUp());
|
after(() => cleanUp());
|
||||||
|
|
||||||
describe('Rollup indices', () => {
|
describe('indices', () => {
|
||||||
it('should return an empty object when there are no rollup indices', async () => {
|
it('should return an empty object when there are no rollup indices', async () => {
|
||||||
const uri = `${API_BASE_PATH}/indices`;
|
const uri = `${API_BASE_PATH}/indices`;
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ export default function ({ getService }) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Crud', () => {
|
describe('crud', () => {
|
||||||
describe('list', () => {
|
describe('list', () => {
|
||||||
it('should return an empty array when there are no jobs', async () => {
|
it('should return an empty array when there are no jobs', async () => {
|
||||||
const { body } = await supertest
|
const { body } = await supertest
|
||||||
|
@ -206,7 +206,7 @@ export default function ({ getService }) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Actions', () => {
|
describe('actions', () => {
|
||||||
describe('start', () => {
|
describe('start', () => {
|
||||||
let job;
|
let job;
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { initElasticsearchIndicesHelpers, getRandomString } from './lib';
|
import { initElasticsearchIndicesHelpers, getRandomString, wait } from './lib';
|
||||||
import { API_BASE_PATH, ROLLUP_INDEX_NAME, INDEX_TO_ROLLUP_MAPPINGS } from './constants';
|
import { API_BASE_PATH, ROLLUP_INDEX_NAME, INDEX_TO_ROLLUP_MAPPINGS } from './constants';
|
||||||
|
|
||||||
const jobsCreated = [];
|
const jobsCreated = [];
|
||||||
|
@ -17,11 +17,11 @@ export const registerHelpers = ({ supertest, es }) => {
|
||||||
return createIndex(indexName, { mappings });
|
return createIndex(indexName, { mappings });
|
||||||
};
|
};
|
||||||
|
|
||||||
const getJobPayload = (indexName, id = getRandomString()) => ({
|
const getJobPayload = (indexName, id = getRandomString(), rollupIndex = ROLLUP_INDEX_NAME) => ({
|
||||||
job: {
|
job: {
|
||||||
id,
|
id,
|
||||||
index_pattern: indexName,
|
index_pattern: indexName,
|
||||||
rollup_index: ROLLUP_INDEX_NAME,
|
rollup_index: rollupIndex,
|
||||||
cron: '0 0 0 ? * 7',
|
cron: '0 0 0 ? * 7',
|
||||||
page_size: 1000,
|
page_size: 1000,
|
||||||
groups: {
|
groups: {
|
||||||
|
@ -86,9 +86,29 @@ export const registerHelpers = ({ supertest, es }) => {
|
||||||
.send({ jobIds });
|
.send({ jobIds });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadJobs = () => supertest.get(`${API_BASE_PATH}/jobs`);
|
||||||
|
|
||||||
|
const waitForJobsToStop = (attempt = 0) => (
|
||||||
|
loadJobs()
|
||||||
|
.then(async ({ body: { jobs } }) => {
|
||||||
|
const jobBeingStopped = jobs.filter(job => job.status.job_state !== 'stopped' && job.status.job_state !== 'started');
|
||||||
|
|
||||||
|
if (!jobBeingStopped.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attempt < 3 && jobBeingStopped.length) {
|
||||||
|
await wait(500);
|
||||||
|
return waitForJobsToStop(++attempt);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Error while waiting for Rollup Jobs to stop');
|
||||||
|
}));
|
||||||
|
|
||||||
const stopAllJobStarted = (jobIds = jobsStarted, attempt = 0) => (
|
const stopAllJobStarted = (jobIds = jobsStarted, attempt = 0) => (
|
||||||
stopJob(jobIds)
|
stopJob(jobIds)
|
||||||
.then(() => supertest.get(`${API_BASE_PATH}/jobs`))
|
.then(waitForJobsToStop)
|
||||||
|
.then(loadJobs)
|
||||||
.then(({ body: { jobs } }) => {
|
.then(({ body: { jobs } }) => {
|
||||||
// We make sure that there are no more jobs started
|
// We make sure that there are no more jobs started
|
||||||
// as trying to delete a job that is started will throw an exception
|
// as trying to delete a job that is started will throw an exception
|
||||||
|
@ -109,7 +129,7 @@ export const registerHelpers = ({ supertest, es }) => {
|
||||||
throw response;
|
throw response;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => supertest.get(`${API_BASE_PATH}/jobs`))
|
.then(loadJobs)
|
||||||
.then(({ body: { jobs } }) => {
|
.then(({ body: { jobs } }) => {
|
||||||
if (jobs.length && attempt < 3) {
|
if (jobs.length && attempt < 3) {
|
||||||
// There are still some jobs left to delete.
|
// There are still some jobs left to delete.
|
||||||
|
@ -135,7 +155,7 @@ export const registerHelpers = ({ supertest, es }) => {
|
||||||
const cleanUp = () => (
|
const cleanUp = () => (
|
||||||
Promise.all([
|
Promise.all([
|
||||||
deleteAllIndices(),
|
deleteAllIndices(),
|
||||||
stopAllJobStarted().then(() => deleteJobsCreated()),
|
stopAllJobStarted().then(deleteJobsCreated),
|
||||||
deleteIndicesGeneratedByJobs(),
|
deleteIndicesGeneratedByJobs(),
|
||||||
]).catch(err => {
|
]).catch(err => {
|
||||||
console.log('ERROR cleaning up!');
|
console.log('ERROR cleaning up!');
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* 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 expect from 'expect.js';
|
||||||
|
|
||||||
|
import { registerHelpers } from './rollup.test_helpers';
|
||||||
|
import { API_BASE_PATH } from './constants';
|
||||||
|
import { getRandomString } from './lib';
|
||||||
|
|
||||||
|
export default function ({ getService }) {
|
||||||
|
const supertest = getService('supertest');
|
||||||
|
const es = getService('es');
|
||||||
|
|
||||||
|
const {
|
||||||
|
createIndexWithMappings,
|
||||||
|
getJobPayload,
|
||||||
|
createJob,
|
||||||
|
cleanUp,
|
||||||
|
} = registerHelpers({ supertest, es });
|
||||||
|
|
||||||
|
describe('search', () => {
|
||||||
|
const URI = `${API_BASE_PATH}/search`;
|
||||||
|
|
||||||
|
it('return a 404 if the rollup index does not exist', async () => {
|
||||||
|
const { body } = await supertest
|
||||||
|
.post(URI)
|
||||||
|
.set('kbn-xsrf', 'xxx')
|
||||||
|
.send([{ index: 'unknown', query: {} } ])
|
||||||
|
.expect(404);
|
||||||
|
|
||||||
|
expect(body.message).to.contain('no such index [unknown]');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a 200 when searching on existing rollup index', async () => {
|
||||||
|
// Create a Rollup job on an index with the INDEX_TO_ROLLUP_MAPPINGS
|
||||||
|
const indexName = await createIndexWithMappings();
|
||||||
|
const rollupIndex = getRandomString();
|
||||||
|
await createJob(getJobPayload(indexName, undefined, rollupIndex));
|
||||||
|
|
||||||
|
const { body } = await supertest
|
||||||
|
.post(URI)
|
||||||
|
.set('kbn-xsrf', 'xxx')
|
||||||
|
.send([{ index: rollupIndex, query: { size: 0 } } ])
|
||||||
|
.expect(200);
|
||||||
|
|
||||||
|
// make sure total hits is an integer and not an object
|
||||||
|
expect(body[0].hits.total).to.equal(0);
|
||||||
|
|
||||||
|
await cleanUp();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
61
yarn.lock
61
yarn.lock
|
@ -796,34 +796,10 @@
|
||||||
tabbable "^1.1.0"
|
tabbable "^1.1.0"
|
||||||
uuid "^3.1.0"
|
uuid "^3.1.0"
|
||||||
|
|
||||||
"@elastic/eui@5.0.0":
|
"@elastic/eui@9.4.0":
|
||||||
version "5.0.0"
|
version "9.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-5.0.0.tgz#e6fe9e1aa8b00c93045178f78a6dd0d457d56fa8"
|
resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-9.4.0.tgz#e5f83c612674fc6f59e990f557e563be1409d25e"
|
||||||
integrity sha512-WL6sp6u2Rt1O7a2exLU/RuDcRnpluPN6aQ2JexBl+G6mVyF8F5I3RGJKTJp3jOozOaODRY2ev+Nq57EydkjrKg==
|
integrity sha512-cQnsU3UeQ1s6F427vY53lzlh7mvNoPmIvPL24B5jH3JYaWULhIL1xSJXJgDSOSdrdHCxkXDD9Q8Y7256x4Xf4Q==
|
||||||
dependencies:
|
|
||||||
classnames "^2.2.5"
|
|
||||||
core-js "^2.5.1"
|
|
||||||
focus-trap-react "^3.0.4"
|
|
||||||
highlight.js "^9.12.0"
|
|
||||||
html "^1.0.0"
|
|
||||||
keymirror "^0.1.1"
|
|
||||||
lodash "npm:@elastic/lodash@3.10.1-kibana1"
|
|
||||||
numeral "^2.0.6"
|
|
||||||
prop-types "^15.6.0"
|
|
||||||
react-ace "^5.5.0"
|
|
||||||
react-color "^2.13.8"
|
|
||||||
react-datepicker v1.5.0
|
|
||||||
react-input-autosize "^2.2.1"
|
|
||||||
react-virtualized "^9.18.5"
|
|
||||||
react-vis "1.10.2"
|
|
||||||
resize-observer-polyfill "^1.5.0"
|
|
||||||
tabbable "^1.1.0"
|
|
||||||
uuid "^3.1.0"
|
|
||||||
|
|
||||||
"@elastic/eui@9.2.1":
|
|
||||||
version "9.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-9.2.1.tgz#3860a7219f0ee8f33ec43447edb2eda3c96a00a7"
|
|
||||||
integrity sha512-U92s0nh6vBS6NBiHDCq6e+49Dam8It+Iy81b2NProf1OIRk/nB0RE781x6zgUzmOFpJ1T0xiThWiiDP776v0LQ==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/lodash" "^4.14.116"
|
"@types/lodash" "^4.14.116"
|
||||||
"@types/numeral" "^0.0.25"
|
"@types/numeral" "^0.0.25"
|
||||||
|
@ -18609,11 +18585,6 @@ polished@^1.9.2:
|
||||||
resolved "https://registry.yarnpkg.com/polished/-/polished-1.9.2.tgz#d705cac66f3a3ed1bd38aad863e2c1e269baf6b6"
|
resolved "https://registry.yarnpkg.com/polished/-/polished-1.9.2.tgz#d705cac66f3a3ed1bd38aad863e2c1e269baf6b6"
|
||||||
integrity sha512-mPocQrVUSiqQdHNZFGL1iHJmsR/etiv05Nf2oZUbya+GMsQkZVEBl5wonN+Sr/e9zQBEhT6yrMjxAUJ06eyocQ==
|
integrity sha512-mPocQrVUSiqQdHNZFGL1iHJmsR/etiv05Nf2oZUbya+GMsQkZVEBl5wonN+Sr/e9zQBEhT6yrMjxAUJ06eyocQ==
|
||||||
|
|
||||||
popper.js@^1.14.1:
|
|
||||||
version "1.14.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095"
|
|
||||||
integrity sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU=
|
|
||||||
|
|
||||||
popper.js@^1.14.3:
|
popper.js@^1.14.3:
|
||||||
version "1.14.6"
|
version "1.14.6"
|
||||||
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.6.tgz#ab20dd4edf9288b8b3b6531c47c361107b60b4b0"
|
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.6.tgz#ab20dd4edf9288b8b3b6531c47c361107b60b4b0"
|
||||||
|
@ -19500,16 +19471,6 @@ react-color@^2.13.8, react-color@^2.14.1:
|
||||||
reactcss "^1.2.0"
|
reactcss "^1.2.0"
|
||||||
tinycolor2 "^1.4.1"
|
tinycolor2 "^1.4.1"
|
||||||
|
|
||||||
react-datepicker@v1.5.0:
|
|
||||||
version "1.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-1.5.0.tgz#7eacd9609313189c84a21bb7421486054939a4b2"
|
|
||||||
integrity sha512-Neh1rz0d1QeR7KuoTiYeR6oj73DJkqt0vuNSgfMuxXEwGmz/4sPynouYGo6gdKiQbxIXBJJ/FLDLHJEr5XNThw==
|
|
||||||
dependencies:
|
|
||||||
classnames "^2.2.5"
|
|
||||||
prop-types "^15.6.0"
|
|
||||||
react-onclickoutside "^6.7.1"
|
|
||||||
react-popper "^0.9.1"
|
|
||||||
|
|
||||||
react-datetime@^2.14.0:
|
react-datetime@^2.14.0:
|
||||||
version "2.15.0"
|
version "2.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-datetime/-/react-datetime-2.15.0.tgz#a8f7da6c58b6b45dbeea32d4e8485db17614e12c"
|
resolved "https://registry.yarnpkg.com/react-datetime/-/react-datetime-2.15.0.tgz#a8f7da6c58b6b45dbeea32d4e8485db17614e12c"
|
||||||
|
@ -19590,7 +19551,7 @@ react-docgen@^3.0.0-rc.1:
|
||||||
node-dir "^0.1.10"
|
node-dir "^0.1.10"
|
||||||
recast "^0.16.0"
|
recast "^0.16.0"
|
||||||
|
|
||||||
react-dom@^16.2.0, react-dom@^16.3.0, react-dom@^16.8.0:
|
react-dom@^16.2.0, react-dom@^16.8.0:
|
||||||
version "16.8.2"
|
version "16.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.2.tgz#7c8a69545dd554d45d66442230ba04a6a0a3c3d3"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.2.tgz#7c8a69545dd554d45d66442230ba04a6a0a3c3d3"
|
||||||
integrity sha512-cPGfgFfwi+VCZjk73buu14pYkYBR1b/SRMSYqkLDdhSEHnSwcuYTPu6/Bh6ZphJFIk80XLvbSe2azfcRzNF+Xg==
|
integrity sha512-cPGfgFfwi+VCZjk73buu14pYkYBR1b/SRMSYqkLDdhSEHnSwcuYTPu6/Bh6ZphJFIk80XLvbSe2azfcRzNF+Xg==
|
||||||
|
@ -19777,19 +19738,11 @@ react-motion@^0.5.2:
|
||||||
prop-types "^15.5.8"
|
prop-types "^15.5.8"
|
||||||
raf "^3.1.0"
|
raf "^3.1.0"
|
||||||
|
|
||||||
react-onclickoutside@^6.5.0, react-onclickoutside@^6.7.1:
|
react-onclickoutside@^6.5.0:
|
||||||
version "6.7.1"
|
version "6.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.7.1.tgz#6a5b5b8b4eae6b776259712c89c8a2b36b17be93"
|
resolved "https://registry.yarnpkg.com/react-onclickoutside/-/react-onclickoutside-6.7.1.tgz#6a5b5b8b4eae6b776259712c89c8a2b36b17be93"
|
||||||
integrity sha512-p84kBqGaMoa7VYT0vZ/aOYRfJB+gw34yjpda1Z5KeLflg70HipZOT+MXQenEhdkPAABuE2Astq4zEPdMqUQxcg==
|
integrity sha512-p84kBqGaMoa7VYT0vZ/aOYRfJB+gw34yjpda1Z5KeLflg70HipZOT+MXQenEhdkPAABuE2Astq4zEPdMqUQxcg==
|
||||||
|
|
||||||
react-popper@^0.9.1:
|
|
||||||
version "0.9.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-0.9.5.tgz#02a24ef3eec33af9e54e8358ab70eb0e331edd05"
|
|
||||||
integrity sha1-AqJO8+7DOvnlToNYq3DrDjMe3QU=
|
|
||||||
dependencies:
|
|
||||||
popper.js "^1.14.1"
|
|
||||||
prop-types "^15.6.1"
|
|
||||||
|
|
||||||
react-portal@^3.2.0:
|
react-portal@^3.2.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-3.2.0.tgz#4224e19b2b05d5cbe730a7ba0e34ec7585de0043"
|
resolved "https://registry.yarnpkg.com/react-portal/-/react-portal-3.2.0.tgz#4224e19b2b05d5cbe730a7ba0e34ec7585de0043"
|
||||||
|
@ -20055,7 +20008,7 @@ react-vis@^1.8.1:
|
||||||
prop-types "^15.5.8"
|
prop-types "^15.5.8"
|
||||||
react-motion "^0.4.8"
|
react-motion "^0.4.8"
|
||||||
|
|
||||||
react@^16.2.0, react@^16.3.0, react@^16.6.0, react@^16.8.0:
|
react@^16.2.0, react@^16.6.0, react@^16.8.0:
|
||||||
version "16.8.2"
|
version "16.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.8.2.tgz#83064596feaa98d9c2857c4deae1848b542c9c0c"
|
resolved "https://registry.yarnpkg.com/react/-/react-16.8.2.tgz#83064596feaa98d9c2857c4deae1848b542c9c0c"
|
||||||
integrity sha512-aB2ctx9uQ9vo09HVknqv3DGRpI7OIGJhCx3Bt0QqoRluEjHSaObJl+nG12GDdYH6sTgE7YiPJ6ZUyMx9kICdXw==
|
integrity sha512-aB2ctx9uQ9vo09HVknqv3DGRpI7OIGJhCx3Bt0QqoRluEjHSaObJl+nG12GDdYH6sTgE7YiPJ6ZUyMx9kICdXw==
|
||||||
|
|
Loading…
Reference in a new issue