mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
Merge remote-tracking branch 'origin/master' into feature/merge-code
This commit is contained in:
commit
f11e08068f
133 changed files with 1209 additions and 1020 deletions
|
@ -103,3 +103,16 @@ The port is now protocol dependent: https ports will use 443, and http ports wil
|
|||
`server.ssl.supportedProtocols`
|
||||
|
||||
*Impact:* Users relying upon TLSv1 will be unable to use Kibana unless `server.ssl.supportedProtocols` is explicitly set.
|
||||
|
||||
[float]
|
||||
=== kibana.yml setting `server.ssl.cert` is no longer valid
|
||||
*Details:* This deprecated setting has been removed and `server.ssl.certificate` should be used instead.
|
||||
|
||||
*Impact:* Users with `server.ssl.cert` set should use `server.ssl.certificate` instead
|
||||
|
||||
[float]
|
||||
=== kibana.yml `server.ssl.enabled` must be set to `true` to enable SSL
|
||||
*Details:* Previously, if `server.ssl.certificate` and `server.ssl.key` were set, SSL would automatically be enabled.
|
||||
It's now required that the user sets `server.ssl.enabled` to true for this to occur.
|
||||
|
||||
*Impact:* Users with both `server.ssl.certificate` and `server.ssl.key` set must now also set `server.ssl.enabled` to enable SSL.
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@elastic/datemath": "5.0.2",
|
||||
"@elastic/eui": "6.0.1",
|
||||
"@elastic/eui": "6.3.1",
|
||||
"@elastic/filesaver": "1.1.2",
|
||||
"@elastic/good": "8.1.1-kibana2",
|
||||
"@elastic/numeral": "2.3.2",
|
||||
|
|
|
@ -45,7 +45,7 @@ exports.downloadSnapshot = async function installSnapshot({
|
|||
log = defaultLog,
|
||||
}) {
|
||||
const fileName = getFilename(license, version);
|
||||
const url = `https://snapshots.elastic.co/downloads/elasticsearch/${fileName}`;
|
||||
const url = getUrl(fileName);
|
||||
const dest = path.resolve(basePath, 'cache', fileName);
|
||||
|
||||
log.info('version: %s', chalk.bold(version));
|
||||
|
@ -150,3 +150,13 @@ function getFilename(license, version) {
|
|||
|
||||
return `${basename}-SNAPSHOT.${extension}`;
|
||||
}
|
||||
|
||||
function getUrl(fileName) {
|
||||
if (process.env.TEST_ES_SNAPSHOT_VERSION) {
|
||||
return `https://snapshots.elastic.co/${
|
||||
process.env.TEST_ES_SNAPSHOT_VERSION
|
||||
}/downloads/elasticsearch/${fileName}`;
|
||||
} else {
|
||||
return `https://snapshots.elastic.co/downloads/elasticsearch/${fileName}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2944,8 +2944,7 @@ main {
|
|||
/* 1 */
|
||||
padding: 10px;
|
||||
height: 40px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #D3DAE6; }
|
||||
background-color: #ffffff; }
|
||||
|
||||
.kuiToolBarFooterSection {
|
||||
display: -webkit-box;
|
||||
|
|
|
@ -37,6 +37,7 @@ export interface Brand {
|
|||
export interface Breadcrumb {
|
||||
text: string;
|
||||
href?: string;
|
||||
'data-test-subj'?: string;
|
||||
}
|
||||
|
||||
export class ChromeService {
|
||||
|
|
|
@ -17,40 +17,6 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`#get correctly handles server config.: deprecated missing ssl.enabled 1`] = `
|
||||
Object {
|
||||
"autoListen": true,
|
||||
"basePath": "/abc",
|
||||
"cors": false,
|
||||
"host": "host",
|
||||
"maxPayload": 1000,
|
||||
"port": 1234,
|
||||
"rewriteBasePath": false,
|
||||
"ssl": Object {
|
||||
"certificate": "cert",
|
||||
"enabled": true,
|
||||
"key": "key",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`#get correctly handles server config.: deprecated ssl.cert 1`] = `
|
||||
Object {
|
||||
"autoListen": true,
|
||||
"basePath": "/abc",
|
||||
"cors": false,
|
||||
"host": "host",
|
||||
"maxPayload": 1000,
|
||||
"port": 1234,
|
||||
"rewriteBasePath": false,
|
||||
"ssl": Object {
|
||||
"certificate": "deprecated-cert",
|
||||
"enabled": true,
|
||||
"key": "key",
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`#get correctly handles server config.: disabled ssl 1`] = `
|
||||
Object {
|
||||
"autoListen": true,
|
||||
|
|
|
@ -90,40 +90,8 @@ describe('#get', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const configAdapterWithCert = new LegacyObjectToConfigAdapter({
|
||||
server: {
|
||||
autoListen: true,
|
||||
basePath: '/abc',
|
||||
cors: false,
|
||||
host: 'host',
|
||||
maxPayloadBytes: 1000,
|
||||
port: 1234,
|
||||
rewriteBasePath: false,
|
||||
ssl: { enabled: true, cert: 'deprecated-cert', key: 'key' },
|
||||
someNotSupportedValue: 'val',
|
||||
},
|
||||
});
|
||||
|
||||
const configAdapterWithoutSSLEnabled = new LegacyObjectToConfigAdapter({
|
||||
server: {
|
||||
autoListen: true,
|
||||
basePath: '/abc',
|
||||
cors: false,
|
||||
host: 'host',
|
||||
maxPayloadBytes: 1000,
|
||||
port: 1234,
|
||||
rewriteBasePath: false,
|
||||
ssl: { certificate: 'cert', key: 'key' },
|
||||
someNotSupportedValue: 'val',
|
||||
},
|
||||
});
|
||||
|
||||
expect(configAdapter.get('server')).toMatchSnapshot('default');
|
||||
expect(configAdapterWithDisabledSSL.get('server')).toMatchSnapshot('disabled ssl');
|
||||
expect(configAdapterWithCert.get('server')).toMatchSnapshot('deprecated ssl.cert');
|
||||
expect(configAdapterWithoutSSLEnabled.get('server')).toMatchSnapshot(
|
||||
'deprecated missing ssl.enabled'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -67,26 +67,10 @@ export class LegacyObjectToConfigAdapter extends ObjectToConfigAdapter {
|
|||
maxPayload: configValue.maxPayloadBytes,
|
||||
port: configValue.port,
|
||||
rewriteBasePath: configValue.rewriteBasePath,
|
||||
ssl: configValue.ssl && LegacyObjectToConfigAdapter.transformSSL(configValue.ssl),
|
||||
ssl: configValue.ssl,
|
||||
};
|
||||
}
|
||||
|
||||
private static transformSSL(configValue: Record<string, any>) {
|
||||
// `server.ssl.cert` is deprecated, legacy platform will issue deprecation warning.
|
||||
if (configValue.cert) {
|
||||
configValue.certificate = configValue.cert;
|
||||
delete configValue.cert;
|
||||
}
|
||||
|
||||
// Enabling ssl by only specifying server.ssl.certificate and server.ssl.key is deprecated,
|
||||
// legacy platform will issue deprecation warning.
|
||||
if (typeof configValue.enabled !== 'boolean' && configValue.certificate && configValue.key) {
|
||||
configValue.enabled = true;
|
||||
}
|
||||
|
||||
return configValue;
|
||||
}
|
||||
|
||||
private static transformPlugins(configValue: Record<string, any>) {
|
||||
// This property is the only one we use from the existing `plugins` config node
|
||||
// since `scanDirs` and `paths` aren't respected by new platform plugin discovery.
|
||||
|
|
|
@ -29,9 +29,11 @@ fi
|
|||
export KIBANA_DIR="$dir"
|
||||
export XPACK_DIR="$KIBANA_DIR/x-pack"
|
||||
export PARENT_DIR="$(cd "$KIBANA_DIR/.."; pwd)"
|
||||
export TEST_ES_SNAPSHOT_VERSION="7.0.0-fbd1a09d"
|
||||
echo "-> KIBANA_DIR $KIBANA_DIR"
|
||||
echo "-> XPACK_DIR $XPACK_DIR"
|
||||
echo "-> PARENT_DIR $PARENT_DIR"
|
||||
echo "-> TEST_ES_SNAPSHOT_VERSION $TEST_ES_SNAPSHOT_VERSION"
|
||||
|
||||
###
|
||||
### download node
|
||||
|
|
|
@ -93,6 +93,7 @@ exports[`Table should render normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -55,6 +55,7 @@ exports[`Table should render normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -86,6 +86,7 @@ exports[`Table should render normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -50,6 +50,7 @@ exports[`ObjectsTable delete should show a confirm modal 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -93,6 +93,7 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -95,6 +95,7 @@ exports[`Relationships should render dashboards normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
@ -302,6 +303,7 @@ exports[`Relationships should render searches normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
@ -369,6 +371,7 @@ exports[`Relationships should render searches normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
@ -481,6 +484,7 @@ exports[`Relationships should render visualizations normally 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
executeQueryOptions={Object {}}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -119,7 +119,7 @@ export class EMSClientV66 {
|
|||
if (!i18nObject) {
|
||||
return '';
|
||||
}
|
||||
return i18nObject[this._language] ? i18nObject[this._language] : i18nObject[DEFAULT_LANGUAGE];
|
||||
return i18nObject[this._language] ? i18nObject[this._language] : i18nObject[DEFAULT_LANGUAGE];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,9 +139,7 @@ export class EMSClientV66 {
|
|||
}
|
||||
throw new Error(`Unable to retrieve manifest from ${manifestUrl}: ${e.message}`);
|
||||
} finally {
|
||||
return result
|
||||
? await result.json()
|
||||
: null;
|
||||
return result ? await result.json() : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,17 @@ export class FileLayer {
|
|||
this._emsClient = emsClient;
|
||||
}
|
||||
|
||||
getAttributions() {
|
||||
const attributions = this._config.attribution.map(attribution => {
|
||||
const url = this._emsClient.getValueInLanguage(attribution.url);
|
||||
const label = this._emsClient.getValueInLanguage(attribution.label);
|
||||
return {
|
||||
url: url,
|
||||
label: label
|
||||
};
|
||||
});
|
||||
return attributions;
|
||||
}
|
||||
|
||||
getHTMLAttribution() {
|
||||
const attributions = this._config.attribution.map(attribution => {
|
||||
|
|
|
@ -34,6 +34,10 @@ export class TMSService {
|
|||
return this._emsClient.sanitizeMarkdown(this._config.attribution);
|
||||
}
|
||||
|
||||
getMarkdownAttribution() {
|
||||
return this._config.attribution;
|
||||
}
|
||||
|
||||
getMinZoom() {
|
||||
return this._config.minZoom;
|
||||
}
|
||||
|
|
|
@ -17,22 +17,12 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import _, { partial, set } from 'lodash';
|
||||
import _, { set } from 'lodash';
|
||||
import { createTransform, Deprecations } from '../../deprecation';
|
||||
import { unset } from '../../utils';
|
||||
|
||||
const { rename, unused } = Deprecations;
|
||||
|
||||
const serverSslEnabled = (settings, log) => {
|
||||
const has = partial(_.has, settings);
|
||||
const set = partial(_.set, settings);
|
||||
|
||||
if (!has('server.ssl.enabled') && has('server.ssl.certificate') && has('server.ssl.key')) {
|
||||
set('server.ssl.enabled', true);
|
||||
log('Enabling ssl by only specifying server.ssl.certificate and server.ssl.key is deprecated. Please set server.ssl.enabled to true');
|
||||
}
|
||||
};
|
||||
|
||||
const savedObjectsIndexCheckTimeout = (settings, log) => {
|
||||
if (_.has(settings, 'savedObjects.indexCheckTimeout')) {
|
||||
log('savedObjects.indexCheckTimeout is no longer necessary.');
|
||||
|
@ -67,7 +57,6 @@ const loggingTimezone = (settings, log) => {
|
|||
|
||||
const deprecations = [
|
||||
//server
|
||||
rename('server.ssl.cert', 'server.ssl.certificate'),
|
||||
unused('server.xsrf.token'),
|
||||
unused('uiSettings.enabled'),
|
||||
rename('optimize.lazy', 'optimize.watch'),
|
||||
|
@ -76,7 +65,6 @@ const deprecations = [
|
|||
rename('optimize.lazyPrebuild', 'optimize.watchPrebuild'),
|
||||
rename('optimize.lazyProxyTimeout', 'optimize.watchProxyTimeout'),
|
||||
rename('i18n.defaultLocale', 'i18n.locale'),
|
||||
serverSslEnabled,
|
||||
savedObjectsIndexCheckTimeout,
|
||||
rewriteBasePath,
|
||||
loggingTimezone,
|
||||
|
|
|
@ -22,59 +22,6 @@ import { transformDeprecations } from './transform_deprecations';
|
|||
|
||||
describe('server/config', function () {
|
||||
describe('transformDeprecations', function () {
|
||||
describe('server.ssl.enabled', function () {
|
||||
it('sets enabled to true when certificate and key are set', function () {
|
||||
const settings = {
|
||||
server: {
|
||||
ssl: {
|
||||
certificate: '/cert.crt',
|
||||
key: '/key.key'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = transformDeprecations(settings);
|
||||
expect(result.server.ssl.enabled).toBe(true);
|
||||
});
|
||||
|
||||
it('logs a message when automatically setting enabled to true', function () {
|
||||
const settings = {
|
||||
server: {
|
||||
ssl: {
|
||||
certificate: '/cert.crt',
|
||||
key: '/key.key'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const log = sinon.spy();
|
||||
transformDeprecations(settings, log);
|
||||
expect(log.calledOnce).toBe(true);
|
||||
});
|
||||
|
||||
it(`doesn't set enabled when key and cert aren't set`, function () {
|
||||
const settings = {
|
||||
server: {
|
||||
ssl: {}
|
||||
}
|
||||
};
|
||||
|
||||
const result = transformDeprecations(settings);
|
||||
expect(result.server.ssl.enabled).toBe(undefined);
|
||||
});
|
||||
|
||||
it(`doesn't log a message when not automatically setting enabled`, function () {
|
||||
const settings = {
|
||||
server: {
|
||||
ssl: {}
|
||||
}
|
||||
};
|
||||
|
||||
const log = sinon.spy();
|
||||
transformDeprecations(settings, log);
|
||||
expect(log.called).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('savedObjects.indexCheckTimeout', () => {
|
||||
it('removes the indexCheckTimeout and savedObjects properties', () => {
|
||||
|
|
|
@ -67,6 +67,7 @@ export interface PutMappingOpts {
|
|||
body: DocMapping;
|
||||
index: string;
|
||||
type: string;
|
||||
include_type_name?: boolean;
|
||||
}
|
||||
|
||||
export interface PutTemplateOpts {
|
||||
|
@ -87,6 +88,7 @@ export interface IndexOpts {
|
|||
|
||||
export interface IndexCreationOpts {
|
||||
index: string;
|
||||
include_type_name?: boolean;
|
||||
body?: {
|
||||
mappings?: IndexMapping;
|
||||
settings?: {
|
||||
|
|
|
@ -222,7 +222,12 @@ export async function migrationsUpToDate(
|
|||
* @param {IndexMapping} mappings
|
||||
*/
|
||||
export function putMappings(callCluster: CallCluster, index: string, mappings: IndexMapping) {
|
||||
return callCluster('indices.putMapping', { body: mappings.doc, index, type: ROOT_TYPE });
|
||||
return callCluster('indices.putMapping', {
|
||||
body: mappings.doc,
|
||||
index,
|
||||
type: ROOT_TYPE,
|
||||
include_type_name: true,
|
||||
});
|
||||
}
|
||||
|
||||
export async function createIndex(
|
||||
|
@ -230,7 +235,11 @@ export async function createIndex(
|
|||
index: string,
|
||||
mappings?: IndexMapping
|
||||
) {
|
||||
await callCluster('indices.create', { body: { mappings, settings }, index });
|
||||
await callCluster('indices.create', {
|
||||
body: { mappings, settings },
|
||||
index,
|
||||
include_type_name: true,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteIndex(callCluster: CallCluster, index: string) {
|
||||
|
|
|
@ -53,6 +53,7 @@ describe('IndexMigrator', () => {
|
|||
},
|
||||
},
|
||||
index: '.kibana_1',
|
||||
include_type_name: true,
|
||||
type: ROOT_TYPE,
|
||||
});
|
||||
});
|
||||
|
@ -89,6 +90,7 @@ describe('IndexMigrator', () => {
|
|||
settings: { number_of_shards: 1, auto_expand_replicas: '0-1' },
|
||||
},
|
||||
index: '.kibana_1',
|
||||
include_type_name: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -175,6 +177,7 @@ describe('IndexMigrator', () => {
|
|||
},
|
||||
},
|
||||
},
|
||||
include_type_name: true,
|
||||
});
|
||||
|
||||
await new IndexMigrator(opts).migrate();
|
||||
|
@ -201,6 +204,7 @@ describe('IndexMigrator', () => {
|
|||
settings: { number_of_shards: 1, auto_expand_replicas: '0-1' },
|
||||
},
|
||||
index: '.kibana_2',
|
||||
include_type_name: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ export function createSavedObjectsService(server, schema, serializer, migrator)
|
|||
const index = server.config().get('kibana.index');
|
||||
await adminCluster.callWithInternalUser('indices.putTemplate', {
|
||||
name: `kibana_index_template:${index}`,
|
||||
include_type_name: true,
|
||||
body: {
|
||||
template: index,
|
||||
settings: {
|
||||
|
|
1
src/ui/public/chrome/api/angular.js
vendored
1
src/ui/public/chrome/api/angular.js
vendored
|
@ -68,6 +68,7 @@ export function initAngularApi(chrome, internals) {
|
|||
})
|
||||
.run(internals.capture$httpLoadingCount)
|
||||
.run(internals.$setupBreadcrumbsAutoClear)
|
||||
.run(internals.$initNavLinksDeepWatch)
|
||||
.run(($location, $rootScope, Private, config) => {
|
||||
chrome.getFirstPathSegment = () => {
|
||||
return $location.path().split('/')[1];
|
||||
|
|
|
@ -17,15 +17,33 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import * as Rx from 'rxjs';
|
||||
import { mapTo } from 'rxjs/operators';
|
||||
import { remove } from 'lodash';
|
||||
import { relativeToAbsolute } from '../../url/relative_to_absolute';
|
||||
import { absoluteToParsedUrl } from '../../url/absolute_to_parsed_url';
|
||||
|
||||
export function initChromeNavApi(chrome, internals) {
|
||||
const navUpdate$ = new Rx.BehaviorSubject(undefined);
|
||||
|
||||
chrome.getNavLinks = function () {
|
||||
return internals.nav;
|
||||
};
|
||||
|
||||
chrome.getNavLinks$ = function () {
|
||||
return navUpdate$.pipe(mapTo(internals.nav));
|
||||
};
|
||||
|
||||
// track navLinks with $rootScope.$watch like the old nav used to, necessary
|
||||
// as long as random parts of the app are directly mutating the navLinks
|
||||
internals.$initNavLinksDeepWatch = function ($rootScope) {
|
||||
$rootScope.$watch(
|
||||
() => internals.nav,
|
||||
() => navUpdate$.next(),
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
chrome.navLinkExists = (id) => {
|
||||
return !!internals.nav.find(link => link.id === id);
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@ exports[`HeaderBreadcrumbs renders updates to the breadcrumbs$ observable 1`] =
|
|||
<span
|
||||
aria-current="page"
|
||||
className="euiBreadcrumb euiBreadcrumb--last"
|
||||
data-test-subj="breadcrumb first last"
|
||||
title="First"
|
||||
>
|
||||
First
|
||||
|
@ -15,11 +16,13 @@ Array [
|
|||
<EuiLink
|
||||
className="euiBreadcrumb"
|
||||
color="subdued"
|
||||
data-test-subj="breadcrumb first"
|
||||
title="First"
|
||||
type="button"
|
||||
>
|
||||
<button
|
||||
className="euiLink euiLink--subdued euiBreadcrumb"
|
||||
data-test-subj="breadcrumb first"
|
||||
title="First"
|
||||
type="button"
|
||||
>
|
||||
|
@ -28,6 +31,7 @@ Array [
|
|||
</EuiLink>,
|
||||
<button
|
||||
className="euiLink euiLink--subdued euiBreadcrumb"
|
||||
data-test-subj="breadcrumb first"
|
||||
title="First"
|
||||
type="button"
|
||||
>
|
||||
|
@ -36,6 +40,7 @@ Array [
|
|||
<span
|
||||
aria-current="page"
|
||||
className="euiBreadcrumb euiBreadcrumb--last"
|
||||
data-test-subj="breadcrumb last"
|
||||
title="Second"
|
||||
>
|
||||
Second
|
||||
|
|
|
@ -46,7 +46,7 @@ interface Props {
|
|||
breadcrumbs$: Rx.Observable<Breadcrumb[]>;
|
||||
homeHref: string;
|
||||
isVisible: boolean;
|
||||
navLinks: NavLink[];
|
||||
navLinks$: Rx.Observable<NavLink[]>;
|
||||
navControls: ChromeHeaderNavControlsRegistry;
|
||||
intl: InjectedIntl;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ class HeaderUI extends Component<Props> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
const { appTitle, breadcrumbs$, isVisible, navControls, navLinks } = this.props;
|
||||
const { appTitle, breadcrumbs$, isVisible, navControls, navLinks$ } = this.props;
|
||||
|
||||
if (!isVisible) {
|
||||
return null;
|
||||
|
@ -90,7 +90,7 @@ class HeaderUI extends Component<Props> {
|
|||
<HeaderNavControls navControls={rightNavControls} />
|
||||
|
||||
<EuiHeaderSectionItem>
|
||||
<HeaderAppMenu navLinks={navLinks} />
|
||||
<HeaderAppMenu navLinks$={navLinks$} />
|
||||
</EuiHeaderSectionItem>
|
||||
</EuiHeaderSection>
|
||||
</EuiHeader>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import * as Rx from 'rxjs';
|
||||
|
||||
import {
|
||||
// TODO: add type annotations
|
||||
|
@ -36,25 +37,45 @@ import { InjectedIntl, injectI18n } from '@kbn/i18n/react';
|
|||
import { NavLink } from '../';
|
||||
|
||||
interface Props {
|
||||
navLinks: NavLink[];
|
||||
navLinks$: Rx.Observable<NavLink[]>;
|
||||
intl: InjectedIntl;
|
||||
}
|
||||
|
||||
interface State {
|
||||
isOpen: boolean;
|
||||
navLinks: NavLink[];
|
||||
}
|
||||
|
||||
class HeaderAppMenuUI extends Component<Props, State> {
|
||||
private subscription?: Rx.Subscription;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isOpen: false,
|
||||
navLinks: [],
|
||||
};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
this.subscription = this.props.navLinks$.subscribe({
|
||||
next: navLinks => {
|
||||
this.setState({ navLinks });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
this.subscription = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { navLinks = [], intl } = this.props;
|
||||
const { intl } = this.props;
|
||||
const { navLinks } = this.state;
|
||||
|
||||
const button = (
|
||||
<EuiHeaderSectionItemButton
|
||||
|
@ -103,7 +124,7 @@ class HeaderAppMenuUI extends Component<Props, State> {
|
|||
private renderNavLink = (navLink: NavLink) => (
|
||||
<EuiKeyPadMenuItem
|
||||
label={navLink.title}
|
||||
href={navLink.url}
|
||||
href={navLink.active || !navLink.lastSubUrl ? navLink.url : navLink.lastSubUrl}
|
||||
key={navLink.id}
|
||||
onClick={this.closeMenu}
|
||||
>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import React, { Component } from 'react';
|
||||
import * as Rx from 'rxjs';
|
||||
|
||||
|
@ -63,13 +64,9 @@ export class HeaderBreadcrumbs extends Component<Props, State> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
let breadcrumbs = this.state.breadcrumbs;
|
||||
|
||||
if (breadcrumbs.length === 0 && this.props.appTitle) {
|
||||
breadcrumbs = [{ text: this.props.appTitle }];
|
||||
}
|
||||
|
||||
return <EuiHeaderBreadcrumbs breadcrumbs={breadcrumbs} />;
|
||||
return (
|
||||
<EuiHeaderBreadcrumbs breadcrumbs={this.getBreadcrumbs()} data-test-subj="breadcrumbs" />
|
||||
);
|
||||
}
|
||||
|
||||
private subscribe() {
|
||||
|
@ -86,4 +83,22 @@ export class HeaderBreadcrumbs extends Component<Props, State> {
|
|||
delete this.subscription;
|
||||
}
|
||||
}
|
||||
|
||||
private getBreadcrumbs() {
|
||||
let breadcrumbs = this.state.breadcrumbs;
|
||||
|
||||
if (breadcrumbs.length === 0 && this.props.appTitle) {
|
||||
breadcrumbs = [{ text: this.props.appTitle }];
|
||||
}
|
||||
|
||||
return breadcrumbs.map((breadcrumb, i) => ({
|
||||
...breadcrumb,
|
||||
'data-test-subj': classNames(
|
||||
'breadcrumb',
|
||||
breadcrumb['data-test-subj'],
|
||||
i === 0 && 'first',
|
||||
i === breadcrumbs.length - 1 && 'last'
|
||||
),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ const module = uiModules.get('kibana');
|
|||
|
||||
module.directive('headerGlobalNav', (reactDirective, chrome, Private) => {
|
||||
const navControls = Private(chromeHeaderNavControlsRegistry);
|
||||
const navLinks = chrome.getNavLinks();
|
||||
const homeHref = chrome.addBasePath('/app/kibana#/home');
|
||||
|
||||
return reactDirective(injectI18nProvider(Header), [
|
||||
|
@ -39,7 +38,7 @@ module.directive('headerGlobalNav', (reactDirective, chrome, Private) => {
|
|||
// angular injected React props
|
||||
{
|
||||
breadcrumbs$: chrome.breadcrumbs.get$(),
|
||||
navLinks,
|
||||
navLinks$: chrome.getNavLinks$(),
|
||||
navControls,
|
||||
homeHref
|
||||
});
|
||||
|
|
|
@ -37,4 +37,6 @@ export interface NavLink {
|
|||
url: string;
|
||||
id: string;
|
||||
euiIconType: IconType;
|
||||
lastSubUrl?: string;
|
||||
active: boolean;
|
||||
}
|
||||
|
|
|
@ -74,11 +74,11 @@
|
|||
|
||||
var ticks = [],
|
||||
end = ceilAsLog10(axis.max),
|
||||
start = floorAsLog10(axis.datamin),
|
||||
start = floorAsLog10(axis.min),
|
||||
tick = Number.NaN,
|
||||
i = 0;
|
||||
|
||||
if (axis.datamin === null || axis.datamin <= 0) {
|
||||
if (axis.min === null || axis.min <= 0) {
|
||||
// Bad minimum, make ticks from 1 (10**0) to max
|
||||
start = 0;
|
||||
axis.min = 0.6;
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const PageObjects = getPageObjects(['dashboard', 'header']);
|
||||
const dashboardExpect = getService('dashboardExpect');
|
||||
const pieChart = getService('pieChart');
|
||||
const browser = getService('browser');
|
||||
const log = getService('log');
|
||||
const queryBar = getService('queryBar');
|
||||
|
@ -67,7 +68,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const query = await queryBar.getQueryString();
|
||||
expect(query).to.equal('memory:>220000');
|
||||
|
||||
await dashboardExpect.pieSliceCount(5);
|
||||
await pieChart.expectPieSliceCount(5);
|
||||
await dashboardExpect.panelCount(2);
|
||||
await dashboardExpect.selectedLegendColorCount('#F9D9F9', 5);
|
||||
});
|
||||
|
@ -83,7 +84,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const query = await queryBar.getQueryString();
|
||||
expect(query).to.equal('memory:>220000');
|
||||
|
||||
await dashboardExpect.pieSliceCount(5);
|
||||
await pieChart.expectPieSliceCount(5);
|
||||
await dashboardExpect.panelCount(2);
|
||||
await dashboardExpect.selectedLegendColorCount('#F9D9F9', 5);
|
||||
});
|
||||
|
|
|
@ -24,6 +24,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const filterBar = getService('filterBar');
|
||||
const pieChart = getService('pieChart');
|
||||
const PageObjects = getPageObjects(['dashboard', 'header', 'visualize']);
|
||||
|
||||
describe('dashboard filter bar', async () => {
|
||||
|
@ -92,11 +93,11 @@ export default function ({ getService, getPageObjects }) {
|
|||
it('are added when a pie chart slice is clicked', async function () {
|
||||
await dashboardAddPanel.addVisualization('Rendering Test: pie');
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await PageObjects.dashboard.filterOnPieSlice('4,886');
|
||||
await pieChart.filterOnPieSlice('4,886');
|
||||
const filters = await PageObjects.dashboard.getFilters();
|
||||
expect(filters.length).to.equal(1);
|
||||
|
||||
await dashboardExpect.pieSliceCount(1);
|
||||
await pieChart.expectPieSliceCount(1);
|
||||
});
|
||||
|
||||
it('are preserved after saving a dashboard', async () => {
|
||||
|
@ -106,7 +107,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const filters = await PageObjects.dashboard.getFilters();
|
||||
expect(filters.length).to.equal(1);
|
||||
|
||||
await dashboardExpect.pieSliceCount(1);
|
||||
await pieChart.expectPieSliceCount(1);
|
||||
});
|
||||
|
||||
it('are preserved after opening a dashboard saved with filters', async () => {
|
||||
|
@ -117,7 +118,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const filters = await PageObjects.dashboard.getFilters();
|
||||
expect(filters.length).to.equal(1);
|
||||
|
||||
await dashboardExpect.pieSliceCount(1);
|
||||
await pieChart.expectPieSliceCount(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -25,6 +25,7 @@ import expect from 'expect.js';
|
|||
*/
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const dashboardExpect = getService('dashboardExpect');
|
||||
const pieChart = getService('pieChart');
|
||||
const queryBar = getService('queryBar');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
const renderable = getService('renderable');
|
||||
|
@ -57,7 +58,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('filters on pie charts', async () => {
|
||||
await dashboardExpect.pieSliceCount(0);
|
||||
await pieChart.expectPieSliceCount(0);
|
||||
});
|
||||
|
||||
it('area, bar and heatmap charts filtered', async () => {
|
||||
|
@ -119,7 +120,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('filters on pie charts', async () => {
|
||||
await dashboardExpect.pieSliceCount(0);
|
||||
await pieChart.expectPieSliceCount(0);
|
||||
});
|
||||
|
||||
it('area, bar and heatmap charts filtered', async () => {
|
||||
|
@ -177,7 +178,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('pie charts', async () => {
|
||||
await dashboardExpect.pieSliceCount(5);
|
||||
await pieChart.expectPieSliceCount(5);
|
||||
});
|
||||
|
||||
it('area, bar and heatmap charts', async () => {
|
||||
|
@ -238,7 +239,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await dashboardAddPanel.addVisualization('Rendering-Test:-animal-sounds-pie');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await dashboardExpect.pieSliceCount(5);
|
||||
await pieChart.expectPieSliceCount(5);
|
||||
|
||||
await dashboardPanelActions.openContextMenu();
|
||||
await dashboardPanelActions.clickEdit();
|
||||
|
@ -250,13 +251,13 @@ export default function ({ getService, getPageObjects }) {
|
|||
// We are on the visualize page, not dashboard, so can't use "PageObjects.dashboard.waitForRenderComplete();"
|
||||
// as that expects an item with the `data-shared-items-count` tag.
|
||||
await renderable.waitForRender();
|
||||
await dashboardExpect.pieSliceCount(3);
|
||||
await pieChart.expectPieSliceCount(3);
|
||||
|
||||
await PageObjects.visualize.saveVisualizationExpectSuccess('Rendering Test: animal sounds pie');
|
||||
await PageObjects.header.clickDashboard();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await dashboardExpect.pieSliceCount(3);
|
||||
await pieChart.expectPieSliceCount(3);
|
||||
});
|
||||
|
||||
it('Nested visualization filter pills filters data as expected', async () => {
|
||||
|
@ -264,14 +265,14 @@ export default function ({ getService, getPageObjects }) {
|
|||
await dashboardPanelActions.clickEdit();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await renderable.waitForRender();
|
||||
await PageObjects.dashboard.filterOnPieSlice('grr');
|
||||
await pieChart.filterOnPieSlice('grr');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await dashboardExpect.pieSliceCount(1);
|
||||
await pieChart.expectPieSliceCount(1);
|
||||
|
||||
await PageObjects.visualize.saveVisualizationExpectSuccess('animal sounds pie');
|
||||
await PageObjects.header.clickDashboard();
|
||||
|
||||
await dashboardExpect.pieSliceCount(1);
|
||||
await pieChart.expectPieSliceCount(1);
|
||||
});
|
||||
|
||||
it('Removing filter pills and query unfiters data as expected', async () => {
|
||||
|
@ -283,17 +284,17 @@ export default function ({ getService, getPageObjects }) {
|
|||
await queryBar.submitQuery();
|
||||
await filterBar.removeFilter('sound.keyword');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await dashboardExpect.pieSliceCount(5);
|
||||
await pieChart.expectPieSliceCount(5);
|
||||
|
||||
await PageObjects.visualize.saveVisualization('Rendering Test: animal sounds pie');
|
||||
await PageObjects.header.clickDashboard();
|
||||
|
||||
await dashboardExpect.pieSliceCount(5);
|
||||
await pieChart.expectPieSliceCount(5);
|
||||
});
|
||||
|
||||
it('Pie chart linked to saved search filters data', async () => {
|
||||
await dashboardAddPanel.addVisualization('Filter Test: animals: linked to search with filter');
|
||||
await dashboardExpect.pieSliceCount(7);
|
||||
await pieChart.expectPieSliceCount(7);
|
||||
});
|
||||
|
||||
it('Pie chart linked to saved search filters shows no data with conflicting dashboard query', async () => {
|
||||
|
@ -301,7 +302,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await queryBar.submitQuery();
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
|
||||
await dashboardExpect.pieSliceCount(5);
|
||||
await pieChart.expectPieSliceCount(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const dashboardExpect = getService('dashboardExpect');
|
||||
const pieChart = getService('pieChart');
|
||||
const queryBar = getService('queryBar');
|
||||
const PageObjects = getPageObjects(['dashboard', 'discover']);
|
||||
|
||||
|
@ -37,7 +37,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const headers = await PageObjects.discover.getColumnHeaders();
|
||||
expect(headers.length).to.be(0);
|
||||
|
||||
await dashboardExpect.pieSliceCount(0);
|
||||
await pieChart.expectPieSliceCount(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
const testSubjects = getService('testSubjects');
|
||||
const browser = getService('browser');
|
||||
const queryBar = getService('queryBar');
|
||||
const pieChart = getService('pieChart');
|
||||
const inspector = getService('inspector');
|
||||
const retry = getService('retry');
|
||||
const dashboardPanelActions = getService('dashboardPanelActions');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
|
@ -140,8 +142,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.dashboard.saveDashboard('No local edits');
|
||||
|
||||
await dashboardPanelActions.openInspector();
|
||||
const tileMapData = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
const tileMapData = await inspector.getTableData();
|
||||
await inspector.close();
|
||||
|
||||
await PageObjects.dashboard.switchToEditMode();
|
||||
await dashboardPanelActions.openContextMenu();
|
||||
|
@ -157,8 +159,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.header.clickDashboard();
|
||||
|
||||
await dashboardPanelActions.openInspector();
|
||||
const changedTileMapData = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
const changedTileMapData = await inspector.getTableData();
|
||||
await inspector.close();
|
||||
expect(changedTileMapData.length).to.not.equal(tileMapData.length);
|
||||
});
|
||||
|
||||
|
@ -228,7 +230,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
await retry.try(async () => {
|
||||
const allPieSlicesColor = await PageObjects.visualize.getAllPieSliceStyles('80,000');
|
||||
const allPieSlicesColor = await pieChart.getAllPieSliceStyles('80,000');
|
||||
let whitePieSliceCounts = 0;
|
||||
allPieSlicesColor.forEach(style => {
|
||||
if (style.indexOf('rgb(255, 255, 255)') > 0) {
|
||||
|
@ -255,7 +257,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
await retry.try(async () => {
|
||||
const pieSliceStyle = await PageObjects.visualize.getPieSliceStyle('80,000');
|
||||
const pieSliceStyle = await pieChart.getPieSliceStyle('80,000');
|
||||
// The default green color that was stored with the visualization before any dashboard overrides.
|
||||
expect(pieSliceStyle.indexOf('rgb(87, 193, 123)')).to.be.greaterThan(0);
|
||||
});
|
||||
|
|
|
@ -21,6 +21,7 @@ import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const dashboardExpect = getService('dashboardExpect');
|
||||
const pieChart = getService('pieChart');
|
||||
const dashboardVisualizations = getService('dashboardVisualizations');
|
||||
const PageObjects = getPageObjects(['dashboard', 'header', 'visualize']);
|
||||
|
||||
|
@ -41,10 +42,10 @@ export default function ({ getService, getPageObjects }) {
|
|||
it('Visualization updated when time picker changes', async () => {
|
||||
await PageObjects.dashboard.clickNewDashboard();
|
||||
await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]);
|
||||
await dashboardExpect.pieSliceCount(0);
|
||||
await pieChart.expectPieSliceCount(0);
|
||||
|
||||
await PageObjects.dashboard.setTimepickerInHistoricalDataRange();
|
||||
await dashboardExpect.pieSliceCount(10);
|
||||
await pieChart.expectPieSliceCount(10);
|
||||
});
|
||||
|
||||
it('Saved search updated when time picker changes', async () => {
|
||||
|
|
|
@ -30,12 +30,13 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const find = getService('find');
|
||||
const browser = getService('browser');
|
||||
const pieChart = getService('pieChart');
|
||||
const dashboardExpect = getService('dashboardExpect');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'discover']);
|
||||
|
||||
const expectAllDataRenders = async () => {
|
||||
await dashboardExpect.pieSliceCount(16);
|
||||
await pieChart.expectPieSliceCount(16);
|
||||
await dashboardExpect.seriesElementCount(19);
|
||||
await dashboardExpect.dataTableRowCount(5);
|
||||
await dashboardExpect.savedSearchRowCount(50);
|
||||
|
@ -57,7 +58,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
};
|
||||
|
||||
const expectNoDataRenders = async () => {
|
||||
await dashboardExpect.pieSliceCount(0);
|
||||
await pieChart.expectPieSliceCount(0);
|
||||
await dashboardExpect.seriesElementCount(0);
|
||||
await dashboardExpect.dataTableRowCount(0);
|
||||
await dashboardExpect.savedSearchRowCount(0);
|
||||
|
|
|
@ -21,7 +21,7 @@ import path from 'path';
|
|||
import expect from 'expect.js';
|
||||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const dashboardExpect = getService('dashboardExpect');
|
||||
const pieChart = getService('pieChart');
|
||||
const PageObjects = getPageObjects(['dashboard', 'header', 'settings', 'common']);
|
||||
|
||||
describe('dashboard time zones', () => {
|
||||
|
@ -43,7 +43,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
it('Exported dashboard adjusts EST time to UTC', async () => {
|
||||
const timeRange = await PageObjects.header.getPrettyDuration();
|
||||
expect(timeRange).to.be('April 10th 2018, 03:00:00.000 to April 10th 2018, 04:00:00.000');
|
||||
await dashboardExpect.pieSliceCount(4);
|
||||
await pieChart.expectPieSliceCount(4);
|
||||
});
|
||||
|
||||
it('Changing timezone changes dashboard timestamp and shows the same data', async () => {
|
||||
|
@ -54,7 +54,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.dashboard.loadSavedDashboard('time zone test');
|
||||
const timeRange = await PageObjects.header.getPrettyDuration();
|
||||
expect(timeRange).to.be('April 9th 2018, 22:00:00.000 to April 9th 2018, 23:00:00.000');
|
||||
await dashboardExpect.pieSliceCount(4);
|
||||
await pieChart.expectPieSliceCount(4);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const PageObjects = getPageObjects(['common', 'header', 'visualize']);
|
||||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const inspector = getService('inspector');
|
||||
|
||||
const STATS_ROW_NAME_INDEX = 0;
|
||||
const STATS_ROW_VALUE_INDEX = 1;
|
||||
|
@ -47,12 +48,12 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await PageObjects.visualize.closeInspector();
|
||||
await inspector.close();
|
||||
});
|
||||
|
||||
it('should display request stats with no results', async () => {
|
||||
await PageObjects.visualize.openInspector();
|
||||
const requestStats = await PageObjects.visualize.getInspectorTableData();
|
||||
await inspector.open();
|
||||
const requestStats = await inspector.getTableData();
|
||||
|
||||
expect(getHitCount(requestStats)).to.be('0');
|
||||
});
|
||||
|
@ -60,8 +61,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
it('should display request stats with results', async () => {
|
||||
await PageObjects.header.setAbsoluteRange('2015-09-19 06:31:44.000', '2015-09-23 18:31:44.000');
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
const requestStats = await PageObjects.visualize.getInspectorTableData();
|
||||
await inspector.open();
|
||||
const requestStats = await inspector.getTableData();
|
||||
|
||||
expect(getHitCount(requestStats)).to.be('14004');
|
||||
});
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const retry = getService('retry');
|
||||
const find = getService('find');
|
||||
const pieChart = getService('pieChart');
|
||||
const dashboardExpect = getService('dashboardExpect');
|
||||
const PageObjects = getPageObjects(['common', 'header', 'home', 'dashboard']);
|
||||
|
||||
|
@ -91,7 +92,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
|
||||
it.skip('pie charts rendered', async () => {
|
||||
await dashboardExpect.pieSliceCount(4);
|
||||
await pieChart.expectPieSliceCount(4);
|
||||
});
|
||||
|
||||
it.skip('area, bar and heatmap charts rendered', async () => {
|
||||
|
|
|
@ -36,6 +36,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const log = getService('log');
|
||||
const browser = getService('browser');
|
||||
const retry = getService('retry');
|
||||
const inspector = getService('inspector');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const PageObjects = getPageObjects(['common', 'header', 'settings', 'visualize', 'discover']);
|
||||
|
||||
|
@ -131,13 +132,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
await PageObjects.visualize.openInspector();
|
||||
await PageObjects.visualize.setInspectorTablePageSize(50);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await log.debug('getDataTableData = ' + data);
|
||||
await log.debug('data=' + data);
|
||||
await log.debug('data.length=' + data.length);
|
||||
expect(data).to.eql(expectedChartValues);
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(50);
|
||||
await inspector.expectTableData(expectedChartValues);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -195,12 +192,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await log.debug('getDataTableData = ' + data);
|
||||
await log.debug('data=' + data);
|
||||
await log.debug('data.length=' + data.length);
|
||||
expect(data).to.eql([
|
||||
await inspector.open();
|
||||
await inspector.expectTableData([
|
||||
['good', '359'],
|
||||
['bad', '27']
|
||||
]);
|
||||
|
@ -261,12 +254,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await log.debug('getDataTableData = ' + data);
|
||||
await log.debug('data=' + data);
|
||||
await log.debug('data.length=' + data.length);
|
||||
expect(data).to.eql([
|
||||
await inspector.open();
|
||||
await inspector.expectTableData([
|
||||
['true', '359'],
|
||||
['false', '27']
|
||||
]);
|
||||
|
@ -327,13 +316,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
await PageObjects.visualize.openInspector();
|
||||
await PageObjects.visualize.setInspectorTablePageSize(50);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await log.debug('getDataTableData = ' + data);
|
||||
await log.debug('data=' + data);
|
||||
await log.debug('data.length=' + data.length);
|
||||
expect(data).to.eql([
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(50);
|
||||
await inspector.expectTableData([
|
||||
['2015-09-17 20:00', '1'],
|
||||
['2015-09-17 21:00', '1'],
|
||||
['2015-09-17 23:00', '1'],
|
||||
|
|
|
@ -21,6 +21,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const browser = getService('browser');
|
||||
const retry = getService('retry');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings']);
|
||||
|
@ -81,12 +82,10 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.waitForVisualizationSavedToastGone();
|
||||
await PageObjects.visualize.loadSavedVisualization(vizName1);
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
return PageObjects.common.sleep(2000);
|
||||
});
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct chart', async function () {
|
||||
|
@ -140,11 +139,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
['2015-09-22 21:00', '29']
|
||||
];
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
await PageObjects.visualize.setInspectorTablePageSize(50);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
log.debug('getDataTableData = ' + data);
|
||||
expect(data).to.eql(expectedTableData);
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(50);
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
});
|
||||
|
||||
it('should hide side editor if embed is set to true in url', async () => {
|
||||
|
|
|
@ -21,6 +21,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const retry = getService('retry');
|
||||
const filterBar = getService('filterBar');
|
||||
const renderable = getService('renderable');
|
||||
|
@ -77,8 +78,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct data', function () {
|
||||
|
@ -96,11 +96,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
];
|
||||
|
||||
return retry.try(async function () {
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedChartData);
|
||||
await inspector.open();
|
||||
await inspector.expectTableData(expectedChartData);
|
||||
await inspector.close();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const retry = getService('retry');
|
||||
const filterBar = getService('filterBar');
|
||||
const renderable = getService('renderable');
|
||||
|
@ -72,8 +73,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct data', function () {
|
||||
|
@ -91,11 +91,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
];
|
||||
|
||||
return retry.try(async function () {
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedChartData);
|
||||
await inspector.open();
|
||||
await inspector.expectTableData(expectedChartData);
|
||||
await inspector.close();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const inspector = getService('inspector');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
|
||||
describe('gauge chart', function indexPatternCreation() {
|
||||
|
@ -40,8 +41,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show Count', function () {
|
||||
|
|
|
@ -21,6 +21,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
|
||||
describe('heatmap chart', function indexPatternCreation() {
|
||||
|
@ -69,8 +70,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct data', async function () {
|
||||
|
@ -99,11 +99,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
];
|
||||
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedChartData);
|
||||
await PageObjects.visualize.closeInspector();
|
||||
await inspector.open();
|
||||
await inspector.expectTableData(expectedChartData);
|
||||
await inspector.close();
|
||||
});
|
||||
|
||||
it('should show 4 color ranges as default colorNumbers param', async function () {
|
||||
|
|
|
@ -23,6 +23,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const filterBar = getService('filterBar');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const inspector = getService('inspector');
|
||||
const find = getService('find');
|
||||
const comboBox = getService('comboBox');
|
||||
|
||||
|
@ -44,8 +45,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
|
||||
it('should not have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(false);
|
||||
await inspector.expectIsNotEnabled();
|
||||
});
|
||||
|
||||
describe('updateFiltersOnChange is false', () => {
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const filterBar = getService('filterBar');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
|
||||
|
@ -39,9 +39,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
describe('inspector table', function indexPatternCreation() {
|
||||
it('should update table header when columns change', async function () {
|
||||
await PageObjects.visualize.openInspector();
|
||||
let headers = await PageObjects.visualize.getInspectorTableHeaders();
|
||||
expect(headers).to.eql(['Count']);
|
||||
await inspector.open();
|
||||
await inspector.expectTableHeaders(['Count']);
|
||||
|
||||
log.debug('Add Average Metric on machine.ram field');
|
||||
await PageObjects.visualize.clickAddMetric();
|
||||
|
@ -49,10 +48,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.selectAggregation('Average', 'metrics');
|
||||
await PageObjects.visualize.selectField('machine.ram', 'metrics');
|
||||
await PageObjects.visualize.clickGo();
|
||||
await PageObjects.visualize.openInspector();
|
||||
|
||||
headers = await PageObjects.visualize.getInspectorTableHeaders();
|
||||
expect(headers).to.eql(['Count', 'Average machine.ram']);
|
||||
await inspector.open();
|
||||
await inspector.expectTableHeaders(['Count', 'Average machine.ram']);
|
||||
});
|
||||
|
||||
describe('filtering on inspector table values', function () {
|
||||
|
@ -67,33 +64,30 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
beforeEach(async function () {
|
||||
await PageObjects.visualize.openInspector();
|
||||
await inspector.open();
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await PageObjects.visualize.closeInspector();
|
||||
await inspector.close();
|
||||
await filterBar.removeFilter('machine.os.raw');
|
||||
});
|
||||
|
||||
it('should allow filtering for values', async function () {
|
||||
let data = await PageObjects.visualize.getInspectorTableData();
|
||||
expect(data).to.eql([
|
||||
await inspector.expectTableData([
|
||||
['win 8', '2,904', '13,031,579,645.108'],
|
||||
['win xp', '2,858', '13,073,190,186.423'],
|
||||
['Other', '6,920', '13,123,599,766.011'],
|
||||
]);
|
||||
|
||||
await PageObjects.visualize.filterForInspectorTableCell(1, 1);
|
||||
data = await PageObjects.visualize.getInspectorTableData();
|
||||
expect(data).to.eql([
|
||||
await inspector.filterForTableCell(1, 1);
|
||||
await inspector.expectTableData([
|
||||
['win 8', '2,904', '13,031,579,645.108'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should allow filtering out values', async function () {
|
||||
await PageObjects.visualize.filterOutInspectorTableCell(1, 1);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
expect(data).to.eql([
|
||||
await inspector.filterOutTableCell(1, 1);
|
||||
await inspector.expectTableData([
|
||||
['win xp', '2,858', '13,073,190,186.423'],
|
||||
['win 7', '2,814', '13,186,695,551.251'],
|
||||
['Other', '4,106', '13,080,420,659.354'],
|
||||
|
@ -101,9 +95,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should allow filtering for other values', async function () {
|
||||
await PageObjects.visualize.filterForInspectorTableCell(1, 3);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
expect(data).to.eql([
|
||||
await inspector.filterForTableCell(1, 3);
|
||||
await inspector.expectTableData([
|
||||
['win 7', '2,814', '13,186,695,551.251'],
|
||||
['ios', '2,784', '13,009,497,206.823'],
|
||||
['Other', '1,322', '13,228,964,670.613'],
|
||||
|
@ -111,9 +104,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should allow filtering out other values', async function () {
|
||||
await PageObjects.visualize.filterOutInspectorTableCell(1, 3);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
expect(data).to.eql([
|
||||
await inspector.filterOutTableCell(1, 3);
|
||||
await inspector.expectTableData([
|
||||
['win 8', '2,904', '13,031,579,645.108'],
|
||||
['win xp', '2,858', '13,073,190,186.423'],
|
||||
]);
|
||||
|
|
|
@ -21,6 +21,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const retry = getService('retry');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
|
||||
|
@ -52,7 +53,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
before(initLineChart);
|
||||
|
||||
afterEach(async () => {
|
||||
await PageObjects.visualize.closeInspector();
|
||||
await inspector.close();
|
||||
});
|
||||
|
||||
it('should show correct chart', async function () {
|
||||
|
@ -77,8 +78,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct chart order by Term', async function () {
|
||||
|
@ -107,10 +107,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
const expectedChartData = [['png', '1,373'], ['php', '445'], ['jpg', '9,109'], ['gif', '918'], ['css', '2,159']];
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedChartData);
|
||||
await inspector.open();
|
||||
await inspector.expectTableData(expectedChartData);
|
||||
});
|
||||
|
||||
it('should be able to save and load', async function () {
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getPageObjects, getService }) {
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
const find = getService('find');
|
||||
const inspector = getService('inspector');
|
||||
const markdown = `
|
||||
# Heading 1
|
||||
|
||||
|
@ -39,8 +40,7 @@ export default function ({ getPageObjects, getService }) {
|
|||
describe('markdown vis', async () => {
|
||||
|
||||
it('should not have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(false);
|
||||
await inspector.expectIsNotEnabled();
|
||||
});
|
||||
|
||||
it('should render markdown as html', async function () {
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const inspector = getService('inspector');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
|
||||
describe('metric chart', function () {
|
||||
|
@ -39,8 +40,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show Count', async function () {
|
||||
|
|
|
@ -22,6 +22,8 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const filterBar = getService('filterBar');
|
||||
const pieChart = getService('pieChart');
|
||||
const inspector = getService('inspector');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings']);
|
||||
const fromTime = '2015-09-19 06:31:44.000';
|
||||
const toTime = '2015-09-23 18:31:44.000';
|
||||
|
@ -58,22 +60,15 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.waitForVisualizationSavedToastGone();
|
||||
await PageObjects.visualize.loadSavedVisualization(vizName1);
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
// sleep a bit before trying to get the pie chart data below
|
||||
await PageObjects.common.sleep(2000);
|
||||
});
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
|
||||
it('should show 10 slices in pie chart', async function () {
|
||||
const expectedPieChartSliceCount = 10;
|
||||
|
||||
const pieData = await PageObjects.visualize.getPieChartData();
|
||||
log.debug('pieData.length = ' + pieData.length);
|
||||
expect(pieData.length).to.be(expectedPieChartSliceCount);
|
||||
pieChart.expectPieSliceCount(10);
|
||||
});
|
||||
|
||||
it('should show correct data', async function () {
|
||||
|
@ -81,11 +76,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
['160,000', '44'], ['200,000', '40'], ['240,000', '46'], ['280,000', '39'], ['320,000', '40'], ['360,000', '47']
|
||||
];
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
await PageObjects.visualize.setInspectorTablePageSize(50);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedTableData);
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(50);
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
});
|
||||
|
||||
describe('other bucket', () => {
|
||||
|
@ -108,35 +101,29 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.toggleMissingBucket();
|
||||
log.debug('clickGo');
|
||||
await PageObjects.visualize.clickGo();
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug(`pieData.length = ${pieData.length}`);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
await pieChart.expectPieChartLabels(expectedTableData);
|
||||
});
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/25955
|
||||
it.skip('should apply correct filter on other bucket', async () => {
|
||||
it('should apply correct filter on other bucket', async () => {
|
||||
const expectedTableData = [ 'Missing', 'osx' ];
|
||||
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.visualize.filterPieSlice('Other');
|
||||
await pieChart.filterOnPieSlice('Other');
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug(`pieData.length = ${pieData.length}`);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
await pieChart.expectPieChartLabels(expectedTableData);
|
||||
await filterBar.removeFilter('machine.os.raw');
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
});
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/26323
|
||||
it.skip('should apply correct filter on other bucket by clicking on a legend', async () => {
|
||||
it('should apply correct filter on other bucket by clicking on a legend', async () => {
|
||||
const expectedTableData = [ 'Missing', 'osx' ];
|
||||
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.visualize.filterLegend('Other');
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug(`pieData.length = ${pieData.length}`);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
await pieChart.expectPieChartLabels(expectedTableData);
|
||||
await filterBar.removeFilter('machine.os.raw');
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
});
|
||||
|
||||
it('should show two levels of other buckets', async () => {
|
||||
|
@ -155,9 +142,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.toggleMissingBucket();
|
||||
log.debug('clickGo');
|
||||
await PageObjects.visualize.clickGo();
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug(`pieData.length = ${pieData.length}`);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
await pieChart.expectPieChartLabels(expectedTableData);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -179,9 +164,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.toggleDisabledAgg(2);
|
||||
await PageObjects.visualize.clickGo();
|
||||
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug('pieData.length = ' + pieData.length);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
await pieChart.expectPieChartLabels(expectedTableData);
|
||||
});
|
||||
|
||||
it('should correctly save disabled agg', async () => {
|
||||
|
@ -194,9 +177,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.waitForVisualization();
|
||||
|
||||
const expectedTableData = [ 'win 8', 'win xp', 'win 7', 'ios', 'osx' ];
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug('pieData.length = ' + pieData.length);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
await pieChart.expectPieChartLabels(expectedTableData);
|
||||
});
|
||||
|
||||
it('should show correct result when agg is re-enabled', async () => {
|
||||
|
@ -209,9 +190,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
'win 8', 'ios', 'win 7', 'win xp', 'osx', '200,000', 'win 8', 'ios', 'win xp', 'win 7', 'osx', '240,000',
|
||||
'ios', 'win 7', 'win xp', 'win 8', 'osx', '280,000', 'win xp', 'win 8', 'win 7', 'ios', 'osx', '320,000',
|
||||
'win xp', 'win 7', 'ios', 'win 8', 'osx', '360,000', 'win 7', 'win xp', 'ios', 'win 8', 'osx' ];
|
||||
const pieData = await PageObjects.visualize.getPieChartLabels();
|
||||
log.debug('pieData.length = ' + pieData.length);
|
||||
expect(pieData).to.eql(expectedTableData);
|
||||
|
||||
await pieChart.expectPieChartLabels(expectedTableData);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -239,7 +219,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
log.debug('Switch to a different time range from \"' + emptyFromTime + '\" to \"' + emptyToTime + '\"');
|
||||
await PageObjects.header.setAbsoluteRange(emptyFromTime, emptyToTime);
|
||||
await PageObjects.visualize.waitForVisualization();
|
||||
await PageObjects.visualize.expectPieChartError();
|
||||
await PageObjects.visualize.expectError();
|
||||
});
|
||||
});
|
||||
describe('multi series slice', () => {
|
||||
|
@ -323,12 +303,10 @@ export default function ({ getService, getPageObjects }) {
|
|||
[ 'osx', '1,322', 'ID', '56' ],
|
||||
[ 'osx', '1,322', 'BR', '30' ]
|
||||
];
|
||||
await PageObjects.visualize.openInspector();
|
||||
await PageObjects.visualize.setInspectorTablePageSize(50);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedTableData);
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(50);
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
await inspector.close();
|
||||
});
|
||||
|
||||
it ('correctly applies filter', async () => {
|
||||
|
@ -336,12 +314,10 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.filterLegend('CN');
|
||||
await PageObjects.visualize.applyFilters();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.visualize.openInspector();
|
||||
await PageObjects.visualize.setInspectorTablePageSize(50);
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedTableData);
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(50);
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
await inspector.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const fromTime = '2015-09-19 06:31:44.000';
|
||||
const toTime = '2015-09-23 18:31:44.000';
|
||||
|
||||
const inspector = getService('inspector');
|
||||
const log = getService('log');
|
||||
const find = getService('find');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings']);
|
||||
|
@ -51,15 +52,13 @@ export default function ({ getService, getPageObjects }) {
|
|||
describe('vector map', function indexPatternCreation() {
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show results after clicking play (join on states)', async function () {
|
||||
const expectedData = [['CN', '2,592'], ['IN', '2,373'], ['US', '1,194'], ['ID', '489'], ['BR', '415']];
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
expect(data).to.eql(expectedData);
|
||||
await inspector.open();
|
||||
await inspector.expectTableData(expectedData);
|
||||
});
|
||||
|
||||
it('should change results after changing layer to world', async function () {
|
||||
|
@ -76,8 +75,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.selectFieldById('ISO 3166-1 alpha-2 code', 'joinField');
|
||||
await PageObjects.common.sleep(2000);//need some time for the data to load
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
const actualData = await PageObjects.visualize.getInspectorTableData();
|
||||
await inspector.open();
|
||||
const actualData = await inspector.getTableData();
|
||||
const expectedData = [['CN', '2,592'], ['IN', '2,373'], ['US', '1,194'], ['ID', '489'], ['BR', '415']];
|
||||
expect(actualData).to.eql(expectedData);
|
||||
});
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const filterBar = getService('filterBar');
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const browser = getService('browser');
|
||||
const retry = getService('retry');
|
||||
const find = getService('find');
|
||||
|
@ -55,8 +56,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct tag cloud data', async function () {
|
||||
|
@ -127,11 +127,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
[ '18,253,611,008', '679' ]
|
||||
];
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
await await PageObjects.visualize.setInspectorTablePageSize('50');
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedTableData);
|
||||
await inspector.open();
|
||||
await await inspector.setTablePageSize('50');
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
});
|
||||
|
||||
describe('formatted field', function () {
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const inspector = getService('inspector');
|
||||
const find = getService('find');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const browser = getService('browser');
|
||||
|
@ -104,8 +105,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
describe('tile map chart', function indexPatternCreation() {
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct tile map data on default zoom level', async function () {
|
||||
|
@ -122,10 +122,10 @@ export default function ({ getService, getPageObjects }) {
|
|||
//level 0
|
||||
await PageObjects.visualize.clickMapZoomOut();
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
await PageObjects.visualize.setInspectorTablePageSize(50);
|
||||
const actualTableData = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(50);
|
||||
const actualTableData = await inspector.getTableData();
|
||||
await inspector.close();
|
||||
compareTableData(actualTableData, expectedTableData);
|
||||
});
|
||||
|
||||
|
@ -161,9 +161,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
];
|
||||
|
||||
await PageObjects.visualize.clickMapFitDataBounds();
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
await inspector.open();
|
||||
const data = await inspector.getTableData();
|
||||
await inspector.close();
|
||||
compareTableData(data, expectedPrecision2DataTable);
|
||||
});
|
||||
|
||||
|
@ -174,13 +174,13 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.clickMapZoomIn();
|
||||
|
||||
const mapBounds = await PageObjects.visualize.getMapBounds();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
await inspector.close();
|
||||
|
||||
await PageObjects.visualize.saveVisualizationExpectSuccess(vizName1);
|
||||
|
||||
const afterSaveMapBounds = await PageObjects.visualize.getMapBounds();
|
||||
|
||||
await PageObjects.visualize.closeInspector();
|
||||
await inspector.close();
|
||||
// For some reason the values are slightly different, so we can't check that they are equal. But we did
|
||||
// have a bug where after the save, there were _no_ map bounds. So this checks for the later case, but
|
||||
// until we figure out how to make sure the map center is always the exact same, we can't comparison check.
|
||||
|
@ -195,20 +195,18 @@ export default function ({ getService, getPageObjects }) {
|
|||
it('when checked adds filters to aggregation', async () => {
|
||||
const vizName1 = 'Visualization TileMap';
|
||||
await PageObjects.visualize.loadSavedVisualization(vizName1);
|
||||
await PageObjects.visualize.openInspector();
|
||||
const tableHeaders = await PageObjects.visualize.getInspectorTableHeaders();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
expect(tableHeaders).to.eql(['filter', 'geohash_grid', 'Count', 'Geo Centroid']);
|
||||
await inspector.open();
|
||||
await inspector.expectTableHeaders(['filter', 'geohash_grid', 'Count', 'Geo Centroid']);
|
||||
await inspector.close();
|
||||
});
|
||||
|
||||
it('when not checked does not add filters to aggregation', async () => {
|
||||
await PageObjects.visualize.toggleOpenEditor(2);
|
||||
await PageObjects.visualize.toggleIsFilteredByCollarCheckbox();
|
||||
await PageObjects.visualize.clickGo();
|
||||
await PageObjects.visualize.openInspector();
|
||||
const tableHeaders = await PageObjects.visualize.getInspectorTableHeaders();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
expect(tableHeaders).to.eql(['geohash_grid', 'Count', 'Geo Centroid']);
|
||||
await inspector.open();
|
||||
await inspector.expectTableHeaders(['geohash_grid', 'Count', 'Geo Centroid']);
|
||||
await inspector.close();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const retry = getService('retry');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings', 'visualBuilder']);
|
||||
|
||||
|
@ -70,8 +71,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should not have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(false);
|
||||
await inspector.expectIsNotEnabled();
|
||||
});
|
||||
|
||||
it('should show correct data', async function () {
|
||||
|
@ -91,8 +91,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should not have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(false);
|
||||
await inspector.expectIsNotEnabled();
|
||||
});
|
||||
|
||||
it('should show correct data', async function () {
|
||||
|
|
|
@ -21,6 +21,7 @@ import expect from 'expect.js';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
|
||||
describe('visualize app', () => {
|
||||
|
@ -33,8 +34,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
|
||||
describe('vega chart', () => {
|
||||
it('should not have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(false);
|
||||
await inspector.expectIsNotEnabled();
|
||||
});
|
||||
|
||||
it.skip('should have some initial vega spec text', async function () {
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const inspector = getService('inspector');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
|
||||
describe('vertical bar chart', function () {
|
||||
|
@ -64,8 +65,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct chart', async function () {
|
||||
|
@ -109,11 +109,9 @@ export default function ({ getService, getPageObjects }) {
|
|||
[ '2015-09-22 09:00', '1,408' ],
|
||||
];
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
await PageObjects.visualize.closeInspector();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedChartData);
|
||||
await inspector.open();
|
||||
await inspector.expectTableData(expectedChartData);
|
||||
await inspector.close();
|
||||
});
|
||||
|
||||
it('should have `drop partial buckets` option', async () => {
|
||||
|
|
|
@ -22,6 +22,7 @@ import expect from 'expect.js';
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const inspector = getService('inspector');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'header']);
|
||||
|
||||
describe.skip('vertical bar chart with index without time filter', function () {
|
||||
|
@ -61,8 +62,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
|
||||
it('should have inspector enabled', async function () {
|
||||
const spyToggleExists = await PageObjects.visualize.isInspectorButtonEnabled();
|
||||
expect(spyToggleExists).to.be(true);
|
||||
await inspector.expectIsEnabled();
|
||||
});
|
||||
|
||||
it('should show correct chart', async function () {
|
||||
|
@ -106,10 +106,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
[ '2015-09-22 09:00', '1,408' ],
|
||||
];
|
||||
|
||||
await PageObjects.visualize.openInspector();
|
||||
const data = await PageObjects.visualize.getInspectorTableData();
|
||||
log.debug(data);
|
||||
expect(data).to.eql(expectedChartData);
|
||||
await inspector.open();
|
||||
await inspector.expectTableData(expectedChartData);
|
||||
});
|
||||
|
||||
describe.skip('switch between Y axis scale types', () => {
|
||||
|
|
|
@ -55,6 +55,8 @@ import {
|
|||
RenderableProvider,
|
||||
TableProvider,
|
||||
BrowserProvider,
|
||||
InspectorProvider,
|
||||
PieChartProvider,
|
||||
} from './services';
|
||||
|
||||
export default async function ({ readConfigFile }) {
|
||||
|
@ -115,6 +117,8 @@ export default async function ({ readConfigFile }) {
|
|||
renderable: RenderableProvider,
|
||||
table: TableProvider,
|
||||
browser: BrowserProvider,
|
||||
pieChart: PieChartProvider,
|
||||
inspector: InspectorProvider,
|
||||
},
|
||||
servers: commonConfig.get('servers'),
|
||||
|
||||
|
|
|
@ -125,7 +125,9 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
|
|||
*/
|
||||
async onDashboardLandingPage() {
|
||||
log.debug(`onDashboardLandingPage`);
|
||||
return await testSubjects.exists('dashboardLandingPage', 5000);
|
||||
return await testSubjects.exists('dashboardLandingPage', {
|
||||
timeout: 5000
|
||||
});
|
||||
}
|
||||
|
||||
async expectExistsDashboardLandingPage() {
|
||||
|
@ -560,28 +562,6 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
|
|||
return _.map(filters, async (filter) => await filter.getVisibleText());
|
||||
}
|
||||
|
||||
async getPieSliceCount(timeout) {
|
||||
log.debug('getPieSliceCount');
|
||||
return await retry.try(async () => {
|
||||
const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice', timeout);
|
||||
return slices.length;
|
||||
});
|
||||
}
|
||||
|
||||
async filterOnPieSlice(sliceValue) {
|
||||
log.debug(`Filtering on a pie slice with optional value ${sliceValue}`);
|
||||
if (sliceValue) {
|
||||
await testSubjects.click(`pieSlice-${sliceValue}`);
|
||||
} else {
|
||||
// If no pie slice has been provided, find the first one available.
|
||||
await retry.try(async () => {
|
||||
const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice');
|
||||
log.debug('Slices found:' + slices.length);
|
||||
return slices[0].click();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async getSharedItemsCount() {
|
||||
log.debug('in getSharedItemsCount');
|
||||
const attributeName = 'data-shared-items-count';
|
||||
|
|
|
@ -254,8 +254,10 @@ export function HeaderPageProvider({ getService, getPageObjects }) {
|
|||
}
|
||||
|
||||
async awaitGlobalLoadingIndicatorHidden() {
|
||||
log.debug('awaitGlobalLoadingIndicatorHidden');
|
||||
await testSubjects.find('globalLoadingIndicator-hidden', defaultFindTimeout * 10);
|
||||
await testSubjects.existOrFail('globalLoadingIndicator-hidden', {
|
||||
allowHidden: true,
|
||||
timeout: defaultFindTimeout * 10
|
||||
});
|
||||
}
|
||||
|
||||
async awaitKibanaChrome() {
|
||||
|
|
|
@ -90,7 +90,9 @@ export function HomePageProvider({ getService }) {
|
|||
async loadSavedObjects() {
|
||||
await retry.try(async () => {
|
||||
await testSubjects.click('loadSavedObjects');
|
||||
const successMsgExists = await testSubjects.exists('loadSavedObjects_success', 5000);
|
||||
const successMsgExists = await testSubjects.exists('loadSavedObjects_success', {
|
||||
timeout: 5000
|
||||
});
|
||||
if (!successMsgExists) {
|
||||
throw new Error('Failed to load saved objects');
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
const retry = getService('retry');
|
||||
const find = getService('find');
|
||||
const log = getService('log');
|
||||
const flyout = getService('flyout');
|
||||
const inspector = getService('inspector');
|
||||
const renderable = getService('renderable');
|
||||
const table = getService('table');
|
||||
const PageObjects = getPageObjects(['common', 'header']);
|
||||
|
@ -289,41 +289,10 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
await options[optionIndex].click();
|
||||
}
|
||||
|
||||
async isInspectorButtonEnabled() {
|
||||
const button = await testSubjects.find('openInspectorButton');
|
||||
const ariaDisabled = await button.getAttribute('aria-disabled');
|
||||
return ariaDisabled !== 'true';
|
||||
}
|
||||
|
||||
async getSideEditorExists() {
|
||||
return await find.existsByCssSelector('.collapsible-sidebar');
|
||||
}
|
||||
|
||||
async openInspector() {
|
||||
log.debug('Open Inspector');
|
||||
const isOpen = await testSubjects.exists('inspectorPanel');
|
||||
if (!isOpen) {
|
||||
await retry.try(async () => {
|
||||
await testSubjects.click('openInspectorButton');
|
||||
await testSubjects.find('inspectorPanel');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async closeInspector() {
|
||||
log.debug('Close Inspector');
|
||||
let isOpen = await testSubjects.exists('inspectorPanel');
|
||||
if (isOpen) {
|
||||
await retry.try(async () => {
|
||||
await flyout.close('inspectorPanel');
|
||||
isOpen = await testSubjects.exists('inspectorPanel');
|
||||
if (isOpen) {
|
||||
throw new Error('Failed to close inspector');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async setInspectorTablePageSize(size) {
|
||||
const panel = await testSubjects.find('inspectorPanel');
|
||||
await find.clickByButtonText('Rows per page: 20', panel);
|
||||
|
@ -531,10 +500,8 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
}
|
||||
|
||||
async getInterval() {
|
||||
const select = await find.byCssSelector('select[ng-model="agg.params.interval"]');
|
||||
const selectedIndex = await select.getProperty('selectedIndex');
|
||||
const intervalElement = await find.byCssSelector(
|
||||
`select[ng-model="agg.params.interval"] option:nth-child(${(selectedIndex + 1)})`);
|
||||
`select[ng-model="agg.params.interval"] option[selected]`);
|
||||
return await intervalElement.getProperty('label');
|
||||
}
|
||||
|
||||
|
@ -650,11 +617,11 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
const table = await testSubjects.find('heatmapCustomRangesTable');
|
||||
const lastRow = await table.findByCssSelector('tr:last-child');
|
||||
const fromCell = await lastRow.findByCssSelector('td:first-child input');
|
||||
fromCell.clearValue();
|
||||
fromCell.type(`${from}`);
|
||||
await fromCell.clearValue();
|
||||
await fromCell.type(`${from}`);
|
||||
const toCell = await lastRow.findByCssSelector('td:nth-child(2) input');
|
||||
toCell.clearValue();
|
||||
toCell.type(`${to}`);
|
||||
await toCell.clearValue();
|
||||
await toCell.type(`${to}`);
|
||||
}
|
||||
|
||||
async clickYAxisOptions(axisId) {
|
||||
|
@ -719,13 +686,17 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
|
||||
async saveVisualizationExpectSuccess(vizName, { saveAsNew = false } = {}) {
|
||||
await this.saveVisualization(vizName, { saveAsNew });
|
||||
const successToast = await testSubjects.exists('saveVisualizationSuccess', defaultFindTimeout);
|
||||
const successToast = await testSubjects.exists('saveVisualizationSuccess', {
|
||||
timeout: defaultFindTimeout
|
||||
});
|
||||
expect(successToast).to.be(true);
|
||||
}
|
||||
|
||||
async saveVisualizationExpectFail(vizName, { saveAsNew = false } = {}) {
|
||||
await this.saveVisualization(vizName, { saveAsNew });
|
||||
const errorToast = await testSubjects.exists('saveVisualizationError', defaultFindTimeout);
|
||||
const errorToast = await testSubjects.exists('saveVisualizationError', {
|
||||
timeout: defaultFindTimeout
|
||||
});
|
||||
expect(errorToast).to.be(true);
|
||||
}
|
||||
|
||||
|
@ -879,25 +850,7 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
return await Promise.all(getChartTypesPromises);
|
||||
}
|
||||
|
||||
async getPieChartData() {
|
||||
const chartTypes = await find.allByCssSelector('path.slice', defaultFindTimeout * 2);
|
||||
|
||||
const getChartTypesPromises = chartTypes.map(async chart => await chart.getAttribute('d'));
|
||||
return await Promise.all(getChartTypesPromises);
|
||||
}
|
||||
|
||||
async getPieChartLabels() {
|
||||
// Outer retry is because because of stale element references getting thrown on grabbing the data-label.
|
||||
// I suspect it's due to a rendering bug with pie charts not emitting the render-complete flag
|
||||
// when actually done rendering.
|
||||
return await retry.try(async () => {
|
||||
const chartTypes = await find.allByCssSelector('path.slice', defaultFindTimeout * 2);
|
||||
|
||||
const getChartTypesPromises = chartTypes.map(async chart => await chart.getAttribute('data-label'));
|
||||
return await Promise.all(getChartTypesPromises);
|
||||
});
|
||||
}
|
||||
async expectPieChartError() {
|
||||
async expectError() {
|
||||
return await testSubjects.existOrFail('visLibVisualizeError');
|
||||
}
|
||||
|
||||
|
@ -951,32 +904,6 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
});
|
||||
}
|
||||
|
||||
async getInspectorTableData() {
|
||||
// TODO: we should use datat-test-subj=inspectorTable as soon as EUI supports it
|
||||
const inspectorPanel = await testSubjects.find('inspectorPanel');
|
||||
const tableBody = await retry.try(async () => inspectorPanel.findByTagName('tbody'));
|
||||
// Convert the data into a nested array format:
|
||||
// [ [cell1_in_row1, cell2_in_row1], [cell1_in_row2, cell2_in_row2] ]
|
||||
const rows = await tableBody.findAllByTagName('tr');
|
||||
return await Promise.all(rows.map(async row => {
|
||||
const cells = await row.findAllByTagName('td');
|
||||
return await Promise.all(cells.map(async cell => cell.getVisibleText()));
|
||||
}));
|
||||
}
|
||||
|
||||
async getInspectorTableHeaders() {
|
||||
// TODO: we should use datat-test-subj=inspectorTable as soon as EUI supports it
|
||||
const dataTableHeader = await retry.try(async () => {
|
||||
const inspectorPanel = await testSubjects.find('inspectorPanel');
|
||||
return await inspectorPanel.findByTagName('thead');
|
||||
});
|
||||
const cells = await dataTableHeader.findAllByTagName('th');
|
||||
return await Promise.all(cells.map(async (cell) => {
|
||||
const untrimmed = await cell.getVisibleText();
|
||||
return untrimmed.trim();
|
||||
}));
|
||||
}
|
||||
|
||||
async toggleIsFilteredByCollarCheckbox() {
|
||||
await testSubjects.click('isFilteredByCollarCheckbox');
|
||||
}
|
||||
|
@ -1014,7 +941,7 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
|
||||
async getVisualizationRequest() {
|
||||
log.debug('getVisualizationRequest');
|
||||
await this.openInspector();
|
||||
await inspector.open();
|
||||
await testSubjects.click('inspectorViewChooser');
|
||||
await testSubjects.click('inspectorViewChooserRequests');
|
||||
await testSubjects.click('inspectorRequestDetailRequest');
|
||||
|
@ -1023,7 +950,7 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
|
||||
async getVisualizationResponse() {
|
||||
log.debug('getVisualizationResponse');
|
||||
await this.openInspector();
|
||||
await inspector.open();
|
||||
await testSubjects.click('inspectorViewChooser');
|
||||
await testSubjects.click('inspectorViewChooserRequests');
|
||||
await testSubjects.click('inspectorRequestDetailResponse');
|
||||
|
@ -1129,28 +1056,6 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
});
|
||||
}
|
||||
|
||||
async filterForInspectorTableCell(column, row) {
|
||||
await retry.try(async () => {
|
||||
const table = await testSubjects.find('inspectorTable');
|
||||
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
|
||||
await browser.moveMouseTo(cell);
|
||||
const filterBtn = await testSubjects.findDescendant('filterForInspectorCellValue', cell);
|
||||
await filterBtn.click();
|
||||
});
|
||||
await renderable.waitForRender();
|
||||
}
|
||||
|
||||
async filterOutInspectorTableCell(column, row) {
|
||||
await retry.try(async () => {
|
||||
const table = await testSubjects.find('inspectorTable');
|
||||
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
|
||||
await browser.moveMouseTo(cell);
|
||||
const filterBtn = await testSubjects.findDescendant('filterOutInspectorCellValue', cell);
|
||||
await filterBtn.click();
|
||||
});
|
||||
await renderable.waitForRender();
|
||||
}
|
||||
|
||||
async toggleLegend(show = true) {
|
||||
await retry.try(async () => {
|
||||
const isVisible = find.byCssSelector('vislib-legend');
|
||||
|
@ -1188,33 +1093,6 @@ export function VisualizePageProvider({ getService, getPageObjects }) {
|
|||
return await bucketType.click();
|
||||
}
|
||||
|
||||
async filterPieSlice(name) {
|
||||
const slice = await this.getPieSlice(name);
|
||||
// Since slice is an SVG element we can't simply use .click() for it
|
||||
await browser.moveMouseTo(slice);
|
||||
await browser.clickMouseButton();
|
||||
}
|
||||
|
||||
async getPieSlice(name) {
|
||||
return await testSubjects.find(`pieSlice-${name.split(' ').join('-')}`);
|
||||
}
|
||||
|
||||
async getAllPieSlices(name) {
|
||||
return await testSubjects.findAll(`pieSlice-${name.split(' ').join('-')}`);
|
||||
}
|
||||
|
||||
async getPieSliceStyle(name) {
|
||||
log.debug(`VisualizePage.getPieSliceStyle(${name})`);
|
||||
const pieSlice = await this.getPieSlice(name);
|
||||
return await pieSlice.getAttribute('style');
|
||||
}
|
||||
|
||||
async getAllPieSliceStyles(name) {
|
||||
log.debug(`VisualizePage.getAllPieSliceStyles(${name})`);
|
||||
const pieSlices = await this.getAllPieSlices(name);
|
||||
return await Promise.all(pieSlices.map(async pieSlice => await pieSlice.getAttribute('style')));
|
||||
}
|
||||
|
||||
async getBucketErrorMessage() {
|
||||
const error = await find.byCssSelector('.visEditorAggParam__error');
|
||||
const errorMessage = await error.getProperty('innerText');
|
||||
|
|
|
@ -28,13 +28,6 @@ export function DashboardExpectProvider({ getService, getPageObjects }) {
|
|||
const PageObjects = getPageObjects(['dashboard', 'visualize']);
|
||||
|
||||
return new class DashboardExpect {
|
||||
async pieSliceCount(expectedCount) {
|
||||
log.debug(`DashboardExpect.expectPieSliceCount(${expectedCount})`);
|
||||
await retry.try(async () => {
|
||||
const slicesCount = await PageObjects.dashboard.getPieSliceCount();
|
||||
expect(slicesCount).to.be(expectedCount);
|
||||
});
|
||||
}
|
||||
|
||||
async panelCount(expectedCount) {
|
||||
log.debug(`DashboardExpect.panelCount(${expectedCount})`);
|
||||
|
|
|
@ -32,5 +32,7 @@ export { ComboBoxProvider } from './combo_box';
|
|||
export { RenderableProvider } from './renderable';
|
||||
export { TableProvider } from './table';
|
||||
export { BrowserProvider } from './browser';
|
||||
export { InspectorProvider } from './inspector';
|
||||
|
||||
export * from './visualizations';
|
||||
export * from './dashboard';
|
||||
|
|
149
test/functional/services/inspector.js
Normal file
149
test/functional/services/inspector.js
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
|
||||
export function InspectorProvider({ getService }) {
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const browser = getService('browser');
|
||||
const renderable = getService('renderable');
|
||||
const flyout = getService('flyout');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
|
||||
return new class Inspector {
|
||||
async getIsEnabled() {
|
||||
const button = await testSubjects.find('openInspectorButton');
|
||||
const ariaDisabled = await button.getAttribute('aria-disabled');
|
||||
return ariaDisabled !== 'true';
|
||||
}
|
||||
|
||||
async expectIsEnabled() {
|
||||
await retry.try(async () => {
|
||||
const isEnabled = await this.getIsEnabled();
|
||||
expect(isEnabled).to.be(true);
|
||||
});
|
||||
}
|
||||
|
||||
async expectIsNotEnabled() {
|
||||
await retry.try(async () => {
|
||||
const isEnabled = await this.getIsEnabled();
|
||||
expect(isEnabled).to.be(false);
|
||||
});
|
||||
}
|
||||
|
||||
async open() {
|
||||
log.debug('Inspector.open');
|
||||
const isOpen = await testSubjects.exists('inspectorPanel');
|
||||
if (!isOpen) {
|
||||
await retry.try(async () => {
|
||||
await testSubjects.click('openInspectorButton');
|
||||
await testSubjects.find('inspectorPanel');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async close() {
|
||||
log.debug('Close Inspector');
|
||||
let isOpen = await testSubjects.exists('inspectorPanel');
|
||||
if (isOpen) {
|
||||
await retry.try(async () => {
|
||||
await flyout.close('inspectorPanel');
|
||||
isOpen = await testSubjects.exists('inspectorPanel');
|
||||
if (isOpen) {
|
||||
throw new Error('Failed to close inspector');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async expectTableData(expectedData) {
|
||||
await log.debug(`Inspector.expectTableData(${expectedData.join(',')})`);
|
||||
const data = await this.getTableData();
|
||||
expect(data).to.eql(expectedData);
|
||||
}
|
||||
|
||||
async setTablePageSize(size) {
|
||||
const panel = await testSubjects.find('inspectorPanel');
|
||||
await find.clickByButtonText('Rows per page: 20', panel);
|
||||
// The buttons for setting table page size are in a popover element. This popover
|
||||
// element appears as if it's part of the inspectorPanel but it's really attached
|
||||
// to the body element by a portal.
|
||||
const tableSizesPopover = await find.byCssSelector('.euiPanel');
|
||||
await find.clickByButtonText(`${size} rows`, tableSizesPopover);
|
||||
}
|
||||
|
||||
async getTableData() {
|
||||
// TODO: we should use datat-test-subj=inspectorTable as soon as EUI supports it
|
||||
const inspectorPanel = await testSubjects.find('inspectorPanel');
|
||||
const tableBody = await retry.try(async () => inspectorPanel.findByTagName('tbody'));
|
||||
// Convert the data into a nested array format:
|
||||
// [ [cell1_in_row1, cell2_in_row1], [cell1_in_row2, cell2_in_row2] ]
|
||||
const rows = await tableBody.findAllByTagName('tr');
|
||||
return await Promise.all(rows.map(async row => {
|
||||
const cells = await row.findAllByTagName('td');
|
||||
return await Promise.all(cells.map(async cell => cell.getVisibleText()));
|
||||
}));
|
||||
}
|
||||
|
||||
async getTableHeaders() {
|
||||
log.debug('Inspector.getTableHeaders');
|
||||
// TODO: we should use datat-test-subj=inspectorTable as soon as EUI supports it
|
||||
const dataTableHeader = await retry.try(async () => {
|
||||
const inspectorPanel = await testSubjects.find('inspectorPanel');
|
||||
return await inspectorPanel.findByTagName('thead');
|
||||
});
|
||||
const cells = await dataTableHeader.findAllByTagName('th');
|
||||
return await Promise.all(cells.map(async (cell) => {
|
||||
const untrimmed = await cell.getVisibleText();
|
||||
return untrimmed.trim();
|
||||
}));
|
||||
}
|
||||
|
||||
async expectTableHeaders(expected) {
|
||||
await retry.try(async () => {
|
||||
const headers = await this.getTableHeaders();
|
||||
expect(headers).to.eql(expected);
|
||||
});
|
||||
}
|
||||
|
||||
async filterForTableCell(column, row) {
|
||||
await retry.try(async () => {
|
||||
const table = await testSubjects.find('inspectorTable');
|
||||
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
|
||||
await browser.moveMouseTo(cell);
|
||||
const filterBtn = await testSubjects.findDescendant('filterForInspectorCellValue', cell);
|
||||
await filterBtn.click();
|
||||
});
|
||||
await renderable.waitForRender();
|
||||
}
|
||||
|
||||
async filterOutTableCell(column, row) {
|
||||
await retry.try(async () => {
|
||||
const table = await testSubjects.find('inspectorTable');
|
||||
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
|
||||
await browser.moveMouseTo(cell);
|
||||
const filterBtn = await testSubjects.findDescendant('filterOutInspectorCellValue', cell);
|
||||
await filterBtn.click();
|
||||
});
|
||||
await renderable.waitForRender();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -17,7 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
import testSubjSelector from '@kbn/test-subj-selector';
|
||||
import {
|
||||
filter as filterAsync,
|
||||
|
@ -32,28 +31,34 @@ export function TestSubjectsProvider({ getService }) {
|
|||
const config = getService('config');
|
||||
|
||||
const FIND_TIME = config.get('timeouts.find');
|
||||
const TRY_TIME = config.get('timeouts.try');
|
||||
const WAIT_FOR_EXISTS_TIME = config.get('timeouts.waitForExists');
|
||||
|
||||
class TestSubjects {
|
||||
async exists(selector, timeout = WAIT_FOR_EXISTS_TIME) {
|
||||
async exists(selector, options = {}) {
|
||||
const {
|
||||
timeout = WAIT_FOR_EXISTS_TIME,
|
||||
allowHidden = false,
|
||||
} = options;
|
||||
|
||||
log.debug(`TestSubjects.exists(${selector})`);
|
||||
return await find.existsByDisplayedByCssSelector(testSubjSelector(selector), timeout);
|
||||
return await (
|
||||
allowHidden
|
||||
? find.existsByCssSelector(testSubjSelector(selector), timeout)
|
||||
: find.existsByDisplayedByCssSelector(testSubjSelector(selector), timeout)
|
||||
);
|
||||
}
|
||||
|
||||
async existOrFail(selector, timeout = WAIT_FOR_EXISTS_TIME) {
|
||||
await retry.try(async () => {
|
||||
log.debug(`TestSubjects.existOrFail(${selector})`);
|
||||
const doesExist = await this.exists(selector, timeout);
|
||||
// Verify element exists, or else fail the test consuming this.
|
||||
expect(doesExist).to.be(true);
|
||||
});
|
||||
async existOrFail(selector, existsOptions) {
|
||||
if (!await this.exists(selector, { timeout: TRY_TIME, ...existsOptions })) {
|
||||
throw new Error(`expected testSubject(${selector}) to exist`);
|
||||
}
|
||||
}
|
||||
|
||||
async missingOrFail(selector, timeout = WAIT_FOR_EXISTS_TIME) {
|
||||
log.debug(`TestSubjects.missingOrFail(${selector})`);
|
||||
const doesExist = await this.exists(selector, timeout);
|
||||
// Verify element is missing, or else fail the test consuming this.
|
||||
expect(doesExist).to.be(false);
|
||||
async missingOrFail(selector, existsOptions) {
|
||||
if (await this.exists(selector, existsOptions)) {
|
||||
throw new Error(`expected testSubject(${selector}) to not exist`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
20
test/functional/services/visualizations/index.js
Normal file
20
test/functional/services/visualizations/index.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { PieChartProvider } from './pie_chart';
|
111
test/functional/services/visualizations/pie_chart.js
Normal file
111
test/functional/services/visualizations/pie_chart.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
|
||||
export function PieChartProvider({ getService }) {
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const config = getService('config');
|
||||
const inspector = getService('inspector');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
const defaultFindTimeout = config.get('timeouts.find');
|
||||
|
||||
return new class PieChart {
|
||||
|
||||
async filterOnPieSlice(name) {
|
||||
log.debug(`PieChart.filterOnPieSlice(${name})`);
|
||||
if (name) {
|
||||
await testSubjects.click(`pieSlice-${name.split(' ').join('-')}`);
|
||||
} else {
|
||||
// If no pie slice has been provided, find the first one available.
|
||||
await retry.try(async () => {
|
||||
const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice');
|
||||
log.debug('Slices found:' + slices.length);
|
||||
return slices[0].click();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async getPieSlice(name) {
|
||||
return await testSubjects.find(`pieSlice-${name.split(' ').join('-')}`);
|
||||
}
|
||||
|
||||
async getAllPieSlices(name) {
|
||||
return await testSubjects.findAll(`pieSlice-${name.split(' ').join('-')}`);
|
||||
}
|
||||
|
||||
async getPieSliceStyle(name) {
|
||||
log.debug(`VisualizePage.getPieSliceStyle(${name})`);
|
||||
const pieSlice = await this.getPieSlice(name);
|
||||
return await pieSlice.getAttribute('style');
|
||||
}
|
||||
|
||||
async getAllPieSliceStyles(name) {
|
||||
log.debug(`VisualizePage.getAllPieSliceStyles(${name})`);
|
||||
const pieSlices = await this.getAllPieSlices(name);
|
||||
return await Promise.all(pieSlices.map(async pieSlice => await pieSlice.getAttribute('style')));
|
||||
}
|
||||
|
||||
async getPieChartData() {
|
||||
const chartTypes = await find.allByCssSelector('path.slice', defaultFindTimeout * 2);
|
||||
|
||||
const getChartTypesPromises = chartTypes.map(async chart => await chart.getAttribute('d'));
|
||||
return await Promise.all(getChartTypesPromises);
|
||||
}
|
||||
|
||||
async expectPieChartTableData(expectedTableData) {
|
||||
await inspector.open();
|
||||
await inspector.setTablePageSize(50);
|
||||
await inspector.expectTableData(expectedTableData);
|
||||
}
|
||||
|
||||
async getPieChartLabels() {
|
||||
const chartTypes = await find.allByCssSelector('path.slice', defaultFindTimeout * 2);
|
||||
|
||||
const getChartTypesPromises = chartTypes.map(async chart => await chart.getAttribute('data-label'));
|
||||
return await Promise.all(getChartTypesPromises);
|
||||
}
|
||||
|
||||
async getPieSliceCount() {
|
||||
log.debug('PieChart.getPieSliceCount');
|
||||
return await retry.try(async () => {
|
||||
const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice');
|
||||
return slices.length;
|
||||
});
|
||||
}
|
||||
|
||||
async expectPieSliceCount(expectedCount) {
|
||||
log.debug(`PieChart.expectPieSliceCount(${expectedCount})`);
|
||||
await retry.try(async () => {
|
||||
const slicesCount = await this.getPieSliceCount();
|
||||
expect(slicesCount).to.be(expectedCount);
|
||||
});
|
||||
}
|
||||
|
||||
async expectPieChartLabels(expectedLabels) {
|
||||
log.debug(`PieChart.expectPieChartLabels(${expectedLabels.join(',')})`);
|
||||
await retry.try(async () => {
|
||||
const pieData = await this.getPieChartLabels();
|
||||
expect(pieData).to.eql(expectedLabels);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
|
@ -139,7 +139,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@elastic/datemath": "5.0.2",
|
||||
"@elastic/eui": "6.0.1",
|
||||
"@elastic/eui": "6.3.1",
|
||||
"@elastic/javascript-typescript-langserver": "^0.1.9",
|
||||
"@elastic/lsp-extension": "^0.1.1",
|
||||
"@elastic/node-crypto": "0.1.2",
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
EuiTitle
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import idx from 'idx';
|
||||
import { first, get } from 'lodash';
|
||||
import React from 'react';
|
||||
import { RRRRenderResponse } from 'react-redux-request';
|
||||
|
@ -122,7 +123,10 @@ export function DetailView({ errorGroup, urlParams, location }: Props) {
|
|||
{
|
||||
fieldName: REQUEST_URL_FULL,
|
||||
label: 'URL',
|
||||
val: get(error, REQUEST_URL_FULL, notAvailableLabel),
|
||||
val:
|
||||
idx(error, _ => _.context.page.url) ||
|
||||
idx(transaction, _ => _.context.request.url.full) ||
|
||||
notAvailableLabel,
|
||||
truncated: true,
|
||||
width: '50%'
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import idx from 'idx';
|
||||
import { get } from 'lodash';
|
||||
import React from 'react';
|
||||
import {
|
||||
|
@ -29,7 +30,11 @@ export function StickyTransactionProperties({
|
|||
totalDuration
|
||||
}: Props) {
|
||||
const timestamp = transaction['@timestamp'];
|
||||
const url = get(transaction, REQUEST_URL_FULL, 'N/A');
|
||||
|
||||
const url =
|
||||
idx(transaction, _ => _.context.page.url) ||
|
||||
idx(transaction, _ => _.context.request.url) ||
|
||||
'N/A';
|
||||
const duration = transaction.transaction.duration.us;
|
||||
const stickyProperties: IStickyProperty[] = [
|
||||
{
|
||||
|
|
|
@ -29,6 +29,9 @@ interface Context {
|
|||
service: ContextService;
|
||||
system?: ContextSystem;
|
||||
request?: ContextRequest;
|
||||
page?: {
|
||||
url: string;
|
||||
};
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ interface Context {
|
|||
username?: string;
|
||||
email?: string;
|
||||
};
|
||||
page?: {
|
||||
url: string;
|
||||
};
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
|
|
5
x-pack/plugins/canvas/.gitignore
vendored
5
x-pack/plugins/canvas/.gitignore
vendored
|
@ -51,4 +51,7 @@ build
|
|||
public/style/index.css
|
||||
|
||||
# Don't commit built plugin files
|
||||
canvas_plugin/*
|
||||
canvas_plugin/*
|
||||
|
||||
# Don't commit the Webpack statistics
|
||||
webpack_stats.json
|
|
@ -25,6 +25,8 @@ export const WorkpadTemplates = compose(
|
|||
// Clone workpad given an id
|
||||
cloneWorkpad: props => workpad => {
|
||||
workpad.id = getId('workpad');
|
||||
workpad.name = `Untitled Workpad - ${workpad.name}`;
|
||||
workpad.tags = undefined;
|
||||
return workpadService
|
||||
.create(workpad)
|
||||
.then(() => props.router.navigateTo('loadWorkpad', { id: workpad.id, page: 1 }))
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
const { writeFileSync } = require('fs');
|
||||
const path = require('path');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const {
|
||||
|
@ -13,12 +14,11 @@ const {
|
|||
const sourceDir = path.resolve(__dirname, '../../canvas_plugin_src');
|
||||
const buildDir = path.resolve(__dirname, '../../canvas_plugin');
|
||||
|
||||
export function getWebpackConfig({ devtool, watch } = {}) {
|
||||
export function getWebpackConfig({ devtool, watch, production } = {}) {
|
||||
return {
|
||||
watch,
|
||||
devtool,
|
||||
|
||||
mode: 'none',
|
||||
mode: production ? 'production' : 'none',
|
||||
entry: {
|
||||
'elements/all': path.join(sourceDir, 'elements/register.js'),
|
||||
'renderers/all': path.join(sourceDir, 'renderers/register.js'),
|
||||
|
@ -94,6 +94,16 @@ export function getWebpackConfig({ devtool, watch } = {}) {
|
|||
ignore: '**/__tests__/**',
|
||||
},
|
||||
]),
|
||||
function canvasStatsGenerator() {
|
||||
if (!process.env.CANVAS_GENERATE_STATS) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hooks.done.tap('canvas_stats', stats => {
|
||||
const content = JSON.stringify(stats.toJson());
|
||||
writeFileSync(path.resolve(__dirname, '../../webpack_stats.json'), content);
|
||||
});
|
||||
},
|
||||
],
|
||||
|
||||
module: {
|
||||
|
|
|
@ -40,6 +40,6 @@ export default function pluginsTasks(gulp, { log, colors }) {
|
|||
});
|
||||
|
||||
gulp.task('canvas:plugins:build-prod', function(done) {
|
||||
del(buildDir).then(() => webpack(getWebpackConfig(), onComplete(done)));
|
||||
del(buildDir).then(() => webpack(getWebpackConfig({ production: true }), onComplete(done)));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -43,14 +43,18 @@ map-listing, .gisListingPage {
|
|||
.gisWidgetOverlay {
|
||||
position: absolute;
|
||||
z-index: $euiZLevel1;
|
||||
min-width: 17rem;
|
||||
max-width: 24rem;
|
||||
top: $euiSizeM;
|
||||
right: $euiSizeM;
|
||||
bottom: $euiSizeM;
|
||||
// left: $euiSizeM;
|
||||
pointer-events: none; /* 1 */
|
||||
}
|
||||
|
||||
.gisWidgetOverlay__rightSide {
|
||||
min-width: 17rem;
|
||||
max-width: 24rem;
|
||||
}
|
||||
|
||||
.gisWidgetControl {
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
|
@ -70,6 +74,21 @@ map-listing, .gisListingPage {
|
|||
}
|
||||
}
|
||||
|
||||
.gisAttributionControl {
|
||||
padding: 0 $euiSizeXS;
|
||||
}
|
||||
|
||||
.gisViewControl__coordinates {
|
||||
padding: $euiSizeXS $euiSizeS;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.gisViewControl__gotoButton {
|
||||
min-width: 0;
|
||||
pointer-events: all; /* 1 */
|
||||
}
|
||||
|
||||
.gisWidgetControl__tocHolder {
|
||||
@include euiScrollBar;
|
||||
overflow-y: auto;
|
||||
|
@ -173,9 +192,12 @@ map-listing, .gisListingPage {
|
|||
overflow-y: auto;
|
||||
@include euiScrollBar;
|
||||
|
||||
> * {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
> *:not(:last-child) {
|
||||
margin-bottom: $euiSize;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -296,20 +296,22 @@ export function updateSourceProp(layerId, propName, value) {
|
|||
propName,
|
||||
value,
|
||||
});
|
||||
|
||||
dispatch(syncDataForLayer(layerId));
|
||||
};
|
||||
}
|
||||
|
||||
export function syncDataForLayer(layerId) {
|
||||
return (dispatch, getState) => {
|
||||
return async (dispatch, getState) => {
|
||||
const targetLayer = getLayerList(getState()).find(layer => {
|
||||
return layer.getId() === layerId;
|
||||
});
|
||||
if (targetLayer) {
|
||||
const dataFilters = getDataFilters(getState());
|
||||
const loadingFunctions = getLayerLoadingCallbacks(dispatch, layerId);
|
||||
targetLayer.syncData({ ...loadingFunctions, dataFilters });
|
||||
await targetLayer.syncData({
|
||||
...loadingFunctions,
|
||||
dataFilters
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { ALL_SOURCES } from '../../shared/layers/sources/all_sources';
|
||||
import {
|
||||
EuiSpacer,
|
||||
|
@ -14,63 +14,48 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiTitle,
|
||||
EuiForm,
|
||||
EuiFormRow,
|
||||
EuiSuperSelect,
|
||||
EuiPanel,
|
||||
EuiCard,
|
||||
EuiIcon,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export class AddLayerPanel extends React.Component {
|
||||
export class AddLayerPanel extends Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
label: '',
|
||||
sourceType: '',
|
||||
minZoom: 0,
|
||||
maxZoom: 24,
|
||||
alphaValue: 1
|
||||
sourceType: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.layer && this.state.alphaValue === null) {
|
||||
const defaultAlphaValue = this.layer._descriptor.type === 'TILE' ? 1 : 1;
|
||||
if (this.state.alphaValue !== defaultAlphaValue) {
|
||||
this.setState({
|
||||
alphaValue: defaultAlphaValue
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_previewLayer = (source) => {
|
||||
this.layer = source.createDefaultLayer({
|
||||
temporary: true,
|
||||
label: this.state.label,
|
||||
minZoom: this.state.minZoom,
|
||||
maxZoom: this.state.maxZoom,
|
||||
});
|
||||
this.props.previewLayer(this.layer);
|
||||
};
|
||||
|
||||
_onSourceTypeChange = (sourceType) => {
|
||||
this.setState({
|
||||
sourceType,
|
||||
});
|
||||
_clearSource = () => {
|
||||
this.setState({ sourceType: null });
|
||||
|
||||
if (this.layer) {
|
||||
this.props.removeLayer(this.layer.getId());
|
||||
}
|
||||
}
|
||||
|
||||
_onSourceTypeChange = (sourceType) => {
|
||||
this.setState({ sourceType });
|
||||
}
|
||||
|
||||
_renderNextBtn() {
|
||||
if (!this.state.sourceType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { layerLoading, temporaryLayers, nextAction } = this.props;
|
||||
const addToMapBtnText = 'Next';
|
||||
return (
|
||||
<EuiButton
|
||||
style={{ width: '9rem' }}
|
||||
disabled={!temporaryLayers || layerLoading}
|
||||
isLoading={layerLoading}
|
||||
iconSide="right"
|
||||
|
@ -82,42 +67,41 @@ export class AddLayerPanel extends React.Component {
|
|||
}}
|
||||
fill
|
||||
>
|
||||
{addToMapBtnText}
|
||||
Create layer
|
||||
</EuiButton>
|
||||
);
|
||||
}
|
||||
|
||||
_renderSourceSelect() {
|
||||
|
||||
|
||||
const sourceOptions = ALL_SOURCES.map(Source => {
|
||||
return {
|
||||
value: Source.type,
|
||||
inputDisplay: Source.typeDisplayName,
|
||||
dropdownDisplay: Source.renderDropdownDisplayOption()
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
<EuiFormRow label="Data source">
|
||||
<EuiSuperSelect
|
||||
itemClassName="sourceSelectItem"
|
||||
options={sourceOptions}
|
||||
valueOfSelected={this.state.sourceType}
|
||||
onChange={this._onSourceTypeChange}
|
||||
itemLayoutAlign="top"
|
||||
hasDividers
|
||||
_renderSourceCards() {
|
||||
return ALL_SOURCES.map(Source => {
|
||||
const icon = Source.icon
|
||||
? <EuiIcon type={Source.icon} size="xl" />
|
||||
: null;
|
||||
return (
|
||||
<EuiCard
|
||||
key={Source.type}
|
||||
title={Source.title}
|
||||
icon={icon}
|
||||
onClick={() => this._onSourceTypeChange(Source.type)}
|
||||
description={Source.description}
|
||||
layout="horizontal"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
_renderSourceSelect() {
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiTitle size="xs">
|
||||
<h2>Choose data source</h2>
|
||||
</EuiTitle>
|
||||
{this._renderSourceCards()}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
_renderSourceEditor() {
|
||||
if (!this.state.sourceType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editorProperties = {
|
||||
onPreviewSource: this._previewLayer,
|
||||
dataSourcesMeta: this.props.dataSourcesMeta
|
||||
|
@ -130,16 +114,28 @@ export class AddLayerPanel extends React.Component {
|
|||
throw new Error(`Unexepected source type: ${this.state.sourceType}`);
|
||||
}
|
||||
|
||||
return Source.renderEditor(editorProperties);
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiButtonEmpty
|
||||
contentProps={{ style: { justifyContent: 'left' } }}
|
||||
onClick={this._clearSource}
|
||||
iconType="arrowLeft"
|
||||
>
|
||||
Change data source
|
||||
</EuiButtonEmpty>
|
||||
<EuiPanel>
|
||||
{Source.renderEditor(editorProperties)}
|
||||
</EuiPanel>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
_renderAddLayerForm() {
|
||||
return (
|
||||
<EuiForm>
|
||||
{this._renderSourceSelect()}
|
||||
{this._renderSourceEditor()}
|
||||
</EuiForm>
|
||||
);
|
||||
if (!this.state.sourceType) {
|
||||
return this._renderSourceSelect();
|
||||
}
|
||||
|
||||
return this._renderSourceEditor();
|
||||
}
|
||||
|
||||
_renderFlyout() {
|
||||
|
@ -157,9 +153,7 @@ export class AddLayerPanel extends React.Component {
|
|||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem className="gisViewPanel__body">
|
||||
<EuiPanel>
|
||||
{this._renderAddLayerForm()}
|
||||
</EuiPanel>
|
||||
{this._renderAddLayerForm()}
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false} className="gisViewPanel__footer">
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
mapDestroyed,
|
||||
setMouseCoordinates,
|
||||
clearMouseCoordinates,
|
||||
clearGoto,
|
||||
clearGoto
|
||||
} from '../../../actions/store_actions';
|
||||
import { getLayerList, getMapReady, getGoto } from "../../../selectors/map_selectors";
|
||||
|
||||
|
@ -20,7 +20,7 @@ function mapStateToProps(state = {}) {
|
|||
return {
|
||||
isMapReady: getMapReady(state),
|
||||
layerList: getLayerList(state),
|
||||
goto: getGoto(state),
|
||||
goto: getGoto(state)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import mapboxgl from 'mapbox-gl';
|
|||
export async function createMbMapInstance(node, initialView) {
|
||||
return new Promise((resolve) => {
|
||||
const options = {
|
||||
attributionControl: false,
|
||||
container: node,
|
||||
style: {
|
||||
version: 8,
|
||||
|
|
|
@ -174,7 +174,7 @@ export class MBMapContainer extends React.Component {
|
|||
lng: goto.lon,
|
||||
lat: goto.lat
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_syncMbMapWithLayerList = () => {
|
||||
const {
|
||||
|
@ -190,7 +190,7 @@ export class MBMapContainer extends React.Component {
|
|||
layer.syncLayerWithMB(this._mbMap);
|
||||
});
|
||||
syncLayerOrder(this._mbMap, layerList);
|
||||
}
|
||||
};
|
||||
|
||||
_syncMbMapWithInspector = () => {
|
||||
if (!this.props.isMapReady) {
|
||||
|
@ -206,7 +206,7 @@ export class MBMapContainer extends React.Component {
|
|||
stats,
|
||||
style: this._mbMap.getStyle(),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
// do not debounce syncing zoom and center
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 { connect } from 'react-redux';
|
||||
import { AttributionControl } from './view';
|
||||
import { getLayerList } from "../../../selectors/map_selectors";
|
||||
|
||||
function mapStateToProps(state = {}) {
|
||||
return {
|
||||
layerList: getLayerList(state)
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
const connectedViewControl = connect(mapStateToProps, mapDispatchToProps)(AttributionControl);
|
||||
export { connectedViewControl as AttributionControl };
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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 React, { Fragment } from 'react';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
EuiText,
|
||||
EuiPanel,
|
||||
EuiLink,
|
||||
} from '@elastic/eui';
|
||||
|
||||
|
||||
export class AttributionControl extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
uniqueAttributions: []
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this._syncMbMapWithAttribution();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._syncMbMapWithAttribution();
|
||||
}
|
||||
|
||||
_syncMbMapWithAttribution = async () => {
|
||||
|
||||
const attributionPromises = this.props.layerList.map(layer => {
|
||||
return layer.getAttributions();
|
||||
});
|
||||
const attributions = await Promise.all(attributionPromises);
|
||||
if (!this._isMounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uniqueAttributions = [];
|
||||
for (let i = 0; i < attributions.length; i++) {
|
||||
for (let j = 0; j < attributions[i].length; j++) {
|
||||
const testAttr = attributions[i][j];
|
||||
const attr = uniqueAttributions.find((added) => {
|
||||
return (added.url === testAttr.url && added.label === testAttr.label);
|
||||
});
|
||||
if (!attr) {
|
||||
uniqueAttributions.push(testAttr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_.isEqual(this.state.uniqueAttributions, uniqueAttributions)) {
|
||||
this.setState({ uniqueAttributions });
|
||||
}
|
||||
};
|
||||
|
||||
_renderAttributions() {
|
||||
return this.state.uniqueAttributions.map((attribution, index) => {
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
<EuiLink color="subdued" href={attribution.url} target="_blank">{attribution.label}</EuiLink>
|
||||
{index < (this.state.uniqueAttributions.length - 1) && ', '}
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.uniqueAttributions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<EuiPanel className="gisWidgetControl gisAttributionControl" paddingSize="none" grow={false}>
|
||||
<EuiText color="subdued" size="xs">
|
||||
<small>{this._renderAttributions()}</small>
|
||||
</EuiText>
|
||||
</EuiPanel>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -4,12 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiPanel,
|
||||
EuiButtonEmpty,
|
||||
EuiButton,
|
||||
EuiPopover,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
|
@ -26,15 +26,17 @@ export function ViewControl({ isSetViewOpen, closeSetView, openSetView, mouseCoo
|
|||
};
|
||||
const setView = (
|
||||
<EuiPopover
|
||||
anchorPosition="upRight"
|
||||
button={(
|
||||
<EuiButtonEmpty
|
||||
flush="right"
|
||||
size="xs"
|
||||
<EuiButton
|
||||
className="gisViewControl__gotoButton"
|
||||
fill
|
||||
size="s"
|
||||
onClick={toggleSetViewVisibility}
|
||||
data-test-subj="toggleSetViewVisibilityButton"
|
||||
>
|
||||
Goto
|
||||
</EuiButtonEmpty>)}
|
||||
</EuiButton>)}
|
||||
isOpen={isSetViewOpen}
|
||||
closePopover={closeSetView}
|
||||
>
|
||||
|
@ -44,39 +46,30 @@ export function ViewControl({ isSetViewOpen, closeSetView, openSetView, mouseCoo
|
|||
|
||||
function renderMouseCoordinates() {
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="xs">
|
||||
<p>
|
||||
<strong>lat:</strong> {mouseCoordinates && mouseCoordinates.lat}
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="xs">
|
||||
<p>
|
||||
<strong>long:</strong> {mouseCoordinates && mouseCoordinates.lon}
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</Fragment>
|
||||
<EuiPanel className="gisWidgetControl gisViewControl__coordinates" paddingSize="none">
|
||||
<EuiText size="xs">
|
||||
<p>
|
||||
<strong>lat:</strong> {mouseCoordinates && mouseCoordinates.lat},{' '}
|
||||
<strong>lon:</strong> {mouseCoordinates && mouseCoordinates.lon}
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiPanel>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiPanel className="gisWidgetControl" hasShadow paddingSize="s">
|
||||
<EuiFlexGroup
|
||||
justifyContent="spaceBetween"
|
||||
alignItems="center"
|
||||
gutterSize="s"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
justifyContent="spaceBetween"
|
||||
gutterSize="s"
|
||||
responsive={false}
|
||||
>
|
||||
<EuiFlexItem>
|
||||
{mouseCoordinates && renderMouseCoordinates()}
|
||||
</EuiFlexItem>
|
||||
|
||||
{renderMouseCoordinates()}
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
{setView}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
<EuiFlexItem grow={false}>
|
||||
{setView}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,19 +11,28 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { LayerControl } from './layer_control';
|
||||
import { ViewControl } from './view_control';
|
||||
import { AttributionControl } from './attribution_control';
|
||||
|
||||
export function WidgetOverlay() {
|
||||
return (
|
||||
<EuiFlexGroup
|
||||
className="gisWidgetOverlay"
|
||||
direction="column"
|
||||
justifyContent="spaceBetween"
|
||||
>
|
||||
<EuiFlexGroup className="gisWidgetOverlay" responsive={false} direction="column" alignItems="flexEnd" gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<LayerControl/>
|
||||
<EuiFlexGroup
|
||||
className="gisWidgetOverlay__rightSide"
|
||||
direction="column"
|
||||
justifyContent="spaceBetween"
|
||||
responsive={false}
|
||||
>
|
||||
<EuiFlexItem>
|
||||
<LayerControl/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ViewControl/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ViewControl/>
|
||||
<AttributionControl/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
|
|
|
@ -19,7 +19,7 @@ const AGG_OPTIONS = [
|
|||
|
||||
export const METRIC_AGGREGATION_VALUES = AGG_OPTIONS.map(({ value }) => { return value; });
|
||||
|
||||
export function MetricSelect({ value, onChange }) {
|
||||
export function MetricSelect({ value, onChange, metricsFilter }) {
|
||||
|
||||
function onAggChange(selectedOptions) {
|
||||
if (selectedOptions.length === 0) {
|
||||
|
@ -30,12 +30,14 @@ export function MetricSelect({ value, onChange }) {
|
|||
onChange(aggType);
|
||||
}
|
||||
|
||||
const options = metricsFilter ? AGG_OPTIONS.filter(metricsFilter) : AGG_OPTIONS;
|
||||
|
||||
return (
|
||||
<EuiComboBox
|
||||
placeholder="Select aggregation"
|
||||
singleSelection={true}
|
||||
isClearable={false}
|
||||
options={AGG_OPTIONS}
|
||||
options={options}
|
||||
selectedOptions={AGG_OPTIONS.filter(option => {
|
||||
return value === option.value;
|
||||
})}
|
||||
|
@ -45,6 +47,7 @@ export function MetricSelect({ value, onChange }) {
|
|||
}
|
||||
|
||||
MetricSelect.propTypes = {
|
||||
metricsFilter: PropTypes.func,
|
||||
value: PropTypes.oneOf(METRIC_AGGREGATION_VALUES),
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
} from './metric_select';
|
||||
import { SingleFieldSelect } from './single_field_select';
|
||||
|
||||
export function MetricsEditor({ fields, metrics, onChange }) {
|
||||
export function MetricsEditor({ fields, metrics, onChange, allowMultipleMetrics, metricsFilter }) {
|
||||
|
||||
function onMetricChange(metric, index) {
|
||||
onChange([
|
||||
|
@ -91,6 +91,7 @@ export function MetricsEditor({ fields, metrics, onChange }) {
|
|||
<MetricSelect
|
||||
onChange={onAggChange}
|
||||
value={metric.type}
|
||||
metricsFilter={metricsFilter}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
|
@ -110,6 +111,21 @@ export function MetricsEditor({ fields, metrics, onChange }) {
|
|||
]);
|
||||
}
|
||||
|
||||
function renderAddMetricButton() {
|
||||
|
||||
if (!allowMultipleMetrics) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (<EuiButtonIcon
|
||||
iconType="plusInCircle"
|
||||
onClick={addMetric}
|
||||
aria-label="Add metric"
|
||||
title="Add metric"
|
||||
/>);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
|
@ -119,12 +135,7 @@ export function MetricsEditor({ fields, metrics, onChange }) {
|
|||
</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
iconType="plusInCircle"
|
||||
onClick={addMetric}
|
||||
aria-label="Add metric"
|
||||
title="Add metric"
|
||||
/>
|
||||
{renderAddMetricButton()}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
|
@ -140,6 +151,8 @@ MetricsEditor.propTypes = {
|
|||
})),
|
||||
fields: PropTypes.object, // indexPattern.fields IndexedArray object
|
||||
onChange: PropTypes.func.isRequired,
|
||||
allowMultipleMetrics: PropTypes.bool,
|
||||
metricsFilter: PropTypes.func,
|
||||
};
|
||||
|
||||
MetricsEditor.defaultProps = {
|
||||
|
|
|
@ -11,6 +11,8 @@ import { EuiIcon } from '@elastic/eui';
|
|||
import { HeatmapStyle } from './styles/heatmap_style';
|
||||
import { ZOOM_TO_PRECISION } from '../utils/zoom_to_precision';
|
||||
|
||||
const SCALED_PROPERTY_NAME = '__kbn_heatmap_weight__';//unique name to store scaled value for weighting
|
||||
|
||||
export class HeatmapLayer extends ALayer {
|
||||
|
||||
static type = "HEATMAP";
|
||||
|
@ -39,6 +41,11 @@ export class HeatmapLayer extends ALayer {
|
|||
return this._source.getIndexPatternIds();
|
||||
}
|
||||
|
||||
_getPropKeyOfSelectedMetric() {
|
||||
const metricfields = this._source.getMetricFields();
|
||||
return metricfields[0].propertyKey;
|
||||
}
|
||||
|
||||
syncLayerWithMB(mbMap) {
|
||||
|
||||
const mbSource = mbMap.getSource(this.getId());
|
||||
|
@ -67,22 +74,21 @@ export class HeatmapLayer extends ALayer {
|
|||
return;
|
||||
}
|
||||
|
||||
const scaledPropertyName = '__kbn_heatmap_weight__';
|
||||
const propertyName = 'doc_count';
|
||||
const propertyKey = this._getPropKeyOfSelectedMetric();
|
||||
const dataBoundToMap = ALayer.getBoundDataForSource(mbMap, this.getId());
|
||||
if (featureCollection !== dataBoundToMap) {
|
||||
let max = 0;
|
||||
for (let i = 0; i < featureCollection.features.length; i++) {
|
||||
max = Math.max(featureCollection.features[i].properties[propertyName], max);
|
||||
max = Math.max(featureCollection.features[i].properties[propertyKey], max);
|
||||
}
|
||||
for (let i = 0; i < featureCollection.features.length; i++) {
|
||||
featureCollection.features[i].properties[scaledPropertyName] = featureCollection.features[i].properties[propertyName] / max;
|
||||
featureCollection.features[i].properties[SCALED_PROPERTY_NAME] = featureCollection.features[i].properties[propertyKey] / max;
|
||||
}
|
||||
mbSourceAfter.setData(featureCollection);
|
||||
}
|
||||
|
||||
mbMap.setLayoutProperty(heatmapLayerId, 'visibility', this.isVisible() ? 'visible' : 'none');
|
||||
this._style.setMBPaintProperties(mbMap, heatmapLayerId, scaledPropertyName);
|
||||
this._style.setMBPaintProperties(mbMap, heatmapLayerId, SCALED_PROPERTY_NAME);
|
||||
mbMap.setLayerZoomRange(heatmapLayerId, this._descriptor.minZoom, this._descriptor.maxZoom);
|
||||
}
|
||||
|
||||
|
@ -112,19 +118,24 @@ export class HeatmapLayer extends ALayer {
|
|||
const updateDueToQuery = dataFilters.query
|
||||
&& !_.isEqual(dataMeta.query, dataFilters.query);
|
||||
|
||||
const metricPropertyKey = this._getPropKeyOfSelectedMetric();
|
||||
const updateDueToMetricChange = !_.isEqual(dataMeta.metric, metricPropertyKey);
|
||||
|
||||
if (isSamePrecision
|
||||
&& isSameTime
|
||||
&& !updateDueToExtent
|
||||
&& !updateDueToRefreshTimer
|
||||
&& !updateDueToQuery) {
|
||||
&& !updateDueToQuery
|
||||
&& !updateDueToMetricChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newDataMeta = {
|
||||
...dataFilters,
|
||||
precision: targetPrecision
|
||||
precision: targetPrecision,
|
||||
metric: metricPropertyKey
|
||||
};
|
||||
return this._fetchNewData({ startLoading, stopLoading, onLoadError, dataMeta: newDataMeta });
|
||||
await this._fetchNewData({ startLoading, stopLoading, onLoadError, dataMeta: newDataMeta });
|
||||
}
|
||||
|
||||
async _fetchNewData({ startLoading, stopLoading, onLoadError, dataMeta }) {
|
||||
|
@ -133,7 +144,7 @@ export class HeatmapLayer extends ALayer {
|
|||
startLoading('source', requestToken, dataMeta);
|
||||
try {
|
||||
const layerName = await this.getDisplayName();
|
||||
const data = await this._source.getGeoJsonPointsWithTotalCount({
|
||||
const data = await this._source.getGeoJsonPoints({
|
||||
precision,
|
||||
extent: buffer,
|
||||
timeFilters,
|
||||
|
|
|
@ -64,6 +64,10 @@ export class ALayer {
|
|||
return (await this._source.getDisplayName()) || `Layer ${this._descriptor.id}`;
|
||||
}
|
||||
|
||||
async getAttributions() {
|
||||
return await this._source.getAttributions();
|
||||
}
|
||||
|
||||
getLabel() {
|
||||
return this._descriptor.label ? this._descriptor.label : '';
|
||||
}
|
||||
|
|
|
@ -5,13 +5,12 @@
|
|||
*/
|
||||
|
||||
import { VectorSource } from './vector_source';
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import {
|
||||
EuiLink,
|
||||
EuiText,
|
||||
EuiSelect,
|
||||
EuiFormRow,
|
||||
EuiSpacer
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { GIS_API_PATH } from '../../../../common/constants';
|
||||
|
@ -20,7 +19,9 @@ import { emsServiceSettings } from '../../../kibana_services';
|
|||
export class EMSFileSource extends VectorSource {
|
||||
|
||||
static type = 'EMS_FILE';
|
||||
static typeDisplayName = 'Elastic Maps Service vector shapes';
|
||||
static title = 'Elastic Maps Service vector shapes';
|
||||
static description = 'Vector shapes of administrative boundaries from Elastic Maps Service';
|
||||
static icon = 'emsApp';
|
||||
|
||||
static createDescriptor(id) {
|
||||
return {
|
||||
|
@ -54,20 +55,6 @@ export class EMSFileSource extends VectorSource {
|
|||
);
|
||||
}
|
||||
|
||||
static renderDropdownDisplayOption() {
|
||||
return (
|
||||
<Fragment>
|
||||
<strong>{EMSFileSource.typeDisplayName}</strong>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiText size="s" color="subdued">
|
||||
<p className="euiTextColor--subdued">
|
||||
Vector shapes of administrative boundaries from Elastic Maps Service
|
||||
</p>
|
||||
</EuiText>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
constructor(descriptor, { emsFileLayers }) {
|
||||
super(descriptor);
|
||||
this._emsFiles = emsFileLayers;
|
||||
|
@ -100,6 +87,13 @@ export class EMSFileSource extends VectorSource {
|
|||
const fileSource = this._emsFiles.find((source => source.id === this._descriptor.id));
|
||||
return fileSource.name;
|
||||
}
|
||||
|
||||
async getAttributions() {
|
||||
const fileSource = this._emsFiles.find((source => source.id === this._descriptor.id));
|
||||
return fileSource.attributions;
|
||||
}
|
||||
|
||||
|
||||
async getStringFields() {
|
||||
//todo: use map/service-settings instead.
|
||||
const fileSource = this._emsFiles.find((source => source.id === this._descriptor.id));
|
||||
|
|
|
@ -3,14 +3,13 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import React, { Fragment } from 'react';
|
||||
import { TMSSource } from './tms_source';
|
||||
import { TileLayer } from '../tile_layer';
|
||||
import React from 'react';
|
||||
import { TMSSource } from '../tms_source';
|
||||
import { TileLayer } from '../../tile_layer';
|
||||
import {
|
||||
EuiText,
|
||||
EuiSelect,
|
||||
EuiFormRow,
|
||||
EuiSpacer
|
||||
} from '@elastic/eui';
|
||||
import _ from 'lodash';
|
||||
|
||||
|
@ -18,7 +17,9 @@ import _ from 'lodash';
|
|||
export class EMSTMSSource extends TMSSource {
|
||||
|
||||
static type = 'EMS_TMS';
|
||||
static typeDisplayName = 'Elastic Maps Service tiles';
|
||||
static title = 'Elastic Maps Service tiles';
|
||||
static description = 'Map tiles from Elastic Maps Service';
|
||||
static icon = 'emsApp';
|
||||
|
||||
static createDescriptor(serviceId) {
|
||||
return {
|
||||
|
@ -52,20 +53,6 @@ export class EMSTMSSource extends TMSSource {
|
|||
);
|
||||
}
|
||||
|
||||
static renderDropdownDisplayOption() {
|
||||
return (
|
||||
<Fragment>
|
||||
<strong>{EMSTMSSource.typeDisplayName}</strong>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiText size="s" color="subdued">
|
||||
<p className="euiTextColor--subdued">
|
||||
Map tiles from Elastic Maps Service
|
||||
</p>
|
||||
</EuiText>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
constructor(descriptor, { emsTmsServices }) {
|
||||
super(descriptor);
|
||||
this._emsTileServices = emsTmsServices;
|
||||
|
@ -107,6 +94,22 @@ export class EMSTMSSource extends TMSSource {
|
|||
return this._descriptor.id;
|
||||
}
|
||||
|
||||
async getAttributions() {
|
||||
const service = this._getTMSOptions();
|
||||
const attributions = service.attributionMarkdown.split('|');
|
||||
|
||||
return attributions.map((attribution) => {
|
||||
attribution = attribution.trim();
|
||||
//this assumes attribution is plain markdown link
|
||||
const extractLink = /\[(.*)\]\((.*)\)/;
|
||||
const result = extractLink.exec(attribution);
|
||||
return {
|
||||
label: result ? result[1] : null,
|
||||
url: result ? result[2] : null
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
getUrlTemplate() {
|
||||
const service = this._getTMSOptions();
|
||||
return service.url;
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 {
|
||||
EMSTMSSource,
|
||||
} from './ems_tms_source';
|
||||
|
||||
describe('EMSTMSSource', () => {
|
||||
|
||||
it('should get attribution from markdown (tiles v2 legacy format)', async () => {
|
||||
|
||||
const emsTmsSource = new EMSTMSSource({
|
||||
id: 'road_map'
|
||||
}, {
|
||||
emsTmsServices: [
|
||||
{
|
||||
id: 'road_map',
|
||||
attributionMarkdown: '[foobar](http://foobar.org) | [foobaz](http://foobaz.org)'
|
||||
}, {
|
||||
id: 'satellite',
|
||||
attributionMarkdown: '[satellite](http://satellite.org)'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
const attributions = await emsTmsSource.getAttributions();
|
||||
|
||||
expect(attributions).toEqual([
|
||||
{
|
||||
label: 'foobar',
|
||||
url: 'http://foobar.org'
|
||||
}, {
|
||||
label: 'foobaz',
|
||||
url: 'http://foobaz.org'
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue