mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[UnifiedFieldList] Remove redundant server routes. Create new example plugin for unified field list components and migrate tests. (#158377)
- Closes https://github.com/elastic/kibana/issues/147885
- Closes https://github.com/elastic/kibana/issues/157109
## Summary
**Before:**
Unified Field List plugin has internal routes (wrappers for client code)
which exist only to run api functional tests against them:
- `/api/unified_field_list/existing_fields/{dataViewId}`
- `/api/unified_field_list/field_stats`
Client code does not call these routes directly. So there is no reason
in keeping and versioning them.
**After:**
- Internal routes are removed
- A new "Unified Field List Examples" page was created
http://localhost:5601/app/unifiedFieldListExamples
- API functional tests (which used the routes) were converted to
functional tests against this new example page
- Created a new `unifiedFieldList` page object which is used now in
functional tests (methods are extracted from existing `discover` page
object).
**For testing:**
Steps:
1. Run Kibana with examples: `yarn start --run-examples`
2. Install sample data
3. And navigate to Developer Examples > Unified Field List Examples
page.

### Checklist
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
f43096a78f
commit
8d399fe3aa
90 changed files with 2104 additions and 1846 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -698,6 +698,7 @@ test/plugin_functional/plugins/ui_settings_plugin @elastic/kibana-core
|
||||||
packages/kbn-ui-shared-deps-npm @elastic/kibana-operations
|
packages/kbn-ui-shared-deps-npm @elastic/kibana-operations
|
||||||
packages/kbn-ui-shared-deps-src @elastic/kibana-operations
|
packages/kbn-ui-shared-deps-src @elastic/kibana-operations
|
||||||
packages/kbn-ui-theme @elastic/kibana-operations
|
packages/kbn-ui-theme @elastic/kibana-operations
|
||||||
|
examples/unified_field_list_examples @elastic/kibana-data-discovery
|
||||||
src/plugins/unified_field_list @elastic/kibana-data-discovery
|
src/plugins/unified_field_list @elastic/kibana-data-discovery
|
||||||
src/plugins/unified_histogram @elastic/kibana-data-discovery
|
src/plugins/unified_histogram @elastic/kibana-data-discovery
|
||||||
src/plugins/unified_search @elastic/kibana-visualizations
|
src/plugins/unified_search @elastic/kibana-visualizations
|
||||||
|
|
9
examples/unified_field_list_examples/README.md
Normal file
9
examples/unified_field_list_examples/README.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# unified_field_list_examples
|
||||||
|
|
||||||
|
Examples of unified field list components.
|
||||||
|
|
||||||
|
To run this example, ensure you have data to search against (for example, the sample datasets) and start kibana with the `--run-examples` flag.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn start --run-examples
|
||||||
|
```
|
|
@ -6,6 +6,5 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const BASE_API_PATH = '/internal/unified_field_list';
|
export const PLUGIN_ID = 'unifiedFieldListExamples';
|
||||||
export const FIELD_STATS_API_PATH = `${BASE_API_PATH}/field_stats`;
|
export const PLUGIN_NAME = 'Unified Field List Examples';
|
||||||
export const FIELD_EXISTING_API_PATH = `${BASE_API_PATH}/existing_fields/{dataViewId}`;
|
|
24
examples/unified_field_list_examples/kibana.jsonc
Normal file
24
examples/unified_field_list_examples/kibana.jsonc
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"type": "plugin",
|
||||||
|
"id": "@kbn/unified-field-list-examples-plugin",
|
||||||
|
"owner": "@elastic/kibana-data-discovery",
|
||||||
|
"description": "Examples for using unified field list.",
|
||||||
|
"plugin": {
|
||||||
|
"id": "unifiedFieldListExamples",
|
||||||
|
"server": false,
|
||||||
|
"browser": true,
|
||||||
|
"requiredPlugins": [
|
||||||
|
"navigation",
|
||||||
|
"developerExamples",
|
||||||
|
"inspector",
|
||||||
|
"kibanaUtils",
|
||||||
|
"unifiedSearch",
|
||||||
|
"unifiedFieldList",
|
||||||
|
"data",
|
||||||
|
"dataViews",
|
||||||
|
"dataViewFieldEditor",
|
||||||
|
"charts",
|
||||||
|
"fieldFormats"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
37
examples/unified_field_list_examples/public/application.tsx
Normal file
37
examples/unified_field_list_examples/public/application.tsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import { I18nProvider } from '@kbn/i18n-react';
|
||||||
|
import type { AppMountParameters, CoreStart } from '@kbn/core/public';
|
||||||
|
import { AppPluginStartDependencies } from './types';
|
||||||
|
import { UnifiedFieldListExampleApp } from './example_app';
|
||||||
|
|
||||||
|
export const renderApp = (
|
||||||
|
core: CoreStart,
|
||||||
|
deps: AppPluginStartDependencies,
|
||||||
|
{ element }: AppMountParameters
|
||||||
|
) => {
|
||||||
|
ReactDOM.render(
|
||||||
|
<I18nProvider>
|
||||||
|
<UnifiedFieldListExampleApp
|
||||||
|
services={{
|
||||||
|
core,
|
||||||
|
uiSettings: core.uiSettings,
|
||||||
|
...deps,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</I18nProvider>,
|
||||||
|
element
|
||||||
|
);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
ReactDOM.unmountComponentAtNode(element);
|
||||||
|
};
|
||||||
|
};
|
161
examples/unified_field_list_examples/public/example_app.tsx
Normal file
161
examples/unified_field_list_examples/public/example_app.tsx
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { css } from '@emotion/react';
|
||||||
|
import {
|
||||||
|
EuiFlexGroup,
|
||||||
|
EuiFlexItem,
|
||||||
|
EuiPage,
|
||||||
|
EuiPageBody,
|
||||||
|
EuiPageSidebar,
|
||||||
|
EuiTitle,
|
||||||
|
EuiEmptyPrompt,
|
||||||
|
EuiLoadingLogo,
|
||||||
|
} from '@elastic/eui';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||||
|
import { RootDragDropProvider } from '@kbn/dom-drag-drop';
|
||||||
|
import type { DataViewField } from '@kbn/data-views-plugin/public';
|
||||||
|
import { PLUGIN_ID, PLUGIN_NAME } from '../common';
|
||||||
|
import { FieldListSidebar, FieldListSidebarProps } from './field_list_sidebar';
|
||||||
|
import { ExampleDropZone } from './example_drop_zone';
|
||||||
|
|
||||||
|
interface UnifiedFieldListExampleAppProps {
|
||||||
|
services: FieldListSidebarProps['services'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UnifiedFieldListExampleApp: React.FC<UnifiedFieldListExampleAppProps> = ({
|
||||||
|
services,
|
||||||
|
}) => {
|
||||||
|
const { navigation, data, unifiedSearch } = services;
|
||||||
|
const { IndexPatternSelect } = unifiedSearch.ui;
|
||||||
|
const [dataView, setDataView] = useState<DataView | null>();
|
||||||
|
const [selectedFieldNames, setSelectedFieldNames] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const onAddFieldToWorkplace = useCallback(
|
||||||
|
(field: DataViewField) => {
|
||||||
|
setSelectedFieldNames((names) => [...names, field.name]);
|
||||||
|
},
|
||||||
|
[setSelectedFieldNames]
|
||||||
|
);
|
||||||
|
|
||||||
|
const onRemoveFieldFromWorkspace = useCallback(
|
||||||
|
(field: DataViewField) => {
|
||||||
|
setSelectedFieldNames((names) => names.filter((name) => name !== field.name));
|
||||||
|
},
|
||||||
|
[setSelectedFieldNames]
|
||||||
|
);
|
||||||
|
|
||||||
|
const onDropFieldToWorkplace = useCallback(
|
||||||
|
(fieldName: string) => {
|
||||||
|
setSelectedFieldNames((names) => [...names.filter((name) => name !== fieldName), fieldName]);
|
||||||
|
},
|
||||||
|
[setSelectedFieldNames]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Fetch the default data view using the `data.dataViews` service, as the component is mounted.
|
||||||
|
useEffect(() => {
|
||||||
|
const setDefaultDataView = async () => {
|
||||||
|
try {
|
||||||
|
const defaultDataView = await data.dataViews.getDefault();
|
||||||
|
setDataView(defaultDataView);
|
||||||
|
} catch (e) {
|
||||||
|
setDataView(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setDefaultDataView();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
if (typeof dataView === 'undefined') {
|
||||||
|
return (
|
||||||
|
<EuiEmptyPrompt
|
||||||
|
icon={<EuiLoadingLogo logo="logoKibana" size="xl" />}
|
||||||
|
title={<h2>{PLUGIN_NAME}</h2>}
|
||||||
|
body={<p>Loading...</p>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiPage grow={true}>
|
||||||
|
<EuiPageBody paddingSize="s">
|
||||||
|
<EuiFlexGroup direction="column" gutterSize="xs">
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiTitle>
|
||||||
|
<h1>{PLUGIN_NAME}</h1>
|
||||||
|
</EuiTitle>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<IndexPatternSelect
|
||||||
|
placeholder={i18n.translate('searchSessionExample.selectDataViewPlaceholder', {
|
||||||
|
defaultMessage: 'Select data view',
|
||||||
|
})}
|
||||||
|
indexPatternId={dataView?.id || ''}
|
||||||
|
onChange={async (dataViewId?: string) => {
|
||||||
|
if (dataViewId) {
|
||||||
|
const newDataView = await data.dataViews.get(dataViewId);
|
||||||
|
setDataView(newDataView);
|
||||||
|
} else {
|
||||||
|
setDataView(undefined);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
isClearable={false}
|
||||||
|
data-test-subj="dataViewSelector"
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
{dataView ? (
|
||||||
|
<>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<navigation.ui.TopNavMenu
|
||||||
|
appName={PLUGIN_ID}
|
||||||
|
showSearchBar={true}
|
||||||
|
useDefaultBehaviors={true}
|
||||||
|
indexPatterns={dataView ? [dataView] : undefined}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={true}>
|
||||||
|
<RootDragDropProvider>
|
||||||
|
<EuiFlexGroup direction="row" alignItems="stretch">
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiPageSidebar
|
||||||
|
css={css`
|
||||||
|
flex: 1;
|
||||||
|
width: 320px;
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<FieldListSidebar
|
||||||
|
services={services}
|
||||||
|
dataView={dataView}
|
||||||
|
selectedFieldNames={selectedFieldNames}
|
||||||
|
onAddFieldToWorkplace={onAddFieldToWorkplace}
|
||||||
|
onRemoveFieldFromWorkspace={onRemoveFieldFromWorkspace}
|
||||||
|
/>
|
||||||
|
</EuiPageSidebar>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem>
|
||||||
|
<ExampleDropZone onDropField={onDropFieldToWorkplace} />
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</RootDragDropProvider>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<EuiEmptyPrompt
|
||||||
|
iconType="warning"
|
||||||
|
color="warning"
|
||||||
|
title={<h2>Select a data view</h2>}
|
||||||
|
body={<p>Make sure to have at least one data view or install sample data.</p>}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</EuiPageBody>
|
||||||
|
</EuiPage>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useContext, useMemo } from 'react';
|
||||||
|
import { DragContext, DragDrop, DropOverlayWrapper, DropType } from '@kbn/dom-drag-drop';
|
||||||
|
import { EuiEmptyPrompt, EuiPanel } from '@elastic/eui';
|
||||||
|
|
||||||
|
const DROP_PROPS = {
|
||||||
|
value: {
|
||||||
|
id: 'exampleDropZone',
|
||||||
|
humanData: {
|
||||||
|
label: 'Drop zone for selecting fields',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
order: [1, 0, 0, 0],
|
||||||
|
types: ['field_add'] as DropType[],
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ExampleDropZoneProps {
|
||||||
|
onDropField: (fieldName: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ExampleDropZone: React.FC<ExampleDropZoneProps> = ({ onDropField }) => {
|
||||||
|
const dragDropContext = useContext(DragContext);
|
||||||
|
const draggingFieldName = dragDropContext.dragging?.id;
|
||||||
|
|
||||||
|
const onDroppingField = useMemo(() => {
|
||||||
|
if (!draggingFieldName) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => onDropField(draggingFieldName);
|
||||||
|
}, [onDropField, draggingFieldName]);
|
||||||
|
|
||||||
|
const isDropAllowed = Boolean(onDroppingField);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DragDrop
|
||||||
|
draggable={false}
|
||||||
|
dropTypes={isDropAllowed ? DROP_PROPS.types : undefined}
|
||||||
|
value={DROP_PROPS.value}
|
||||||
|
order={DROP_PROPS.order}
|
||||||
|
onDrop={onDroppingField}
|
||||||
|
>
|
||||||
|
<DropOverlayWrapper isVisible={isDropAllowed}>
|
||||||
|
<EuiPanel hasShadow={false} paddingSize="l" className="eui-fullHeight">
|
||||||
|
<EuiEmptyPrompt
|
||||||
|
iconType="beaker"
|
||||||
|
title={<h3>Example drop zone</h3>}
|
||||||
|
body={
|
||||||
|
<p>
|
||||||
|
Drop <strong>{draggingFieldName || 'a field'}</strong> here to select it
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</EuiPanel>
|
||||||
|
</DropOverlayWrapper>
|
||||||
|
</DragDrop>
|
||||||
|
);
|
||||||
|
};
|
225
examples/unified_field_list_examples/public/field_list_item.tsx
Normal file
225
examples/unified_field_list_examples/public/field_list_item.tsx
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import type { DataViewField, DataView } from '@kbn/data-views-plugin/common';
|
||||||
|
import { DragDrop } from '@kbn/dom-drag-drop';
|
||||||
|
import {
|
||||||
|
AddFieldFilterHandler,
|
||||||
|
FieldItemButton,
|
||||||
|
FieldItemButtonProps,
|
||||||
|
FieldPopover,
|
||||||
|
FieldPopoverHeader,
|
||||||
|
FieldsGroupNames,
|
||||||
|
FieldStats,
|
||||||
|
hasQuerySubscriberData,
|
||||||
|
RenderFieldItemParams,
|
||||||
|
useQuerySubscriber,
|
||||||
|
} from '@kbn/unified-field-list-plugin/public';
|
||||||
|
import { generateFilters } from '@kbn/data-plugin/public';
|
||||||
|
import type { CoreStart } from '@kbn/core-lifecycle-browser';
|
||||||
|
import type { AppPluginStartDependencies } from './types';
|
||||||
|
|
||||||
|
export interface FieldListItemProps extends RenderFieldItemParams<DataViewField> {
|
||||||
|
dataView: DataView;
|
||||||
|
services: AppPluginStartDependencies & {
|
||||||
|
core: CoreStart;
|
||||||
|
uiSettings: CoreStart['uiSettings'];
|
||||||
|
};
|
||||||
|
isSelected: boolean;
|
||||||
|
onAddFieldToWorkspace: FieldItemButtonProps<DataViewField>['onAddFieldToWorkspace'];
|
||||||
|
onRemoveFieldFromWorkspace: FieldItemButtonProps<DataViewField>['onRemoveFieldFromWorkspace'];
|
||||||
|
onRefreshFields: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FieldListItem({
|
||||||
|
dataView,
|
||||||
|
services,
|
||||||
|
isSelected,
|
||||||
|
field,
|
||||||
|
fieldSearchHighlight,
|
||||||
|
groupIndex,
|
||||||
|
groupName,
|
||||||
|
itemIndex,
|
||||||
|
hideDetails,
|
||||||
|
onRefreshFields,
|
||||||
|
onAddFieldToWorkspace,
|
||||||
|
onRemoveFieldFromWorkspace,
|
||||||
|
}: FieldListItemProps) {
|
||||||
|
const { dataViewFieldEditor, data } = services;
|
||||||
|
const querySubscriberResult = useQuerySubscriber({ data, listenToSearchSessionUpdates: false }); // this example app does not use search sessions
|
||||||
|
const filterManager = data?.query?.filterManager;
|
||||||
|
const [infoIsOpen, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const togglePopover = useCallback(() => {
|
||||||
|
setOpen((value) => !value);
|
||||||
|
}, [setOpen]);
|
||||||
|
|
||||||
|
const closePopover = useCallback(() => {
|
||||||
|
setOpen(false);
|
||||||
|
}, [setOpen]);
|
||||||
|
|
||||||
|
const closeFieldEditor = useRef<() => void | undefined>();
|
||||||
|
const setFieldEditorRef = useCallback((ref: () => void | undefined) => {
|
||||||
|
closeFieldEditor.current = ref;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const value = useMemo(
|
||||||
|
() => ({
|
||||||
|
id: field.name,
|
||||||
|
humanData: { label: field.displayName || field.name },
|
||||||
|
}),
|
||||||
|
[field]
|
||||||
|
);
|
||||||
|
|
||||||
|
const order = useMemo(() => [0, groupIndex, itemIndex], [groupIndex, itemIndex]);
|
||||||
|
|
||||||
|
const addFilterAndClose: AddFieldFilterHandler | undefined = useMemo(
|
||||||
|
() =>
|
||||||
|
filterManager && dataView
|
||||||
|
? (clickedField, values, operation) => {
|
||||||
|
closePopover();
|
||||||
|
const newFilters = generateFilters(
|
||||||
|
filterManager,
|
||||||
|
clickedField,
|
||||||
|
values,
|
||||||
|
operation,
|
||||||
|
dataView
|
||||||
|
);
|
||||||
|
filterManager.addFilters(newFilters);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
[dataView, filterManager, closePopover]
|
||||||
|
);
|
||||||
|
|
||||||
|
const editFieldAndClose = useMemo(
|
||||||
|
() =>
|
||||||
|
dataView
|
||||||
|
? (fieldName?: string) => {
|
||||||
|
const ref = dataViewFieldEditor.openEditor({
|
||||||
|
ctx: {
|
||||||
|
dataView,
|
||||||
|
},
|
||||||
|
fieldName,
|
||||||
|
onSave: async () => {
|
||||||
|
onRefreshFields();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (setFieldEditorRef) {
|
||||||
|
setFieldEditorRef(ref);
|
||||||
|
}
|
||||||
|
closePopover();
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
[dataViewFieldEditor, dataView, setFieldEditorRef, closePopover, onRefreshFields]
|
||||||
|
);
|
||||||
|
|
||||||
|
const removeFieldAndClose = useMemo(
|
||||||
|
() =>
|
||||||
|
dataView
|
||||||
|
? async (fieldName: string) => {
|
||||||
|
const ref = dataViewFieldEditor.openDeleteModal({
|
||||||
|
ctx: {
|
||||||
|
dataView,
|
||||||
|
},
|
||||||
|
fieldName,
|
||||||
|
onDelete: async () => {
|
||||||
|
onRefreshFields();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (setFieldEditorRef) {
|
||||||
|
setFieldEditorRef(ref);
|
||||||
|
}
|
||||||
|
closePopover();
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
[dataView, setFieldEditorRef, closePopover, dataViewFieldEditor, onRefreshFields]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const cleanup = () => {
|
||||||
|
if (closeFieldEditor?.current) {
|
||||||
|
closeFieldEditor?.current();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return () => {
|
||||||
|
// Make sure to close the editor when unmounting
|
||||||
|
cleanup();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li>
|
||||||
|
<FieldPopover
|
||||||
|
isOpen={infoIsOpen}
|
||||||
|
closePopover={closePopover}
|
||||||
|
button={
|
||||||
|
<DragDrop
|
||||||
|
draggable
|
||||||
|
order={order}
|
||||||
|
value={value}
|
||||||
|
dataTestSubj={`fieldListPanelField-${field.name}`}
|
||||||
|
onDragStart={closePopover}
|
||||||
|
>
|
||||||
|
<FieldItemButton
|
||||||
|
field={field}
|
||||||
|
fieldSearchHighlight={fieldSearchHighlight}
|
||||||
|
size="xs"
|
||||||
|
isActive={infoIsOpen}
|
||||||
|
isEmpty={groupName === FieldsGroupNames.EmptyFields}
|
||||||
|
isSelected={isSelected}
|
||||||
|
onClick={togglePopover}
|
||||||
|
onAddFieldToWorkspace={onAddFieldToWorkspace}
|
||||||
|
onRemoveFieldFromWorkspace={onRemoveFieldFromWorkspace}
|
||||||
|
/>
|
||||||
|
</DragDrop>
|
||||||
|
}
|
||||||
|
renderHeader={() => {
|
||||||
|
return (
|
||||||
|
<FieldPopoverHeader
|
||||||
|
field={field}
|
||||||
|
closePopover={closePopover}
|
||||||
|
onAddFieldToWorkspace={!isSelected ? onAddFieldToWorkspace : undefined}
|
||||||
|
onAddFilter={addFilterAndClose}
|
||||||
|
onEditField={editFieldAndClose}
|
||||||
|
onDeleteField={removeFieldAndClose}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
renderContent={
|
||||||
|
!hideDetails
|
||||||
|
? () => (
|
||||||
|
<>
|
||||||
|
{hasQuerySubscriberData(querySubscriberResult) && (
|
||||||
|
<FieldStats
|
||||||
|
services={services}
|
||||||
|
query={querySubscriberResult.query}
|
||||||
|
filters={querySubscriberResult.filters}
|
||||||
|
fromDate={querySubscriberResult.fromDate}
|
||||||
|
toDate={querySubscriberResult.toDate}
|
||||||
|
dataViewOrDataViewId={dataView}
|
||||||
|
onAddFilter={addFilterAndClose}
|
||||||
|
field={field}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback, useContext, useMemo } from 'react';
|
||||||
|
import type { DataView, DataViewField } from '@kbn/data-views-plugin/public';
|
||||||
|
import { ChildDragDropProvider, DragContext } from '@kbn/dom-drag-drop';
|
||||||
|
import {
|
||||||
|
FieldList,
|
||||||
|
FieldListFilters,
|
||||||
|
FieldListGrouped,
|
||||||
|
FieldListGroupedProps,
|
||||||
|
FieldsGroupNames,
|
||||||
|
useExistingFieldsFetcher,
|
||||||
|
useGroupedFields,
|
||||||
|
useQuerySubscriber,
|
||||||
|
} from '@kbn/unified-field-list-plugin/public';
|
||||||
|
import { FieldListItem, FieldListItemProps } from './field_list_item';
|
||||||
|
|
||||||
|
export interface FieldListSidebarProps {
|
||||||
|
dataView: DataView;
|
||||||
|
selectedFieldNames: string[];
|
||||||
|
services: FieldListItemProps['services'];
|
||||||
|
onAddFieldToWorkplace: FieldListItemProps['onAddFieldToWorkspace'];
|
||||||
|
onRemoveFieldFromWorkspace: FieldListItemProps['onRemoveFieldFromWorkspace'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FieldListSidebar: React.FC<FieldListSidebarProps> = ({
|
||||||
|
dataView,
|
||||||
|
selectedFieldNames,
|
||||||
|
services,
|
||||||
|
onAddFieldToWorkplace,
|
||||||
|
onRemoveFieldFromWorkspace,
|
||||||
|
}) => {
|
||||||
|
const dragDropContext = useContext(DragContext);
|
||||||
|
const allFields = dataView.fields;
|
||||||
|
const activeDataViews = useMemo(() => [dataView], [dataView]);
|
||||||
|
const querySubscriberResult = useQuerySubscriber({
|
||||||
|
data: services.data,
|
||||||
|
listenToSearchSessionUpdates: false, // this example app does not use search sessions
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSelectedFieldFilter = useCallback(
|
||||||
|
(field: DataViewField) => {
|
||||||
|
return selectedFieldNames.includes(field.name);
|
||||||
|
},
|
||||||
|
[selectedFieldNames]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { refetchFieldsExistenceInfo, isProcessing } = useExistingFieldsFetcher({
|
||||||
|
dataViews: activeDataViews, // if you need field existence info for more than one data view, you can specify it here
|
||||||
|
query: querySubscriberResult.query,
|
||||||
|
filters: querySubscriberResult.filters,
|
||||||
|
fromDate: querySubscriberResult.fromDate,
|
||||||
|
toDate: querySubscriberResult.toDate,
|
||||||
|
services,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { fieldListFiltersProps, fieldListGroupedProps } = useGroupedFields({
|
||||||
|
dataViewId: dataView.id ?? null,
|
||||||
|
allFields,
|
||||||
|
services,
|
||||||
|
isAffectedByGlobalFilter: Boolean(querySubscriberResult.filters?.length),
|
||||||
|
onSupportedFieldFilter,
|
||||||
|
onSelectedFieldFilter,
|
||||||
|
});
|
||||||
|
|
||||||
|
const onRefreshFields = useCallback(() => {
|
||||||
|
refetchFieldsExistenceInfo();
|
||||||
|
}, [refetchFieldsExistenceInfo]);
|
||||||
|
|
||||||
|
const renderFieldItem: FieldListGroupedProps<DataViewField>['renderFieldItem'] = useCallback(
|
||||||
|
(params) => (
|
||||||
|
<FieldListItem
|
||||||
|
dataView={dataView}
|
||||||
|
services={services}
|
||||||
|
isSelected={
|
||||||
|
params.groupName === FieldsGroupNames.SelectedFields ||
|
||||||
|
selectedFieldNames.includes(params.field.name)
|
||||||
|
}
|
||||||
|
onRefreshFields={onRefreshFields}
|
||||||
|
onAddFieldToWorkspace={onAddFieldToWorkplace}
|
||||||
|
onRemoveFieldFromWorkspace={onRemoveFieldFromWorkspace}
|
||||||
|
{...params}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[
|
||||||
|
dataView,
|
||||||
|
services,
|
||||||
|
onRefreshFields,
|
||||||
|
selectedFieldNames,
|
||||||
|
onAddFieldToWorkplace,
|
||||||
|
onRemoveFieldFromWorkspace,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ChildDragDropProvider {...dragDropContext}>
|
||||||
|
<FieldList
|
||||||
|
isProcessing={isProcessing}
|
||||||
|
prepend={<FieldListFilters {...fieldListFiltersProps} />}
|
||||||
|
>
|
||||||
|
<FieldListGrouped
|
||||||
|
{...fieldListGroupedProps}
|
||||||
|
renderFieldItem={renderFieldItem}
|
||||||
|
localStorageKeyPrefix="examples"
|
||||||
|
/>
|
||||||
|
</FieldList>
|
||||||
|
</ChildDragDropProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function onSupportedFieldFilter(field: DataViewField): boolean {
|
||||||
|
return field.name !== '_source';
|
||||||
|
}
|
19
examples/unified_field_list_examples/public/index.ts
Normal file
19
examples/unified_field_list_examples/public/index.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { UnifiedFieldListExamplesPlugin } from './plugin';
|
||||||
|
|
||||||
|
// This exports static code and TypeScript types,
|
||||||
|
// as well as, Kibana Platform `plugin()` initializer.
|
||||||
|
export function plugin() {
|
||||||
|
return new UnifiedFieldListExamplesPlugin();
|
||||||
|
}
|
||||||
|
export type {
|
||||||
|
UnifiedFieldListExamplesPluginSetup,
|
||||||
|
UnifiedFieldListExamplesPluginStart,
|
||||||
|
} from './types';
|
77
examples/unified_field_list_examples/public/plugin.ts
Normal file
77
examples/unified_field_list_examples/public/plugin.ts
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
AppMountParameters,
|
||||||
|
AppNavLinkStatus,
|
||||||
|
CoreSetup,
|
||||||
|
CoreStart,
|
||||||
|
Plugin,
|
||||||
|
} from '@kbn/core/public';
|
||||||
|
import {
|
||||||
|
AppPluginSetupDependencies,
|
||||||
|
AppPluginStartDependencies,
|
||||||
|
UnifiedFieldListExamplesPluginSetup,
|
||||||
|
UnifiedFieldListExamplesPluginStart,
|
||||||
|
} from './types';
|
||||||
|
import { PLUGIN_ID, PLUGIN_NAME } from '../common';
|
||||||
|
import image from './unified_field_list.png';
|
||||||
|
|
||||||
|
export class UnifiedFieldListExamplesPlugin
|
||||||
|
implements
|
||||||
|
Plugin<
|
||||||
|
UnifiedFieldListExamplesPluginSetup,
|
||||||
|
UnifiedFieldListExamplesPluginStart,
|
||||||
|
AppPluginSetupDependencies,
|
||||||
|
AppPluginStartDependencies
|
||||||
|
>
|
||||||
|
{
|
||||||
|
public setup(
|
||||||
|
core: CoreSetup<AppPluginStartDependencies>,
|
||||||
|
{ developerExamples }: AppPluginSetupDependencies
|
||||||
|
): UnifiedFieldListExamplesPluginSetup {
|
||||||
|
// Register an application into the side navigation menu
|
||||||
|
core.application.register({
|
||||||
|
id: PLUGIN_ID,
|
||||||
|
title: PLUGIN_NAME,
|
||||||
|
navLinkStatus: AppNavLinkStatus.hidden,
|
||||||
|
mount: async (params: AppMountParameters) => {
|
||||||
|
// Load application bundle
|
||||||
|
const { renderApp } = await import('./application');
|
||||||
|
// Get start services as specified in kibana.json
|
||||||
|
const [coreStart, depsStart] = await core.getStartServices();
|
||||||
|
// Render the application
|
||||||
|
return renderApp(coreStart, depsStart, params);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
developerExamples.register({
|
||||||
|
appId: PLUGIN_ID,
|
||||||
|
title: PLUGIN_NAME,
|
||||||
|
description: `Examples of unified field list functionality.`,
|
||||||
|
image,
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
label: 'README',
|
||||||
|
href: 'https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/README.md',
|
||||||
|
iconType: 'logoGithub',
|
||||||
|
target: '_blank',
|
||||||
|
size: 's',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public start(core: CoreStart): UnifiedFieldListExamplesPluginStart {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public stop() {}
|
||||||
|
}
|
35
examples/unified_field_list_examples/public/types.ts
Normal file
35
examples/unified_field_list_examples/public/types.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public';
|
||||||
|
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||||
|
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
|
||||||
|
import type { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public';
|
||||||
|
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||||
|
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||||
|
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||||
|
import type { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface UnifiedFieldListExamplesPluginSetup {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
export interface UnifiedFieldListExamplesPluginStart {}
|
||||||
|
|
||||||
|
export interface AppPluginSetupDependencies {
|
||||||
|
developerExamples: DeveloperExamplesSetup;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AppPluginStartDependencies {
|
||||||
|
navigation: NavigationPublicPluginStart;
|
||||||
|
data: DataPublicPluginStart;
|
||||||
|
dataViews: DataViewsPublicPluginStart;
|
||||||
|
dataViewFieldEditor: DataViewFieldEditorStart;
|
||||||
|
unifiedSearch: UnifiedSearchPublicPluginStart;
|
||||||
|
charts: ChartsPluginStart;
|
||||||
|
fieldFormats: FieldFormatsStart;
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 112 KiB |
32
examples/unified_field_list_examples/tsconfig.json
Normal file
32
examples/unified_field_list_examples/tsconfig.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "target/types"
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"index.ts",
|
||||||
|
"common/**/*.ts",
|
||||||
|
"public/**/*.ts",
|
||||||
|
"public/**/*.tsx",
|
||||||
|
"../../typings/**/*",
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"target/**/*",
|
||||||
|
],
|
||||||
|
"kbn_references": [
|
||||||
|
"@kbn/core",
|
||||||
|
"@kbn/data-plugin",
|
||||||
|
"@kbn/data-views-plugin",
|
||||||
|
"@kbn/navigation-plugin",
|
||||||
|
"@kbn/developer-examples-plugin",
|
||||||
|
"@kbn/unified-search-plugin",
|
||||||
|
"@kbn/i18n-react",
|
||||||
|
"@kbn/i18n",
|
||||||
|
"@kbn/dom-drag-drop",
|
||||||
|
"@kbn/unified-field-list-plugin",
|
||||||
|
"@kbn/core-lifecycle-browser",
|
||||||
|
"@kbn/charts-plugin",
|
||||||
|
"@kbn/field-formats-plugin",
|
||||||
|
"@kbn/data-view-field-editor-plugin",
|
||||||
|
]
|
||||||
|
}
|
|
@ -687,6 +687,7 @@
|
||||||
"@kbn/ui-shared-deps-npm": "link:packages/kbn-ui-shared-deps-npm",
|
"@kbn/ui-shared-deps-npm": "link:packages/kbn-ui-shared-deps-npm",
|
||||||
"@kbn/ui-shared-deps-src": "link:packages/kbn-ui-shared-deps-src",
|
"@kbn/ui-shared-deps-src": "link:packages/kbn-ui-shared-deps-src",
|
||||||
"@kbn/ui-theme": "link:packages/kbn-ui-theme",
|
"@kbn/ui-theme": "link:packages/kbn-ui-theme",
|
||||||
|
"@kbn/unified-field-list-examples-plugin": "link:examples/unified_field_list_examples",
|
||||||
"@kbn/unified-field-list-plugin": "link:src/plugins/unified_field_list",
|
"@kbn/unified-field-list-plugin": "link:src/plugins/unified_field_list",
|
||||||
"@kbn/unified-histogram-plugin": "link:src/plugins/unified_histogram",
|
"@kbn/unified-histogram-plugin": "link:src/plugins/unified_histogram",
|
||||||
"@kbn/unified-search-plugin": "link:src/plugins/unified_search",
|
"@kbn/unified-search-plugin": "link:src/plugins/unified_search",
|
||||||
|
|
|
@ -39,30 +39,25 @@ function getCommonFieldItemButtonProps({
|
||||||
}: GetCommonFieldItemButtonPropsParams): {
|
}: GetCommonFieldItemButtonPropsParams): {
|
||||||
field: FieldItemButtonProps<DataViewField>['field'];
|
field: FieldItemButtonProps<DataViewField>['field'];
|
||||||
isSelected: FieldItemButtonProps<DataViewField>['isSelected'];
|
isSelected: FieldItemButtonProps<DataViewField>['isSelected'];
|
||||||
dataTestSubj: FieldItemButtonProps<DataViewField>['dataTestSubj'];
|
|
||||||
buttonAddFieldToWorkspaceProps: FieldItemButtonProps<DataViewField>['buttonAddFieldToWorkspaceProps'];
|
buttonAddFieldToWorkspaceProps: FieldItemButtonProps<DataViewField>['buttonAddFieldToWorkspaceProps'];
|
||||||
buttonRemoveFieldFromWorkspaceProps: FieldItemButtonProps<DataViewField>['buttonRemoveFieldFromWorkspaceProps'];
|
buttonRemoveFieldFromWorkspaceProps: FieldItemButtonProps<DataViewField>['buttonRemoveFieldFromWorkspaceProps'];
|
||||||
onAddFieldToWorkspace: FieldItemButtonProps<DataViewField>['onAddFieldToWorkspace'];
|
onAddFieldToWorkspace: FieldItemButtonProps<DataViewField>['onAddFieldToWorkspace'];
|
||||||
onRemoveFieldFromWorkspace: FieldItemButtonProps<DataViewField>['onRemoveFieldFromWorkspace'];
|
onRemoveFieldFromWorkspace: FieldItemButtonProps<DataViewField>['onRemoveFieldFromWorkspace'];
|
||||||
} {
|
} {
|
||||||
const dataTestSubj = `fieldToggle-${field.name}`;
|
|
||||||
const handler =
|
const handler =
|
||||||
field.name === '_source' ? undefined : (f: DataViewField) => toggleDisplay(f, isSelected);
|
field.name === '_source' ? undefined : (f: DataViewField) => toggleDisplay(f, isSelected);
|
||||||
return {
|
return {
|
||||||
field,
|
field,
|
||||||
isSelected,
|
isSelected,
|
||||||
dataTestSubj: `field-${field.name}-showDetails`,
|
|
||||||
buttonAddFieldToWorkspaceProps: {
|
buttonAddFieldToWorkspaceProps: {
|
||||||
'aria-label': i18n.translate('discover.fieldChooser.discoverField.addFieldTooltip', {
|
'aria-label': i18n.translate('discover.fieldChooser.discoverField.addFieldTooltip', {
|
||||||
defaultMessage: 'Add field as column',
|
defaultMessage: 'Add field as column',
|
||||||
}),
|
}),
|
||||||
'data-test-subj': dataTestSubj,
|
|
||||||
},
|
},
|
||||||
buttonRemoveFieldFromWorkspaceProps: {
|
buttonRemoveFieldFromWorkspaceProps: {
|
||||||
'aria-label': i18n.translate('discover.fieldChooser.discoverField.removeFieldTooltip', {
|
'aria-label': i18n.translate('discover.fieldChooser.discoverField.removeFieldTooltip', {
|
||||||
defaultMessage: 'Remove field from table',
|
defaultMessage: 'Remove field from table',
|
||||||
}),
|
}),
|
||||||
'data-test-subj': dataTestSubj,
|
|
||||||
},
|
},
|
||||||
onAddFieldToWorkspace: handler,
|
onAddFieldToWorkspace: handler,
|
||||||
onRemoveFieldFromWorkspace: handler,
|
onRemoveFieldFromWorkspace: handler,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"description": "Contains functionality for the field list which can be integrated into apps",
|
"description": "Contains functionality for the field list which can be integrated into apps",
|
||||||
"plugin": {
|
"plugin": {
|
||||||
"id": "unifiedFieldList",
|
"id": "unifiedFieldList",
|
||||||
"server": true,
|
"server": false,
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"requiredPlugins": [
|
"requiredPlugins": [
|
||||||
"dataViews",
|
"dataViews",
|
||||||
|
|
|
@ -8,6 +8,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly 1`] = `
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
||||||
|
dataTestSubj="field-bytes-showDetails"
|
||||||
fieldIcon={
|
fieldIcon={
|
||||||
<WrappedFieldIcon
|
<WrappedFieldIcon
|
||||||
scripted={false}
|
scripted={false}
|
||||||
|
@ -38,6 +39,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly for Records (Lens
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--document unifiedFieldListItemButton--exists"
|
className="unifiedFieldListItemButton unifiedFieldListItemButton--document unifiedFieldListItemButton--exists"
|
||||||
|
dataTestSubj="field-___records___-showDetails"
|
||||||
fieldIcon={
|
fieldIcon={
|
||||||
<WrappedFieldIcon
|
<WrappedFieldIcon
|
||||||
scripted={false}
|
scripted={false}
|
||||||
|
@ -68,6 +70,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly for text-based co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--string unifiedFieldListItemButton--exists"
|
className="unifiedFieldListItemButton unifiedFieldListItemButton--string unifiedFieldListItemButton--exists"
|
||||||
|
dataTestSubj="field-agent-showDetails"
|
||||||
fieldIcon={
|
fieldIcon={
|
||||||
<WrappedFieldIcon
|
<WrappedFieldIcon
|
||||||
type="string"
|
type="string"
|
||||||
|
@ -96,6 +99,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly for wildcard sear
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--date unifiedFieldListItemButton--exists"
|
className="unifiedFieldListItemButton unifiedFieldListItemButton--date unifiedFieldListItemButton--exists"
|
||||||
|
dataTestSubj="field-script date-showDetails"
|
||||||
fieldIcon={
|
fieldIcon={
|
||||||
<WrappedFieldIcon
|
<WrappedFieldIcon
|
||||||
scripted={true}
|
scripted={true}
|
||||||
|
@ -125,6 +129,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly when a conflict f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--conflict unifiedFieldListItemButton--exists"
|
className="unifiedFieldListItemButton unifiedFieldListItemButton--conflict unifiedFieldListItemButton--exists"
|
||||||
|
dataTestSubj="field-custom_user_field-showDetails"
|
||||||
fieldIcon={
|
fieldIcon={
|
||||||
<WrappedFieldIcon
|
<WrappedFieldIcon
|
||||||
scripted={false}
|
scripted={false}
|
||||||
|
@ -156,6 +161,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly when empty 1`] =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--date unifiedFieldListItemButton--missing"
|
className="unifiedFieldListItemButton unifiedFieldListItemButton--date unifiedFieldListItemButton--missing"
|
||||||
|
dataTestSubj="field-script date-showDetails"
|
||||||
fieldIcon={
|
fieldIcon={
|
||||||
<WrappedFieldIcon
|
<WrappedFieldIcon
|
||||||
scripted={true}
|
scripted={true}
|
||||||
|
@ -221,6 +227,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly with an action wh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
||||||
|
dataTestSubj="field-bytes-showDetails"
|
||||||
fieldAction={
|
fieldAction={
|
||||||
<EuiToolTip
|
<EuiToolTip
|
||||||
content="Add \\"bytes\\" field"
|
content="Add \\"bytes\\" field"
|
||||||
|
@ -232,7 +239,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly with an action wh
|
||||||
aria-label="Add \\"bytes\\" field"
|
aria-label="Add \\"bytes\\" field"
|
||||||
className="unifiedFieldListItemButton__action unifiedFieldListItemButton__action--always"
|
className="unifiedFieldListItemButton__action unifiedFieldListItemButton__action--always"
|
||||||
color="text"
|
color="text"
|
||||||
data-test-subj="unifiedFieldListItem_addField-bytes"
|
data-test-subj="fieldToggle-bytes"
|
||||||
iconType="plusInCircle"
|
iconType="plusInCircle"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
/>
|
/>
|
||||||
|
@ -267,6 +274,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly with an action wh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
||||||
|
dataTestSubj="field-bytes-showDetails"
|
||||||
fieldAction={
|
fieldAction={
|
||||||
<EuiToolTip
|
<EuiToolTip
|
||||||
content="Remove \\"bytes\\" field"
|
content="Remove \\"bytes\\" field"
|
||||||
|
@ -278,7 +286,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly with an action wh
|
||||||
aria-label="Remove \\"bytes\\" field"
|
aria-label="Remove \\"bytes\\" field"
|
||||||
className="unifiedFieldListItemButton__action"
|
className="unifiedFieldListItemButton__action"
|
||||||
color="danger"
|
color="danger"
|
||||||
data-test-subj="unifiedFieldListItem_removeField-bytes"
|
data-test-subj="fieldToggle-bytes"
|
||||||
iconType="cross"
|
iconType="cross"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -136,7 +136,7 @@ export function FieldItemButton<T extends FieldListItem = DataViewField>({
|
||||||
content={removeFieldFromWorkspaceTooltip}
|
content={removeFieldFromWorkspaceTooltip}
|
||||||
>
|
>
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
data-test-subj={`unifiedFieldListItem_removeField-${field.name}`}
|
data-test-subj={`fieldToggle-${field.name}`}
|
||||||
aria-label={removeFieldFromWorkspaceTooltip}
|
aria-label={removeFieldFromWorkspaceTooltip}
|
||||||
{...(buttonRemoveFieldFromWorkspaceProps || {})}
|
{...(buttonRemoveFieldFromWorkspaceProps || {})}
|
||||||
className={classnames(
|
className={classnames(
|
||||||
|
@ -159,7 +159,7 @@ export function FieldItemButton<T extends FieldListItem = DataViewField>({
|
||||||
content={addFieldToWorkspaceTooltip}
|
content={addFieldToWorkspaceTooltip}
|
||||||
>
|
>
|
||||||
<EuiButtonIcon
|
<EuiButtonIcon
|
||||||
data-test-subj={`unifiedFieldListItem_addField-${field.name}`}
|
data-test-subj={`fieldToggle-${field.name}`}
|
||||||
aria-label={addFieldToWorkspaceTooltip}
|
aria-label={addFieldToWorkspaceTooltip}
|
||||||
{...(buttonAddFieldToWorkspaceProps || {})}
|
{...(buttonAddFieldToWorkspaceProps || {})}
|
||||||
className={classnames(fieldActionClassName, buttonAddFieldToWorkspaceProps?.className)}
|
className={classnames(fieldActionClassName, buttonAddFieldToWorkspaceProps?.className)}
|
||||||
|
@ -179,7 +179,7 @@ export function FieldItemButton<T extends FieldListItem = DataViewField>({
|
||||||
return (
|
return (
|
||||||
<FieldButton
|
<FieldButton
|
||||||
key={`field-item-button-${field.name}`}
|
key={`field-item-button-${field.name}`}
|
||||||
dataTestSubj={dataTestSubj}
|
dataTestSubj={dataTestSubj || `field-${field.name}-showDetails`}
|
||||||
size={size || 's'}
|
size={size || 's'}
|
||||||
className={classes}
|
className={classes}
|
||||||
isActive={isActive}
|
isActive={isActive}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { type DataViewField } from '@kbn/data-views-plugin/common';
|
import { type DataViewField } from '@kbn/data-views-plugin/common';
|
||||||
import { type FieldListItem, FieldsGroupNames } from '../../types';
|
import { type FieldListItem, FieldsGroupNames, type RenderFieldItemParams } from '../../types';
|
||||||
import './fields_accordion.scss';
|
import './fields_accordion.scss';
|
||||||
|
|
||||||
export interface FieldsAccordionProps<T extends FieldListItem> {
|
export interface FieldsAccordionProps<T extends FieldListItem> {
|
||||||
|
@ -35,14 +35,7 @@ export interface FieldsAccordionProps<T extends FieldListItem> {
|
||||||
groupName: FieldsGroupNames;
|
groupName: FieldsGroupNames;
|
||||||
fieldSearchHighlight?: string;
|
fieldSearchHighlight?: string;
|
||||||
paginatedFields: T[];
|
paginatedFields: T[];
|
||||||
renderFieldItem: (params: {
|
renderFieldItem: (params: RenderFieldItemParams<T>) => JSX.Element;
|
||||||
field: T;
|
|
||||||
hideDetails?: boolean;
|
|
||||||
itemIndex: number;
|
|
||||||
groupIndex: number;
|
|
||||||
groupName: FieldsGroupNames;
|
|
||||||
fieldSearchHighlight?: string;
|
|
||||||
}) => JSX.Element;
|
|
||||||
renderCallout: () => JSX.Element;
|
renderCallout: () => JSX.Element;
|
||||||
showExistenceFetchError?: boolean;
|
showExistenceFetchError?: boolean;
|
||||||
showExistenceFetchTimeout?: boolean;
|
showExistenceFetchTimeout?: boolean;
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
/* 1 - `important` is to ensure that even if styles ordering is different (like for some reason on Developer Examples page),
|
||||||
|
this one will be used instead of eui defaults */
|
||||||
|
|
||||||
.unifiedFieldList__fieldPopover__fieldPopoverPanel {
|
.unifiedFieldList__fieldPopover__fieldPopoverPanel {
|
||||||
min-width: $euiSizeXXL * 6.5;
|
min-width: $euiSizeXXL * 6.5 !important; /* 1 */
|
||||||
max-width: $euiSizeXXL * 7.5;
|
max-width: $euiSizeXXL * 7.5 !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,13 +34,13 @@ import {
|
||||||
} from '@elastic/charts';
|
} from '@elastic/charts';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { buildEsQuery, Query, Filter, AggregateQuery } from '@kbn/es-query';
|
import { buildEsQuery, Query, Filter, AggregateQuery } from '@kbn/es-query';
|
||||||
import { showExamplesForField } from '../../../common/utils/field_examples_calculator';
|
import { showExamplesForField } from '../../services/field_stats/field_examples_calculator';
|
||||||
import { OverrideFieldTopValueBarCallback } from './field_top_values_bucket';
|
import { OverrideFieldTopValueBarCallback } from './field_top_values_bucket';
|
||||||
import type { BucketedAggregation, NumberSummary } from '../../../common/types';
|
import type { BucketedAggregation, NumberSummary } from '../../../common/types';
|
||||||
import {
|
import {
|
||||||
canProvideStatsForField,
|
canProvideStatsForField,
|
||||||
canProvideNumberSummaryForField,
|
canProvideNumberSummaryForField,
|
||||||
} from '../../../common/utils/field_stats_utils';
|
} from '../../services/field_stats/field_stats_utils';
|
||||||
import { loadFieldStats } from '../../services/field_stats';
|
import { loadFieldStats } from '../../services/field_stats';
|
||||||
import type { AddFieldFilterHandler } from '../../types';
|
import type { AddFieldFilterHandler } from '../../types';
|
||||||
import {
|
import {
|
||||||
|
@ -284,6 +284,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
||||||
let title = <></>;
|
let title = <></>;
|
||||||
|
|
||||||
function combineWithTitleAndFooter(el: React.ReactElement) {
|
function combineWithTitleAndFooter(el: React.ReactElement) {
|
||||||
|
const dataTestSubjDocsCount = 'unifiedFieldStats-statsFooter-docsCount';
|
||||||
const countsElement = totalDocuments ? (
|
const countsElement = totalDocuments ? (
|
||||||
<EuiText color="subdued" size="xs" data-test-subj={`${dataTestSubject}-statsFooter`}>
|
<EuiText color="subdued" size="xs" data-test-subj={`${dataTestSubject}-statsFooter`}>
|
||||||
{sampledDocuments && sampledDocuments < totalDocuments ? (
|
{sampledDocuments && sampledDocuments < totalDocuments ? (
|
||||||
|
@ -293,7 +294,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
||||||
values={{
|
values={{
|
||||||
sampledDocuments,
|
sampledDocuments,
|
||||||
sampledDocumentsFormatted: (
|
sampledDocumentsFormatted: (
|
||||||
<strong>
|
<strong data-test-subj={dataTestSubjDocsCount}>
|
||||||
{fieldFormats
|
{fieldFormats
|
||||||
.getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER])
|
.getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER])
|
||||||
.convert(sampledDocuments)}
|
.convert(sampledDocuments)}
|
||||||
|
@ -308,7 +309,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
||||||
values={{
|
values={{
|
||||||
totalDocuments,
|
totalDocuments,
|
||||||
totalDocumentsFormatted: (
|
totalDocumentsFormatted: (
|
||||||
<strong>
|
<strong data-test-subj={dataTestSubjDocsCount}>
|
||||||
{fieldFormats
|
{fieldFormats
|
||||||
.getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER])
|
.getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER])
|
||||||
.convert(totalDocuments)}
|
.convert(totalDocuments)}
|
||||||
|
@ -418,6 +419,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
||||||
title = (
|
title = (
|
||||||
<>
|
<>
|
||||||
<EuiButtonGroup
|
<EuiButtonGroup
|
||||||
|
data-test-subj="unifiedFieldStats-buttonGroup"
|
||||||
buttonSize="compressed"
|
buttonSize="compressed"
|
||||||
isFullWidth
|
isFullWidth
|
||||||
legend={i18n.translate('unifiedFieldList.fieldStats.displayToggleLegend', {
|
legend={i18n.translate('unifiedFieldList.fieldStats.displayToggleLegend', {
|
||||||
|
@ -480,34 +482,71 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
||||||
|
|
||||||
if (field.type === 'date') {
|
if (field.type === 'date') {
|
||||||
return combineWithTitleAndFooter(
|
return combineWithTitleAndFooter(
|
||||||
<div data-test-subj={`${dataTestSubject}-histogram`}>
|
<div data-test-subj="unifiedFieldStats-timeDistribution">
|
||||||
<Chart size={{ height: 200, width: 300 - 32 }}>
|
<div data-test-subj={`${dataTestSubject}-histogram`}>
|
||||||
|
<Chart size={{ height: 200, width: 300 - 32 }}>
|
||||||
|
<Settings
|
||||||
|
tooltip={{ type: TooltipType.None }}
|
||||||
|
theme={customChartTheme}
|
||||||
|
baseTheme={chartBaseTheme}
|
||||||
|
xDomain={
|
||||||
|
fromDateParsed && toDateParsed
|
||||||
|
? {
|
||||||
|
min: fromDateParsed.valueOf(),
|
||||||
|
max: toDateParsed.valueOf(),
|
||||||
|
minInterval: Math.round(
|
||||||
|
(toDateParsed.valueOf() - fromDateParsed.valueOf()) / 10
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Axis
|
||||||
|
id="key"
|
||||||
|
position={Position.Bottom}
|
||||||
|
tickFormat={
|
||||||
|
fromDateParsed && toDateParsed
|
||||||
|
? niceTimeFormatter([fromDateParsed.valueOf(), toDateParsed.valueOf()])
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
showOverlappingTicks={true}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<HistogramBarSeries
|
||||||
|
data={histogram.buckets}
|
||||||
|
id={specId}
|
||||||
|
xAccessor={'key'}
|
||||||
|
yAccessors={['count']}
|
||||||
|
xScaleType={ScaleType.Time}
|
||||||
|
yScaleType={ScaleType.Linear}
|
||||||
|
timeZone="local"
|
||||||
|
/>
|
||||||
|
</Chart>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showingHistogram || !topValues || !topValues.buckets.length) {
|
||||||
|
return combineWithTitleAndFooter(
|
||||||
|
<div data-test-subj="unifiedFieldStats-histogram">
|
||||||
|
<Chart
|
||||||
|
data-test-subj={`${dataTestSubject}-histogram`}
|
||||||
|
size={{ height: 200, width: '100%' }}
|
||||||
|
>
|
||||||
<Settings
|
<Settings
|
||||||
|
rotation={90}
|
||||||
tooltip={{ type: TooltipType.None }}
|
tooltip={{ type: TooltipType.None }}
|
||||||
theme={customChartTheme}
|
theme={customChartTheme}
|
||||||
baseTheme={chartBaseTheme}
|
baseTheme={chartBaseTheme}
|
||||||
xDomain={
|
|
||||||
fromDateParsed && toDateParsed
|
|
||||||
? {
|
|
||||||
min: fromDateParsed.valueOf(),
|
|
||||||
max: toDateParsed.valueOf(),
|
|
||||||
minInterval: Math.round(
|
|
||||||
(toDateParsed.valueOf() - fromDateParsed.valueOf()) / 10
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Axis
|
<Axis
|
||||||
id="key"
|
id="key"
|
||||||
position={Position.Bottom}
|
position={Position.Left}
|
||||||
tickFormat={
|
|
||||||
fromDateParsed && toDateParsed
|
|
||||||
? niceTimeFormatter([fromDateParsed.valueOf(), toDateParsed.valueOf()])
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
showOverlappingTicks={true}
|
showOverlappingTicks={true}
|
||||||
|
tickFormat={(d) => formatter.convert(d)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HistogramBarSeries
|
<HistogramBarSeries
|
||||||
|
@ -515,51 +554,19 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
||||||
id={specId}
|
id={specId}
|
||||||
xAccessor={'key'}
|
xAccessor={'key'}
|
||||||
yAccessors={['count']}
|
yAccessors={['count']}
|
||||||
xScaleType={ScaleType.Time}
|
xScaleType={ScaleType.Linear}
|
||||||
yScaleType={ScaleType.Linear}
|
yScaleType={ScaleType.Linear}
|
||||||
timeZone="local"
|
|
||||||
/>
|
/>
|
||||||
</Chart>
|
</Chart>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showingHistogram || !topValues || !topValues.buckets.length) {
|
|
||||||
return combineWithTitleAndFooter(
|
|
||||||
<Chart
|
|
||||||
data-test-subj={`${dataTestSubject}-histogram`}
|
|
||||||
size={{ height: 200, width: '100%' }}
|
|
||||||
>
|
|
||||||
<Settings
|
|
||||||
rotation={90}
|
|
||||||
tooltip={{ type: TooltipType.None }}
|
|
||||||
theme={customChartTheme}
|
|
||||||
baseTheme={chartBaseTheme}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Axis
|
|
||||||
id="key"
|
|
||||||
position={Position.Left}
|
|
||||||
showOverlappingTicks={true}
|
|
||||||
tickFormat={(d) => formatter.convert(d)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<HistogramBarSeries
|
|
||||||
data={histogram.buckets}
|
|
||||||
id={specId}
|
|
||||||
xAccessor={'key'}
|
|
||||||
yAccessors={['count']}
|
|
||||||
xScaleType={ScaleType.Linear}
|
|
||||||
yScaleType={ScaleType.Linear}
|
|
||||||
/>
|
|
||||||
</Chart>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topValues && topValues.buckets.length) {
|
if (topValues && topValues.buckets.length) {
|
||||||
return combineWithTitleAndFooter(
|
return combineWithTitleAndFooter(
|
||||||
<FieldTopValues
|
<FieldTopValues
|
||||||
|
areExamples={showExamplesForField(field)}
|
||||||
buckets={topValues.buckets}
|
buckets={topValues.buckets}
|
||||||
dataView={dataView}
|
dataView={dataView}
|
||||||
field={field}
|
field={field}
|
||||||
|
|
|
@ -44,6 +44,7 @@ describe('UnifiedFieldList <FieldTopValues />', () => {
|
||||||
} as unknown as DataView;
|
} as unknown as DataView;
|
||||||
|
|
||||||
defaultProps = {
|
defaultProps = {
|
||||||
|
areExamples: false,
|
||||||
dataView,
|
dataView,
|
||||||
field: dataView.fields.find((f) => f.name === 'source')!,
|
field: dataView.fields.find((f) => f.name === 'source')!,
|
||||||
sampledValuesCount: 5000,
|
sampledValuesCount: 5000,
|
||||||
|
|
|
@ -15,6 +15,7 @@ import FieldTopValuesBucket from './field_top_values_bucket';
|
||||||
import type { OverrideFieldTopValueBarCallback } from './field_top_values_bucket';
|
import type { OverrideFieldTopValueBarCallback } from './field_top_values_bucket';
|
||||||
|
|
||||||
export interface FieldTopValuesProps {
|
export interface FieldTopValuesProps {
|
||||||
|
areExamples: boolean; // real top values or only examples
|
||||||
buckets: BucketedAggregation<number | string>['buckets'];
|
buckets: BucketedAggregation<number | string>['buckets'];
|
||||||
dataView: DataView;
|
dataView: DataView;
|
||||||
field: DataViewField;
|
field: DataViewField;
|
||||||
|
@ -26,6 +27,7 @@ export interface FieldTopValuesProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FieldTopValues: React.FC<FieldTopValuesProps> = ({
|
export const FieldTopValues: React.FC<FieldTopValuesProps> = ({
|
||||||
|
areExamples,
|
||||||
buckets,
|
buckets,
|
||||||
dataView,
|
dataView,
|
||||||
field,
|
field,
|
||||||
|
@ -46,54 +48,60 @@ export const FieldTopValues: React.FC<FieldTopValuesProps> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-test-subj={`${dataTestSubject}-topValues`}>
|
<div
|
||||||
{buckets.map((bucket, index) => {
|
data-test-subj={
|
||||||
const fieldValue = bucket.key;
|
areExamples ? 'unifiedFieldStats-exampleValueBuckets' : 'unifiedFieldStats-topValueBuckets'
|
||||||
const formatted = formatter.convert(fieldValue);
|
}
|
||||||
|
>
|
||||||
|
<div data-test-subj={`${dataTestSubject}-topValues`}>
|
||||||
|
{buckets.map((bucket, index) => {
|
||||||
|
const fieldValue = bucket.key;
|
||||||
|
const formatted = formatter.convert(fieldValue);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment key={fieldValue}>
|
<Fragment key={fieldValue}>
|
||||||
{index > 0 && <EuiSpacer size="s" />}
|
{index > 0 && <EuiSpacer size="s" />}
|
||||||
|
<FieldTopValuesBucket
|
||||||
|
field={field}
|
||||||
|
fieldValue={fieldValue}
|
||||||
|
formattedFieldValue={formatted}
|
||||||
|
formattedPercentage={getFormattedPercentageValue(
|
||||||
|
bucket.count,
|
||||||
|
sampledValuesCount,
|
||||||
|
digitsRequired
|
||||||
|
)}
|
||||||
|
progressValue={getProgressValue(bucket.count, sampledValuesCount)}
|
||||||
|
count={bucket.count}
|
||||||
|
color={color}
|
||||||
|
data-test-subj={dataTestSubject}
|
||||||
|
onAddFilter={onAddFilter}
|
||||||
|
overrideFieldTopValueBar={overrideFieldTopValueBar}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{otherCount > 0 && (
|
||||||
|
<>
|
||||||
|
<EuiSpacer size="s" />
|
||||||
<FieldTopValuesBucket
|
<FieldTopValuesBucket
|
||||||
|
type="other"
|
||||||
field={field}
|
field={field}
|
||||||
fieldValue={fieldValue}
|
fieldValue={undefined}
|
||||||
formattedFieldValue={formatted}
|
|
||||||
formattedPercentage={getFormattedPercentageValue(
|
formattedPercentage={getFormattedPercentageValue(
|
||||||
bucket.count,
|
otherCount,
|
||||||
sampledValuesCount,
|
sampledValuesCount,
|
||||||
digitsRequired
|
digitsRequired
|
||||||
)}
|
)}
|
||||||
progressValue={getProgressValue(bucket.count, sampledValuesCount)}
|
progressValue={getProgressValue(otherCount, sampledValuesCount)}
|
||||||
count={bucket.count}
|
count={otherCount}
|
||||||
color={color}
|
color={color}
|
||||||
data-test-subj={dataTestSubject}
|
data-test-subj={dataTestSubject}
|
||||||
onAddFilter={onAddFilter}
|
onAddFilter={onAddFilter}
|
||||||
overrideFieldTopValueBar={overrideFieldTopValueBar}
|
overrideFieldTopValueBar={overrideFieldTopValueBar}
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</>
|
||||||
);
|
)}
|
||||||
})}
|
</div>
|
||||||
{otherCount > 0 && (
|
|
||||||
<>
|
|
||||||
<EuiSpacer size="s" />
|
|
||||||
<FieldTopValuesBucket
|
|
||||||
type="other"
|
|
||||||
field={field}
|
|
||||||
fieldValue={undefined}
|
|
||||||
formattedPercentage={getFormattedPercentageValue(
|
|
||||||
otherCount,
|
|
||||||
sampledValuesCount,
|
|
||||||
digitsRequired
|
|
||||||
)}
|
|
||||||
progressValue={getProgressValue(otherCount, sampledValuesCount)}
|
|
||||||
count={otherCount}
|
|
||||||
color={color}
|
|
||||||
data-test-subj={dataTestSubject}
|
|
||||||
onAddFilter={onAddFilter}
|
|
||||||
overrideFieldTopValueBar={overrideFieldTopValueBar}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { getResolvedDateRange } from '../utils/get_resolved_date_range';
|
||||||
*/
|
*/
|
||||||
export interface QuerySubscriberParams {
|
export interface QuerySubscriberParams {
|
||||||
data: DataPublicPluginStart;
|
data: DataPublicPluginStart;
|
||||||
|
listenToSearchSessionUpdates?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,9 +32,13 @@ export interface QuerySubscriberResult {
|
||||||
/**
|
/**
|
||||||
* Memorizes current query, filters and absolute date range
|
* Memorizes current query, filters and absolute date range
|
||||||
* @param data
|
* @param data
|
||||||
|
* @param listenToSearchSessionUpdates
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export const useQuerySubscriber = ({ data }: QuerySubscriberParams) => {
|
export const useQuerySubscriber = ({
|
||||||
|
data,
|
||||||
|
listenToSearchSessionUpdates = true,
|
||||||
|
}: QuerySubscriberParams) => {
|
||||||
const timefilter = data.query.timefilter.timefilter;
|
const timefilter = data.query.timefilter.timefilter;
|
||||||
const [result, setResult] = useState<QuerySubscriberResult>(() => {
|
const [result, setResult] = useState<QuerySubscriberResult>(() => {
|
||||||
const state = data.query.getState();
|
const state = data.query.getState();
|
||||||
|
@ -47,6 +52,10 @@ export const useQuerySubscriber = ({ data }: QuerySubscriberParams) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!listenToSearchSessionUpdates) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const subscription = data.search.session.state$.subscribe((sessionState) => {
|
const subscription = data.search.session.state$.subscribe((sessionState) => {
|
||||||
const dateRange = getResolvedDateRange(timefilter);
|
const dateRange = getResolvedDateRange(timefilter);
|
||||||
setResult((prevState) => ({
|
setResult((prevState) => ({
|
||||||
|
@ -57,7 +66,24 @@ export const useQuerySubscriber = ({ data }: QuerySubscriberParams) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => subscription.unsubscribe();
|
return () => subscription.unsubscribe();
|
||||||
}, [setResult, timefilter, data.search.session.state$]);
|
}, [setResult, timefilter, data.search.session.state$, listenToSearchSessionUpdates]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (listenToSearchSessionUpdates) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const subscription = timefilter.getTimeUpdate$().subscribe(() => {
|
||||||
|
const dateRange = getResolvedDateRange(timefilter);
|
||||||
|
setResult((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
fromDate: dateRange.fromDate,
|
||||||
|
toDate: dateRange.toDate,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => subscription.unsubscribe();
|
||||||
|
}, [setResult, timefilter, listenToSearchSessionUpdates]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subscription = data.query.state$.subscribe(({ state, changes }) => {
|
const subscription = data.query.state$.subscribe(({ state, changes }) => {
|
||||||
|
|
|
@ -57,6 +57,7 @@ export type {
|
||||||
FieldTypeKnown,
|
FieldTypeKnown,
|
||||||
FieldListItem,
|
FieldListItem,
|
||||||
GetCustomFieldType,
|
GetCustomFieldType,
|
||||||
|
RenderFieldItemParams,
|
||||||
} from './types';
|
} from './types';
|
||||||
export { ExistenceFetchStatus, FieldsGroupNames } from './types';
|
export { ExistenceFetchStatus, FieldsGroupNames } from './types';
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DataView } from '@kbn/data-views-plugin/common';
|
import { DataView } from '@kbn/data-views-plugin/common';
|
||||||
import {
|
import { existingFields, buildFieldList } from './field_existing_utils';
|
||||||
legacyExistingFields,
|
|
||||||
existingFields,
|
|
||||||
Field,
|
|
||||||
buildFieldList,
|
|
||||||
} from './field_existing_utils';
|
|
||||||
|
|
||||||
describe('existingFields', () => {
|
describe('existingFields', () => {
|
||||||
it('should remove missing fields by matching names', () => {
|
it('should remove missing fields by matching names', () => {
|
||||||
|
@ -46,89 +41,6 @@ describe('existingFields', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('legacyExistingFields', () => {
|
|
||||||
function field(opts: string | Partial<Field>): Field {
|
|
||||||
const obj = typeof opts === 'object' ? opts : {};
|
|
||||||
const name = (typeof opts === 'string' ? opts : opts.name) || 'test';
|
|
||||||
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
isScript: false,
|
|
||||||
isMeta: false,
|
|
||||||
...obj,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchResults(fields: Record<string, unknown[]> = {}) {
|
|
||||||
return { fields, _index: '_index', _id: '_id' };
|
|
||||||
}
|
|
||||||
|
|
||||||
it('should handle root level fields', () => {
|
|
||||||
const result = legacyExistingFields(
|
|
||||||
[searchResults({ foo: ['bar'] }), searchResults({ baz: [0] })],
|
|
||||||
[field('foo'), field('bar'), field('baz')]
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toEqual(['foo', 'baz']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle basic arrays, ignoring empty ones', () => {
|
|
||||||
const result = legacyExistingFields(
|
|
||||||
[searchResults({ stuff: ['heyo', 'there'], empty: [] })],
|
|
||||||
[field('stuff'), field('empty')]
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toEqual(['stuff']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle objects with dotted fields', () => {
|
|
||||||
const result = legacyExistingFields(
|
|
||||||
[searchResults({ 'geo.country_name': ['US'] })],
|
|
||||||
[field('geo.country_name')]
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toEqual(['geo.country_name']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('supports scripted fields', () => {
|
|
||||||
const result = legacyExistingFields(
|
|
||||||
[searchResults({ bar: ['scriptvalue'] })],
|
|
||||||
[field({ name: 'bar', isScript: true })]
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toEqual(['bar']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('supports runtime fields', () => {
|
|
||||||
const result = legacyExistingFields(
|
|
||||||
[searchResults({ runtime_foo: ['scriptvalue'] })],
|
|
||||||
[
|
|
||||||
field({
|
|
||||||
name: 'runtime_foo',
|
|
||||||
runtimeField: { type: 'long', script: { source: '2+2' } },
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toEqual(['runtime_foo']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('supports meta fields', () => {
|
|
||||||
const result = legacyExistingFields(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
// @ts-expect-error _mymeta is not defined on estypes.SearchHit
|
|
||||||
_mymeta: 'abc',
|
|
||||||
...searchResults({ bar: ['scriptvalue'] }),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[field({ name: '_mymeta', isMeta: true })]
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result).toEqual(['_mymeta']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('buildFieldList', () => {
|
describe('buildFieldList', () => {
|
||||||
const indexPattern = {
|
const indexPattern = {
|
||||||
title: 'testpattern',
|
title: 'testpattern',
|
|
@ -6,7 +6,6 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Boom from '@hapi/boom';
|
|
||||||
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||||
import { RuntimeField } from '@kbn/data-views-plugin/common';
|
import { RuntimeField } from '@kbn/data-views-plugin/common';
|
||||||
import type { DataViewsContract, DataView, FieldSpec } from '@kbn/data-views-plugin/common';
|
import type { DataViewsContract, DataView, FieldSpec } from '@kbn/data-views-plugin/common';
|
||||||
|
@ -120,35 +119,3 @@ export function existingFields(filteredFields: FieldSpec[], allFields: Field[]):
|
||||||
.filter((field) => field.isScript || field.runtimeField || filteredFieldsSet.has(field.name))
|
.filter((field) => field.isScript || field.runtimeField || filteredFieldsSet.has(field.name))
|
||||||
.map((f) => f.name);
|
.map((f) => f.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Exported only for unit tests.
|
|
||||||
*/
|
|
||||||
export function legacyExistingFields(docs: estypes.SearchHit[], fields: Field[]): string[] {
|
|
||||||
const missingFields = new Set(fields);
|
|
||||||
|
|
||||||
for (const doc of docs) {
|
|
||||||
if (missingFields.size === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
missingFields.forEach((field) => {
|
|
||||||
let fieldStore = doc.fields!;
|
|
||||||
if (field.isMeta) {
|
|
||||||
fieldStore = doc;
|
|
||||||
}
|
|
||||||
const value = fieldStore[field.name];
|
|
||||||
if (Array.isArray(value) && value.length) {
|
|
||||||
missingFields.delete(field);
|
|
||||||
} else if (!Array.isArray(value) && value) {
|
|
||||||
missingFields.delete(field);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return fields.filter((field) => !missingFields.has(field)).map((f) => f.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isBoomError(error: { isBoom?: boolean }): error is Boom.Boom {
|
|
||||||
return error.isBoom === true;
|
|
||||||
}
|
|
|
@ -10,7 +10,7 @@ import { IUiSettingsClient } from '@kbn/core/public';
|
||||||
import { DataPublicPluginStart, UI_SETTINGS } from '@kbn/data-plugin/public';
|
import { DataPublicPluginStart, UI_SETTINGS } from '@kbn/data-plugin/public';
|
||||||
import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/common';
|
import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/common';
|
||||||
import { lastValueFrom } from 'rxjs';
|
import { lastValueFrom } from 'rxjs';
|
||||||
import { fetchFieldExistence } from '../../../common/utils/field_existing_utils';
|
import { fetchFieldExistence } from './field_existing_utils';
|
||||||
|
|
||||||
interface FetchFieldExistenceParams {
|
interface FetchFieldExistenceParams {
|
||||||
data: DataPublicPluginStart;
|
data: DataPublicPluginStart;
|
||||||
|
|
|
@ -11,7 +11,7 @@ import DateMath from '@kbn/datemath';
|
||||||
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
||||||
import type { ESSearchResponse } from '@kbn/es-types';
|
import type { ESSearchResponse } from '@kbn/es-types';
|
||||||
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||||
import type { FieldStatsResponse } from '../types';
|
import type { FieldStatsResponse } from '../../../common/types';
|
||||||
import {
|
import {
|
||||||
getFieldExampleBuckets,
|
getFieldExampleBuckets,
|
||||||
canProvideExamplesForField,
|
canProvideExamplesForField,
|
|
@ -10,11 +10,7 @@ import { lastValueFrom } from 'rxjs';
|
||||||
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
||||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||||
import type { FieldStatsResponse } from '../../../common/types';
|
import type { FieldStatsResponse } from '../../../common/types';
|
||||||
import {
|
import { fetchAndCalculateFieldStats, SearchHandler, buildSearchParams } from './field_stats_utils';
|
||||||
fetchAndCalculateFieldStats,
|
|
||||||
SearchHandler,
|
|
||||||
buildSearchParams,
|
|
||||||
} from '../../../common/utils/field_stats_utils';
|
|
||||||
|
|
||||||
interface FetchFieldStatsParams {
|
interface FetchFieldStatsParams {
|
||||||
services: {
|
services: {
|
||||||
|
|
|
@ -73,3 +73,12 @@ export type FieldTypeKnown = Exclude<
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type GetCustomFieldType<T extends FieldListItem> = (field: T) => FieldTypeKnown;
|
export type GetCustomFieldType<T extends FieldListItem> = (field: T) => FieldTypeKnown;
|
||||||
|
|
||||||
|
export interface RenderFieldItemParams<T extends FieldListItem> {
|
||||||
|
field: T;
|
||||||
|
hideDetails?: boolean;
|
||||||
|
itemIndex: number;
|
||||||
|
groupIndex: number;
|
||||||
|
groupName: FieldsGroupNames;
|
||||||
|
fieldSearchHighlight?: string;
|
||||||
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { PluginInitializerContext } from '@kbn/core/server';
|
|
||||||
import { UnifiedFieldListPlugin } from './plugin';
|
|
||||||
|
|
||||||
// This exports static code and TypeScript types,
|
|
||||||
// as well as, Kibana Platform `plugin()` initializer.
|
|
||||||
|
|
||||||
export function plugin(initializerContext: PluginInitializerContext) {
|
|
||||||
return new UnifiedFieldListPlugin(initializerContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type {
|
|
||||||
UnifiedFieldListServerPluginSetup,
|
|
||||||
UnifiedFieldListServerPluginStart,
|
|
||||||
PluginSetup,
|
|
||||||
PluginStart,
|
|
||||||
} from './types';
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server';
|
|
||||||
import {
|
|
||||||
UnifiedFieldListServerPluginSetup,
|
|
||||||
UnifiedFieldListServerPluginStart,
|
|
||||||
PluginStart,
|
|
||||||
PluginSetup,
|
|
||||||
} from './types';
|
|
||||||
import { defineRoutes } from './routes';
|
|
||||||
|
|
||||||
export class UnifiedFieldListPlugin
|
|
||||||
implements Plugin<UnifiedFieldListServerPluginSetup, UnifiedFieldListServerPluginStart>
|
|
||||||
{
|
|
||||||
private readonly logger: Logger;
|
|
||||||
|
|
||||||
constructor(initializerContext: PluginInitializerContext) {
|
|
||||||
this.logger = initializerContext.logger.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public setup(core: CoreSetup<PluginStart>, plugins: PluginSetup) {
|
|
||||||
this.logger.debug('unifiedFieldList: Setup');
|
|
||||||
|
|
||||||
defineRoutes(core, this.logger);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public start(core: CoreStart, plugins: PluginStart) {
|
|
||||||
this.logger.debug('unifiedFieldList: Started');
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
public stop() {}
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { errors } from '@elastic/elasticsearch';
|
|
||||||
import { schema } from '@kbn/config-schema';
|
|
||||||
import { CoreSetup, Logger } from '@kbn/core/server';
|
|
||||||
import { UI_SETTINGS } from '@kbn/data-plugin/server';
|
|
||||||
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
|
||||||
|
|
||||||
import { fetchFieldExistence, isBoomError } from '../../common/utils/field_existing_utils';
|
|
||||||
import { FIELD_EXISTING_API_PATH } from '../../common/constants';
|
|
||||||
import { PluginStart } from '../types';
|
|
||||||
|
|
||||||
export async function existingFieldsRoute(setup: CoreSetup<PluginStart>, logger: Logger) {
|
|
||||||
const router = setup.http.createRouter();
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
{
|
|
||||||
path: FIELD_EXISTING_API_PATH,
|
|
||||||
validate: {
|
|
||||||
params: schema.object({
|
|
||||||
dataViewId: schema.string(),
|
|
||||||
}),
|
|
||||||
body: schema.object({
|
|
||||||
dslQuery: schema.object({}, { unknowns: 'allow' }),
|
|
||||||
fromDate: schema.maybe(schema.string()),
|
|
||||||
toDate: schema.maybe(schema.string()),
|
|
||||||
timeFieldName: schema.maybe(schema.string()),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
async (context, req, res) => {
|
|
||||||
const [{ savedObjects, elasticsearch, uiSettings }, { dataViews }] =
|
|
||||||
await setup.getStartServices();
|
|
||||||
const savedObjectsClient = savedObjects.getScopedClient(req);
|
|
||||||
const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient);
|
|
||||||
const [includeFrozen, metaFields] = await Promise.all([
|
|
||||||
uiSettingsClient.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN),
|
|
||||||
uiSettingsClient.get(UI_SETTINGS.META_FIELDS),
|
|
||||||
]);
|
|
||||||
const esClient = elasticsearch.client.asScoped(req).asCurrentUser;
|
|
||||||
try {
|
|
||||||
const dataViewsService = await dataViews.dataViewsServiceFactory(
|
|
||||||
savedObjectsClient,
|
|
||||||
esClient
|
|
||||||
);
|
|
||||||
return res.ok({
|
|
||||||
body: await fetchFieldExistence({
|
|
||||||
...req.body,
|
|
||||||
dataViewsService,
|
|
||||||
includeFrozen,
|
|
||||||
metaFields,
|
|
||||||
dataView: await dataViewsService.get(req.params.dataViewId),
|
|
||||||
search: async (params) => {
|
|
||||||
const contextCore = await context.core;
|
|
||||||
return await contextCore.elasticsearch.client.asCurrentUser.search<
|
|
||||||
estypes.SearchHit[]
|
|
||||||
>(
|
|
||||||
{ ...params },
|
|
||||||
{
|
|
||||||
// Global request timeout. Will cancel the request if exceeded. Overrides the elasticsearch.requestTimeout
|
|
||||||
requestTimeout: '5000ms',
|
|
||||||
// Fails fast instead of retrying- default is to retry
|
|
||||||
maxRetries: 0,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof errors.TimeoutError) {
|
|
||||||
logger.info(`Field existence check timed out on ${req.params.dataViewId}`);
|
|
||||||
// 408 is Request Timeout
|
|
||||||
return res.customError({ statusCode: 408, body: e.message });
|
|
||||||
}
|
|
||||||
logger.info(
|
|
||||||
`Field existence check failed on ${req.params.dataViewId}: ${
|
|
||||||
isBoomError(e) ? e.output.payload.message : e.message
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
if (e instanceof errors.ResponseError && e.statusCode === 404) {
|
|
||||||
return res.notFound({ body: e.message });
|
|
||||||
}
|
|
||||||
if (isBoomError(e)) {
|
|
||||||
if (e.output.statusCode === 404) {
|
|
||||||
return res.notFound({ body: e.output.payload.message });
|
|
||||||
}
|
|
||||||
throw new Error(e.output.payload.message);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { errors } from '@elastic/elasticsearch';
|
|
||||||
import { schema } from '@kbn/config-schema';
|
|
||||||
import { CoreSetup } from '@kbn/core/server';
|
|
||||||
import { SavedObjectNotFound } from '@kbn/kibana-utils-plugin/common';
|
|
||||||
import { FIELD_STATS_API_PATH } from '../../common/constants';
|
|
||||||
import type { PluginStart } from '../types';
|
|
||||||
import {
|
|
||||||
fetchAndCalculateFieldStats,
|
|
||||||
SearchHandler,
|
|
||||||
buildSearchParams,
|
|
||||||
} from '../../common/utils/field_stats_utils';
|
|
||||||
|
|
||||||
export async function initFieldStatsRoute(setup: CoreSetup<PluginStart>) {
|
|
||||||
const router = setup.http.createRouter();
|
|
||||||
router.post(
|
|
||||||
{
|
|
||||||
path: FIELD_STATS_API_PATH,
|
|
||||||
validate: {
|
|
||||||
body: schema.object(
|
|
||||||
{
|
|
||||||
dslQuery: schema.object({}, { unknowns: 'allow' }),
|
|
||||||
fromDate: schema.string(),
|
|
||||||
toDate: schema.string(),
|
|
||||||
dataViewId: schema.string(),
|
|
||||||
fieldName: schema.string(),
|
|
||||||
size: schema.maybe(schema.number()),
|
|
||||||
},
|
|
||||||
{ unknowns: 'allow' }
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
async (context, req, res) => {
|
|
||||||
const requestClient = (await context.core).elasticsearch.client.asCurrentUser;
|
|
||||||
const { fromDate, toDate, fieldName, dslQuery, size, dataViewId } = req.body;
|
|
||||||
|
|
||||||
const [{ savedObjects, elasticsearch }, { dataViews }] = await setup.getStartServices();
|
|
||||||
const savedObjectsClient = savedObjects.getScopedClient(req);
|
|
||||||
const esClient = elasticsearch.client.asScoped(req).asCurrentUser;
|
|
||||||
const indexPatternsService = await dataViews.dataViewsServiceFactory(
|
|
||||||
savedObjectsClient,
|
|
||||||
esClient
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const dataView = await indexPatternsService.get(dataViewId);
|
|
||||||
const field = dataView.fields.find((f) => f.name === fieldName);
|
|
||||||
|
|
||||||
if (!field) {
|
|
||||||
throw new Error(`Field {fieldName} not found in data view ${dataView.title}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const searchHandler: SearchHandler = async (body) => {
|
|
||||||
const result = await requestClient.search(
|
|
||||||
buildSearchParams({
|
|
||||||
dataViewPattern: dataView.title,
|
|
||||||
timeFieldName: dataView.timeFieldName,
|
|
||||||
fromDate,
|
|
||||||
toDate,
|
|
||||||
dslQuery,
|
|
||||||
runtimeMappings: dataView.getRuntimeMappings(),
|
|
||||||
...body,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const stats = await fetchAndCalculateFieldStats({
|
|
||||||
searchHandler,
|
|
||||||
dataView,
|
|
||||||
field,
|
|
||||||
fromDate,
|
|
||||||
toDate,
|
|
||||||
size,
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.ok({
|
|
||||||
body: stats,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof SavedObjectNotFound) {
|
|
||||||
return res.notFound();
|
|
||||||
}
|
|
||||||
if (e instanceof errors.ResponseError && e.statusCode === 404) {
|
|
||||||
return res.notFound();
|
|
||||||
}
|
|
||||||
if (e.isBoom) {
|
|
||||||
if (e.output.statusCode === 404) {
|
|
||||||
return res.notFound();
|
|
||||||
}
|
|
||||||
throw new Error(e.output.message);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { CoreSetup, Logger } from '@kbn/core/server';
|
|
||||||
import { PluginStart } from '../types';
|
|
||||||
import { existingFieldsRoute } from './existing_fields';
|
|
||||||
import { initFieldStatsRoute } from './field_stats';
|
|
||||||
|
|
||||||
// These routes are defined only for running integration tests under
|
|
||||||
// test/api_integration/apis/unified_field_list
|
|
||||||
// UnifiedFieldList does not call these API - it uses only the client code.
|
|
||||||
export function defineRoutes(setup: CoreSetup<PluginStart>, logger: Logger) {
|
|
||||||
initFieldStatsRoute(setup);
|
|
||||||
existingFieldsRoute(setup, logger);
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { PluginStart as DataViewsServerPluginStart } from '@kbn/data-views-plugin/server';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
||||||
export interface UnifiedFieldListServerPluginSetup {}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
||||||
export interface UnifiedFieldListServerPluginStart {}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
||||||
export interface PluginSetup {}
|
|
||||||
|
|
||||||
export interface PluginStart {
|
|
||||||
dataViews: DataViewsServerPluginStart;
|
|
||||||
}
|
|
|
@ -7,11 +7,9 @@
|
||||||
"../../typings/**/*",
|
"../../typings/**/*",
|
||||||
"common/**/*",
|
"common/**/*",
|
||||||
"public/**/*",
|
"public/**/*",
|
||||||
"server/**/*",
|
|
||||||
],
|
],
|
||||||
"kbn_references": [
|
"kbn_references": [
|
||||||
"@kbn/core",
|
"@kbn/core",
|
||||||
"@kbn/kibana-utils-plugin",
|
|
||||||
"@kbn/data-views-plugin",
|
"@kbn/data-views-plugin",
|
||||||
"@kbn/data-plugin",
|
"@kbn/data-plugin",
|
||||||
"@kbn/charts-plugin",
|
"@kbn/charts-plugin",
|
||||||
|
@ -24,7 +22,6 @@
|
||||||
"@kbn/field-formats-plugin",
|
"@kbn/field-formats-plugin",
|
||||||
"@kbn/i18n-react",
|
"@kbn/i18n-react",
|
||||||
"@kbn/analytics",
|
"@kbn/analytics",
|
||||||
"@kbn/config-schema",
|
|
||||||
"@kbn/core-lifecycle-browser",
|
"@kbn/core-lifecycle-browser",
|
||||||
"@kbn/react-field",
|
"@kbn/react-field",
|
||||||
"@kbn/field-types",
|
"@kbn/field-types",
|
||||||
|
|
|
@ -9,7 +9,14 @@
|
||||||
import { FtrProviderContext } from '../ftr_provider_context';
|
import { FtrProviderContext } from '../ftr_provider_context';
|
||||||
|
|
||||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'share', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'share',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const dataGrid = getService('dataGrid');
|
const dataGrid = getService('dataGrid');
|
||||||
const a11y = getService('a11y');
|
const a11y = getService('a11y');
|
||||||
const savedQueryManagementComponent = getService('savedQueryManagementComponent');
|
const savedQueryManagementComponent = getService('savedQueryManagementComponent');
|
||||||
|
@ -68,14 +75,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('a11y test on open sidenav filter', async () => {
|
it('a11y test on open sidenav filter', async () => {
|
||||||
await PageObjects.discover.openSidebarFieldFilter();
|
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||||
await a11y.testAppSnapshot();
|
await a11y.testAppSnapshot();
|
||||||
await PageObjects.discover.closeSidebarFieldFilter();
|
await PageObjects.unifiedFieldList.closeSidebarFieldFilter();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('a11y test on tables with columns view', async () => {
|
it('a11y test on tables with columns view', async () => {
|
||||||
for (const columnName of TEST_COLUMN_NAMES) {
|
for (const columnName of TEST_COLUMN_NAMES) {
|
||||||
await PageObjects.discover.clickFieldListItemToggle(columnName);
|
await PageObjects.unifiedFieldList.clickFieldListItemToggle(columnName);
|
||||||
}
|
}
|
||||||
await a11y.testAppSnapshot();
|
await a11y.testAppSnapshot();
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,7 +28,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
||||||
loadTestFile(require.resolve('./stats'));
|
loadTestFile(require.resolve('./stats'));
|
||||||
loadTestFile(require.resolve('./ui_metric'));
|
loadTestFile(require.resolve('./ui_metric'));
|
||||||
loadTestFile(require.resolve('./ui_counters'));
|
loadTestFile(require.resolve('./ui_counters'));
|
||||||
loadTestFile(require.resolve('./unified_field_list'));
|
|
||||||
loadTestFile(require.resolve('./telemetry'));
|
loadTestFile(require.resolve('./telemetry'));
|
||||||
loadTestFile(require.resolve('./guided_onboarding'));
|
loadTestFile(require.resolve('./guided_onboarding'));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import expect from '@kbn/expect';
|
|
||||||
|
|
||||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
|
||||||
|
|
||||||
const TEST_START_TIME = '2010-09-19T06:31:44.000';
|
|
||||||
const TEST_END_TIME = '2023-09-23T18:31:44.000';
|
|
||||||
const COMMON_HEADERS = {
|
|
||||||
'kbn-xsrf': 'some-xsrf-token',
|
|
||||||
};
|
|
||||||
const metaFields = ['_id', '_index', '_score', '_source'];
|
|
||||||
|
|
||||||
const fieldsWithData = [
|
|
||||||
'ts',
|
|
||||||
'filter_field',
|
|
||||||
'textfield1',
|
|
||||||
'textfield2',
|
|
||||||
'mapping_runtime_field',
|
|
||||||
'data_view_runtime_field',
|
|
||||||
];
|
|
||||||
|
|
||||||
export default ({ getService }: FtrProviderContext) => {
|
|
||||||
const esArchiver = getService('esArchiver');
|
|
||||||
const supertest = getService('supertest');
|
|
||||||
const kibanaServer = getService('kibanaServer');
|
|
||||||
const dataViewId = 'existence_index';
|
|
||||||
const API_PATH = `/internal/unified_field_list/existing_fields/${dataViewId}`;
|
|
||||||
|
|
||||||
describe('existing_fields apis', () => {
|
|
||||||
before(async () => {
|
|
||||||
await esArchiver.load(
|
|
||||||
'test/api_integration/fixtures/es_archiver/index_patterns/constant_keyword'
|
|
||||||
);
|
|
||||||
await kibanaServer.importExport.load(
|
|
||||||
'test/api_integration/fixtures/kbn_archiver/index_patterns/constant_keyword.json'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
after(async () => {
|
|
||||||
await esArchiver.unload(
|
|
||||||
'test/api_integration/fixtures/es_archiver/index_patterns/constant_keyword'
|
|
||||||
);
|
|
||||||
await kibanaServer.importExport.unload(
|
|
||||||
'test/api_integration/fixtures/kbn_archiver/index_patterns/constant_keyword.json'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('existence', () => {
|
|
||||||
it('should find which fields exist in the sample documents', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dslQuery: {
|
|
||||||
bool: {
|
|
||||||
filter: [{ match_all: {} }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body.indexPatternTitle).to.eql('existence_index_*');
|
|
||||||
expect(body.existingFieldNames.sort()).to.eql([...metaFields, ...fieldsWithData].sort());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return fields filtered by term query', async () => {
|
|
||||||
const expectedFieldNames = [
|
|
||||||
'ts',
|
|
||||||
'filter_field',
|
|
||||||
'textfield1',
|
|
||||||
// textfield2 and mapping_runtime_field are defined on the other index
|
|
||||||
'data_view_runtime_field',
|
|
||||||
];
|
|
||||||
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dslQuery: {
|
|
||||||
bool: {
|
|
||||||
filter: [{ term: { filter_field: 'a' } }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
expect(body.existingFieldNames.sort()).to.eql(
|
|
||||||
[...metaFields, ...expectedFieldNames].sort()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return fields filtered by match_phrase query', async () => {
|
|
||||||
const expectedFieldNames = [
|
|
||||||
'ts',
|
|
||||||
'filter_field',
|
|
||||||
'textfield1',
|
|
||||||
// textfield2 and mapping_runtime_field are defined on the other index
|
|
||||||
'data_view_runtime_field',
|
|
||||||
];
|
|
||||||
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dslQuery: {
|
|
||||||
bool: {
|
|
||||||
filter: [{ match_phrase: { filter_field: 'a' } }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
expect(body.existingFieldNames.sort()).to.eql(
|
|
||||||
[...metaFields, ...expectedFieldNames].sort()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return fields filtered by time range', async () => {
|
|
||||||
const expectedFieldNames = [
|
|
||||||
'ts',
|
|
||||||
'filter_field',
|
|
||||||
'textfield1',
|
|
||||||
// textfield2 and mapping_runtime_field are defined on the other index
|
|
||||||
'data_view_runtime_field',
|
|
||||||
];
|
|
||||||
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dslQuery: {
|
|
||||||
bool: {
|
|
||||||
filter: [{ term: { filter_field: 'a' } }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: '2021-12-12',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
expect(body.existingFieldNames.sort()).to.eql(
|
|
||||||
[...metaFields, ...expectedFieldNames].sort()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,601 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License
|
|
||||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
||||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
||||||
* Side Public License, v 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import expect from '@kbn/expect';
|
|
||||||
|
|
||||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
|
||||||
|
|
||||||
const TEST_START_TIME = '2015-09-19T06:31:44.000';
|
|
||||||
const TEST_END_TIME = '2015-09-23T18:31:44.000';
|
|
||||||
const COMMON_HEADERS = {
|
|
||||||
'kbn-xsrf': 'some-xsrf-token',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ({ getService }: FtrProviderContext) => {
|
|
||||||
const esArchiver = getService('esArchiver');
|
|
||||||
const kibanaServer = getService('kibanaServer');
|
|
||||||
const supertest = getService('supertest');
|
|
||||||
const API_PATH = '/internal/unified_field_list/field_stats';
|
|
||||||
|
|
||||||
describe('field stats apis', () => {
|
|
||||||
before(async () => {
|
|
||||||
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional');
|
|
||||||
});
|
|
||||||
after(async () => {
|
|
||||||
await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('field distribution', () => {
|
|
||||||
before(async () => {
|
|
||||||
await kibanaServer.savedObjects.cleanStandardList();
|
|
||||||
await kibanaServer.importExport.load(
|
|
||||||
'x-pack/test/functional/fixtures/kbn_archiver/visualize/default'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
after(async () => {
|
|
||||||
await kibanaServer.savedObjects.cleanStandardList();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a 404 for missing index patterns', async () => {
|
|
||||||
await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: '123',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'bytes',
|
|
||||||
})
|
|
||||||
.expect(404);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should also work without specifying a time field', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'bytes',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.have.property('totalDocuments', 4634);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an auto histogram for numbers and top values', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'bytes',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
totalDocuments: 4634,
|
|
||||||
sampledDocuments: 4634,
|
|
||||||
sampledValues: 4634,
|
|
||||||
histogram: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 705,
|
|
||||||
key: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 898,
|
|
||||||
key: 1999,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 886,
|
|
||||||
key: 3998,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 970,
|
|
||||||
key: 5997,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 939,
|
|
||||||
key: 7996,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 44,
|
|
||||||
key: 9995,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 43,
|
|
||||||
key: 11994,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 43,
|
|
||||||
key: 13993,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 57,
|
|
||||||
key: 15992,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 49,
|
|
||||||
key: 17991,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
topValues: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 147,
|
|
||||||
key: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 5,
|
|
||||||
key: 3954,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 5,
|
|
||||||
key: 5846,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 5,
|
|
||||||
key: 6497,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 4,
|
|
||||||
key: 1840,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 4,
|
|
||||||
key: 4206,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 4,
|
|
||||||
key: 4328,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 4,
|
|
||||||
key: 4669,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 4,
|
|
||||||
key: 5863,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 4,
|
|
||||||
key: 6631,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an auto histogram for dates', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: '@timestamp',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
totalDocuments: 4634,
|
|
||||||
histogram: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 1162,
|
|
||||||
key: 1442875680000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 3420,
|
|
||||||
key: 1442914560000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 52,
|
|
||||||
key: 1442953440000,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return top values for strings', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'geo.src',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
totalDocuments: 4634,
|
|
||||||
sampledDocuments: 4634,
|
|
||||||
sampledValues: 4633,
|
|
||||||
topValues: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 832,
|
|
||||||
key: 'CN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 804,
|
|
||||||
key: 'IN',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 425,
|
|
||||||
key: 'US',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 158,
|
|
||||||
key: 'ID',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 143,
|
|
||||||
key: 'BR',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 116,
|
|
||||||
key: 'PK',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 106,
|
|
||||||
key: 'BD',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 94,
|
|
||||||
key: 'NG',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 84,
|
|
||||||
key: 'RU',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 73,
|
|
||||||
key: 'JP',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return top values for ip fields', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'ip',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
totalDocuments: 4634,
|
|
||||||
sampledDocuments: 4634,
|
|
||||||
sampledValues: 4633,
|
|
||||||
topValues: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 13,
|
|
||||||
key: '177.194.175.66',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 12,
|
|
||||||
key: '18.55.141.62',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 12,
|
|
||||||
key: '53.55.251.105',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 11,
|
|
||||||
key: '21.111.249.239',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 11,
|
|
||||||
key: '97.63.84.25',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 11,
|
|
||||||
key: '100.99.207.174',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 11,
|
|
||||||
key: '112.34.138.226',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 11,
|
|
||||||
key: '194.68.89.92',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 11,
|
|
||||||
key: '235.186.79.201',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 10,
|
|
||||||
key: '57.79.108.136',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return histograms for scripted date fields', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'scripted_date',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
histogram: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 4634,
|
|
||||||
key: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
totalDocuments: 4634,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return top values for scripted string fields', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'scripted_string',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
totalDocuments: 4634,
|
|
||||||
sampledDocuments: 4634,
|
|
||||||
sampledValues: 4634,
|
|
||||||
topValues: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 4634,
|
|
||||||
key: 'hello',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return examples for non-aggregatable fields', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'extension', // `extension.keyword` is an aggregatable field but `extension` is not
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body.totalDocuments).to.eql(4634);
|
|
||||||
expect(body.sampledDocuments).to.eql(100);
|
|
||||||
expect(body.sampledValues).to.eql(100);
|
|
||||||
expect(body.topValues.buckets.length).to.be.greaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return top values for index pattern runtime string fields', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'runtime_string_field',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
totalDocuments: 4634,
|
|
||||||
sampledDocuments: 4634,
|
|
||||||
sampledValues: 4634,
|
|
||||||
topValues: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 4634,
|
|
||||||
key: 'hello world!',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should apply filters and queries', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: {
|
|
||||||
bool: {
|
|
||||||
filter: [{ match: { 'geo.src': 'US' } }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'bytes',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body.totalDocuments).to.eql(425);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow filtering on a runtime field other than the field in use', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'logstash-2015.09.22',
|
|
||||||
dslQuery: {
|
|
||||||
bool: {
|
|
||||||
filter: [{ exists: { field: 'runtime_string_field' } }],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'runtime_number_field',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
totalDocuments: 4634,
|
|
||||||
sampledDocuments: 4634,
|
|
||||||
sampledValues: 4634,
|
|
||||||
topValues: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 4634,
|
|
||||||
key: 5,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
histogram: { buckets: [] },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('histogram', () => {
|
|
||||||
before(async () => {
|
|
||||||
await esArchiver.loadIfNeeded(
|
|
||||||
'x-pack/test/functional/es_archives/pre_calculated_histogram'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
after(async () => {
|
|
||||||
await esArchiver.unload('x-pack/test/functional/es_archives/pre_calculated_histogram');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an auto histogram for precalculated histograms', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'histogram-test',
|
|
||||||
dslQuery: { match_all: {} },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'histogram-content',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
histogram: {
|
|
||||||
buckets: [
|
|
||||||
{
|
|
||||||
count: 237,
|
|
||||||
key: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 323,
|
|
||||||
key: 0.47000000000000003,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 454,
|
|
||||||
key: 0.9400000000000001,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 166,
|
|
||||||
key: 1.4100000000000001,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 168,
|
|
||||||
key: 1.8800000000000001,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 425,
|
|
||||||
key: 2.35,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 311,
|
|
||||||
key: 2.8200000000000003,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 391,
|
|
||||||
key: 3.29,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 406,
|
|
||||||
key: 3.7600000000000002,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 324,
|
|
||||||
key: 4.23,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
count: 628,
|
|
||||||
key: 4.7,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
sampledDocuments: 7,
|
|
||||||
sampledValues: 3833,
|
|
||||||
totalDocuments: 7,
|
|
||||||
topValues: { buckets: [] },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a single-value histogram when filtering a precalculated histogram', async () => {
|
|
||||||
const { body } = await supertest
|
|
||||||
.post(API_PATH)
|
|
||||||
.set(COMMON_HEADERS)
|
|
||||||
.send({
|
|
||||||
dataViewId: 'histogram-test',
|
|
||||||
dslQuery: { match: { 'histogram-title': 'single value' } },
|
|
||||||
fromDate: TEST_START_TIME,
|
|
||||||
toDate: TEST_END_TIME,
|
|
||||||
fieldName: 'histogram-content',
|
|
||||||
})
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(body).to.eql({
|
|
||||||
histogram: { buckets: [{ count: 1, key: 1 }] },
|
|
||||||
sampledDocuments: 1,
|
|
||||||
sampledValues: 1,
|
|
||||||
totalDocuments: 1,
|
|
||||||
topValues: { buckets: [] },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -29,6 +29,7 @@ export default async function ({ readConfigFile }) {
|
||||||
require.resolve('./partial_results'),
|
require.resolve('./partial_results'),
|
||||||
require.resolve('./search'),
|
require.resolve('./search'),
|
||||||
require.resolve('./content_management'),
|
require.resolve('./content_management'),
|
||||||
|
require.resolve('./unified_field_list_examples'),
|
||||||
],
|
],
|
||||||
services: {
|
services: {
|
||||||
...functionalConfig.get('services'),
|
...functionalConfig.get('services'),
|
||||||
|
|
167
test/examples/unified_field_list_examples/existing_fields.ts
Normal file
167
test/examples/unified_field_list_examples/existing_fields.ts
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import expect from '@kbn/expect';
|
||||||
|
import type { FtrProviderContext } from '../../functional/ftr_provider_context';
|
||||||
|
|
||||||
|
const TEST_START_TIME = 'Jan 2, 2021 @ 00:00:00.000';
|
||||||
|
const TEST_END_TIME = 'Jan 2, 2022 @ 00:00:00.000';
|
||||||
|
const metaFields = ['_id', '_index', '_score'];
|
||||||
|
|
||||||
|
const fieldsWithData = [
|
||||||
|
'ts',
|
||||||
|
'filter_field',
|
||||||
|
'textfield1',
|
||||||
|
'textfield2',
|
||||||
|
'mapping_runtime_field',
|
||||||
|
'data_view_runtime_field',
|
||||||
|
];
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
export default ({ getService, getPageObjects }: FtrProviderContext) => {
|
||||||
|
const esArchiver = getService('esArchiver');
|
||||||
|
const kibanaServer = getService('kibanaServer');
|
||||||
|
const comboBox = getService('comboBox');
|
||||||
|
const retry = getService('retry');
|
||||||
|
const testSubjects = getService('testSubjects');
|
||||||
|
const monacoEditor = getService('monacoEditor');
|
||||||
|
const PageObjects = getPageObjects(['common', 'timePicker', 'header', 'unifiedFieldList']);
|
||||||
|
const dataViewTitle = 'existence_index_*';
|
||||||
|
|
||||||
|
async function addDSLFilter(value: string) {
|
||||||
|
await testSubjects.click('addFilter');
|
||||||
|
await testSubjects.click('editQueryDSL');
|
||||||
|
await monacoEditor.waitCodeEditorReady('addFilterPopover');
|
||||||
|
await monacoEditor.setCodeEditorValue(value);
|
||||||
|
await testSubjects.scrollIntoView('saveFilter');
|
||||||
|
await testSubjects.clickWhenNotDisabled('saveFilter');
|
||||||
|
await retry.try(async () => {
|
||||||
|
await testSubjects.waitForDeleted('saveFilter');
|
||||||
|
});
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeAllDSLFilters() {
|
||||||
|
await testSubjects.click('showQueryBarMenu');
|
||||||
|
await testSubjects.click('filter-sets-removeAllFilters');
|
||||||
|
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Fields existence info', () => {
|
||||||
|
before(async () => {
|
||||||
|
await esArchiver.load(
|
||||||
|
'test/api_integration/fixtures/es_archiver/index_patterns/constant_keyword'
|
||||||
|
);
|
||||||
|
await kibanaServer.importExport.load(
|
||||||
|
'test/api_integration/fixtures/kbn_archiver/index_patterns/constant_keyword.json'
|
||||||
|
);
|
||||||
|
await PageObjects.common.navigateToApp('unifiedFieldListExamples');
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await retry.waitFor('combobox is ready', async () => {
|
||||||
|
return await testSubjects.exists('dataViewSelector');
|
||||||
|
});
|
||||||
|
await comboBox.setCustom('dataViewSelector', dataViewTitle);
|
||||||
|
await retry.waitFor('page is ready', async () => {
|
||||||
|
return await testSubjects.exists('globalQueryBar');
|
||||||
|
});
|
||||||
|
await PageObjects.timePicker.setAbsoluteRange(TEST_START_TIME, TEST_END_TIME);
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
await PageObjects.unifiedFieldList.toggleSidebarSection('meta');
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await esArchiver.unload(
|
||||||
|
'test/api_integration/fixtures/es_archiver/index_patterns/constant_keyword'
|
||||||
|
);
|
||||||
|
await kibanaServer.importExport.unload(
|
||||||
|
'test/api_integration/fixtures/kbn_archiver/index_patterns/constant_keyword.json'
|
||||||
|
);
|
||||||
|
await PageObjects.unifiedFieldList.cleanSidebarLocalStorage();
|
||||||
|
await kibanaServer.savedObjects.cleanStandardList();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('existence', () => {
|
||||||
|
it('should find which fields exist in the sample documents', async () => {
|
||||||
|
const sidebarFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
|
expect(sidebarFields.sort()).to.eql([...metaFields, ...fieldsWithData].sort());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return fields filtered by term query', async () => {
|
||||||
|
const expectedFieldNames = [
|
||||||
|
'ts',
|
||||||
|
'filter_field',
|
||||||
|
'textfield1',
|
||||||
|
// textfield2 and mapping_runtime_field are defined on the other index
|
||||||
|
'data_view_runtime_field',
|
||||||
|
];
|
||||||
|
|
||||||
|
await addDSLFilter(`{
|
||||||
|
"bool": {
|
||||||
|
"filter": [{ "term": { "filter_field": "a" } }]
|
||||||
|
}
|
||||||
|
}`);
|
||||||
|
|
||||||
|
const sidebarFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
|
expect(sidebarFields.sort()).to.eql([...metaFields, ...expectedFieldNames].sort());
|
||||||
|
|
||||||
|
await removeAllDSLFilters();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return fields filtered by match_phrase query', async () => {
|
||||||
|
const expectedFieldNames = [
|
||||||
|
'ts',
|
||||||
|
'filter_field',
|
||||||
|
'textfield1',
|
||||||
|
// textfield2 and mapping_runtime_field are defined on the other index
|
||||||
|
'data_view_runtime_field',
|
||||||
|
];
|
||||||
|
|
||||||
|
await addDSLFilter(`{
|
||||||
|
"bool": {
|
||||||
|
"filter": [{ "match_phrase": { "filter_field": "a" } }]
|
||||||
|
}
|
||||||
|
}`);
|
||||||
|
|
||||||
|
const sidebarFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
|
expect(sidebarFields.sort()).to.eql([...metaFields, ...expectedFieldNames].sort());
|
||||||
|
|
||||||
|
await removeAllDSLFilters();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return fields filtered by time range', async () => {
|
||||||
|
const expectedFieldNames = [
|
||||||
|
'ts',
|
||||||
|
'filter_field',
|
||||||
|
'textfield1',
|
||||||
|
// textfield2 and mapping_runtime_field are defined on the other index
|
||||||
|
'data_view_runtime_field',
|
||||||
|
];
|
||||||
|
|
||||||
|
await addDSLFilter(`{
|
||||||
|
"bool": {
|
||||||
|
"filter": [{ "term": { "filter_field": "a" } }]
|
||||||
|
}
|
||||||
|
}`);
|
||||||
|
|
||||||
|
await PageObjects.timePicker.setAbsoluteRange(
|
||||||
|
TEST_START_TIME,
|
||||||
|
'Dec 12, 2021 @ 00:00:00.000'
|
||||||
|
);
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
|
const sidebarFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
|
expect(sidebarFields.sort()).to.eql([...metaFields, ...expectedFieldNames].sort());
|
||||||
|
|
||||||
|
await removeAllDSLFilters();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
191
test/examples/unified_field_list_examples/field_stats.ts
Normal file
191
test/examples/unified_field_list_examples/field_stats.ts
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import expect from '@kbn/expect';
|
||||||
|
import type { FtrProviderContext } from '../../functional/ftr_provider_context';
|
||||||
|
|
||||||
|
const TEST_START_TIME = 'Sep 19, 2015 @ 06:31:44.000';
|
||||||
|
const TEST_END_TIME = 'Sep 23, 2015 @ 18:31:44.000';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
export default ({ getService, getPageObjects }: FtrProviderContext) => {
|
||||||
|
const PageObjects = getPageObjects(['common', 'timePicker', 'header', 'unifiedFieldList']);
|
||||||
|
const esArchiver = getService('esArchiver');
|
||||||
|
const kibanaServer = getService('kibanaServer');
|
||||||
|
const comboBox = getService('comboBox');
|
||||||
|
const retry = getService('retry');
|
||||||
|
const testSubjects = getService('testSubjects');
|
||||||
|
const filterBar = getService('filterBar');
|
||||||
|
const dataViewTitle = 'logstash-2015.09.22';
|
||||||
|
|
||||||
|
describe('Field stats', () => {
|
||||||
|
before(async () => {
|
||||||
|
await kibanaServer.savedObjects.cleanStandardList();
|
||||||
|
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional');
|
||||||
|
await kibanaServer.importExport.load(
|
||||||
|
'x-pack/test/functional/fixtures/kbn_archiver/visualize/default'
|
||||||
|
);
|
||||||
|
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/pre_calculated_histogram');
|
||||||
|
await PageObjects.common.navigateToApp('unifiedFieldListExamples');
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await retry.waitFor('combobox is ready', async () => {
|
||||||
|
return await testSubjects.exists('dataViewSelector');
|
||||||
|
});
|
||||||
|
await comboBox.setCustom('dataViewSelector', dataViewTitle);
|
||||||
|
await retry.waitFor('page is ready', async () => {
|
||||||
|
return await testSubjects.exists('globalQueryBar');
|
||||||
|
});
|
||||||
|
await PageObjects.timePicker.setAbsoluteRange(TEST_START_TIME, TEST_END_TIME);
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional');
|
||||||
|
await esArchiver.unload('x-pack/test/functional/es_archives/pre_calculated_histogram');
|
||||||
|
await kibanaServer.savedObjects.cleanStandardList();
|
||||||
|
await PageObjects.unifiedFieldList.cleanSidebarLocalStorage();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('field distribution', () => {
|
||||||
|
before(async () => {
|
||||||
|
await PageObjects.unifiedFieldList.toggleSidebarSection('empty'); // it will allow to render more fields in Available fields section
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an auto histogram for numbers and top values', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be(
|
||||||
|
'topValuesAndDistribution'
|
||||||
|
);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(4634);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsTopValueBucketsVisibleText()).to.be(
|
||||||
|
'0\n3.2%\n3,954\n0.1%\n5,846\n0.1%\n6,497\n0.1%\n1,840\n0.1%\n4,206\n0.1%\n4,328\n0.1%\n4,669\n0.1%\n5,863\n0.1%\n6,631\n0.1%\nOther\n96.0%'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an auto histogram for dates', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('@timestamp');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be(
|
||||||
|
'timeDistribution'
|
||||||
|
);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(4634);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return top values for strings', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('geo.src');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be('topValues');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(4634);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsTopValueBucketsVisibleText()).to.be(
|
||||||
|
'CN\n18.0%\nIN\n17.4%\nUS\n9.2%\nID\n3.4%\nBR\n3.1%\nPK\n2.5%\nBD\n2.3%\nNG\n2.0%\nRU\n1.8%\nJP\n1.6%\nOther\n38.8%'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return top values for ip fields', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('ip');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be('topValues');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(4634);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsTopValueBucketsVisibleText()).to.be(
|
||||||
|
'177.194.175.66\n0.3%\n18.55.141.62\n0.3%\n53.55.251.105\n0.3%\n21.111.249.239\n0.2%\n97.63.84.25\n0.2%\n100.99.207.174\n0.2%\n112.34.138.226\n0.2%\n194.68.89.92\n0.2%\n235.186.79.201\n0.2%\n57.79.108.136\n0.2%\nOther\n97.6%'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return histograms for scripted date fields', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('scripted_date');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be(
|
||||||
|
'timeDistribution'
|
||||||
|
);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(4634);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return top values for scripted string fields', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('scripted_string');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be('topValues');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(4634);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsTopValueBucketsVisibleText()).to.be(
|
||||||
|
'hello\n100%'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return examples for non-aggregatable fields', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be('exampleValues');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(100);
|
||||||
|
// actual hits might vary
|
||||||
|
expect(
|
||||||
|
(await PageObjects.unifiedFieldList.getFieldStatsExampleBucketsVisibleText()).length
|
||||||
|
).to.above(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return top values for index pattern runtime string fields', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('runtime_string_field');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be('topValues');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(4634);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsTopValueBucketsVisibleText()).to.be(
|
||||||
|
'hello world!\n100%'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply filters and queries', async () => {
|
||||||
|
await filterBar.addFilter({ field: 'geo.src', operation: 'is', value: 'US' });
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be(
|
||||||
|
'topValuesAndDistribution'
|
||||||
|
);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(425);
|
||||||
|
await filterBar.removeFilter('geo.src');
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow filtering on a runtime field other than the field in use', async () => {
|
||||||
|
await filterBar.addFilter({ field: 'runtime_string_field', operation: 'exists' });
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('runtime_number_field');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be('topValues');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(4634);
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsTopValueBucketsVisibleText()).to.be(
|
||||||
|
'5\n100%'
|
||||||
|
);
|
||||||
|
await filterBar.removeFilter('runtime_string_field');
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('histogram', () => {
|
||||||
|
before(async () => {
|
||||||
|
await comboBox.setCustom('dataViewSelector', 'histogram-test');
|
||||||
|
await retry.waitFor('page is ready', async () => {
|
||||||
|
return await testSubjects.exists('globalQueryBar');
|
||||||
|
});
|
||||||
|
await PageObjects.timePicker.setAbsoluteRange(TEST_START_TIME, TEST_END_TIME);
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an auto histogram for precalculated histograms', async () => {
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('histogram-content');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be('histogram');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(7);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a single-value histogram when filtering a precalculated histogram', async () => {
|
||||||
|
await filterBar.addFilter({
|
||||||
|
field: 'histogram-title',
|
||||||
|
operation: 'is',
|
||||||
|
value: 'single value',
|
||||||
|
});
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItem('histogram-content');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsViewType()).to.be('histogram');
|
||||||
|
expect(await PageObjects.unifiedFieldList.getFieldStatsDocsCount()).to.be(1);
|
||||||
|
await filterBar.removeFilter('histogram-title');
|
||||||
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
|
@ -6,11 +6,12 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
import { FtrProviderContext } from '../../functional/ftr_provider_context';
|
||||||
|
|
||||||
export default function lensApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
|
// eslint-disable-next-line import/no-default-export
|
||||||
describe('UnifiedFieldList', () => {
|
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||||
loadTestFile(require.resolve('./existing_fields'));
|
describe('Unified Field List Examples', () => {
|
||||||
loadTestFile(require.resolve('./field_stats'));
|
loadTestFile(require.resolve('./field_stats'));
|
||||||
|
loadTestFile(require.resolve('./existing_fields'));
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -27,6 +27,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'dashboard',
|
'dashboard',
|
||||||
'context',
|
'context',
|
||||||
'header',
|
'header',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||||
|
@ -43,7 +44,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
for (const columnName of TEST_COLUMN_NAMES) {
|
for (const columnName of TEST_COLUMN_NAMES) {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(columnName);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(columnName);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) {
|
for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'dashboard',
|
'dashboard',
|
||||||
'context',
|
'context',
|
||||||
'header',
|
'header',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||||
|
@ -43,12 +44,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
for (const columnName of TEST_COLUMN_NAMES) {
|
for (const columnName of TEST_COLUMN_NAMES) {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(columnName);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(columnName);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) {
|
for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) {
|
||||||
await PageObjects.discover.clickFieldListItem(columnName);
|
await PageObjects.unifiedFieldList.clickFieldListItem(columnName);
|
||||||
await PageObjects.discover.clickFieldListPlusFilter(columnName, value);
|
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(columnName, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
after(async () => {
|
after(async () => {
|
||||||
|
|
|
@ -24,6 +24,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'visChart',
|
'visChart',
|
||||||
'share',
|
'share',
|
||||||
'timePicker',
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const browser = getService('browser');
|
const browser = getService('browser');
|
||||||
|
@ -121,7 +122,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
await PageObjects.header.clickDiscover();
|
await PageObjects.header.clickDiscover();
|
||||||
await PageObjects.timePicker.setHistoricalDataRange();
|
await PageObjects.timePicker.setHistoricalDataRange();
|
||||||
await PageObjects.discover.clickFieldListItemAdd('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||||
await PageObjects.discover.saveSearch('my search');
|
await PageObjects.discover.saveSearch('my search');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -135,7 +136,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
expect(inViewMode).to.be(true);
|
expect(inViewMode).to.be(true);
|
||||||
|
|
||||||
await PageObjects.header.clickDiscover();
|
await PageObjects.header.clickDiscover();
|
||||||
await PageObjects.discover.clickFieldListItemAdd('agent');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('agent');
|
||||||
await PageObjects.discover.saveSearch('my search');
|
await PageObjects.discover.saveSearch('my search');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -154,7 +155,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.dashboard.saveDashboard('Has local edits');
|
await PageObjects.dashboard.saveDashboard('Has local edits');
|
||||||
|
|
||||||
await PageObjects.header.clickDiscover();
|
await PageObjects.header.clickDiscover();
|
||||||
await PageObjects.discover.clickFieldListItemAdd('clientip');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('clientip');
|
||||||
await PageObjects.discover.saveSearch('my search');
|
await PageObjects.discover.saveSearch('my search');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const retry = getService('retry');
|
const retry = getService('retry');
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker', 'settings']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'timePicker',
|
||||||
|
'settings',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
defaultIndex: 'logstash-*',
|
defaultIndex: 'logstash-*',
|
||||||
'discover:searchFieldsFromSource': false,
|
'discover:searchFieldsFromSource': false,
|
||||||
|
@ -48,13 +55,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adding a column removes a default column', async function () {
|
it('adding a column removes a default column', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd('_score');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('_score');
|
||||||
expect(await PageObjects.discover.getDocHeader()).to.have.string('_score');
|
expect(await PageObjects.discover.getDocHeader()).to.have.string('_score');
|
||||||
expect(await PageObjects.discover.getDocHeader()).not.to.have.string('Document');
|
expect(await PageObjects.discover.getDocHeader()).not.to.have.string('Document');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('removing a column adds a default column', async function () {
|
it('removing a column adds a default column', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemRemove('_score');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('_score');
|
||||||
expect(await PageObjects.discover.getDocHeader()).not.to.have.string('_score');
|
expect(await PageObjects.discover.getDocHeader()).not.to.have.string('_score');
|
||||||
expect(await PageObjects.discover.getDocHeader()).to.have.string('Document');
|
expect(await PageObjects.discover.getDocHeader()).to.have.string('Document');
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const docTable = getService('docTable');
|
const docTable = getService('docTable');
|
||||||
const queryBar = getService('queryBar');
|
const queryBar = getService('queryBar');
|
||||||
const find = getService('find');
|
const find = getService('find');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
defaultIndex: 'logstash-*',
|
defaultIndex: 'logstash-*',
|
||||||
hideAnnouncements: true,
|
hideAnnouncements: true,
|
||||||
|
@ -229,19 +235,19 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
afterEach(async function () {
|
afterEach(async function () {
|
||||||
for (const column of extraColumns) {
|
for (const column of extraColumns) {
|
||||||
await PageObjects.discover.clickFieldListItemRemove(column);
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove(column);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add more columns to the table', async function () {
|
it('should add more columns to the table', async function () {
|
||||||
for (const column of extraColumns) {
|
for (const column of extraColumns) {
|
||||||
await PageObjects.discover.clearFieldSearchInput();
|
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||||
await PageObjects.discover.findFieldByName(column);
|
await PageObjects.unifiedFieldList.findFieldByName(column);
|
||||||
await retry.waitFor('field to appear', async function () {
|
await retry.waitFor('field to appear', async function () {
|
||||||
return await testSubjects.exists(`field-${column}`);
|
return await testSubjects.exists(`field-${column}`);
|
||||||
});
|
});
|
||||||
await PageObjects.discover.clickFieldListItemAdd(column);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(column);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// test the header now
|
// test the header now
|
||||||
const docHeader = await find.byCssSelector('thead > tr:nth-child(1)');
|
const docHeader = await find.byCssSelector('thead > tr:nth-child(1)');
|
||||||
|
@ -252,16 +258,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
it('should remove columns from the table', async function () {
|
it('should remove columns from the table', async function () {
|
||||||
for (const column of extraColumns) {
|
for (const column of extraColumns) {
|
||||||
await PageObjects.discover.clearFieldSearchInput();
|
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||||
await PageObjects.discover.findFieldByName(column);
|
await PageObjects.unifiedFieldList.findFieldByName(column);
|
||||||
await retry.waitFor('field to appear', async function () {
|
await retry.waitFor('field to appear', async function () {
|
||||||
return await testSubjects.exists(`field-${column}`);
|
return await testSubjects.exists(`field-${column}`);
|
||||||
});
|
});
|
||||||
await PageObjects.discover.clickFieldListItemAdd(column);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(column);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
}
|
}
|
||||||
// remove the second column
|
// remove the second column
|
||||||
await PageObjects.discover.clickFieldListItemRemove(extraColumns[1]);
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove(extraColumns[1]);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// test that the second column is no longer there
|
// test that the second column is no longer there
|
||||||
const docHeader = await find.byCssSelector('thead > tr:nth-child(1)');
|
const docHeader = await find.byCssSelector('thead > tr:nth-child(1)');
|
||||||
|
@ -270,9 +276,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should make the document table scrollable', async function () {
|
it('should make the document table scrollable', async function () {
|
||||||
await PageObjects.discover.clearFieldSearchInput();
|
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||||
const dscTableWrapper = await find.byCssSelector('.kbnDocTableWrapper');
|
const dscTableWrapper = await find.byCssSelector('.kbnDocTableWrapper');
|
||||||
const fieldNames = await PageObjects.discover.getAllFieldNames();
|
const fieldNames = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
const clientHeight = await dscTableWrapper.getAttribute('clientHeight');
|
const clientHeight = await dscTableWrapper.getAttribute('clientHeight');
|
||||||
let fieldCounter = 0;
|
let fieldCounter = 0;
|
||||||
const checkScrollable = async () => {
|
const checkScrollable = async () => {
|
||||||
|
@ -282,7 +288,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
return Number(scrollWidth) > Number(clientWidth);
|
return Number(scrollWidth) > Number(clientWidth);
|
||||||
};
|
};
|
||||||
const addColumn = async () => {
|
const addColumn = async () => {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(fieldNames[fieldCounter++]);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(fieldNames[fieldCounter++]);
|
||||||
};
|
};
|
||||||
|
|
||||||
await addColumn();
|
await addColumn();
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { FtrProviderContext } from '../ftr_provider_context';
|
||||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const PageObjects = getPageObjects(['common', 'discover']);
|
const PageObjects = getPageObjects(['common', 'discover', 'unifiedFieldList']);
|
||||||
const find = getService('find');
|
const find = getService('find');
|
||||||
const log = getService('log');
|
const log = getService('log');
|
||||||
const retry = getService('retry');
|
const retry = getService('retry');
|
||||||
|
@ -39,7 +39,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should break text on newlines', async function () {
|
it('should break text on newlines', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemToggle('message');
|
await PageObjects.unifiedFieldList.clickFieldListItemToggle('message');
|
||||||
const dscTableRows = await find.allByCssSelector('.kbnDocTable__row');
|
const dscTableRows = await find.allByCssSelector('.kbnDocTable__row');
|
||||||
|
|
||||||
await retry.waitFor('height of multi-line content > single-line content', async () => {
|
await retry.waitFor('height of multi-line content > single-line content', async () => {
|
||||||
|
|
|
@ -19,7 +19,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const queryBar = getService('queryBar');
|
const queryBar = getService('queryBar');
|
||||||
const inspector = getService('inspector');
|
const inspector = getService('inspector');
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
defaultIndex: 'logstash-*',
|
defaultIndex: 'logstash-*',
|
||||||
|
@ -235,21 +241,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('should add a field, sort by it, remove it and also sorting by it', async function () {
|
it('should add a field, sort by it, remove it and also sorting by it', async function () {
|
||||||
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
|
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.discover.clickFieldListItemAdd('_score');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('_score');
|
||||||
await PageObjects.discover.clickFieldSort('_score', 'Sort Low-High');
|
await PageObjects.discover.clickFieldSort('_score', 'Sort Low-High');
|
||||||
const currentUrlWithScore = await browser.getCurrentUrl();
|
const currentUrlWithScore = await browser.getCurrentUrl();
|
||||||
expect(currentUrlWithScore).to.contain('_score');
|
expect(currentUrlWithScore).to.contain('_score');
|
||||||
await PageObjects.discover.clickFieldListItemRemove('_score');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('_score');
|
||||||
const currentUrlWithoutScore = await browser.getCurrentUrl();
|
const currentUrlWithoutScore = await browser.getCurrentUrl();
|
||||||
expect(currentUrlWithoutScore).not.to.contain('_score');
|
expect(currentUrlWithoutScore).not.to.contain('_score');
|
||||||
});
|
});
|
||||||
it('should add a field with customLabel, sort by it, display it correctly', async function () {
|
it('should add a field with customLabel, sort by it, display it correctly', async function () {
|
||||||
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
|
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.discover.clickFieldListItemAdd('referer');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('referer');
|
||||||
await PageObjects.discover.clickFieldSort('referer', 'Sort A-Z');
|
await PageObjects.discover.clickFieldSort('referer', 'Sort A-Z');
|
||||||
expect(await PageObjects.discover.getDocHeader()).to.have.string('Referer custom');
|
expect(await PageObjects.discover.getDocHeader()).to.have.string('Referer custom');
|
||||||
expect(await PageObjects.discover.getAllFieldNames()).to.contain('Referer custom');
|
expect(await PageObjects.unifiedFieldList.getAllFieldNames()).to.contain('Referer custom');
|
||||||
const url = await browser.getCurrentUrl();
|
const url = await browser.getCurrentUrl();
|
||||||
expect(url).to.contain('referer');
|
expect(url).to.contain('referer');
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,7 +16,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const queryBar = getService('queryBar');
|
const queryBar = getService('queryBar');
|
||||||
const browser = getService('browser');
|
const browser = getService('browser');
|
||||||
const PageObjects = getPageObjects(['common', 'header', 'discover', 'visualize', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'header',
|
||||||
|
'discover',
|
||||||
|
'visualize',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
|
|
||||||
describe('discover tab', function describeIndexTests() {
|
describe('discover tab', function describeIndexTests() {
|
||||||
this.tags('includeFirefox');
|
this.tags('includeFirefox');
|
||||||
|
@ -46,11 +53,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
// marks is the style that highlights the text in yellow
|
// marks is the style that highlights the text in yellow
|
||||||
await queryBar.setQuery('php');
|
await queryBar.setQuery('php');
|
||||||
await queryBar.submitQuery();
|
await queryBar.submitQuery();
|
||||||
await PageObjects.discover.clickFieldListItemAdd('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||||
const marks = await PageObjects.discover.getMarks();
|
const marks = await PageObjects.discover.getMarks();
|
||||||
expect(marks.length).to.be.greaterThan(0);
|
expect(marks.length).to.be.greaterThan(0);
|
||||||
expect(marks.indexOf('php')).to.be(0);
|
expect(marks.indexOf('php')).to.be(0);
|
||||||
await PageObjects.discover.clickFieldListItemRemove('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('extension');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('search type:apache should show the correct hit count', async function () {
|
it('search type:apache should show the correct hit count', async function () {
|
||||||
|
|
|
@ -16,7 +16,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const queryBar = getService('queryBar');
|
const queryBar = getService('queryBar');
|
||||||
const browser = getService('browser');
|
const browser = getService('browser');
|
||||||
const PageObjects = getPageObjects(['common', 'header', 'discover', 'visualize', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'header',
|
||||||
|
'discover',
|
||||||
|
'visualize',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
|
|
||||||
describe('discover tab with new fields API', function describeIndexTests() {
|
describe('discover tab with new fields API', function describeIndexTests() {
|
||||||
this.tags('includeFirefox');
|
this.tags('includeFirefox');
|
||||||
|
@ -44,11 +51,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
it('the search term should be highlighted in the field data', async function () {
|
it('the search term should be highlighted in the field data', async function () {
|
||||||
// marks is the style that highlights the text in yellow
|
// marks is the style that highlights the text in yellow
|
||||||
await PageObjects.discover.clickFieldListItemAdd('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||||
const marks = await PageObjects.discover.getMarks();
|
const marks = await PageObjects.discover.getMarks();
|
||||||
expect(marks.length).to.be.greaterThan(0);
|
expect(marks.length).to.be.greaterThan(0);
|
||||||
expect(marks.indexOf('php')).to.be(0);
|
expect(marks.indexOf('php')).to.be(0);
|
||||||
await PageObjects.discover.clickFieldListItemRemove('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('extension');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('search type:apache should show the correct hit count', async function () {
|
it('search type:apache should show the correct hit count', async function () {
|
||||||
|
|
|
@ -15,7 +15,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const retry = getService('retry');
|
const retry = getService('retry');
|
||||||
const PageObjects = getPageObjects(['common', 'timePicker', 'discover', 'header', 'settings']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'timePicker',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'settings',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
|
|
||||||
describe('source filters', function () {
|
describe('source filters', function () {
|
||||||
before(async function () {
|
before(async function () {
|
||||||
|
@ -51,7 +58,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not get the field referer', async function () {
|
it('should not get the field referer', async function () {
|
||||||
const fieldNames = await PageObjects.discover.getAllFieldNames();
|
const fieldNames = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
expect(fieldNames).to.not.contain('referer');
|
expect(fieldNames).to.not.contain('referer');
|
||||||
const relatedContentFields = fieldNames.filter(
|
const relatedContentFields = fieldNames.filter(
|
||||||
(fieldName) => fieldName.indexOf('relatedContent') === 0
|
(fieldName) => fieldName.indexOf('relatedContent') === 0
|
||||||
|
|
|
@ -30,6 +30,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'header',
|
'header',
|
||||||
'context',
|
'context',
|
||||||
'dashboard',
|
'dashboard',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const find = getService('find');
|
const find = getService('find');
|
||||||
const security = getService('security');
|
const security = getService('security');
|
||||||
|
@ -64,7 +65,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'_bytes-runtimefield',
|
'_bytes-runtimefield',
|
||||||
`emit(doc["bytes"].value.toString())`
|
`emit(doc["bytes"].value.toString())`
|
||||||
);
|
);
|
||||||
await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield');
|
await PageObjects.unifiedFieldList.clickFieldListItemToggle('_bytes-runtimefield');
|
||||||
|
|
||||||
const second = await PageObjects.discover.getCurrentDataViewId();
|
const second = await PageObjects.discover.getCurrentDataViewId();
|
||||||
expect(first).not.to.equal(second);
|
expect(first).not.to.equal(second);
|
||||||
|
@ -144,7 +145,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'_bytes-runtimefield',
|
'_bytes-runtimefield',
|
||||||
`emit(doc["bytes"].value.toString())`
|
`emit(doc["bytes"].value.toString())`
|
||||||
);
|
);
|
||||||
await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield');
|
await PageObjects.unifiedFieldList.clickFieldListItemToggle('_bytes-runtimefield');
|
||||||
const newDataViewId = await PageObjects.discover.getCurrentDataViewId();
|
const newDataViewId = await PageObjects.discover.getCurrentDataViewId();
|
||||||
expect(newDataViewId).not.to.equal(prevDataViewId);
|
expect(newDataViewId).not.to.equal(prevDataViewId);
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
// remove field and create with the same name, but different value
|
// remove field and create with the same name, but different value
|
||||||
await PageObjects.discover.clickFieldListItemRemove('_bytes-runtimefield');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('_bytes-runtimefield');
|
||||||
await PageObjects.discover.removeField('_bytes-runtimefield');
|
await PageObjects.discover.removeField('_bytes-runtimefield');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -162,7 +163,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'_bytes-runtimefield',
|
'_bytes-runtimefield',
|
||||||
`emit((doc["bytes"].value * 2).toString())`
|
`emit((doc["bytes"].value * 2).toString())`
|
||||||
);
|
);
|
||||||
await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield');
|
await PageObjects.unifiedFieldList.clickFieldListItemToggle('_bytes-runtimefield');
|
||||||
|
|
||||||
// save second search
|
// save second search
|
||||||
await PageObjects.discover.saveSearch('logst*-ss-_bytes-runtimefield-updated', true);
|
await PageObjects.discover.saveSearch('logst*-ss-_bytes-runtimefield-updated', true);
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { FtrProviderContext } from '../ftr_provider_context';
|
||||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
describe('discover data grid tests', function describeDiscoverDataGrid() {
|
describe('discover data grid tests', function describeDiscoverDataGrid() {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'timePicker']);
|
const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'unifiedFieldList']);
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const defaultSettings = { defaultIndex: 'logstash-*' };
|
const defaultSettings = { defaultIndex: 'logstash-*' };
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
|
@ -34,16 +34,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
expect(await getTitles()).to.be('@timestamp Document');
|
expect(await getTitles()).to.be('@timestamp Document');
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemAdd('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||||
expect(await getTitles()).to.be('@timestamp bytes');
|
expect(await getTitles()).to.be('@timestamp bytes');
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemAdd('agent');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('agent');
|
||||||
expect(await getTitles()).to.be('@timestamp bytes agent');
|
expect(await getTitles()).to.be('@timestamp bytes agent');
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemRemove('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('bytes');
|
||||||
expect(await getTitles()).to.be('@timestamp agent');
|
expect(await getTitles()).to.be('@timestamp agent');
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemRemove('agent');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('agent');
|
||||||
expect(await getTitles()).to.be('@timestamp Document');
|
expect(await getTitles()).to.be('@timestamp Document');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,6 +28,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'settings',
|
'settings',
|
||||||
'dashboard',
|
'dashboard',
|
||||||
'header',
|
'header',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const defaultSettings = { defaultIndex: 'logstash-*' };
|
const defaultSettings = { defaultIndex: 'logstash-*' };
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
|
@ -47,12 +48,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
|
|
||||||
for (const columnName of TEST_COLUMN_NAMES) {
|
for (const columnName of TEST_COLUMN_NAMES) {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(columnName);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(columnName);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) {
|
for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) {
|
||||||
await PageObjects.discover.clickFieldListItem(columnName);
|
await PageObjects.unifiedFieldList.clickFieldListItem(columnName);
|
||||||
await PageObjects.discover.clickFieldListPlusFilter(columnName, value);
|
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(columnName, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
after(async () => {
|
after(async () => {
|
||||||
|
|
|
@ -18,7 +18,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const monacoEditor = getService('monacoEditor');
|
const monacoEditor = getService('monacoEditor');
|
||||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker', 'dashboard']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'timePicker',
|
||||||
|
'dashboard',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
defaultIndex: 'logstash-*',
|
defaultIndex: 'logstash-*',
|
||||||
};
|
};
|
||||||
|
@ -221,16 +228,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
afterEach(async function () {
|
afterEach(async function () {
|
||||||
for (const column of extraColumns) {
|
for (const column of extraColumns) {
|
||||||
await PageObjects.discover.clickFieldListItemRemove(column);
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove(column);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add more columns to the table', async function () {
|
it('should add more columns to the table', async function () {
|
||||||
for (const column of extraColumns) {
|
for (const column of extraColumns) {
|
||||||
await PageObjects.discover.clearFieldSearchInput();
|
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||||
await PageObjects.discover.findFieldByName(column);
|
await PageObjects.unifiedFieldList.findFieldByName(column);
|
||||||
await PageObjects.discover.clickFieldListItemAdd(column);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(column);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// test the header now
|
// test the header now
|
||||||
const header = await dataGrid.getHeaderFields();
|
const header = await dataGrid.getHeaderFields();
|
||||||
|
@ -240,13 +247,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
it('should remove columns from the table', async function () {
|
it('should remove columns from the table', async function () {
|
||||||
for (const column of extraColumns) {
|
for (const column of extraColumns) {
|
||||||
await PageObjects.discover.clearFieldSearchInput();
|
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||||
await PageObjects.discover.findFieldByName(column);
|
await PageObjects.unifiedFieldList.findFieldByName(column);
|
||||||
await PageObjects.discover.clickFieldListItemAdd(column);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(column);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
}
|
}
|
||||||
// remove the second column
|
// remove the second column
|
||||||
await PageObjects.discover.clickFieldListItemRemove(extraColumns[1]);
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove(extraColumns[1]);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// test that the second column is no longer there
|
// test that the second column is no longer there
|
||||||
const header = await dataGrid.getHeaderFields();
|
const header = await dataGrid.getHeaderFields();
|
||||||
|
|
|
@ -14,7 +14,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const queryBar = getService('queryBar');
|
const queryBar = getService('queryBar');
|
||||||
const PageObjects = getPageObjects(['common', 'header', 'discover', 'visualize', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'header',
|
||||||
|
'discover',
|
||||||
|
'visualize',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const defaultSettings = { defaultIndex: 'logstash-*' };
|
const defaultSettings = { defaultIndex: 'logstash-*' };
|
||||||
const dataGrid = getService('dataGrid');
|
const dataGrid = getService('dataGrid');
|
||||||
const security = getService('security');
|
const security = getService('security');
|
||||||
|
@ -43,11 +50,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
it('the search term should be highlighted in the field data', async function () {
|
it('the search term should be highlighted in the field data', async function () {
|
||||||
// marks is the style that highlights the text in yellow
|
// marks is the style that highlights the text in yellow
|
||||||
await PageObjects.discover.clickFieldListItemAdd('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||||
const marks = await PageObjects.discover.getMarks();
|
const marks = await PageObjects.discover.getMarks();
|
||||||
expect(marks.length).to.be.greaterThan(0);
|
expect(marks.length).to.be.greaterThan(0);
|
||||||
expect(marks.indexOf('php')).to.be(0);
|
expect(marks.indexOf('php')).to.be(0);
|
||||||
await PageObjects.discover.clickFieldListItemRemove('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('extension');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('search type:apache should show the correct hit count', async function () {
|
it('search type:apache should show the correct hit count', async function () {
|
||||||
|
|
|
@ -21,6 +21,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'discover',
|
'discover',
|
||||||
'timePicker',
|
'timePicker',
|
||||||
'dashboard',
|
'dashboard',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
describe('data view flyout', function () {
|
describe('data view flyout', function () {
|
||||||
|
@ -76,10 +77,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await retry.waitFor('current data view to get updated', async () => {
|
await retry.waitFor('current data view to get updated', async () => {
|
||||||
return (await PageObjects.discover.getCurrentlySelectedDataView()) === `${initialPattern}*`;
|
return (await PageObjects.discover.getCurrentlySelectedDataView()) === `${initialPattern}*`;
|
||||||
});
|
});
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getHitCountInt()).to.be(2);
|
expect(await PageObjects.discover.getHitCountInt()).to.be(2);
|
||||||
expect((await PageObjects.discover.getAllFieldNames()).length).to.be(3);
|
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).length).to.be(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('create saved data view', async function () {
|
it('create saved data view', async function () {
|
||||||
|
@ -91,8 +92,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
expect(await PageObjects.discover.getHitCountInt()).to.be(1);
|
expect(await PageObjects.discover.getHitCountInt()).to.be(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
expect((await PageObjects.discover.getAllFieldNames()).length).to.be(2);
|
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).length).to.be(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('update data view with a different time field', async function () {
|
it('update data view with a different time field', async function () {
|
||||||
|
@ -122,8 +123,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await retry.try(async () => {
|
await retry.try(async () => {
|
||||||
expect(await PageObjects.discover.getHitCountInt()).to.be(3);
|
expect(await PageObjects.discover.getHitCountInt()).to.be(3);
|
||||||
});
|
});
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
expect((await PageObjects.discover.getAllFieldNames()).length).to.be(3);
|
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).length).to.be(3);
|
||||||
expect(await PageObjects.discover.isChartVisible()).to.be(true);
|
expect(await PageObjects.discover.isChartVisible()).to.be(true);
|
||||||
expect(await PageObjects.timePicker.timePickerExists()).to.be(true);
|
expect(await PageObjects.timePicker.timePickerExists()).to.be(true);
|
||||||
});
|
});
|
||||||
|
@ -137,8 +138,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await retry.try(async () => {
|
await retry.try(async () => {
|
||||||
expect(await PageObjects.discover.getHitCountInt()).to.be(4);
|
expect(await PageObjects.discover.getHitCountInt()).to.be(4);
|
||||||
});
|
});
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
expect((await PageObjects.discover.getAllFieldNames()).length).to.be(3);
|
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).length).to.be(3);
|
||||||
expect(await PageObjects.discover.isChartVisible()).to.be(false);
|
expect(await PageObjects.discover.isChartVisible()).to.be(false);
|
||||||
expect(await PageObjects.timePicker.timePickerExists()).to.be(false);
|
expect(await PageObjects.timePicker.timePickerExists()).to.be(false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const dataGrid = getService('dataGrid');
|
const dataGrid = getService('dataGrid');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker', 'settings']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'timePicker',
|
||||||
|
'settings',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const security = getService('security');
|
const security = getService('security');
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
defaultIndex: 'logstash-*',
|
defaultIndex: 'logstash-*',
|
||||||
|
@ -50,13 +57,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adding a column removes a default column', async function () {
|
it('adding a column removes a default column', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd('_score');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('_score');
|
||||||
expect(await PageObjects.discover.getDocHeader()).to.have.string('_score');
|
expect(await PageObjects.discover.getDocHeader()).to.have.string('_score');
|
||||||
expect(await PageObjects.discover.getDocHeader()).not.to.have.string('Document');
|
expect(await PageObjects.discover.getDocHeader()).not.to.have.string('Document');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('removing a column adds a default column', async function () {
|
it('removing a column adds a default column', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemRemove('_score');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('_score');
|
||||||
expect(await PageObjects.discover.getDocHeader()).not.to.have.string('_score');
|
expect(await PageObjects.discover.getDocHeader()).not.to.have.string('_score');
|
||||||
expect(await PageObjects.discover.getDocHeader()).to.have.string('Document');
|
expect(await PageObjects.discover.getDocHeader()).to.have.string('Document');
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,7 +14,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const security = getService('security');
|
const security = getService('security');
|
||||||
const retry = getService('retry');
|
const retry = getService('retry');
|
||||||
const PageObjects = getPageObjects(['common', 'timePicker', 'discover']);
|
const PageObjects = getPageObjects(['common', 'timePicker', 'discover', 'unifiedFieldList']);
|
||||||
|
|
||||||
describe('index pattern with unmapped fields', () => {
|
describe('index pattern with unmapped fields', () => {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
@ -48,18 +48,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
expect(await PageObjects.discover.getHitCount()).to.be(expectedHitCount);
|
expect(await PageObjects.discover.getHitCount()).to.be(expectedHitCount);
|
||||||
});
|
});
|
||||||
let allFields = await PageObjects.discover.getAllFieldNames();
|
let allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
// message is a mapped field
|
// message is a mapped field
|
||||||
expect(allFields.includes('message')).to.be(true);
|
expect(allFields.includes('message')).to.be(true);
|
||||||
// sender is not a mapped field
|
// sender is not a mapped field
|
||||||
expect(allFields.includes('sender')).to.be(false);
|
expect(allFields.includes('sender')).to.be(false);
|
||||||
|
|
||||||
await PageObjects.discover.toggleSidebarSection('unmapped');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('unmapped');
|
||||||
|
|
||||||
allFields = await PageObjects.discover.getAllFieldNames();
|
allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
expect(allFields.includes('sender')).to.be(true); // now visible under Unmapped section
|
expect(allFields.includes('sender')).to.be(true); // now visible under Unmapped section
|
||||||
|
|
||||||
await PageObjects.discover.toggleSidebarSection('unmapped');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('unmapped');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('unmapped fields exist on an existing saved search', async () => {
|
it('unmapped fields exist on an existing saved search', async () => {
|
||||||
|
@ -68,20 +68,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
expect(await PageObjects.discover.getHitCount()).to.be(expectedHitCount);
|
expect(await PageObjects.discover.getHitCount()).to.be(expectedHitCount);
|
||||||
});
|
});
|
||||||
let allFields = await PageObjects.discover.getAllFieldNames();
|
let allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
expect(allFields.includes('message')).to.be(true);
|
expect(allFields.includes('message')).to.be(true);
|
||||||
expect(allFields.includes('sender')).to.be(false);
|
expect(allFields.includes('sender')).to.be(false);
|
||||||
expect(allFields.includes('receiver')).to.be(false);
|
expect(allFields.includes('receiver')).to.be(false);
|
||||||
|
|
||||||
await PageObjects.discover.toggleSidebarSection('unmapped');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('unmapped');
|
||||||
|
|
||||||
allFields = await PageObjects.discover.getAllFieldNames();
|
allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
|
|
||||||
// now visible under Unmapped section
|
// now visible under Unmapped section
|
||||||
expect(allFields.includes('sender')).to.be(true);
|
expect(allFields.includes('sender')).to.be(true);
|
||||||
expect(allFields.includes('receiver')).to.be(true);
|
expect(allFields.includes('receiver')).to.be(true);
|
||||||
|
|
||||||
await PageObjects.discover.toggleSidebarSection('unmapped');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('unmapped');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const fieldEditor = getService('fieldEditor');
|
const fieldEditor = getService('fieldEditor');
|
||||||
const security = getService('security');
|
const security = getService('security');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
defaultIndex: 'logstash-*',
|
defaultIndex: 'logstash-*',
|
||||||
'discover:searchFieldsFromSource': false,
|
'discover:searchFieldsFromSource': false,
|
||||||
|
@ -55,8 +61,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await fieldEditor.setCustomLabel(customLabel);
|
await fieldEditor.setCustomLabel(customLabel);
|
||||||
await fieldEditor.save();
|
await fieldEditor.save();
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
expect((await PageObjects.discover.getAllFieldNames()).includes(customLabel)).to.be(true);
|
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).includes(customLabel)).to.be(
|
||||||
await PageObjects.discover.clickFieldListItemAdd('bytes');
|
true
|
||||||
|
);
|
||||||
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||||
expect(await PageObjects.discover.getDocHeader()).to.have.string(customLabel);
|
expect(await PageObjects.discover.getDocHeader()).to.have.string(customLabel);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -64,7 +72,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const field = '_runtimefield';
|
const field = '_runtimefield';
|
||||||
await createRuntimeField(field);
|
await createRuntimeField(field);
|
||||||
await retry.waitForWithTimeout('fieldNames to include runtimefield', 5000, async () => {
|
await retry.waitForWithTimeout('fieldNames to include runtimefield', 5000, async () => {
|
||||||
const fieldNames = await PageObjects.discover.getAllFieldNames();
|
const fieldNames = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
return fieldNames.includes(field);
|
return fieldNames.includes(field);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -81,7 +89,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.discover.waitForDocTableLoadingComplete();
|
await PageObjects.discover.waitForDocTableLoadingComplete();
|
||||||
|
|
||||||
await retry.waitForWithTimeout('fieldNames to include edits', 5000, async () => {
|
await retry.waitForWithTimeout('fieldNames to include edits', 5000, async () => {
|
||||||
const fieldNames = await PageObjects.discover.getAllFieldNames();
|
const fieldNames = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
return fieldNames.includes(newFieldName);
|
return fieldNames.includes(newFieldName);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -89,7 +97,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('allows creation of a new field and use it in a saved search', async function () {
|
it('allows creation of a new field and use it in a saved search', async function () {
|
||||||
const fieldName = '_runtimefield-saved-search';
|
const fieldName = '_runtimefield-saved-search';
|
||||||
await createRuntimeField(fieldName);
|
await createRuntimeField(fieldName);
|
||||||
await PageObjects.discover.clickFieldListItemAdd(fieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(fieldName);
|
||||||
expect(await PageObjects.discover.getDocHeader()).to.have.string(fieldName);
|
expect(await PageObjects.discover.getDocHeader()).to.have.string(fieldName);
|
||||||
expect(await PageObjects.discover.saveSearch('Saved Search with runtimefield'));
|
expect(await PageObjects.discover.saveSearch('Saved Search with runtimefield'));
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
@ -108,7 +116,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.discover.removeField(fieldName);
|
await PageObjects.discover.removeField(fieldName);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await retry.waitForWithTimeout('fieldNames to include edits', 5000, async () => {
|
await retry.waitForWithTimeout('fieldNames to include edits', 5000, async () => {
|
||||||
const fieldNames = await PageObjects.discover.getAllFieldNames();
|
const fieldNames = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
return !fieldNames.includes(fieldName);
|
return !fieldNames.includes(fieldName);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,7 +16,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const queryBar = getService('queryBar');
|
const queryBar = getService('queryBar');
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const security = getService('security');
|
const security = getService('security');
|
||||||
const refreshButtonSelector = 'refreshDataButton';
|
const refreshButtonSelector = 'refreshDataButton';
|
||||||
|
@ -72,7 +78,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('should not fetch data from ES initially', async function () {
|
it('should not fetch data from ES initially', async function () {
|
||||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||||
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not fetch on indexPattern change', async function () {
|
it('should not fetch on indexPattern change', async function () {
|
||||||
|
@ -83,56 +89,56 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||||
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fetch data from ES after refreshDataButton click', async function () {
|
it('should fetch data from ES after refreshDataButton click', async function () {
|
||||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||||
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(false);
|
||||||
|
|
||||||
await testSubjects.click(refreshButtonSelector);
|
await testSubjects.click(refreshButtonSelector);
|
||||||
await testSubjects.missingOrFail(refreshButtonSelector);
|
await testSubjects.missingOrFail(refreshButtonSelector);
|
||||||
|
|
||||||
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fetch data from ES after submit query', async function () {
|
it('should fetch data from ES after submit query', async function () {
|
||||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||||
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(false);
|
||||||
|
|
||||||
await queryBar.submitQuery();
|
await queryBar.submitQuery();
|
||||||
await testSubjects.missingOrFail(refreshButtonSelector);
|
await testSubjects.missingOrFail(refreshButtonSelector);
|
||||||
|
|
||||||
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fetch data from ES after choosing commonly used time range', async function () {
|
it('should fetch data from ES after choosing commonly used time range', async function () {
|
||||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||||
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(false);
|
||||||
|
|
||||||
await PageObjects.timePicker.setCommonlyUsedTime('This_week');
|
await PageObjects.timePicker.setCommonlyUsedTime('This_week');
|
||||||
await testSubjects.missingOrFail(refreshButtonSelector);
|
await testSubjects.missingOrFail(refreshButtonSelector);
|
||||||
|
|
||||||
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fetch data when a search is saved', async function () {
|
it('should fetch data when a search is saved', async function () {
|
||||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||||
|
|
||||||
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(false);
|
||||||
|
|
||||||
await PageObjects.discover.saveSearch(savedSearchName);
|
await PageObjects.discover.saveSearch(savedSearchName);
|
||||||
|
|
||||||
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reset state after opening a saved search and pressing New', async function () {
|
it('should reset state after opening a saved search and pressing New', async function () {
|
||||||
|
@ -140,20 +146,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||||
|
|
||||||
await testSubjects.click('discoverNewButton');
|
await testSubjects.click('discoverNewButton');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
await retry.waitFor('number of fetches to be 0', waitForFetches(0));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`when it's true should fetch data from ES initially`, async function () {
|
it(`when it's true should fetch data from ES initially`, async function () {
|
||||||
await initSearchOnPageLoad(true);
|
await initSearchOnPageLoad(true);
|
||||||
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
await retry.waitFor('number of fetches to be 1', waitForFetches(1));
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const monacoEditor = getService('monacoEditor');
|
const monacoEditor = getService('monacoEditor');
|
||||||
const security = getService('security');
|
const security = getService('security');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
defaultIndex: 'logstash-*',
|
defaultIndex: 'logstash-*',
|
||||||
|
@ -39,7 +45,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
describe('test', () => {
|
describe('test', () => {
|
||||||
it('should render sql view correctly', async function () {
|
it('should render sql view correctly', async function () {
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await testSubjects.exists('showQueryBarMenu')).to.be(true);
|
expect(await testSubjects.exists('showQueryBarMenu')).to.be(true);
|
||||||
expect(await testSubjects.exists('superDatePickerToggleQuickMenuButton')).to.be(true);
|
expect(await testSubjects.exists('superDatePickerToggleQuickMenuButton')).to.be(true);
|
||||||
|
@ -57,7 +63,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
expect(await testSubjects.exists('discoverFieldListPanelEdit-@message')).to.be(true);
|
expect(await testSubjects.exists('discoverFieldListPanelEdit-@message')).to.be(true);
|
||||||
|
|
||||||
await PageObjects.discover.selectTextBaseLang('SQL');
|
await PageObjects.discover.selectTextBaseLang('SQL');
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await testSubjects.exists('fieldListFiltersFieldSearch')).to.be(true);
|
expect(await testSubjects.exists('fieldListFiltersFieldSearch')).to.be(true);
|
||||||
expect(await testSubjects.exists('TextBasedLangEditor')).to.be(true);
|
expect(await testSubjects.exists('TextBasedLangEditor')).to.be(true);
|
||||||
|
|
|
@ -12,7 +12,13 @@ import { FtrProviderContext } from '../ftr_provider_context';
|
||||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'header']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'timePicker',
|
||||||
|
'header',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
|
|
||||||
describe('discover drag and drop', function describeIndexTests() {
|
describe('discover drag and drop', function describeIndexTests() {
|
||||||
before(async function () {
|
before(async function () {
|
||||||
|
@ -33,15 +39,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
|
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
|
||||||
await kibanaServer.savedObjects.cleanStandardList();
|
await kibanaServer.savedObjects.cleanStandardList();
|
||||||
await kibanaServer.uiSettings.replace({});
|
await kibanaServer.uiSettings.replace({});
|
||||||
await PageObjects.discover.cleanSidebarLocalStorage();
|
await PageObjects.unifiedFieldList.cleanSidebarLocalStorage();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('should add fields as columns via drag and drop', function () {
|
describe('should add fields as columns via drag and drop', function () {
|
||||||
it('should support dragging and dropping a field onto the grid', async function () {
|
it('should support dragging and dropping a field onto the grid', async function () {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'53 available fields. 0 empty fields. 3 meta fields.'
|
'53 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
expect((await PageObjects.discover.getColumnHeaders()).join(', ')).to.be(
|
expect((await PageObjects.discover.getColumnHeaders()).join(', ')).to.be(
|
||||||
|
@ -63,7 +69,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
(await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ')
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ')
|
||||||
).to.be('extension, @message');
|
).to.be('extension, @message');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,6 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'timePicker',
|
'timePicker',
|
||||||
'header',
|
'header',
|
||||||
'unifiedSearch',
|
'unifiedSearch',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const find = getService('find');
|
const find = getService('find');
|
||||||
|
@ -48,21 +49,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
|
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
|
||||||
await kibanaServer.savedObjects.cleanStandardList();
|
await kibanaServer.savedObjects.cleanStandardList();
|
||||||
await kibanaServer.uiSettings.replace({});
|
await kibanaServer.uiSettings.replace({});
|
||||||
await PageObjects.discover.cleanSidebarLocalStorage();
|
await PageObjects.unifiedFieldList.cleanSidebarLocalStorage();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('field filtering', function () {
|
describe('field filtering', function () {
|
||||||
it('should reveal and hide the filter form when the toggle is clicked', async function () {
|
it('should reveal and hide the filter form when the toggle is clicked', async function () {
|
||||||
await PageObjects.discover.openSidebarFieldFilter();
|
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||||
await PageObjects.discover.closeSidebarFieldFilter();
|
await PageObjects.unifiedFieldList.closeSidebarFieldFilter();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by field type', async function () {
|
it('should filter by field type', async function () {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
await PageObjects.discover.openSidebarFieldFilter();
|
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
await retry.waitFor('first updates', async () => {
|
await retry.waitFor('first updates', async () => {
|
||||||
return (
|
return (
|
||||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||||
'7 available fields. 0 empty fields. 2 meta fields.'
|
'7 available fields. 0 empty fields. 2 meta fields.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -79,7 +80,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
await retry.waitFor('second updates', async () => {
|
await retry.waitFor('second updates', async () => {
|
||||||
return (
|
return (
|
||||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||||
'13 available fields. 0 empty fields. 3 meta fields.'
|
'13 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -88,7 +89,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
await retry.waitFor('reset', async () => {
|
await retry.waitFor('reset', async () => {
|
||||||
return (
|
return (
|
||||||
(await PageObjects.discover.getSidebarAriaDescription()) === INITIAL_FIELD_LIST_SUMMARY
|
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||||
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -97,20 +99,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await kibanaServer.uiSettings.update({ 'discover:enableSql': true });
|
await kibanaServer.uiSettings.update({ 'discover:enableSql': true });
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
|
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
await PageObjects.discover.openSidebarFieldFilter();
|
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||||
let options = await find.allByCssSelector('[data-test-subj*="typeFilter"]');
|
let options = await find.allByCssSelector('[data-test-subj*="typeFilter"]');
|
||||||
expect(options).to.have.length(6);
|
expect(options).to.have.length(6);
|
||||||
await PageObjects.discover.closeSidebarFieldFilter();
|
await PageObjects.unifiedFieldList.closeSidebarFieldFilter();
|
||||||
|
|
||||||
await PageObjects.discover.selectTextBaseLang('SQL');
|
await PageObjects.discover.selectTextBaseLang('SQL');
|
||||||
|
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
await PageObjects.discover.openSidebarFieldFilter();
|
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||||
options = await find.allByCssSelector('[data-test-subj*="typeFilter"]');
|
options = await find.allByCssSelector('[data-test-subj*="typeFilter"]');
|
||||||
expect(options).to.have.length(3);
|
expect(options).to.have.length(3);
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'50 selected fields. 51 available fields.'
|
'50 selected fields. 51 available fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -118,7 +120,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
await retry.waitFor('updates', async () => {
|
await retry.waitFor('updates', async () => {
|
||||||
return (
|
return (
|
||||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||||
'6 selected fields. 6 available fields.'
|
'6 selected fields. 6 available fields.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -126,26 +128,26 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
it('should be able to search by string', async function () {
|
it('should be able to search by string', async function () {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.findFieldByName('i');
|
await PageObjects.unifiedFieldList.findFieldByName('i');
|
||||||
|
|
||||||
await retry.waitFor('first updates', async () => {
|
await retry.waitFor('first updates', async () => {
|
||||||
return (
|
return (
|
||||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||||
'30 available fields. 0 empty fields. 2 meta fields.'
|
'30 available fields. 0 empty fields. 2 meta fields.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
await PageObjects.discover.findFieldByName('p');
|
await PageObjects.unifiedFieldList.findFieldByName('p');
|
||||||
|
|
||||||
await retry.waitFor('second updates', async () => {
|
await retry.waitFor('second updates', async () => {
|
||||||
return (
|
return (
|
||||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||||
'4 available fields. 0 empty fields. 0 meta fields.'
|
'4 available fields. 0 empty fields. 0 meta fields.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -155,7 +157,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
await retry.waitFor('reset', async () => {
|
await retry.waitFor('reset', async () => {
|
||||||
return (
|
return (
|
||||||
(await PageObjects.discover.getSidebarAriaDescription()) === INITIAL_FIELD_LIST_SUMMARY
|
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||||
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -166,21 +169,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
const allTermsResult = 'jpg\n65.0%\ncss\n15.4%\npng\n9.8%\ngif\n6.6%\nphp\n3.2%';
|
const allTermsResult = 'jpg\n65.0%\ncss\n15.4%\npng\n9.8%\ngif\n6.6%\nphp\n3.2%';
|
||||||
await PageObjects.discover.clickFieldListItem('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(allTermsResult);
|
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(allTermsResult);
|
||||||
|
|
||||||
await filterBar.addFilter({ field: 'extension', operation: 'is', value: 'jpg' });
|
await filterBar.addFilter({ field: 'extension', operation: 'is', value: 'jpg' });
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
const onlyJpgResult = 'jpg\n100%';
|
const onlyJpgResult = 'jpg\n100%';
|
||||||
await PageObjects.discover.clickFieldListItem('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(onlyJpgResult);
|
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(onlyJpgResult);
|
||||||
|
|
||||||
await filterBar.toggleFilterNegated('extension');
|
await filterBar.toggleFilterNegated('extension');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
const jpgExcludedResult = 'css\n44.1%\npng\n28.0%\ngif\n18.8%\nphp\n9.1%';
|
const jpgExcludedResult = 'css\n44.1%\npng\n28.0%\ngif\n18.8%\nphp\n9.1%';
|
||||||
await PageObjects.discover.clickFieldListItem('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
||||||
jpgExcludedResult
|
jpgExcludedResult
|
||||||
);
|
);
|
||||||
|
@ -188,14 +191,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await filterBar.toggleFilterPinned('extension');
|
await filterBar.toggleFilterPinned('extension');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
||||||
jpgExcludedResult
|
jpgExcludedResult
|
||||||
);
|
);
|
||||||
|
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
||||||
jpgExcludedResult
|
jpgExcludedResult
|
||||||
);
|
);
|
||||||
|
@ -203,7 +206,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await filterBar.toggleFilterEnabled('extension');
|
await filterBar.toggleFilterEnabled('extension');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(allTermsResult);
|
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(allTermsResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -226,24 +229,28 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
describe('renders field groups', function () {
|
describe('renders field groups', function () {
|
||||||
it('should show field list groups excluding subfields', async function () {
|
it('should show field list groups excluding subfields', async function () {
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||||
|
|
||||||
// Initial Available fields
|
// Initial Available fields
|
||||||
const expectedInitialAvailableFields =
|
const expectedInitialAvailableFields =
|
||||||
'@message, @tags, @timestamp, agent, bytes, clientip, extension, geo.coordinates, geo.dest, geo.src, geo.srcdest, headings, host, id, index, ip, links, machine.os, machine.ram, machine.ram_range, memory, meta.char, meta.related, meta.user.firstname, meta.user.lastname, nestedField.child, phpmemory, referer, relatedContent.article:modified_time, relatedContent.article:published_time, relatedContent.article:section, relatedContent.article:tag, relatedContent.og:description, relatedContent.og:image, relatedContent.og:image:height, relatedContent.og:image:width, relatedContent.og:site_name, relatedContent.og:title, relatedContent.og:type, relatedContent.og:url, relatedContent.twitter:card, relatedContent.twitter:description, relatedContent.twitter:image, relatedContent.twitter:site, relatedContent.twitter:title, relatedContent.url, request, response, spaces, type';
|
'@message, @tags, @timestamp, agent, bytes, clientip, extension, geo.coordinates, geo.dest, geo.src, geo.srcdest, headings, host, id, index, ip, links, machine.os, machine.ram, machine.ram_range, memory, meta.char, meta.related, meta.user.firstname, meta.user.lastname, nestedField.child, phpmemory, referer, relatedContent.article:modified_time, relatedContent.article:published_time, relatedContent.article:section, relatedContent.article:tag, relatedContent.og:description, relatedContent.og:image, relatedContent.og:image:height, relatedContent.og:image:width, relatedContent.og:site_name, relatedContent.og:title, relatedContent.og:type, relatedContent.og:url, relatedContent.twitter:card, relatedContent.twitter:description, relatedContent.twitter:image, relatedContent.twitter:site, relatedContent.twitter:title, relatedContent.url, request, response, spaces, type';
|
||||||
let availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available');
|
let availableFields = await PageObjects.unifiedFieldList.getSidebarSectionFieldNames(
|
||||||
|
'available'
|
||||||
|
);
|
||||||
expect(availableFields.length).to.be(50);
|
expect(availableFields.length).to.be(50);
|
||||||
expect(availableFields.join(', ')).to.be(expectedInitialAvailableFields);
|
expect(availableFields.join(', ')).to.be(expectedInitialAvailableFields);
|
||||||
|
|
||||||
// Available fields after scrolling down
|
// Available fields after scrolling down
|
||||||
const emptySectionButton = await find.byCssSelector(
|
const emptySectionButton = await find.byCssSelector(
|
||||||
PageObjects.discover.getSidebarSectionSelector('empty', true)
|
PageObjects.unifiedFieldList.getSidebarSectionSelector('empty', true)
|
||||||
);
|
);
|
||||||
await emptySectionButton.scrollIntoViewIfNecessary();
|
await emptySectionButton.scrollIntoViewIfNecessary();
|
||||||
|
|
||||||
await retry.waitFor('list to update after scrolling', async () => {
|
await retry.waitFor('list to update after scrolling', async () => {
|
||||||
availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available');
|
availableFields = await PageObjects.unifiedFieldList.getSidebarSectionFieldNames(
|
||||||
|
'available'
|
||||||
|
);
|
||||||
return availableFields.length === 53;
|
return availableFields.length === 53;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -252,18 +259,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Expand Empty section
|
// Expand Empty section
|
||||||
await PageObjects.discover.toggleSidebarSection('empty');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('empty');
|
||||||
expect((await PageObjects.discover.getSidebarSectionFieldNames('empty')).join(', ')).to.be(
|
expect(
|
||||||
''
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('empty')).join(', ')
|
||||||
);
|
).to.be('');
|
||||||
|
|
||||||
// Expand Meta section
|
// Expand Meta section
|
||||||
await PageObjects.discover.toggleSidebarSection('meta');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('meta');
|
||||||
expect((await PageObjects.discover.getSidebarSectionFieldNames('meta')).join(', ')).to.be(
|
expect(
|
||||||
'_id, _index, _score'
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('meta')).join(', ')
|
||||||
);
|
).to.be('_id, _index, _score');
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -272,11 +279,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await kibanaServer.uiSettings.update({ 'discover:searchFieldsFromSource': true });
|
await kibanaServer.uiSettings.update({ 'discover:searchFieldsFromSource': true });
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
|
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||||
|
|
||||||
// Initial Available fields
|
// Initial Available fields
|
||||||
const availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available');
|
const availableFields = await PageObjects.unifiedFieldList.getSidebarSectionFieldNames(
|
||||||
|
'available'
|
||||||
|
);
|
||||||
expect(availableFields.length).to.be(50);
|
expect(availableFields.length).to.be(50);
|
||||||
expect(
|
expect(
|
||||||
availableFields
|
availableFields
|
||||||
|
@ -288,68 +297,70 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
// Available fields after scrolling down
|
// Available fields after scrolling down
|
||||||
const emptySectionButton = await find.byCssSelector(
|
const emptySectionButton = await find.byCssSelector(
|
||||||
PageObjects.discover.getSidebarSectionSelector('empty', true)
|
PageObjects.unifiedFieldList.getSidebarSectionSelector('empty', true)
|
||||||
);
|
);
|
||||||
await emptySectionButton.scrollIntoViewIfNecessary();
|
await emptySectionButton.scrollIntoViewIfNecessary();
|
||||||
|
|
||||||
// Expand Empty section
|
// Expand Empty section
|
||||||
await PageObjects.discover.toggleSidebarSection('empty');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('empty');
|
||||||
expect((await PageObjects.discover.getSidebarSectionFieldNames('empty')).join(', ')).to.be(
|
expect(
|
||||||
''
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('empty')).join(', ')
|
||||||
);
|
).to.be('');
|
||||||
|
|
||||||
// Expand Meta section
|
// Expand Meta section
|
||||||
await PageObjects.discover.toggleSidebarSection('meta');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('meta');
|
||||||
expect((await PageObjects.discover.getSidebarSectionFieldNames('meta')).join(', ')).to.be(
|
expect(
|
||||||
'_id, _index, _score'
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('meta')).join(', ')
|
||||||
);
|
).to.be('_id, _index, _score');
|
||||||
|
|
||||||
// Expand Unmapped section
|
// Expand Unmapped section
|
||||||
await PageObjects.discover.toggleSidebarSection('unmapped');
|
await PageObjects.unifiedFieldList.toggleSidebarSection('unmapped');
|
||||||
expect(
|
expect(
|
||||||
(await PageObjects.discover.getSidebarSectionFieldNames('unmapped')).join(', ')
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('unmapped')).join(', ')
|
||||||
).to.be('relatedContent');
|
).to.be('relatedContent');
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'53 available fields. 1 unmapped field. 0 empty fields. 3 meta fields.'
|
'53 available fields. 1 unmapped field. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show selected and popular fields', async function () {
|
it('should show selected and popular fields', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||||
await PageObjects.discover.clickFieldListItemAdd('@message');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('@message');
|
||||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
(await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ')
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ')
|
||||||
).to.be('extension, @message');
|
).to.be('extension, @message');
|
||||||
|
|
||||||
const availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available');
|
const availableFields = await PageObjects.unifiedFieldList.getSidebarSectionFieldNames(
|
||||||
|
'available'
|
||||||
|
);
|
||||||
expect(availableFields.includes('extension')).to.be(true);
|
expect(availableFields.includes('extension')).to.be(true);
|
||||||
expect(availableFields.includes('@message')).to.be(true);
|
expect(availableFields.includes('@message')).to.be(true);
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'2 selected fields. 2 popular fields. 53 available fields. 0 empty fields. 3 meta fields.'
|
'2 selected fields. 2 popular fields. 53 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemRemove('@message');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('@message');
|
||||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemAdd('_id');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('_id');
|
||||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||||
await PageObjects.discover.clickFieldListItemAdd('@message');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('@message');
|
||||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
(await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ')
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ')
|
||||||
).to.be('extension, _id, @message');
|
).to.be('extension, _id, @message');
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
(await PageObjects.discover.getSidebarSectionFieldNames('popular')).join(', ')
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('popular')).join(', ')
|
||||||
).to.be('@message, _id, extension');
|
).to.be('@message, _id, extension');
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'3 selected fields. 3 popular fields. 53 available fields. 0 empty fields. 3 meta fields.'
|
'3 selected fields. 3 popular fields. 53 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -358,22 +369,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await kibanaServer.uiSettings.update({ 'discover:enableSql': true });
|
await kibanaServer.uiSettings.update({ 'discover:enableSql': true });
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
|
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.selectTextBaseLang('SQL');
|
await PageObjects.discover.selectTextBaseLang('SQL');
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'50 selected fields. 51 available fields.'
|
'50 selected fields. 51 available fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemRemove('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItemRemove('extension');
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'49 selected fields. 51 available fields.'
|
'49 selected fields. 51 available fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -385,13 +396,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await monacoEditor.setCodeEditorValue(testQuery);
|
await monacoEditor.setCodeEditorValue(testQuery);
|
||||||
await testSubjects.click('querySubmitButton');
|
await testSubjects.click('querySubmitButton');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'3 selected fields. 3 available fields.'
|
'3 selected fields. 3 available fields.'
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
(await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ')
|
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ')
|
||||||
).to.be('@tags, geo.dest, occurred');
|
).to.be('@tags, geo.dest, occurred');
|
||||||
|
|
||||||
await PageObjects.unifiedSearch.switchDataView(
|
await PageObjects.unifiedSearch.switchDataView(
|
||||||
|
@ -401,9 +412,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'53 available fields. 0 empty fields. 3 meta fields.'
|
'53 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -414,25 +425,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield'
|
'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield'
|
||||||
);
|
);
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.selectIndexPattern('with-timefield');
|
await PageObjects.discover.selectIndexPattern('with-timefield');
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'0 available fields. 0 empty fields. 0 meta fields.'
|
'0 available fields. 0 empty fields. 0 meta fields.'
|
||||||
);
|
);
|
||||||
await testSubjects.missingOrFail(
|
await testSubjects.missingOrFail(
|
||||||
`${PageObjects.discover.getSidebarSectionSelector('available')}-fetchWarning`
|
`${PageObjects.unifiedFieldList.getSidebarSectionSelector('available')}-fetchWarning`
|
||||||
);
|
);
|
||||||
await testSubjects.existOrFail(
|
await testSubjects.existOrFail(
|
||||||
`${PageObjects.discover.getSidebarSectionSelector(
|
`${PageObjects.unifiedFieldList.getSidebarSectionSelector(
|
||||||
'available'
|
'available'
|
||||||
)}NoFieldsCallout-noFieldsExist`
|
)}NoFieldsCallout-noFieldsExist`
|
||||||
);
|
);
|
||||||
|
@ -440,9 +451,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
await kibanaServer.importExport.unload(
|
await kibanaServer.importExport.unload(
|
||||||
|
@ -459,31 +470,31 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
);
|
);
|
||||||
|
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.selectIndexPattern('without-timefield');
|
await PageObjects.discover.selectIndexPattern('without-timefield');
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'6 available fields. 0 empty fields. 3 meta fields.'
|
'6 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.selectIndexPattern('with-timefield');
|
await PageObjects.discover.selectIndexPattern('with-timefield');
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'0 available fields. 7 empty fields. 3 meta fields.'
|
'0 available fields. 7 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
await testSubjects.existOrFail(
|
await testSubjects.existOrFail(
|
||||||
`${PageObjects.discover.getSidebarSectionSelector(
|
`${PageObjects.unifiedFieldList.getSidebarSectionSelector(
|
||||||
'available'
|
'available'
|
||||||
)}NoFieldsCallout-noFieldsMatch`
|
)}NoFieldsCallout-noFieldsMatch`
|
||||||
);
|
);
|
||||||
|
@ -491,9 +502,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -509,25 +520,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('should work when filters change', async () => {
|
it('should work when filters change', async () => {
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
||||||
'jpg\n65.0%\ncss\n15.4%\npng\n9.8%\ngif\n6.6%\nphp\n3.2%'
|
'jpg\n65.0%\ncss\n15.4%\npng\n9.8%\ngif\n6.6%\nphp\n3.2%'
|
||||||
);
|
);
|
||||||
|
|
||||||
await filterBar.addFilter({ field: 'extension', operation: 'is', value: 'jpg' });
|
await filterBar.addFilter({ field: 'extension', operation: 'is', value: 'jpg' });
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
// check that the filter was passed down to the sidebar
|
// check that the filter was passed down to the sidebar
|
||||||
await PageObjects.discover.clickFieldListItem('extension');
|
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be('jpg\n100%');
|
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be('jpg\n100%');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -538,27 +549,27 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
);
|
);
|
||||||
|
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.selectIndexPattern('indices-stats*');
|
await PageObjects.discover.selectIndexPattern('indices-stats*');
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'6873 available fields. 0 empty fields. 3 meta fields.'
|
'6873 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -572,7 +583,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.discover.createAdHocDataView('logstash', true);
|
await PageObjects.discover.createAdHocDataView('logstash', true);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -586,13 +597,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'54 available fields. 0 empty fields. 3 meta fields.'
|
'54 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
let allFields = await PageObjects.discover.getAllFieldNames();
|
let allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
expect(allFields.includes('_bytes-runtimefield')).to.be(true);
|
expect(allFields.includes('_bytes-runtimefield')).to.be(true);
|
||||||
|
|
||||||
await PageObjects.discover.editField('_bytes-runtimefield');
|
await PageObjects.discover.editField('_bytes-runtimefield');
|
||||||
|
@ -605,25 +616,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'54 available fields. 0 empty fields. 3 meta fields.'
|
'54 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
allFields = await PageObjects.discover.getAllFieldNames();
|
allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
expect(allFields.includes('_bytes-runtimefield2')).to.be(true);
|
expect(allFields.includes('_bytes-runtimefield2')).to.be(true);
|
||||||
expect(allFields.includes('_bytes-runtimefield')).to.be(false);
|
expect(allFields.includes('_bytes-runtimefield')).to.be(false);
|
||||||
|
|
||||||
await PageObjects.discover.removeField('_bytes-runtimefield');
|
await PageObjects.discover.removeField('_bytes-runtimefield');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
allFields = await PageObjects.discover.getAllFieldNames();
|
allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
expect(allFields.includes('_bytes-runtimefield2')).to.be(false);
|
expect(allFields.includes('_bytes-runtimefield2')).to.be(false);
|
||||||
expect(allFields.includes('_bytes-runtimefield')).to.be(false);
|
expect(allFields.includes('_bytes-runtimefield')).to.be(false);
|
||||||
});
|
});
|
||||||
|
@ -633,7 +644,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
await testSubjects.missingOrFail('discoverNoResultsError');
|
await testSubjects.missingOrFail('discoverNoResultsError');
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -644,13 +655,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
// error in fetching documents because of the invalid runtime field
|
// error in fetching documents because of the invalid runtime field
|
||||||
await testSubjects.existOrFail('discoverNoResultsError');
|
await testSubjects.existOrFail('discoverNoResultsError');
|
||||||
|
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
// check that the sidebar is rendered
|
// check that the sidebar is rendered
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'54 available fields. 0 empty fields. 3 meta fields.'
|
'54 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
let allFields = await PageObjects.discover.getAllFieldNames();
|
let allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
expect(allFields.includes('_invalid-runtimefield')).to.be(true);
|
expect(allFields.includes('_invalid-runtimefield')).to.be(true);
|
||||||
|
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
|
@ -658,13 +669,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await testSubjects.existOrFail('discoverNoResultsError'); // still has error
|
await testSubjects.existOrFail('discoverNoResultsError'); // still has error
|
||||||
|
|
||||||
// check that the sidebar is rendered event after a refresh
|
// check that the sidebar is rendered event after a refresh
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
allFields = await PageObjects.discover.getAllFieldNames();
|
allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
expect(allFields.includes('_invalid-runtimefield')).to.be(true);
|
expect(allFields.includes('_invalid-runtimefield')).to.be(true);
|
||||||
|
|
||||||
await PageObjects.discover.removeField('_invalid-runtimefield');
|
await PageObjects.discover.removeField('_invalid-runtimefield');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
await testSubjects.missingOrFail('discoverNoResultsError');
|
await testSubjects.missingOrFail('discoverNoResultsError');
|
||||||
});
|
});
|
||||||
|
@ -678,22 +689,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
);
|
);
|
||||||
|
|
||||||
await browser.refresh();
|
await browser.refresh();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
INITIAL_FIELD_LIST_SUMMARY
|
INITIAL_FIELD_LIST_SUMMARY
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.discover.selectIndexPattern('with-timefield');
|
await PageObjects.discover.selectIndexPattern('with-timefield');
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'0 available fields. 7 empty fields. 3 meta fields.'
|
'0 available fields. 7 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
await testSubjects.existOrFail(
|
await testSubjects.existOrFail(
|
||||||
`${PageObjects.discover.getSidebarSectionSelector(
|
`${PageObjects.unifiedFieldList.getSidebarSectionSelector(
|
||||||
'available'
|
'available'
|
||||||
)}NoFieldsCallout-noFieldsMatch`
|
)}NoFieldsCallout-noFieldsMatch`
|
||||||
);
|
);
|
||||||
|
@ -704,9 +715,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
);
|
);
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||||
'7 available fields. 0 empty fields. 3 meta fields.'
|
'7 available fields. 0 empty fields. 3 meta fields.'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -728,26 +739,28 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
let selectedFields = await PageObjects.discover.getSidebarSectionFieldNames('selected');
|
let selectedFields = await PageObjects.unifiedFieldList.getSidebarSectionFieldNames(
|
||||||
|
'selected'
|
||||||
|
);
|
||||||
expect(selectedFields.includes(newField)).to.be(false);
|
expect(selectedFields.includes(newField)).to.be(false);
|
||||||
expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'Document']);
|
expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'Document']);
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemAdd(newField);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(newField);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
selectedFields = await PageObjects.discover.getSidebarSectionFieldNames('selected');
|
selectedFields = await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected');
|
||||||
expect(selectedFields.includes(newField)).to.be(true);
|
expect(selectedFields.includes(newField)).to.be(true);
|
||||||
expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', newField]);
|
expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', newField]);
|
||||||
|
|
||||||
await PageObjects.discover.removeField(newField);
|
await PageObjects.discover.removeField(newField);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
await retry.waitFor('sidebar to update', async () => {
|
await retry.waitFor('sidebar to update', async () => {
|
||||||
return !(await PageObjects.discover.getAllFieldNames()).includes(newField);
|
return !(await PageObjects.unifiedFieldList.getAllFieldNames()).includes(newField);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'Document']);
|
expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'Document']);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// 1. Create scripted field
|
// 1. Create scripted field
|
||||||
// 2. See the expected value of the scripted field in Discover doc view
|
// 2. See the expected value of the scripted field in Discover doc view
|
||||||
// 3. Filter in Discover by the scripted field
|
// 3. Filter in Discover by the scripted field
|
||||||
// 4. Visualize with aggregation on the scripted field by clicking discover.clickFieldListItemVisualize
|
// 4. Visualize with aggregation on the scripted field by clicking unifiedFieldList.clickFieldListItemVisualize
|
||||||
|
|
||||||
// NOTE: Scripted field input is managed by Ace editor, which automatically
|
// NOTE: Scripted field input is managed by Ace editor, which automatically
|
||||||
// appends closing braces, for exmaple, if you type opening square brace [
|
// appends closing braces, for exmaple, if you type opening square brace [
|
||||||
|
@ -41,6 +41,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'visualize',
|
'visualize',
|
||||||
'discover',
|
'discover',
|
||||||
'timePicker',
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
describe('scripted fields', function () {
|
describe('scripted fields', function () {
|
||||||
|
@ -154,9 +155,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('should see scripted field value in Discover', async function () {
|
it('should see scripted field value in Discover', async function () {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName);
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName);
|
||||||
});
|
});
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -196,9 +197,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by scripted field value in Discover', async function () {
|
it('should filter by scripted field value in Discover', async function () {
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName);
|
||||||
await log.debug('filter by the first value (14) in the expanded scripted field list');
|
await log.debug('filter by the first value (14) in the expanded scripted field list');
|
||||||
await PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName, '14');
|
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(
|
||||||
|
scriptedPainlessFieldName,
|
||||||
|
'14'
|
||||||
|
);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
|
@ -208,7 +212,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
it('should visualize scripted field in vertical bar chart', async function () {
|
it('should visualize scripted field in vertical bar chart', async function () {
|
||||||
await filterBar.removeAllFilters();
|
await filterBar.removeAllFilters();
|
||||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// verify Lens opens a visualization
|
// verify Lens opens a visualization
|
||||||
await retry.waitFor('lens visualization', async () => {
|
await retry.waitFor('lens visualization', async () => {
|
||||||
|
@ -257,9 +261,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('should see scripted field value in Discover', async function () {
|
it('should see scripted field value in Discover', async function () {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||||
});
|
});
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -299,9 +303,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by scripted field value in Discover', async function () {
|
it('should filter by scripted field value in Discover', async function () {
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await log.debug('filter by "bad" in the expanded scripted field list');
|
await log.debug('filter by "bad" in the expanded scripted field list');
|
||||||
await PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName2, 'bad');
|
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(
|
||||||
|
scriptedPainlessFieldName2,
|
||||||
|
'bad'
|
||||||
|
);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
|
@ -311,7 +318,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should visualize scripted field in vertical bar chart', async function () {
|
it('should visualize scripted field in vertical bar chart', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// verify Lens opens a visualization
|
// verify Lens opens a visualization
|
||||||
await retry.waitFor('lens visualization', async () => {
|
await retry.waitFor('lens visualization', async () => {
|
||||||
|
@ -359,9 +366,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('should see scripted field value in Discover', async function () {
|
it('should see scripted field value in Discover', async function () {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||||
});
|
});
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -372,9 +379,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by scripted field value in Discover', async function () {
|
it('should filter by scripted field value in Discover', async function () {
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await log.debug('filter by "true" in the expanded scripted field list');
|
await log.debug('filter by "true" in the expanded scripted field list');
|
||||||
await PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName2, 'true');
|
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(
|
||||||
|
scriptedPainlessFieldName2,
|
||||||
|
'true'
|
||||||
|
);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
|
@ -406,7 +416,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should visualize scripted field in vertical bar chart', async function () {
|
it('should visualize scripted field in vertical bar chart', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// verify Lens opens a visualization
|
// verify Lens opens a visualization
|
||||||
await retry.waitFor('lens visualization', async () => {
|
await retry.waitFor('lens visualization', async () => {
|
||||||
|
@ -454,9 +464,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('should see scripted field value in Discover', async function () {
|
it('should see scripted field value in Discover', async function () {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||||
});
|
});
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -502,7 +512,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should visualize scripted field in vertical bar chart', async function () {
|
it('should visualize scripted field in vertical bar chart', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// verify Lens opens a visualization
|
// verify Lens opens a visualization
|
||||||
await retry.waitFor('lens visualization', async () => {
|
await retry.waitFor('lens visualization', async () => {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// 1. Create scripted field
|
// 1. Create scripted field
|
||||||
// 2. See the expected value of the scripted field in Discover doc view
|
// 2. See the expected value of the scripted field in Discover doc view
|
||||||
// 3. Filter in Discover by the scripted field
|
// 3. Filter in Discover by the scripted field
|
||||||
// 4. Visualize with aggregation on the scripted field by clicking discover.clickFieldListItemVisualize
|
// 4. Visualize with aggregation on the scripted field by clicking unifiedFieldList.clickFieldListItemVisualize
|
||||||
|
|
||||||
// NOTE: Scripted field input is managed by Ace editor, which automatically
|
// NOTE: Scripted field input is managed by Ace editor, which automatically
|
||||||
// appends closing braces, for exmaple, if you type opening square brace [
|
// appends closing braces, for exmaple, if you type opening square brace [
|
||||||
|
@ -40,6 +40,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'visualize',
|
'visualize',
|
||||||
'discover',
|
'discover',
|
||||||
'timePicker',
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
describe('scripted fields', function () {
|
describe('scripted fields', function () {
|
||||||
|
@ -142,9 +143,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName);
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName);
|
||||||
});
|
});
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -176,9 +177,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by scripted field value in Discover', async function () {
|
it('should filter by scripted field value in Discover', async function () {
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName);
|
||||||
await log.debug('filter by the first value (14) in the expanded scripted field list');
|
await log.debug('filter by the first value (14) in the expanded scripted field list');
|
||||||
await PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName, '14');
|
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(
|
||||||
|
scriptedPainlessFieldName,
|
||||||
|
'14'
|
||||||
|
);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
|
@ -188,7 +192,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
|
|
||||||
it('should visualize scripted field in vertical bar chart', async function () {
|
it('should visualize scripted field in vertical bar chart', async function () {
|
||||||
await filterBar.removeAllFilters();
|
await filterBar.removeAllFilters();
|
||||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// verify Lens opens a visualization
|
// verify Lens opens a visualization
|
||||||
expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
|
expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
|
||||||
|
@ -229,9 +233,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||||
});
|
});
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -263,9 +267,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by scripted field value in Discover', async function () {
|
it('should filter by scripted field value in Discover', async function () {
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await log.debug('filter by "bad" in the expanded scripted field list');
|
await log.debug('filter by "bad" in the expanded scripted field list');
|
||||||
await PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName2, 'bad');
|
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(
|
||||||
|
scriptedPainlessFieldName2,
|
||||||
|
'bad'
|
||||||
|
);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
|
@ -275,7 +282,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should visualize scripted field in vertical bar chart', async function () {
|
it('should visualize scripted field in vertical bar chart', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// verify Lens opens a visualization
|
// verify Lens opens a visualization
|
||||||
expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
|
expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
|
||||||
|
@ -315,9 +322,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||||
});
|
});
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -328,9 +335,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter by scripted field value in Discover', async function () {
|
it('should filter by scripted field value in Discover', async function () {
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await log.debug('filter by "true" in the expanded scripted field list');
|
await log.debug('filter by "true" in the expanded scripted field list');
|
||||||
await PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName2, 'true');
|
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(
|
||||||
|
scriptedPainlessFieldName2,
|
||||||
|
'true'
|
||||||
|
);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
|
@ -362,7 +372,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should visualize scripted field in vertical bar chart', async function () {
|
it('should visualize scripted field in vertical bar chart', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// verify Lens opens a visualization
|
// verify Lens opens a visualization
|
||||||
expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
|
expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain(
|
||||||
|
@ -402,9 +412,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||||
await retry.try(async function () {
|
await retry.try(async function () {
|
||||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||||
});
|
});
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
|
@ -450,7 +460,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should visualize scripted field in vertical bar chart', async function () {
|
it('should visualize scripted field in vertical bar chart', async function () {
|
||||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
// verify Lens opens a visualization
|
// verify Lens opens a visualization
|
||||||
expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain('painDate');
|
expect(await testSubjects.getVisibleTextAll('lns-dimensionTrigger')).to.contain('painDate');
|
||||||
|
|
|
@ -10,8 +10,6 @@ import expect from '@kbn/expect';
|
||||||
import { FtrService } from '../ftr_provider_context';
|
import { FtrService } from '../ftr_provider_context';
|
||||||
import { WebElementWrapper } from '../services/lib/web_element_wrapper';
|
import { WebElementWrapper } from '../services/lib/web_element_wrapper';
|
||||||
|
|
||||||
type SidebarSectionName = 'meta' | 'empty' | 'available' | 'unmapped' | 'popular' | 'selected';
|
|
||||||
|
|
||||||
export class DiscoverPageObject extends FtrService {
|
export class DiscoverPageObject extends FtrService {
|
||||||
private readonly retry = this.ctx.getService('retry');
|
private readonly retry = this.ctx.getService('retry');
|
||||||
private readonly testSubjects = this.ctx.getService('testSubjects');
|
private readonly testSubjects = this.ctx.getService('testSubjects');
|
||||||
|
@ -19,6 +17,7 @@ export class DiscoverPageObject extends FtrService {
|
||||||
private readonly flyout = this.ctx.getService('flyout');
|
private readonly flyout = this.ctx.getService('flyout');
|
||||||
private readonly header = this.ctx.getPageObject('header');
|
private readonly header = this.ctx.getPageObject('header');
|
||||||
private readonly unifiedSearch = this.ctx.getPageObject('unifiedSearch');
|
private readonly unifiedSearch = this.ctx.getPageObject('unifiedSearch');
|
||||||
|
private readonly unifiedFieldList = this.ctx.getPageObject('unifiedFieldList');
|
||||||
private readonly browser = this.ctx.getService('browser');
|
private readonly browser = this.ctx.getService('browser');
|
||||||
private readonly globalNav = this.ctx.getService('globalNav');
|
private readonly globalNav = this.ctx.getService('globalNav');
|
||||||
private readonly elasticChart = this.ctx.getService('elasticChart');
|
private readonly elasticChart = this.ctx.getService('elasticChart');
|
||||||
|
@ -45,16 +44,6 @@ export class DiscoverPageObject extends FtrService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async findFieldByName(name: string) {
|
|
||||||
const fieldSearch = await this.testSubjects.find('fieldListFiltersFieldSearch');
|
|
||||||
await fieldSearch.type(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clearFieldSearchInput() {
|
|
||||||
const fieldSearch = await this.testSubjects.find('fieldListFiltersFieldSearch');
|
|
||||||
await fieldSearch.clearValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async saveSearch(
|
public async saveSearch(
|
||||||
searchName: string,
|
searchName: string,
|
||||||
saveAsNew?: boolean,
|
saveAsNew?: boolean,
|
||||||
|
@ -391,24 +380,16 @@ export class DiscoverPageObject extends FtrService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getAllFieldNames() {
|
|
||||||
const sidebar = await this.testSubjects.find('discover-sidebar');
|
|
||||||
const $ = await sidebar.parseDomContent();
|
|
||||||
return $('.kbnFieldButton__name')
|
|
||||||
.toArray()
|
|
||||||
.map((field) => $(field).text());
|
|
||||||
}
|
|
||||||
|
|
||||||
public async editField(field: string) {
|
public async editField(field: string) {
|
||||||
await this.retry.try(async () => {
|
await this.retry.try(async () => {
|
||||||
await this.clickFieldListItem(field);
|
await this.unifiedFieldList.clickFieldListItem(field);
|
||||||
await this.testSubjects.click(`discoverFieldListPanelEdit-${field}`);
|
await this.testSubjects.click(`discoverFieldListPanelEdit-${field}`);
|
||||||
await this.find.byClassName('indexPatternFieldEditor__form');
|
await this.find.byClassName('indexPatternFieldEditor__form');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async removeField(field: string) {
|
public async removeField(field: string) {
|
||||||
await this.clickFieldListItem(field);
|
await this.unifiedFieldList.clickFieldListItem(field);
|
||||||
await this.testSubjects.click(`discoverFieldListPanelDelete-${field}`);
|
await this.testSubjects.click(`discoverFieldListPanelDelete-${field}`);
|
||||||
await this.retry.waitFor('modal to open', async () => {
|
await this.retry.waitFor('modal to open', async () => {
|
||||||
return await this.testSubjects.exists('runtimeFieldDeleteConfirmModal');
|
return await this.testSubjects.exists('runtimeFieldDeleteConfirmModal');
|
||||||
|
@ -485,71 +466,6 @@ export class DiscoverPageObject extends FtrService {
|
||||||
return await this.testSubjects.click('discoverNoResultsViewAllMatches');
|
return await this.testSubjects.click('discoverNoResultsViewAllMatches');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getSidebarAriaDescription(): Promise<string> {
|
|
||||||
return await (
|
|
||||||
await this.testSubjects.find('fieldListGrouped__ariaDescription')
|
|
||||||
).getAttribute('innerText');
|
|
||||||
}
|
|
||||||
|
|
||||||
public async cleanSidebarLocalStorage(): Promise<void> {
|
|
||||||
await this.browser.setLocalStorageItem('discover.unifiedFieldList.initiallyOpenSections', '{}');
|
|
||||||
}
|
|
||||||
|
|
||||||
public async waitUntilSidebarHasLoaded() {
|
|
||||||
await this.retry.waitFor('sidebar is loaded', async () => {
|
|
||||||
return (await this.getSidebarAriaDescription()).length > 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async doesSidebarShowFields() {
|
|
||||||
return await this.testSubjects.exists('fieldListGroupedFieldGroups');
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSidebarSectionSelector(
|
|
||||||
sectionName: SidebarSectionName,
|
|
||||||
asCSSSelector: boolean = false
|
|
||||||
) {
|
|
||||||
const testSubj = `fieldListGrouped${sectionName[0].toUpperCase()}${sectionName.substring(
|
|
||||||
1
|
|
||||||
)}Fields`;
|
|
||||||
if (!asCSSSelector) {
|
|
||||||
return testSubj;
|
|
||||||
}
|
|
||||||
return `[data-test-subj="${testSubj}"]`;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getSidebarSectionFieldNames(sectionName: SidebarSectionName): Promise<string[]> {
|
|
||||||
const elements = await this.find.allByCssSelector(
|
|
||||||
`${this.getSidebarSectionSelector(sectionName, true)} li`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!elements?.length) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.all(
|
|
||||||
elements.map(async (element) => await element.getAttribute('data-attr-field'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async toggleSidebarSection(sectionName: SidebarSectionName) {
|
|
||||||
return await this.find.clickByCssSelector(
|
|
||||||
`${this.getSidebarSectionSelector(sectionName, true)} .euiAccordion__iconButton`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async waitUntilFieldPopoverIsOpen() {
|
|
||||||
await this.retry.waitFor('popover is open', async () => {
|
|
||||||
return Boolean(await this.find.byCssSelector('[data-popover-open="true"]'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clickFieldListItem(field: string) {
|
|
||||||
await this.testSubjects.click(`field-${field}`);
|
|
||||||
|
|
||||||
await this.waitUntilFieldPopoverIsOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clickFieldSort(field: string, text = 'Sort New-Old') {
|
public async clickFieldSort(field: string, text = 'Sort New-Old') {
|
||||||
const isLegacyDefault = await this.useLegacyTable();
|
const isLegacyDefault = await this.useLegacyTable();
|
||||||
if (isLegacyDefault) {
|
if (isLegacyDefault) {
|
||||||
|
@ -558,110 +474,12 @@ export class DiscoverPageObject extends FtrService {
|
||||||
return await this.dataGrid.clickDocSortAsc(field, text);
|
return await this.dataGrid.clickDocSortAsc(field, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async clickFieldListItemToggle(field: string) {
|
|
||||||
await this.testSubjects.moveMouseTo(`field-${field}`);
|
|
||||||
await this.testSubjects.click(`fieldToggle-${field}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clickFieldListItemAdd(field: string) {
|
|
||||||
await this.waitUntilSidebarHasLoaded();
|
|
||||||
|
|
||||||
// a filter check may make sense here, but it should be properly handled to make
|
|
||||||
// it work with the _score and _source fields as well
|
|
||||||
if (await this.isFieldSelected(field)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (['_score', '_id', '_index'].includes(field)) {
|
|
||||||
await this.toggleSidebarSection('meta'); // expand Meta section
|
|
||||||
}
|
|
||||||
await this.clickFieldListItemToggle(field);
|
|
||||||
const isLegacyDefault = await this.useLegacyTable();
|
|
||||||
if (isLegacyDefault) {
|
|
||||||
await this.retry.waitFor(`field ${field} to be added to classic table`, async () => {
|
|
||||||
return await this.testSubjects.exists(`docTableHeader-${field}`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await this.retry.waitFor(`field ${field} to be added to new table`, async () => {
|
|
||||||
return await this.testSubjects.exists(`dataGridHeaderCell-${field}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async isAdHocDataViewSelected() {
|
public async isAdHocDataViewSelected() {
|
||||||
const dataView = await this.getCurrentlySelectedDataView();
|
const dataView = await this.getCurrentlySelectedDataView();
|
||||||
await this.testSubjects.click('discover-dataView-switch-link');
|
await this.testSubjects.click('discover-dataView-switch-link');
|
||||||
return this.testSubjects.exists(`dataViewItemTempBadge-${dataView}`);
|
return this.testSubjects.exists(`dataViewItemTempBadge-${dataView}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async isFieldSelected(field: string) {
|
|
||||||
if (!(await this.testSubjects.exists('fieldListGroupedSelectedFields'))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const selectedList = await this.testSubjects.find('fieldListGroupedSelectedFields');
|
|
||||||
return await this.testSubjects.descendantExists(`field-${field}`, selectedList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clickFieldListItemRemove(field: string) {
|
|
||||||
await this.waitUntilSidebarHasLoaded();
|
|
||||||
|
|
||||||
if (
|
|
||||||
!(await this.testSubjects.exists('fieldListGroupedSelectedFields')) ||
|
|
||||||
!(await this.isFieldSelected(field))
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.clickFieldListItemToggle(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clickFieldListItemVisualize(fieldName: string) {
|
|
||||||
await this.waitUntilSidebarHasLoaded();
|
|
||||||
|
|
||||||
const field = await this.testSubjects.find(`field-${fieldName}-showDetails`);
|
|
||||||
const isActive = await field.elementHasClass('kbnFieldButton-isActive');
|
|
||||||
|
|
||||||
if (!isActive) {
|
|
||||||
// expand the field to show the "Visualize" button
|
|
||||||
await field.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.waitUntilFieldPopoverIsOpen();
|
|
||||||
const visualizeButtonTestSubject = `fieldVisualize-${fieldName}`;
|
|
||||||
// wrap visualize button click in retry to ensure button is clicked and retry if button click is not registered
|
|
||||||
await this.retry.try(async () => {
|
|
||||||
await this.testSubjects.click(visualizeButtonTestSubject);
|
|
||||||
await this.testSubjects.waitForDeleted(visualizeButtonTestSubject);
|
|
||||||
await this.testSubjects.missingOrFail(visualizeButtonTestSubject);
|
|
||||||
});
|
|
||||||
await this.header.waitUntilLoadingHasFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async expectFieldListItemVisualize(field: string) {
|
|
||||||
await this.testSubjects.existOrFail(`fieldVisualize-${field}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async expectMissingFieldListItemVisualize(field: string) {
|
|
||||||
await this.testSubjects.missingOrFail(`fieldVisualize-${field}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clickFieldListPlusFilter(field: string, value: string) {
|
|
||||||
const plusFilterTestSubj = `plus-${field}-${value}`;
|
|
||||||
if (!(await this.testSubjects.exists(plusFilterTestSubj))) {
|
|
||||||
// field has to be open
|
|
||||||
await this.clickFieldListItem(field);
|
|
||||||
}
|
|
||||||
// this.testSubjects.find doesn't handle spaces in the data-test-subj value
|
|
||||||
await this.testSubjects.click(plusFilterTestSubj);
|
|
||||||
await this.header.waitUntilLoadingHasFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async clickFieldListMinusFilter(field: string, value: string) {
|
|
||||||
// this method requires the field details to be open from clickFieldListItem()
|
|
||||||
// this.testSubjects.find doesn't handle spaces in the data-test-subj value
|
|
||||||
await this.testSubjects.click(`minus-${field}-${value}`);
|
|
||||||
await this.header.waitUntilLoadingHasFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async selectIndexPattern(indexPattern: string) {
|
public async selectIndexPattern(indexPattern: string) {
|
||||||
await this.testSubjects.click('discover-dataView-switch-link');
|
await this.testSubjects.click('discover-dataView-switch-link');
|
||||||
await this.find.setValue('[data-test-subj="indexPattern-switcher"] input', indexPattern);
|
await this.find.setValue('[data-test-subj="indexPattern-switcher"] input', indexPattern);
|
||||||
|
@ -698,19 +516,6 @@ export class DiscoverPageObject extends FtrService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async openSidebarFieldFilter() {
|
|
||||||
await this.testSubjects.click('fieldListFiltersFieldTypeFilterToggle');
|
|
||||||
await this.testSubjects.existOrFail('fieldListFiltersFieldTypeFilterOptions');
|
|
||||||
}
|
|
||||||
|
|
||||||
public async closeSidebarFieldFilter() {
|
|
||||||
await this.testSubjects.click('fieldListFiltersFieldTypeFilterToggle');
|
|
||||||
|
|
||||||
await this.retry.waitFor('sidebar filter closed', async () => {
|
|
||||||
return !(await this.testSubjects.exists('fieldListFiltersFieldTypeFilterOptions'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async waitForChartLoadingComplete(renderCount: number) {
|
public async waitForChartLoadingComplete(renderCount: number) {
|
||||||
await this.elasticChart.waitForRenderingCount(renderCount, 'unifiedHistogramChart');
|
await this.elasticChart.waitForRenderingCount(renderCount, 'unifiedHistogramChart');
|
||||||
}
|
}
|
||||||
|
@ -886,7 +691,7 @@ export class DiscoverPageObject extends FtrService {
|
||||||
* @param fieldName
|
* @param fieldName
|
||||||
* */
|
* */
|
||||||
public async dragFieldToTable(fieldName: string) {
|
public async dragFieldToTable(fieldName: string) {
|
||||||
await this.waitUntilSidebarHasLoaded();
|
await this.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
const from = `dscFieldListPanelField-${fieldName}`;
|
const from = `dscFieldListPanelField-${fieldName}`;
|
||||||
await this.find.existsByCssSelector(from);
|
await this.find.existsByCssSelector(from);
|
||||||
|
|
|
@ -32,6 +32,7 @@ import { LegacyDataTableVisPageObject } from './legacy/data_table_vis';
|
||||||
import { IndexPatternFieldEditorPageObject } from './management/indexpattern_field_editor_page';
|
import { IndexPatternFieldEditorPageObject } from './management/indexpattern_field_editor_page';
|
||||||
import { DashboardPageControls } from './dashboard_page_controls';
|
import { DashboardPageControls } from './dashboard_page_controls';
|
||||||
import { UnifiedSearchPageObject } from './unified_search_page';
|
import { UnifiedSearchPageObject } from './unified_search_page';
|
||||||
|
import { UnifiedFieldListPageObject } from './unified_field_list';
|
||||||
import { FilesManagementPageObject } from './files_management';
|
import { FilesManagementPageObject } from './files_management';
|
||||||
|
|
||||||
export const pageObjects = {
|
export const pageObjects = {
|
||||||
|
@ -61,5 +62,6 @@ export const pageObjects = {
|
||||||
savedObjects: SavedObjectsPageObject,
|
savedObjects: SavedObjectsPageObject,
|
||||||
indexPatternFieldEditorObjects: IndexPatternFieldEditorPageObject,
|
indexPatternFieldEditorObjects: IndexPatternFieldEditorPageObject,
|
||||||
unifiedSearch: UnifiedSearchPageObject,
|
unifiedSearch: UnifiedSearchPageObject,
|
||||||
|
unifiedFieldList: UnifiedFieldListPageObject,
|
||||||
filesManagement: FilesManagementPageObject,
|
filesManagement: FilesManagementPageObject,
|
||||||
};
|
};
|
||||||
|
|
254
test/functional/page_objects/unified_field_list.ts
Normal file
254
test/functional/page_objects/unified_field_list.ts
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License
|
||||||
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||||
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||||
|
* Side Public License, v 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { FtrService } from '../ftr_provider_context';
|
||||||
|
|
||||||
|
type SidebarSectionName = 'meta' | 'empty' | 'available' | 'unmapped' | 'popular' | 'selected';
|
||||||
|
|
||||||
|
export class UnifiedFieldListPageObject extends FtrService {
|
||||||
|
private readonly retry = this.ctx.getService('retry');
|
||||||
|
private readonly testSubjects = this.ctx.getService('testSubjects');
|
||||||
|
private readonly find = this.ctx.getService('find');
|
||||||
|
private readonly header = this.ctx.getPageObject('header');
|
||||||
|
private readonly browser = this.ctx.getService('browser');
|
||||||
|
|
||||||
|
public async findFieldByName(name: string) {
|
||||||
|
const fieldSearch = await this.testSubjects.find('fieldListFiltersFieldSearch');
|
||||||
|
await fieldSearch.type(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clearFieldSearchInput() {
|
||||||
|
const fieldSearch = await this.testSubjects.find('fieldListFiltersFieldSearch');
|
||||||
|
await fieldSearch.clearValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getAllFieldNames() {
|
||||||
|
const sidebar = await this.testSubjects.find('fieldListGroupedFieldGroups');
|
||||||
|
const $ = await sidebar.parseDomContent();
|
||||||
|
return $('.kbnFieldButton__name')
|
||||||
|
.toArray()
|
||||||
|
.map((field) => $(field).text());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getSidebarAriaDescription(): Promise<string> {
|
||||||
|
return await (
|
||||||
|
await this.testSubjects.find('fieldListGrouped__ariaDescription')
|
||||||
|
).getAttribute('innerText');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async cleanSidebarLocalStorage(): Promise<void> {
|
||||||
|
await this.browser.setLocalStorageItem('discover.unifiedFieldList.initiallyOpenSections', '{}');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async waitUntilSidebarHasLoaded() {
|
||||||
|
await this.retry.waitFor('sidebar is loaded', async () => {
|
||||||
|
return (await this.getSidebarAriaDescription()).length > 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async doesSidebarShowFields() {
|
||||||
|
return await this.testSubjects.exists('fieldListGroupedFieldGroups');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSidebarSectionSelector(
|
||||||
|
sectionName: SidebarSectionName,
|
||||||
|
asCSSSelector: boolean = false
|
||||||
|
) {
|
||||||
|
const testSubj = `fieldListGrouped${sectionName[0].toUpperCase()}${sectionName.substring(
|
||||||
|
1
|
||||||
|
)}Fields`;
|
||||||
|
if (!asCSSSelector) {
|
||||||
|
return testSubj;
|
||||||
|
}
|
||||||
|
return `[data-test-subj="${testSubj}"]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getSidebarSectionFieldNames(sectionName: SidebarSectionName): Promise<string[]> {
|
||||||
|
const elements = await this.find.allByCssSelector(
|
||||||
|
`${this.getSidebarSectionSelector(sectionName, true)} li`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!elements?.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
elements.map(async (element) => await element.getAttribute('data-attr-field'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async toggleSidebarSection(sectionName: SidebarSectionName) {
|
||||||
|
return await this.find.clickByCssSelector(
|
||||||
|
`${this.getSidebarSectionSelector(sectionName, true)} .euiAccordion__iconButton`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async waitUntilFieldPopoverIsOpen() {
|
||||||
|
await this.retry.waitFor('popover is open', async () => {
|
||||||
|
return Boolean(await this.find.byCssSelector('[data-popover-open="true"]'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clickFieldListItem(field: string) {
|
||||||
|
await this.testSubjects.click(`field-${field}`);
|
||||||
|
|
||||||
|
await this.waitUntilFieldPopoverIsOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clickFieldListItemToggle(field: string) {
|
||||||
|
await this.testSubjects.moveMouseTo(`field-${field}`);
|
||||||
|
await this.testSubjects.click(`fieldToggle-${field}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clickFieldListItemAdd(field: string) {
|
||||||
|
await this.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
|
// a filter check may make sense here, but it should be properly handled to make
|
||||||
|
// it work with the _score and _source fields as well
|
||||||
|
if (await this.isFieldSelected(field)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (['_score', '_id', '_index'].includes(field)) {
|
||||||
|
await this.toggleSidebarSection('meta'); // expand Meta section
|
||||||
|
}
|
||||||
|
await this.clickFieldListItemToggle(field);
|
||||||
|
await this.retry.waitFor('field is selected', async () => {
|
||||||
|
return await this.isFieldSelected(field);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async isFieldSelected(field: string) {
|
||||||
|
if (!(await this.testSubjects.exists('fieldListGroupedSelectedFields'))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const selectedList = await this.testSubjects.find('fieldListGroupedSelectedFields');
|
||||||
|
return await this.testSubjects.descendantExists(`field-${field}`, selectedList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clickFieldListItemRemove(field: string) {
|
||||||
|
await this.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(await this.testSubjects.exists('fieldListGroupedSelectedFields')) ||
|
||||||
|
!(await this.isFieldSelected(field))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.clickFieldListItemToggle(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clickFieldListItemVisualize(fieldName: string) {
|
||||||
|
await this.waitUntilSidebarHasLoaded();
|
||||||
|
|
||||||
|
const field = await this.testSubjects.find(`field-${fieldName}-showDetails`);
|
||||||
|
const isActive = await field.elementHasClass('kbnFieldButton-isActive');
|
||||||
|
|
||||||
|
if (!isActive) {
|
||||||
|
// expand the field to show the "Visualize" button
|
||||||
|
await field.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.waitUntilFieldPopoverIsOpen();
|
||||||
|
const visualizeButtonTestSubject = `fieldVisualize-${fieldName}`;
|
||||||
|
// wrap visualize button click in retry to ensure button is clicked and retry if button click is not registered
|
||||||
|
await this.retry.try(async () => {
|
||||||
|
await this.testSubjects.click(visualizeButtonTestSubject);
|
||||||
|
await this.testSubjects.waitForDeleted(visualizeButtonTestSubject);
|
||||||
|
await this.testSubjects.missingOrFail(visualizeButtonTestSubject);
|
||||||
|
});
|
||||||
|
await this.header.waitUntilLoadingHasFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async expectFieldListItemVisualize(field: string) {
|
||||||
|
await this.testSubjects.existOrFail(`fieldVisualize-${field}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async expectMissingFieldListItemVisualize(field: string) {
|
||||||
|
await this.testSubjects.missingOrFail(`fieldVisualize-${field}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clickFieldListPlusFilter(field: string, value: string) {
|
||||||
|
const plusFilterTestSubj = `plus-${field}-${value}`;
|
||||||
|
if (!(await this.testSubjects.exists(plusFilterTestSubj))) {
|
||||||
|
// field has to be open
|
||||||
|
await this.clickFieldListItem(field);
|
||||||
|
}
|
||||||
|
// this.testSubjects.find doesn't handle spaces in the data-test-subj value
|
||||||
|
await this.testSubjects.click(plusFilterTestSubj);
|
||||||
|
await this.header.waitUntilLoadingHasFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clickFieldListMinusFilter(field: string, value: string) {
|
||||||
|
// this method requires the field details to be open from clickFieldListItem()
|
||||||
|
// this.testSubjects.find doesn't handle spaces in the data-test-subj value
|
||||||
|
await this.testSubjects.click(`minus-${field}-${value}`);
|
||||||
|
await this.header.waitUntilLoadingHasFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async openSidebarFieldFilter() {
|
||||||
|
await this.testSubjects.click('fieldListFiltersFieldTypeFilterToggle');
|
||||||
|
await this.testSubjects.existOrFail('fieldListFiltersFieldTypeFilterOptions');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async closeSidebarFieldFilter() {
|
||||||
|
await this.testSubjects.click('fieldListFiltersFieldTypeFilterToggle');
|
||||||
|
|
||||||
|
await this.retry.waitFor('sidebar filter closed', async () => {
|
||||||
|
return !(await this.testSubjects.exists('fieldListFiltersFieldTypeFilterOptions'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getFieldStatsViewType(): Promise<
|
||||||
|
| 'topValuesAndDistribution'
|
||||||
|
| 'histogram'
|
||||||
|
| 'topValues'
|
||||||
|
| 'timeDistribution'
|
||||||
|
| 'exampleValues'
|
||||||
|
| 'unknown'
|
||||||
|
> {
|
||||||
|
if (await this.testSubjects.exists('unifiedFieldStats-buttonGroup')) {
|
||||||
|
return 'topValuesAndDistribution';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await this.testSubjects.exists('unifiedFieldStats-timeDistribution')) {
|
||||||
|
return 'timeDistribution';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await this.testSubjects.exists('unifiedFieldStats-histogram')) {
|
||||||
|
return 'histogram';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await this.testSubjects.exists('unifiedFieldStats-topValueBuckets')) {
|
||||||
|
return 'topValues';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await this.testSubjects.exists('unifiedFieldStats-exampleValueBuckets')) {
|
||||||
|
return 'exampleValues';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getFieldStatsDocsCount() {
|
||||||
|
return parseInt(
|
||||||
|
(
|
||||||
|
await this.testSubjects.getVisibleText('unifiedFieldStats-statsFooter-docsCount')
|
||||||
|
).replaceAll(',', ''),
|
||||||
|
10
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getFieldStatsTopValueBucketsVisibleText() {
|
||||||
|
return await this.testSubjects.getVisibleText('unifiedFieldStats-topValueBuckets');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getFieldStatsExampleBucketsVisibleText() {
|
||||||
|
return await this.testSubjects.getVisibleText('unifiedFieldStats-exampleValueBuckets');
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ export class DashboardVisualizationsService extends FtrService {
|
||||||
private readonly header = this.ctx.getPageObject('header');
|
private readonly header = this.ctx.getPageObject('header');
|
||||||
private readonly discover = this.ctx.getPageObject('discover');
|
private readonly discover = this.ctx.getPageObject('discover');
|
||||||
private readonly timePicker = this.ctx.getPageObject('timePicker');
|
private readonly timePicker = this.ctx.getPageObject('timePicker');
|
||||||
|
private readonly unifiedFieldList = this.ctx.getPageObject('unifiedFieldList');
|
||||||
|
|
||||||
async createAndAddTSVBVisualization(name: string) {
|
async createAndAddTSVBVisualization(name: string) {
|
||||||
this.log.debug(`createAndAddTSVBVisualization(${name})`);
|
this.log.debug(`createAndAddTSVBVisualization(${name})`);
|
||||||
|
@ -54,7 +55,7 @@ export class DashboardVisualizationsService extends FtrService {
|
||||||
|
|
||||||
if (fields) {
|
if (fields) {
|
||||||
for (let i = 0; i < fields.length; i++) {
|
for (let i = 0; i < fields.length; i++) {
|
||||||
await this.discover.clickFieldListItemAdd(fields[i]);
|
await this.unifiedFieldList.clickFieldListItemAdd(fields[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,14 @@ import expect from '@kbn/expect';
|
||||||
import { PluginFunctionalProviderContext } from '../../services';
|
import { PluginFunctionalProviderContext } from '../../services';
|
||||||
|
|
||||||
export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) {
|
export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) {
|
||||||
const PageObjects = getPageObjects(['common', 'header', 'dashboard', 'discover', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'header',
|
||||||
|
'dashboard',
|
||||||
|
'discover',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const filterBar = getService('filterBar');
|
const filterBar = getService('filterBar');
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const toasts = getService('toasts');
|
const toasts = getService('toasts');
|
||||||
|
@ -54,7 +61,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Starts a new session on sort', async () => {
|
it('Starts a new session on sort', async () => {
|
||||||
await PageObjects.discover.clickFieldListItemAdd('speaker');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('speaker');
|
||||||
await PageObjects.discover.clickFieldSort('speaker', 'Sort A-Z');
|
await PageObjects.discover.clickFieldSort('speaker', 'Sort A-Z');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
const sessionIds = await getSessionIds();
|
const sessionIds = await getSessionIds();
|
||||||
|
|
|
@ -1390,6 +1390,8 @@
|
||||||
"@kbn/ui-shared-deps-src/*": ["packages/kbn-ui-shared-deps-src/*"],
|
"@kbn/ui-shared-deps-src/*": ["packages/kbn-ui-shared-deps-src/*"],
|
||||||
"@kbn/ui-theme": ["packages/kbn-ui-theme"],
|
"@kbn/ui-theme": ["packages/kbn-ui-theme"],
|
||||||
"@kbn/ui-theme/*": ["packages/kbn-ui-theme/*"],
|
"@kbn/ui-theme/*": ["packages/kbn-ui-theme/*"],
|
||||||
|
"@kbn/unified-field-list-examples-plugin": ["examples/unified_field_list_examples"],
|
||||||
|
"@kbn/unified-field-list-examples-plugin/*": ["examples/unified_field_list_examples/*"],
|
||||||
"@kbn/unified-field-list-plugin": ["src/plugins/unified_field_list"],
|
"@kbn/unified-field-list-plugin": ["src/plugins/unified_field_list"],
|
||||||
"@kbn/unified-field-list-plugin/*": ["src/plugins/unified_field_list/*"],
|
"@kbn/unified-field-list-plugin/*": ["src/plugins/unified_field_list/*"],
|
||||||
"@kbn/unified-histogram-plugin": ["src/plugins/unified_histogram"],
|
"@kbn/unified-histogram-plugin": ["src/plugins/unified_histogram"],
|
||||||
|
|
|
@ -27,6 +27,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
'share',
|
'share',
|
||||||
'spaceSelector',
|
'spaceSelector',
|
||||||
'header',
|
'header',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const appsMenu = getService('appsMenu');
|
const appsMenu = getService('appsMenu');
|
||||||
|
@ -234,8 +235,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
await PageObjects.common.waitForTopNavToBeVisible();
|
await PageObjects.common.waitForTopNavToBeVisible();
|
||||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||||
await setDiscoverTimeRange();
|
await setDiscoverTimeRange();
|
||||||
await PageObjects.discover.clickFieldListItem('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||||
await PageObjects.discover.expectMissingFieldListItemVisualize('bytes');
|
await PageObjects.unifiedFieldList.expectMissingFieldListItemVisualize('bytes');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`Permalinks doesn't show create short-url button`, async () => {
|
it(`Permalinks doesn't show create short-url button`, async () => {
|
||||||
|
@ -326,8 +327,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.common.waitForTopNavToBeVisible();
|
await PageObjects.common.waitForTopNavToBeVisible();
|
||||||
await setDiscoverTimeRange();
|
await setDiscoverTimeRange();
|
||||||
await PageObjects.discover.clickFieldListItem('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||||
await PageObjects.discover.expectMissingFieldListItemVisualize('bytes');
|
await PageObjects.unifiedFieldList.expectMissingFieldListItemVisualize('bytes');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Permalinks shows create short-url button', async () => {
|
it('Permalinks shows create short-url button', async () => {
|
||||||
|
@ -404,8 +405,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.common.waitForTopNavToBeVisible();
|
await PageObjects.common.waitForTopNavToBeVisible();
|
||||||
await setDiscoverTimeRange();
|
await setDiscoverTimeRange();
|
||||||
await PageObjects.discover.clickFieldListItem('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||||
await PageObjects.discover.expectFieldListItemVisualize('bytes');
|
await PageObjects.unifiedFieldList.expectFieldListItemVisualize('bytes');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
'timePicker',
|
'timePicker',
|
||||||
'security',
|
'security',
|
||||||
'spaceSelector',
|
'spaceSelector',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const testSubjects = getService('testSubjects');
|
const testSubjects = getService('testSubjects');
|
||||||
const appsMenu = getService('appsMenu');
|
const appsMenu = getService('appsMenu');
|
||||||
|
@ -84,8 +85,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
basePath: '/s/custom_space',
|
basePath: '/s/custom_space',
|
||||||
});
|
});
|
||||||
await setDiscoverTimeRange();
|
await setDiscoverTimeRange();
|
||||||
await PageObjects.discover.clickFieldListItem('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||||
await PageObjects.discover.expectFieldListItemVisualize('bytes');
|
await PageObjects.unifiedFieldList.expectFieldListItemVisualize('bytes');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -154,8 +155,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
basePath: '/s/custom_space',
|
basePath: '/s/custom_space',
|
||||||
});
|
});
|
||||||
await setDiscoverTimeRange();
|
await setDiscoverTimeRange();
|
||||||
await PageObjects.discover.clickFieldListItem('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||||
await PageObjects.discover.expectMissingFieldListItemVisualize('bytes');
|
await PageObjects.unifiedFieldList.expectMissingFieldListItemVisualize('bytes');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
'security',
|
'security',
|
||||||
'spaceSelector',
|
'spaceSelector',
|
||||||
'header',
|
'header',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const monacoEditor = getService('monacoEditor');
|
const monacoEditor = getService('monacoEditor');
|
||||||
|
|
||||||
|
@ -58,13 +59,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows "visualize" field button', async () => {
|
it('shows "visualize" field button', async () => {
|
||||||
await PageObjects.discover.clickFieldListItem('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||||
await PageObjects.discover.expectFieldListItemVisualize('bytes');
|
await PageObjects.unifiedFieldList.expectFieldListItemVisualize('bytes');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('visualizes field to Lens and loads fields to the dimesion editor', async () => {
|
it('visualizes field to Lens and loads fields to the dimesion editor', async () => {
|
||||||
await PageObjects.discover.findFieldByName('bytes');
|
await PageObjects.unifiedFieldList.findFieldByName('bytes');
|
||||||
await PageObjects.discover.clickFieldListItemVisualize('bytes');
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('bytes');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await retry.try(async () => {
|
await retry.try(async () => {
|
||||||
const dimensions = await testSubjects.findAll('lns-dimensionTrigger');
|
const dimensions = await testSubjects.findAll('lns-dimensionTrigger');
|
||||||
|
@ -79,8 +80,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
operation: 'is between',
|
operation: 'is between',
|
||||||
value: { from: '3500', to: '4000' },
|
value: { from: '3500', to: '4000' },
|
||||||
});
|
});
|
||||||
await PageObjects.discover.findFieldByName('geo.src');
|
await PageObjects.unifiedFieldList.findFieldByName('geo.src');
|
||||||
await PageObjects.discover.clickFieldListItemVisualize('geo.src');
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('geo.src');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
expect(await filterBar.hasFilter('bytes', '3,500 to 4,000')).to.be(true);
|
expect(await filterBar.hasFilter('bytes', '3,500 to 4,000')).to.be(true);
|
||||||
|
@ -89,8 +90,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||||
it('should preserve query in lens', async () => {
|
it('should preserve query in lens', async () => {
|
||||||
await queryBar.setQuery('machine.os : ios');
|
await queryBar.setQuery('machine.os : ios');
|
||||||
await queryBar.submitQuery();
|
await queryBar.submitQuery();
|
||||||
await PageObjects.discover.findFieldByName('geo.dest');
|
await PageObjects.unifiedFieldList.findFieldByName('geo.dest');
|
||||||
await PageObjects.discover.clickFieldListItemVisualize('geo.dest');
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('geo.dest');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
expect(await queryBar.getQueryString()).to.equal('machine.os : ios');
|
expect(await queryBar.getQueryString()).to.equal('machine.os : ios');
|
||||||
|
|
|
@ -19,6 +19,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'timeToVisualize',
|
'timeToVisualize',
|
||||||
'common',
|
'common',
|
||||||
'discover',
|
'discover',
|
||||||
|
'unifiedFieldList',
|
||||||
]);
|
]);
|
||||||
const elasticChart = getService('elasticChart');
|
const elasticChart = getService('elasticChart');
|
||||||
const fieldEditor = getService('fieldEditor');
|
const fieldEditor = getService('fieldEditor');
|
||||||
|
@ -218,7 +219,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
'_bytes-runtimefield',
|
'_bytes-runtimefield',
|
||||||
`emit(doc["bytes"].value.toString())`
|
`emit(doc["bytes"].value.toString())`
|
||||||
);
|
);
|
||||||
await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield');
|
await PageObjects.unifiedFieldList.clickFieldListItemToggle('_bytes-runtimefield');
|
||||||
const newDataViewId = await PageObjects.discover.getCurrentDataViewId();
|
const newDataViewId = await PageObjects.discover.getCurrentDataViewId();
|
||||||
expect(newDataViewId).not.to.equal(prevDataViewId);
|
expect(newDataViewId).not.to.equal(prevDataViewId);
|
||||||
expect(await PageObjects.unifiedSearch.isAdHocDataView()).to.be(true);
|
expect(await PageObjects.unifiedSearch.isAdHocDataView()).to.be(true);
|
||||||
|
|
|
@ -9,7 +9,14 @@ import expect from '@kbn/expect';
|
||||||
|
|
||||||
export default function ({ getService, getPageObjects }) {
|
export default function ({ getService, getPageObjects }) {
|
||||||
const queryBar = getService('queryBar');
|
const queryBar = getService('queryBar');
|
||||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'maps', 'timePicker']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'discover',
|
||||||
|
'header',
|
||||||
|
'maps',
|
||||||
|
'timePicker',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const security = getService('security');
|
const security = getService('security');
|
||||||
const from = 'Sep 22, 2015 @ 00:00:00.000';
|
const from = 'Sep 22, 2015 @ 00:00:00.000';
|
||||||
const to = 'Sep 22, 2015 @ 04:00:00.000';
|
const to = 'Sep 22, 2015 @ 04:00:00.000';
|
||||||
|
@ -34,7 +41,7 @@ export default function ({ getService, getPageObjects }) {
|
||||||
|
|
||||||
it('should link geo_shape fields to Maps application', async () => {
|
it('should link geo_shape fields to Maps application', async () => {
|
||||||
await PageObjects.discover.selectIndexPattern('geo_shapes*');
|
await PageObjects.discover.selectIndexPattern('geo_shapes*');
|
||||||
await PageObjects.discover.clickFieldListItemVisualize('geometry');
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('geometry');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.maps.waitForLayersToLoad();
|
await PageObjects.maps.waitForLayersToLoad();
|
||||||
const doesLayerExist = await PageObjects.maps.doesLayerExist('geo_shapes*');
|
const doesLayerExist = await PageObjects.maps.doesLayerExist('geo_shapes*');
|
||||||
|
@ -51,7 +58,7 @@ export default function ({ getService, getPageObjects }) {
|
||||||
await queryBar.submitQuery();
|
await queryBar.submitQuery();
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
|
|
||||||
await PageObjects.discover.clickFieldListItemVisualize('geo.coordinates');
|
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('geo.coordinates');
|
||||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||||
await PageObjects.maps.waitForLayersToLoad();
|
await PageObjects.maps.waitForLayersToLoad();
|
||||||
const doesLayerExist = await PageObjects.maps.doesLayerExist('logstash-*');
|
const doesLayerExist = await PageObjects.maps.doesLayerExist('logstash-*');
|
||||||
|
|
|
@ -10,7 +10,14 @@ import { FtrProviderContext } from '../../ftr_provider_context';
|
||||||
|
|
||||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
const esArchiver = getService('esArchiver');
|
const esArchiver = getService('esArchiver');
|
||||||
const PageObjects = getPageObjects(['common', 'visualize', 'discover', 'visChart', 'visEditor']);
|
const PageObjects = getPageObjects([
|
||||||
|
'common',
|
||||||
|
'visualize',
|
||||||
|
'discover',
|
||||||
|
'visChart',
|
||||||
|
'visEditor',
|
||||||
|
'unifiedFieldList',
|
||||||
|
]);
|
||||||
const kibanaServer = getService('kibanaServer');
|
const kibanaServer = getService('kibanaServer');
|
||||||
const log = getService('log');
|
const log = getService('log');
|
||||||
|
|
||||||
|
@ -28,7 +35,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
it('appears correctly in discover', async function () {
|
it('appears correctly in discover', async function () {
|
||||||
await PageObjects.common.navigateToApp('discover');
|
await PageObjects.common.navigateToApp('discover');
|
||||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||||
await PageObjects.discover.clickFieldListItemAdd('histogram-content');
|
await PageObjects.unifiedFieldList.clickFieldListItemAdd('histogram-content');
|
||||||
const rowData = await PageObjects.discover.getDocTableIndex(1);
|
const rowData = await PageObjects.discover.getDocTableIndex(1);
|
||||||
expect(rowData).to.contain('"values":[0.3,1,3,4.2,4.8]');
|
expect(rowData).to.contain('"values":[0.3,1,3,4.2,4.8]');
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,7 +29,7 @@ export function TransformWizardProvider({ getService, getPageObjects }: FtrProvi
|
||||||
const ml = getService('ml');
|
const ml = getService('ml');
|
||||||
const toasts = getService('toasts');
|
const toasts = getService('toasts');
|
||||||
|
|
||||||
const pageObjects = getPageObjects(['discover', 'timePicker']);
|
const pageObjects = getPageObjects(['discover', 'timePicker', 'unifiedFieldList']);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async clickNextButton() {
|
async clickNextButton() {
|
||||||
|
@ -1083,7 +1083,7 @@ export function TransformWizardProvider({ getService, getPageObjects }: FtrProvi
|
||||||
async assertDiscoverContainField(field: string) {
|
async assertDiscoverContainField(field: string) {
|
||||||
await pageObjects.discover.isDiscoverAppOnScreen();
|
await pageObjects.discover.isDiscoverAppOnScreen();
|
||||||
await retry.tryForTime(60 * 1000, async () => {
|
await retry.tryForTime(60 * 1000, async () => {
|
||||||
const allFields = await pageObjects.discover.getAllFieldNames();
|
const allFields = await pageObjects.unifiedFieldList.getAllFieldNames();
|
||||||
if (Array.isArray(allFields)) {
|
if (Array.isArray(allFields)) {
|
||||||
expect(allFields).to.contain(
|
expect(allFields).to.contain(
|
||||||
field,
|
field,
|
||||||
|
|
|
@ -5527,6 +5527,10 @@
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
uid ""
|
uid ""
|
||||||
|
|
||||||
|
"@kbn/unified-field-list-examples-plugin@link:examples/unified_field_list_examples":
|
||||||
|
version "0.0.0"
|
||||||
|
uid ""
|
||||||
|
|
||||||
"@kbn/unified-field-list-plugin@link:src/plugins/unified_field_list":
|
"@kbn/unified-field-list-plugin@link:src/plugins/unified_field_list":
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
uid ""
|
uid ""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue