mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -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-src @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_histogram @elastic/kibana-data-discovery
|
||||
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.
|
||||
*/
|
||||
|
||||
export const BASE_API_PATH = '/internal/unified_field_list';
|
||||
export const FIELD_STATS_API_PATH = `${BASE_API_PATH}/field_stats`;
|
||||
export const FIELD_EXISTING_API_PATH = `${BASE_API_PATH}/existing_fields/{dataViewId}`;
|
||||
export const PLUGIN_ID = 'unifiedFieldListExamples';
|
||||
export const PLUGIN_NAME = 'Unified Field List Examples';
|
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-src": "link:packages/kbn-ui-shared-deps-src",
|
||||
"@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-histogram-plugin": "link:src/plugins/unified_histogram",
|
||||
"@kbn/unified-search-plugin": "link:src/plugins/unified_search",
|
||||
|
|
|
@ -39,30 +39,25 @@ function getCommonFieldItemButtonProps({
|
|||
}: GetCommonFieldItemButtonPropsParams): {
|
||||
field: FieldItemButtonProps<DataViewField>['field'];
|
||||
isSelected: FieldItemButtonProps<DataViewField>['isSelected'];
|
||||
dataTestSubj: FieldItemButtonProps<DataViewField>['dataTestSubj'];
|
||||
buttonAddFieldToWorkspaceProps: FieldItemButtonProps<DataViewField>['buttonAddFieldToWorkspaceProps'];
|
||||
buttonRemoveFieldFromWorkspaceProps: FieldItemButtonProps<DataViewField>['buttonRemoveFieldFromWorkspaceProps'];
|
||||
onAddFieldToWorkspace: FieldItemButtonProps<DataViewField>['onAddFieldToWorkspace'];
|
||||
onRemoveFieldFromWorkspace: FieldItemButtonProps<DataViewField>['onRemoveFieldFromWorkspace'];
|
||||
} {
|
||||
const dataTestSubj = `fieldToggle-${field.name}`;
|
||||
const handler =
|
||||
field.name === '_source' ? undefined : (f: DataViewField) => toggleDisplay(f, isSelected);
|
||||
return {
|
||||
field,
|
||||
isSelected,
|
||||
dataTestSubj: `field-${field.name}-showDetails`,
|
||||
buttonAddFieldToWorkspaceProps: {
|
||||
'aria-label': i18n.translate('discover.fieldChooser.discoverField.addFieldTooltip', {
|
||||
defaultMessage: 'Add field as column',
|
||||
}),
|
||||
'data-test-subj': dataTestSubj,
|
||||
},
|
||||
buttonRemoveFieldFromWorkspaceProps: {
|
||||
'aria-label': i18n.translate('discover.fieldChooser.discoverField.removeFieldTooltip', {
|
||||
defaultMessage: 'Remove field from table',
|
||||
}),
|
||||
'data-test-subj': dataTestSubj,
|
||||
},
|
||||
onAddFieldToWorkspace: handler,
|
||||
onRemoveFieldFromWorkspace: handler,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"description": "Contains functionality for the field list which can be integrated into apps",
|
||||
"plugin": {
|
||||
"id": "unifiedFieldList",
|
||||
"server": true,
|
||||
"server": false,
|
||||
"browser": true,
|
||||
"requiredPlugins": [
|
||||
"dataViews",
|
||||
|
|
|
@ -8,6 +8,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly 1`] = `
|
|||
}
|
||||
}
|
||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
||||
dataTestSubj="field-bytes-showDetails"
|
||||
fieldIcon={
|
||||
<WrappedFieldIcon
|
||||
scripted={false}
|
||||
|
@ -38,6 +39,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly for Records (Lens
|
|||
}
|
||||
}
|
||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--document unifiedFieldListItemButton--exists"
|
||||
dataTestSubj="field-___records___-showDetails"
|
||||
fieldIcon={
|
||||
<WrappedFieldIcon
|
||||
scripted={false}
|
||||
|
@ -68,6 +70,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly for text-based co
|
|||
}
|
||||
}
|
||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--string unifiedFieldListItemButton--exists"
|
||||
dataTestSubj="field-agent-showDetails"
|
||||
fieldIcon={
|
||||
<WrappedFieldIcon
|
||||
type="string"
|
||||
|
@ -96,6 +99,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly for wildcard sear
|
|||
}
|
||||
}
|
||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--date unifiedFieldListItemButton--exists"
|
||||
dataTestSubj="field-script date-showDetails"
|
||||
fieldIcon={
|
||||
<WrappedFieldIcon
|
||||
scripted={true}
|
||||
|
@ -125,6 +129,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly when a conflict f
|
|||
}
|
||||
}
|
||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--conflict unifiedFieldListItemButton--exists"
|
||||
dataTestSubj="field-custom_user_field-showDetails"
|
||||
fieldIcon={
|
||||
<WrappedFieldIcon
|
||||
scripted={false}
|
||||
|
@ -156,6 +161,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly when empty 1`] =
|
|||
}
|
||||
}
|
||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--date unifiedFieldListItemButton--missing"
|
||||
dataTestSubj="field-script date-showDetails"
|
||||
fieldIcon={
|
||||
<WrappedFieldIcon
|
||||
scripted={true}
|
||||
|
@ -221,6 +227,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly with an action wh
|
|||
}
|
||||
}
|
||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
||||
dataTestSubj="field-bytes-showDetails"
|
||||
fieldAction={
|
||||
<EuiToolTip
|
||||
content="Add \\"bytes\\" field"
|
||||
|
@ -232,7 +239,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly with an action wh
|
|||
aria-label="Add \\"bytes\\" field"
|
||||
className="unifiedFieldListItemButton__action unifiedFieldListItemButton__action--always"
|
||||
color="text"
|
||||
data-test-subj="unifiedFieldListItem_addField-bytes"
|
||||
data-test-subj="fieldToggle-bytes"
|
||||
iconType="plusInCircle"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
|
@ -267,6 +274,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly with an action wh
|
|||
}
|
||||
}
|
||||
className="unifiedFieldListItemButton unifiedFieldListItemButton--number unifiedFieldListItemButton--exists"
|
||||
dataTestSubj="field-bytes-showDetails"
|
||||
fieldAction={
|
||||
<EuiToolTip
|
||||
content="Remove \\"bytes\\" field"
|
||||
|
@ -278,7 +286,7 @@ exports[`UnifiedFieldList <FieldItemButton /> renders properly with an action wh
|
|||
aria-label="Remove \\"bytes\\" field"
|
||||
className="unifiedFieldListItemButton__action"
|
||||
color="danger"
|
||||
data-test-subj="unifiedFieldListItem_removeField-bytes"
|
||||
data-test-subj="fieldToggle-bytes"
|
||||
iconType="cross"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
|
|
|
@ -136,7 +136,7 @@ export function FieldItemButton<T extends FieldListItem = DataViewField>({
|
|||
content={removeFieldFromWorkspaceTooltip}
|
||||
>
|
||||
<EuiButtonIcon
|
||||
data-test-subj={`unifiedFieldListItem_removeField-${field.name}`}
|
||||
data-test-subj={`fieldToggle-${field.name}`}
|
||||
aria-label={removeFieldFromWorkspaceTooltip}
|
||||
{...(buttonRemoveFieldFromWorkspaceProps || {})}
|
||||
className={classnames(
|
||||
|
@ -159,7 +159,7 @@ export function FieldItemButton<T extends FieldListItem = DataViewField>({
|
|||
content={addFieldToWorkspaceTooltip}
|
||||
>
|
||||
<EuiButtonIcon
|
||||
data-test-subj={`unifiedFieldListItem_addField-${field.name}`}
|
||||
data-test-subj={`fieldToggle-${field.name}`}
|
||||
aria-label={addFieldToWorkspaceTooltip}
|
||||
{...(buttonAddFieldToWorkspaceProps || {})}
|
||||
className={classnames(fieldActionClassName, buttonAddFieldToWorkspaceProps?.className)}
|
||||
|
@ -179,7 +179,7 @@ export function FieldItemButton<T extends FieldListItem = DataViewField>({
|
|||
return (
|
||||
<FieldButton
|
||||
key={`field-item-button-${field.name}`}
|
||||
dataTestSubj={dataTestSubj}
|
||||
dataTestSubj={dataTestSubj || `field-${field.name}-showDetails`}
|
||||
size={size || 's'}
|
||||
className={classes}
|
||||
isActive={isActive}
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import classNames from 'classnames';
|
||||
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';
|
||||
|
||||
export interface FieldsAccordionProps<T extends FieldListItem> {
|
||||
|
@ -35,14 +35,7 @@ export interface FieldsAccordionProps<T extends FieldListItem> {
|
|||
groupName: FieldsGroupNames;
|
||||
fieldSearchHighlight?: string;
|
||||
paginatedFields: T[];
|
||||
renderFieldItem: (params: {
|
||||
field: T;
|
||||
hideDetails?: boolean;
|
||||
itemIndex: number;
|
||||
groupIndex: number;
|
||||
groupName: FieldsGroupNames;
|
||||
fieldSearchHighlight?: string;
|
||||
}) => JSX.Element;
|
||||
renderFieldItem: (params: RenderFieldItemParams<T>) => JSX.Element;
|
||||
renderCallout: () => JSX.Element;
|
||||
showExistenceFetchError?: 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 {
|
||||
min-width: $euiSizeXXL * 6.5;
|
||||
max-width: $euiSizeXXL * 7.5;
|
||||
min-width: $euiSizeXXL * 6.5 !important; /* 1 */
|
||||
max-width: $euiSizeXXL * 7.5 !important;
|
||||
}
|
||||
|
|
|
@ -34,13 +34,13 @@ import {
|
|||
} from '@elastic/charts';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
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 type { BucketedAggregation, NumberSummary } from '../../../common/types';
|
||||
import {
|
||||
canProvideStatsForField,
|
||||
canProvideNumberSummaryForField,
|
||||
} from '../../../common/utils/field_stats_utils';
|
||||
} from '../../services/field_stats/field_stats_utils';
|
||||
import { loadFieldStats } from '../../services/field_stats';
|
||||
import type { AddFieldFilterHandler } from '../../types';
|
||||
import {
|
||||
|
@ -284,6 +284,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
|||
let title = <></>;
|
||||
|
||||
function combineWithTitleAndFooter(el: React.ReactElement) {
|
||||
const dataTestSubjDocsCount = 'unifiedFieldStats-statsFooter-docsCount';
|
||||
const countsElement = totalDocuments ? (
|
||||
<EuiText color="subdued" size="xs" data-test-subj={`${dataTestSubject}-statsFooter`}>
|
||||
{sampledDocuments && sampledDocuments < totalDocuments ? (
|
||||
|
@ -293,7 +294,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
|||
values={{
|
||||
sampledDocuments,
|
||||
sampledDocumentsFormatted: (
|
||||
<strong>
|
||||
<strong data-test-subj={dataTestSubjDocsCount}>
|
||||
{fieldFormats
|
||||
.getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER])
|
||||
.convert(sampledDocuments)}
|
||||
|
@ -308,7 +309,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
|||
values={{
|
||||
totalDocuments,
|
||||
totalDocumentsFormatted: (
|
||||
<strong>
|
||||
<strong data-test-subj={dataTestSubjDocsCount}>
|
||||
{fieldFormats
|
||||
.getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER])
|
||||
.convert(totalDocuments)}
|
||||
|
@ -418,6 +419,7 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
|||
title = (
|
||||
<>
|
||||
<EuiButtonGroup
|
||||
data-test-subj="unifiedFieldStats-buttonGroup"
|
||||
buttonSize="compressed"
|
||||
isFullWidth
|
||||
legend={i18n.translate('unifiedFieldList.fieldStats.displayToggleLegend', {
|
||||
|
@ -480,34 +482,71 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
|||
|
||||
if (field.type === 'date') {
|
||||
return combineWithTitleAndFooter(
|
||||
<div data-test-subj={`${dataTestSubject}-histogram`}>
|
||||
<Chart size={{ height: 200, width: 300 - 32 }}>
|
||||
<div data-test-subj="unifiedFieldStats-timeDistribution">
|
||||
<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
|
||||
rotation={90}
|
||||
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
|
||||
}
|
||||
position={Position.Left}
|
||||
showOverlappingTicks={true}
|
||||
tickFormat={(d) => formatter.convert(d)}
|
||||
/>
|
||||
|
||||
<HistogramBarSeries
|
||||
|
@ -515,51 +554,19 @@ const FieldStatsComponent: React.FC<FieldStatsProps> = ({
|
|||
id={specId}
|
||||
xAccessor={'key'}
|
||||
yAccessors={['count']}
|
||||
xScaleType={ScaleType.Time}
|
||||
xScaleType={ScaleType.Linear}
|
||||
yScaleType={ScaleType.Linear}
|
||||
timeZone="local"
|
||||
/>
|
||||
</Chart>
|
||||
</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) {
|
||||
return combineWithTitleAndFooter(
|
||||
<FieldTopValues
|
||||
areExamples={showExamplesForField(field)}
|
||||
buckets={topValues.buckets}
|
||||
dataView={dataView}
|
||||
field={field}
|
||||
|
|
|
@ -44,6 +44,7 @@ describe('UnifiedFieldList <FieldTopValues />', () => {
|
|||
} as unknown as DataView;
|
||||
|
||||
defaultProps = {
|
||||
areExamples: false,
|
||||
dataView,
|
||||
field: dataView.fields.find((f) => f.name === 'source')!,
|
||||
sampledValuesCount: 5000,
|
||||
|
|
|
@ -15,6 +15,7 @@ import FieldTopValuesBucket from './field_top_values_bucket';
|
|||
import type { OverrideFieldTopValueBarCallback } from './field_top_values_bucket';
|
||||
|
||||
export interface FieldTopValuesProps {
|
||||
areExamples: boolean; // real top values or only examples
|
||||
buckets: BucketedAggregation<number | string>['buckets'];
|
||||
dataView: DataView;
|
||||
field: DataViewField;
|
||||
|
@ -26,6 +27,7 @@ export interface FieldTopValuesProps {
|
|||
}
|
||||
|
||||
export const FieldTopValues: React.FC<FieldTopValuesProps> = ({
|
||||
areExamples,
|
||||
buckets,
|
||||
dataView,
|
||||
field,
|
||||
|
@ -46,54 +48,60 @@ export const FieldTopValues: React.FC<FieldTopValuesProps> = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<div data-test-subj={`${dataTestSubject}-topValues`}>
|
||||
{buckets.map((bucket, index) => {
|
||||
const fieldValue = bucket.key;
|
||||
const formatted = formatter.convert(fieldValue);
|
||||
<div
|
||||
data-test-subj={
|
||||
areExamples ? 'unifiedFieldStats-exampleValueBuckets' : 'unifiedFieldStats-topValueBuckets'
|
||||
}
|
||||
>
|
||||
<div data-test-subj={`${dataTestSubject}-topValues`}>
|
||||
{buckets.map((bucket, index) => {
|
||||
const fieldValue = bucket.key;
|
||||
const formatted = formatter.convert(fieldValue);
|
||||
|
||||
return (
|
||||
<Fragment key={fieldValue}>
|
||||
{index > 0 && <EuiSpacer size="s" />}
|
||||
return (
|
||||
<Fragment key={fieldValue}>
|
||||
{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
|
||||
type="other"
|
||||
field={field}
|
||||
fieldValue={fieldValue}
|
||||
formattedFieldValue={formatted}
|
||||
fieldValue={undefined}
|
||||
formattedPercentage={getFormattedPercentageValue(
|
||||
bucket.count,
|
||||
otherCount,
|
||||
sampledValuesCount,
|
||||
digitsRequired
|
||||
)}
|
||||
progressValue={getProgressValue(bucket.count, sampledValuesCount)}
|
||||
count={bucket.count}
|
||||
progressValue={getProgressValue(otherCount, sampledValuesCount)}
|
||||
count={otherCount}
|
||||
color={color}
|
||||
data-test-subj={dataTestSubject}
|
||||
onAddFilter={onAddFilter}
|
||||
overrideFieldTopValueBar={overrideFieldTopValueBar}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
{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 {
|
||||
data: DataPublicPluginStart;
|
||||
listenToSearchSessionUpdates?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,9 +32,13 @@ export interface QuerySubscriberResult {
|
|||
/**
|
||||
* Memorizes current query, filters and absolute date range
|
||||
* @param data
|
||||
* @param listenToSearchSessionUpdates
|
||||
* @public
|
||||
*/
|
||||
export const useQuerySubscriber = ({ data }: QuerySubscriberParams) => {
|
||||
export const useQuerySubscriber = ({
|
||||
data,
|
||||
listenToSearchSessionUpdates = true,
|
||||
}: QuerySubscriberParams) => {
|
||||
const timefilter = data.query.timefilter.timefilter;
|
||||
const [result, setResult] = useState<QuerySubscriberResult>(() => {
|
||||
const state = data.query.getState();
|
||||
|
@ -47,6 +52,10 @@ export const useQuerySubscriber = ({ data }: QuerySubscriberParams) => {
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!listenToSearchSessionUpdates) {
|
||||
return;
|
||||
}
|
||||
|
||||
const subscription = data.search.session.state$.subscribe((sessionState) => {
|
||||
const dateRange = getResolvedDateRange(timefilter);
|
||||
setResult((prevState) => ({
|
||||
|
@ -57,7 +66,24 @@ export const useQuerySubscriber = ({ data }: QuerySubscriberParams) => {
|
|||
});
|
||||
|
||||
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(() => {
|
||||
const subscription = data.query.state$.subscribe(({ state, changes }) => {
|
||||
|
|
|
@ -57,6 +57,7 @@ export type {
|
|||
FieldTypeKnown,
|
||||
FieldListItem,
|
||||
GetCustomFieldType,
|
||||
RenderFieldItemParams,
|
||||
} from './types';
|
||||
export { ExistenceFetchStatus, FieldsGroupNames } from './types';
|
||||
|
||||
|
|
|
@ -7,12 +7,7 @@
|
|||
*/
|
||||
|
||||
import { DataView } from '@kbn/data-views-plugin/common';
|
||||
import {
|
||||
legacyExistingFields,
|
||||
existingFields,
|
||||
Field,
|
||||
buildFieldList,
|
||||
} from './field_existing_utils';
|
||||
import { existingFields, buildFieldList } from './field_existing_utils';
|
||||
|
||||
describe('existingFields', () => {
|
||||
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', () => {
|
||||
const indexPattern = {
|
||||
title: 'testpattern',
|
|
@ -6,7 +6,6 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import Boom from '@hapi/boom';
|
||||
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { RuntimeField } 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))
|
||||
.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 type { DataView, DataViewsContract } from '@kbn/data-views-plugin/common';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { fetchFieldExistence } from '../../../common/utils/field_existing_utils';
|
||||
import { fetchFieldExistence } from './field_existing_utils';
|
||||
|
||||
interface FetchFieldExistenceParams {
|
||||
data: DataPublicPluginStart;
|
||||
|
|
|
@ -11,7 +11,7 @@ import DateMath from '@kbn/datemath';
|
|||
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { ESSearchResponse } from '@kbn/es-types';
|
||||
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||
import type { FieldStatsResponse } from '../types';
|
||||
import type { FieldStatsResponse } from '../../../common/types';
|
||||
import {
|
||||
getFieldExampleBuckets,
|
||||
canProvideExamplesForField,
|
|
@ -10,11 +10,7 @@ import { lastValueFrom } from 'rxjs';
|
|||
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { FieldStatsResponse } from '../../../common/types';
|
||||
import {
|
||||
fetchAndCalculateFieldStats,
|
||||
SearchHandler,
|
||||
buildSearchParams,
|
||||
} from '../../../common/utils/field_stats_utils';
|
||||
import { fetchAndCalculateFieldStats, SearchHandler, buildSearchParams } from './field_stats_utils';
|
||||
|
||||
interface FetchFieldStatsParams {
|
||||
services: {
|
||||
|
|
|
@ -73,3 +73,12 @@ export type FieldTypeKnown = Exclude<
|
|||
>;
|
||||
|
||||
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/**/*",
|
||||
"common/**/*",
|
||||
"public/**/*",
|
||||
"server/**/*",
|
||||
],
|
||||
"kbn_references": [
|
||||
"@kbn/core",
|
||||
"@kbn/kibana-utils-plugin",
|
||||
"@kbn/data-views-plugin",
|
||||
"@kbn/data-plugin",
|
||||
"@kbn/charts-plugin",
|
||||
|
@ -24,7 +22,6 @@
|
|||
"@kbn/field-formats-plugin",
|
||||
"@kbn/i18n-react",
|
||||
"@kbn/analytics",
|
||||
"@kbn/config-schema",
|
||||
"@kbn/core-lifecycle-browser",
|
||||
"@kbn/react-field",
|
||||
"@kbn/field-types",
|
||||
|
|
|
@ -9,7 +9,14 @@
|
|||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
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 a11y = getService('a11y');
|
||||
const savedQueryManagementComponent = getService('savedQueryManagementComponent');
|
||||
|
@ -68,14 +75,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('a11y test on open sidenav filter', async () => {
|
||||
await PageObjects.discover.openSidebarFieldFilter();
|
||||
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||
await a11y.testAppSnapshot();
|
||||
await PageObjects.discover.closeSidebarFieldFilter();
|
||||
await PageObjects.unifiedFieldList.closeSidebarFieldFilter();
|
||||
});
|
||||
|
||||
it('a11y test on tables with columns view', async () => {
|
||||
for (const columnName of TEST_COLUMN_NAMES) {
|
||||
await PageObjects.discover.clickFieldListItemToggle(columnName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemToggle(columnName);
|
||||
}
|
||||
await a11y.testAppSnapshot();
|
||||
});
|
||||
|
|
|
@ -28,7 +28,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
|||
loadTestFile(require.resolve('./stats'));
|
||||
loadTestFile(require.resolve('./ui_metric'));
|
||||
loadTestFile(require.resolve('./ui_counters'));
|
||||
loadTestFile(require.resolve('./unified_field_list'));
|
||||
loadTestFile(require.resolve('./telemetry'));
|
||||
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('./search'),
|
||||
require.resolve('./content_management'),
|
||||
require.resolve('./unified_field_list_examples'),
|
||||
],
|
||||
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.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { FtrProviderContext } from '../../functional/ftr_provider_context';
|
||||
|
||||
export default function lensApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
|
||||
describe('UnifiedFieldList', () => {
|
||||
loadTestFile(require.resolve('./existing_fields'));
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('Unified Field List Examples', () => {
|
||||
loadTestFile(require.resolve('./field_stats'));
|
||||
loadTestFile(require.resolve('./existing_fields'));
|
||||
});
|
||||
}
|
|
@ -27,6 +27,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'dashboard',
|
||||
'context',
|
||||
'header',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
|
@ -43,7 +44,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
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) {
|
||||
|
|
|
@ -27,6 +27,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'dashboard',
|
||||
'context',
|
||||
'header',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
|
@ -43,12 +44,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
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) {
|
||||
await PageObjects.discover.clickFieldListItem(columnName);
|
||||
await PageObjects.discover.clickFieldListPlusFilter(columnName, value);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(columnName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(columnName, value);
|
||||
}
|
||||
});
|
||||
after(async () => {
|
||||
|
|
|
@ -24,6 +24,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'visChart',
|
||||
'share',
|
||||
'timePicker',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const browser = getService('browser');
|
||||
|
@ -121,7 +122,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
await PageObjects.header.clickDiscover();
|
||||
await PageObjects.timePicker.setHistoricalDataRange();
|
||||
await PageObjects.discover.clickFieldListItemAdd('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||
await PageObjects.discover.saveSearch('my search');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
|
@ -135,7 +136,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
expect(inViewMode).to.be(true);
|
||||
|
||||
await PageObjects.header.clickDiscover();
|
||||
await PageObjects.discover.clickFieldListItemAdd('agent');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('agent');
|
||||
await PageObjects.discover.saveSearch('my search');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
|
@ -154,7 +155,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.dashboard.saveDashboard('Has local edits');
|
||||
|
||||
await PageObjects.header.clickDiscover();
|
||||
await PageObjects.discover.clickFieldListItemAdd('clientip');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('clientip');
|
||||
await PageObjects.discover.saveSearch('my search');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
|
|
|
@ -14,7 +14,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const retry = getService('retry');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker', 'settings']);
|
||||
const PageObjects = getPageObjects([
|
||||
'common',
|
||||
'discover',
|
||||
'header',
|
||||
'timePicker',
|
||||
'settings',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const defaultSettings = {
|
||||
defaultIndex: 'logstash-*',
|
||||
'discover:searchFieldsFromSource': false,
|
||||
|
@ -48,13 +55,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
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()).not.to.have.string('Document');
|
||||
});
|
||||
|
||||
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()).to.have.string('Document');
|
||||
});
|
||||
|
|
|
@ -18,7 +18,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const docTable = getService('docTable');
|
||||
const queryBar = getService('queryBar');
|
||||
const find = getService('find');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
||||
const PageObjects = getPageObjects([
|
||||
'common',
|
||||
'discover',
|
||||
'header',
|
||||
'timePicker',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const defaultSettings = {
|
||||
defaultIndex: 'logstash-*',
|
||||
hideAnnouncements: true,
|
||||
|
@ -229,19 +235,19 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
afterEach(async function () {
|
||||
for (const column of extraColumns) {
|
||||
await PageObjects.discover.clickFieldListItemRemove(column);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove(column);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
});
|
||||
|
||||
it('should add more columns to the table', async function () {
|
||||
for (const column of extraColumns) {
|
||||
await PageObjects.discover.clearFieldSearchInput();
|
||||
await PageObjects.discover.findFieldByName(column);
|
||||
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||
await PageObjects.unifiedFieldList.findFieldByName(column);
|
||||
await retry.waitFor('field to appear', async function () {
|
||||
return await testSubjects.exists(`field-${column}`);
|
||||
});
|
||||
await PageObjects.discover.clickFieldListItemAdd(column);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(column);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// test the header now
|
||||
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 () {
|
||||
for (const column of extraColumns) {
|
||||
await PageObjects.discover.clearFieldSearchInput();
|
||||
await PageObjects.discover.findFieldByName(column);
|
||||
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||
await PageObjects.unifiedFieldList.findFieldByName(column);
|
||||
await retry.waitFor('field to appear', async function () {
|
||||
return await testSubjects.exists(`field-${column}`);
|
||||
});
|
||||
await PageObjects.discover.clickFieldListItemAdd(column);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(column);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
// remove the second column
|
||||
await PageObjects.discover.clickFieldListItemRemove(extraColumns[1]);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove(extraColumns[1]);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// test that the second column is no longer there
|
||||
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 () {
|
||||
await PageObjects.discover.clearFieldSearchInput();
|
||||
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||
const dscTableWrapper = await find.byCssSelector('.kbnDocTableWrapper');
|
||||
const fieldNames = await PageObjects.discover.getAllFieldNames();
|
||||
const fieldNames = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||
const clientHeight = await dscTableWrapper.getAttribute('clientHeight');
|
||||
let fieldCounter = 0;
|
||||
const checkScrollable = async () => {
|
||||
|
@ -282,7 +288,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
return Number(scrollWidth) > Number(clientWidth);
|
||||
};
|
||||
const addColumn = async () => {
|
||||
await PageObjects.discover.clickFieldListItemAdd(fieldNames[fieldCounter++]);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(fieldNames[fieldCounter++]);
|
||||
};
|
||||
|
||||
await addColumn();
|
||||
|
|
|
@ -11,7 +11,7 @@ import { FtrProviderContext } from '../ftr_provider_context';
|
|||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const PageObjects = getPageObjects(['common', 'discover']);
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'unifiedFieldList']);
|
||||
const find = getService('find');
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
|
@ -39,7 +39,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
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');
|
||||
|
||||
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 inspector = getService('inspector');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
||||
const PageObjects = getPageObjects([
|
||||
'common',
|
||||
'discover',
|
||||
'header',
|
||||
'timePicker',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
|
||||
const defaultSettings = {
|
||||
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 () {
|
||||
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.discover.clickFieldListItemAdd('_score');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('_score');
|
||||
await PageObjects.discover.clickFieldSort('_score', 'Sort Low-High');
|
||||
const currentUrlWithScore = await browser.getCurrentUrl();
|
||||
expect(currentUrlWithScore).to.contain('_score');
|
||||
await PageObjects.discover.clickFieldListItemRemove('_score');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove('_score');
|
||||
const currentUrlWithoutScore = await browser.getCurrentUrl();
|
||||
expect(currentUrlWithoutScore).not.to.contain('_score');
|
||||
});
|
||||
it('should add a field with customLabel, sort by it, display it correctly', async function () {
|
||||
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.discover.clickFieldListItemAdd('referer');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('referer');
|
||||
await PageObjects.discover.clickFieldSort('referer', 'Sort A-Z');
|
||||
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();
|
||||
expect(url).to.contain('referer');
|
||||
});
|
||||
|
|
|
@ -16,7 +16,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const kibanaServer = getService('kibanaServer');
|
||||
const queryBar = getService('queryBar');
|
||||
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() {
|
||||
this.tags('includeFirefox');
|
||||
|
@ -46,11 +53,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
// marks is the style that highlights the text in yellow
|
||||
await queryBar.setQuery('php');
|
||||
await queryBar.submitQuery();
|
||||
await PageObjects.discover.clickFieldListItemAdd('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||
const marks = await PageObjects.discover.getMarks();
|
||||
expect(marks.length).to.be.greaterThan(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 () {
|
||||
|
|
|
@ -16,7 +16,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const kibanaServer = getService('kibanaServer');
|
||||
const queryBar = getService('queryBar');
|
||||
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() {
|
||||
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 () {
|
||||
// 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();
|
||||
expect(marks.length).to.be.greaterThan(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 () {
|
||||
|
|
|
@ -15,7 +15,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
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 () {
|
||||
before(async function () {
|
||||
|
@ -51,7 +58,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
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');
|
||||
const relatedContentFields = fieldNames.filter(
|
||||
(fieldName) => fieldName.indexOf('relatedContent') === 0
|
||||
|
|
|
@ -30,6 +30,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'header',
|
||||
'context',
|
||||
'dashboard',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const find = getService('find');
|
||||
const security = getService('security');
|
||||
|
@ -64,7 +65,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'_bytes-runtimefield',
|
||||
`emit(doc["bytes"].value.toString())`
|
||||
);
|
||||
await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemToggle('_bytes-runtimefield');
|
||||
|
||||
const second = await PageObjects.discover.getCurrentDataViewId();
|
||||
expect(first).not.to.equal(second);
|
||||
|
@ -144,7 +145,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'_bytes-runtimefield',
|
||||
`emit(doc["bytes"].value.toString())`
|
||||
);
|
||||
await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemToggle('_bytes-runtimefield');
|
||||
const newDataViewId = await PageObjects.discover.getCurrentDataViewId();
|
||||
expect(newDataViewId).not.to.equal(prevDataViewId);
|
||||
|
||||
|
@ -153,7 +154,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
// 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.header.waitUntilLoadingHasFinished();
|
||||
|
||||
|
@ -162,7 +163,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'_bytes-runtimefield',
|
||||
`emit((doc["bytes"].value * 2).toString())`
|
||||
);
|
||||
await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemToggle('_bytes-runtimefield');
|
||||
|
||||
// save second search
|
||||
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) {
|
||||
describe('discover data grid tests', function describeDiscoverDataGrid() {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'timePicker']);
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'unifiedFieldList']);
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const defaultSettings = { defaultIndex: 'logstash-*' };
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
@ -34,16 +34,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
expect(await getTitles()).to.be('@timestamp Document');
|
||||
|
||||
await PageObjects.discover.clickFieldListItemAdd('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('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');
|
||||
|
||||
await PageObjects.discover.clickFieldListItemRemove('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove('bytes');
|
||||
expect(await getTitles()).to.be('@timestamp agent');
|
||||
|
||||
await PageObjects.discover.clickFieldListItemRemove('agent');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove('agent');
|
||||
expect(await getTitles()).to.be('@timestamp Document');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -28,6 +28,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'settings',
|
||||
'dashboard',
|
||||
'header',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const defaultSettings = { defaultIndex: 'logstash-*' };
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
|
@ -47,12 +48,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.common.navigateToApp('discover');
|
||||
|
||||
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) {
|
||||
await PageObjects.discover.clickFieldListItem(columnName);
|
||||
await PageObjects.discover.clickFieldListPlusFilter(columnName, value);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(columnName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(columnName, value);
|
||||
}
|
||||
});
|
||||
after(async () => {
|
||||
|
|
|
@ -18,7 +18,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const kibanaServer = getService('kibanaServer');
|
||||
const monacoEditor = getService('monacoEditor');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker', 'dashboard']);
|
||||
const PageObjects = getPageObjects([
|
||||
'common',
|
||||
'discover',
|
||||
'header',
|
||||
'timePicker',
|
||||
'dashboard',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const defaultSettings = {
|
||||
defaultIndex: 'logstash-*',
|
||||
};
|
||||
|
@ -221,16 +228,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
afterEach(async function () {
|
||||
for (const column of extraColumns) {
|
||||
await PageObjects.discover.clickFieldListItemRemove(column);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove(column);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
});
|
||||
|
||||
it('should add more columns to the table', async function () {
|
||||
for (const column of extraColumns) {
|
||||
await PageObjects.discover.clearFieldSearchInput();
|
||||
await PageObjects.discover.findFieldByName(column);
|
||||
await PageObjects.discover.clickFieldListItemAdd(column);
|
||||
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||
await PageObjects.unifiedFieldList.findFieldByName(column);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(column);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// test the header now
|
||||
const header = await dataGrid.getHeaderFields();
|
||||
|
@ -240,13 +247,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
it('should remove columns from the table', async function () {
|
||||
for (const column of extraColumns) {
|
||||
await PageObjects.discover.clearFieldSearchInput();
|
||||
await PageObjects.discover.findFieldByName(column);
|
||||
await PageObjects.discover.clickFieldListItemAdd(column);
|
||||
await PageObjects.unifiedFieldList.clearFieldSearchInput();
|
||||
await PageObjects.unifiedFieldList.findFieldByName(column);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(column);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
// remove the second column
|
||||
await PageObjects.discover.clickFieldListItemRemove(extraColumns[1]);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove(extraColumns[1]);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// test that the second column is no longer there
|
||||
const header = await dataGrid.getHeaderFields();
|
||||
|
|
|
@ -14,7 +14,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const esArchiver = getService('esArchiver');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
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 dataGrid = getService('dataGrid');
|
||||
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 () {
|
||||
// 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();
|
||||
expect(marks.length).to.be.greaterThan(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 () {
|
||||
|
|
|
@ -21,6 +21,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'discover',
|
||||
'timePicker',
|
||||
'dashboard',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
|
||||
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 () => {
|
||||
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.getAllFieldNames()).length).to.be(3);
|
||||
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).length).to.be(3);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
expect((await PageObjects.discover.getAllFieldNames()).length).to.be(2);
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).length).to.be(2);
|
||||
});
|
||||
|
||||
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 () => {
|
||||
expect(await PageObjects.discover.getHitCountInt()).to.be(3);
|
||||
});
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
expect((await PageObjects.discover.getAllFieldNames()).length).to.be(3);
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).length).to.be(3);
|
||||
expect(await PageObjects.discover.isChartVisible()).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 () => {
|
||||
expect(await PageObjects.discover.getHitCountInt()).to.be(4);
|
||||
});
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
expect((await PageObjects.discover.getAllFieldNames()).length).to.be(3);
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).length).to.be(3);
|
||||
expect(await PageObjects.discover.isChartVisible()).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 kibanaServer = getService('kibanaServer');
|
||||
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 defaultSettings = {
|
||||
defaultIndex: 'logstash-*',
|
||||
|
@ -50,13 +57,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
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()).not.to.have.string('Document');
|
||||
});
|
||||
|
||||
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()).to.have.string('Document');
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const kibanaServer = getService('kibanaServer');
|
||||
const security = getService('security');
|
||||
const retry = getService('retry');
|
||||
const PageObjects = getPageObjects(['common', 'timePicker', 'discover']);
|
||||
const PageObjects = getPageObjects(['common', 'timePicker', 'discover', 'unifiedFieldList']);
|
||||
|
||||
describe('index pattern with unmapped fields', () => {
|
||||
before(async () => {
|
||||
|
@ -48,18 +48,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await retry.try(async function () {
|
||||
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
|
||||
expect(allFields.includes('message')).to.be(true);
|
||||
// sender is not a mapped field
|
||||
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
|
||||
|
||||
await PageObjects.discover.toggleSidebarSection('unmapped');
|
||||
await PageObjects.unifiedFieldList.toggleSidebarSection('unmapped');
|
||||
});
|
||||
|
||||
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 () {
|
||||
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('sender')).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
|
||||
expect(allFields.includes('sender')).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 fieldEditor = getService('fieldEditor');
|
||||
const security = getService('security');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
||||
const PageObjects = getPageObjects([
|
||||
'common',
|
||||
'discover',
|
||||
'header',
|
||||
'timePicker',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const defaultSettings = {
|
||||
defaultIndex: 'logstash-*',
|
||||
'discover:searchFieldsFromSource': false,
|
||||
|
@ -55,8 +61,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await fieldEditor.setCustomLabel(customLabel);
|
||||
await fieldEditor.save();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
expect((await PageObjects.discover.getAllFieldNames()).includes(customLabel)).to.be(true);
|
||||
await PageObjects.discover.clickFieldListItemAdd('bytes');
|
||||
expect((await PageObjects.unifiedFieldList.getAllFieldNames()).includes(customLabel)).to.be(
|
||||
true
|
||||
);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||
expect(await PageObjects.discover.getDocHeader()).to.have.string(customLabel);
|
||||
});
|
||||
|
||||
|
@ -64,7 +72,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const field = '_runtimefield';
|
||||
await createRuntimeField(field);
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
@ -81,7 +89,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.discover.waitForDocTableLoadingComplete();
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
@ -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 () {
|
||||
const fieldName = '_runtimefield-saved-search';
|
||||
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.saveSearch('Saved Search with runtimefield'));
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
@ -108,7 +116,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.discover.removeField(fieldName);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,7 +16,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const esArchiver = getService('esArchiver');
|
||||
const queryBar = getService('queryBar');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
||||
const PageObjects = getPageObjects([
|
||||
'common',
|
||||
'discover',
|
||||
'header',
|
||||
'timePicker',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const security = getService('security');
|
||||
const refreshButtonSelector = 'refreshDataButton';
|
||||
|
@ -72,7 +78,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('should not fetch data from ES initially', async function () {
|
||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||
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 () {
|
||||
|
@ -83,56 +89,56 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||
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 () {
|
||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||
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.missingOrFail(refreshButtonSelector);
|
||||
|
||||
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 () {
|
||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||
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 testSubjects.missingOrFail(refreshButtonSelector);
|
||||
|
||||
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 () {
|
||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||
expect(await testSubjects.exists(refreshButtonSelector)).to.be(true);
|
||||
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 testSubjects.missingOrFail(refreshButtonSelector);
|
||||
|
||||
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 () {
|
||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||
|
||||
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 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 () {
|
||||
|
@ -140,20 +146,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
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 PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
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 () {
|
||||
await initSearchOnPageLoad(true);
|
||||
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 monacoEditor = getService('monacoEditor');
|
||||
const security = getService('security');
|
||||
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
|
||||
const PageObjects = getPageObjects([
|
||||
'common',
|
||||
'discover',
|
||||
'header',
|
||||
'timePicker',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
|
||||
const defaultSettings = {
|
||||
defaultIndex: 'logstash-*',
|
||||
|
@ -39,7 +45,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
describe('test', () => {
|
||||
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('superDatePickerToggleQuickMenuButton')).to.be(true);
|
||||
|
@ -57,7 +63,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
expect(await testSubjects.exists('discoverFieldListPanelEdit-@message')).to.be(true);
|
||||
|
||||
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('TextBasedLangEditor')).to.be(true);
|
||||
|
|
|
@ -12,7 +12,13 @@ import { FtrProviderContext } from '../ftr_provider_context';
|
|||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
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() {
|
||||
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.savedObjects.cleanStandardList();
|
||||
await kibanaServer.uiSettings.replace({});
|
||||
await PageObjects.discover.cleanSidebarLocalStorage();
|
||||
await PageObjects.unifiedFieldList.cleanSidebarLocalStorage();
|
||||
});
|
||||
|
||||
describe('should add fields as columns via drag and drop', function () {
|
||||
it('should support dragging and dropping a field onto the grid', async function () {
|
||||
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.'
|
||||
);
|
||||
expect((await PageObjects.discover.getColumnHeaders()).join(', ')).to.be(
|
||||
|
@ -63,7 +69,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
|
||||
expect(
|
||||
(await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ')
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ')
|
||||
).to.be('extension, @message');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'timePicker',
|
||||
'header',
|
||||
'unifiedSearch',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const testSubjects = getService('testSubjects');
|
||||
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.savedObjects.cleanStandardList();
|
||||
await kibanaServer.uiSettings.replace({});
|
||||
await PageObjects.discover.cleanSidebarLocalStorage();
|
||||
await PageObjects.unifiedFieldList.cleanSidebarLocalStorage();
|
||||
});
|
||||
|
||||
describe('field filtering', function () {
|
||||
it('should reveal and hide the filter form when the toggle is clicked', async function () {
|
||||
await PageObjects.discover.openSidebarFieldFilter();
|
||||
await PageObjects.discover.closeSidebarFieldFilter();
|
||||
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||
await PageObjects.unifiedFieldList.closeSidebarFieldFilter();
|
||||
});
|
||||
|
||||
it('should filter by field type', async function () {
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.discover.openSidebarFieldFilter();
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||
|
||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
||||
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||
INITIAL_FIELD_LIST_SUMMARY
|
||||
);
|
||||
|
||||
|
@ -70,7 +71,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
await retry.waitFor('first updates', async () => {
|
||||
return (
|
||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
||||
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||
'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 () => {
|
||||
return (
|
||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
||||
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||
'13 available fields. 0 empty fields. 3 meta fields.'
|
||||
);
|
||||
});
|
||||
|
@ -88,7 +89,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
await retry.waitFor('reset', async () => {
|
||||
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 browser.refresh();
|
||||
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.discover.openSidebarFieldFilter();
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||
let options = await find.allByCssSelector('[data-test-subj*="typeFilter"]');
|
||||
expect(options).to.have.length(6);
|
||||
await PageObjects.discover.closeSidebarFieldFilter();
|
||||
await PageObjects.unifiedFieldList.closeSidebarFieldFilter();
|
||||
|
||||
await PageObjects.discover.selectTextBaseLang('SQL');
|
||||
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.discover.openSidebarFieldFilter();
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.unifiedFieldList.openSidebarFieldFilter();
|
||||
options = await find.allByCssSelector('[data-test-subj*="typeFilter"]');
|
||||
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.'
|
||||
);
|
||||
|
||||
|
@ -118,7 +120,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
await retry.waitFor('updates', async () => {
|
||||
return (
|
||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
||||
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||
'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 () {
|
||||
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
|
||||
);
|
||||
|
||||
await PageObjects.discover.findFieldByName('i');
|
||||
await PageObjects.unifiedFieldList.findFieldByName('i');
|
||||
|
||||
await retry.waitFor('first updates', async () => {
|
||||
return (
|
||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
||||
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||
'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 () => {
|
||||
return (
|
||||
(await PageObjects.discover.getSidebarAriaDescription()) ===
|
||||
(await PageObjects.unifiedFieldList.getSidebarAriaDescription()) ===
|
||||
'4 available fields. 0 empty fields. 0 meta fields.'
|
||||
);
|
||||
});
|
||||
|
@ -155,7 +157,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
await retry.waitFor('reset', async () => {
|
||||
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();
|
||||
|
||||
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);
|
||||
|
||||
await filterBar.addFilter({ field: 'extension', operation: 'is', value: 'jpg' });
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
const onlyJpgResult = 'jpg\n100%';
|
||||
await PageObjects.discover.clickFieldListItem('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(onlyJpgResult);
|
||||
|
||||
await filterBar.toggleFilterNegated('extension');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
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(
|
||||
jpgExcludedResult
|
||||
);
|
||||
|
@ -188,14 +191,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await filterBar.toggleFilterPinned('extension');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
await PageObjects.discover.clickFieldListItem('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
||||
jpgExcludedResult
|
||||
);
|
||||
|
||||
await browser.refresh();
|
||||
|
||||
await PageObjects.discover.clickFieldListItem('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
||||
jpgExcludedResult
|
||||
);
|
||||
|
@ -203,7 +206,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await filterBar.toggleFilterEnabled('extension');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
await PageObjects.discover.clickFieldListItem('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(allTermsResult);
|
||||
});
|
||||
});
|
||||
|
@ -226,24 +229,28 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
describe('renders field groups', function () {
|
||||
it('should show field list groups excluding subfields', async function () {
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||
|
||||
// Initial Available fields
|
||||
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';
|
||||
let availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available');
|
||||
let availableFields = await PageObjects.unifiedFieldList.getSidebarSectionFieldNames(
|
||||
'available'
|
||||
);
|
||||
expect(availableFields.length).to.be(50);
|
||||
expect(availableFields.join(', ')).to.be(expectedInitialAvailableFields);
|
||||
|
||||
// Available fields after scrolling down
|
||||
const emptySectionButton = await find.byCssSelector(
|
||||
PageObjects.discover.getSidebarSectionSelector('empty', true)
|
||||
PageObjects.unifiedFieldList.getSidebarSectionSelector('empty', true)
|
||||
);
|
||||
await emptySectionButton.scrollIntoViewIfNecessary();
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
|
@ -252,18 +259,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
// Expand Empty section
|
||||
await PageObjects.discover.toggleSidebarSection('empty');
|
||||
expect((await PageObjects.discover.getSidebarSectionFieldNames('empty')).join(', ')).to.be(
|
||||
''
|
||||
);
|
||||
await PageObjects.unifiedFieldList.toggleSidebarSection('empty');
|
||||
expect(
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('empty')).join(', ')
|
||||
).to.be('');
|
||||
|
||||
// Expand Meta section
|
||||
await PageObjects.discover.toggleSidebarSection('meta');
|
||||
expect((await PageObjects.discover.getSidebarSectionFieldNames('meta')).join(', ')).to.be(
|
||||
'_id, _index, _score'
|
||||
);
|
||||
await PageObjects.unifiedFieldList.toggleSidebarSection('meta');
|
||||
expect(
|
||||
(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
|
||||
);
|
||||
});
|
||||
|
@ -272,11 +279,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await kibanaServer.uiSettings.update({ 'discover:searchFieldsFromSource': true });
|
||||
await browser.refresh();
|
||||
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true);
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
expect(await PageObjects.unifiedFieldList.doesSidebarShowFields()).to.be(true);
|
||||
|
||||
// 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
|
||||
|
@ -288,68 +297,70 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
// Available fields after scrolling down
|
||||
const emptySectionButton = await find.byCssSelector(
|
||||
PageObjects.discover.getSidebarSectionSelector('empty', true)
|
||||
PageObjects.unifiedFieldList.getSidebarSectionSelector('empty', true)
|
||||
);
|
||||
await emptySectionButton.scrollIntoViewIfNecessary();
|
||||
|
||||
// Expand Empty section
|
||||
await PageObjects.discover.toggleSidebarSection('empty');
|
||||
expect((await PageObjects.discover.getSidebarSectionFieldNames('empty')).join(', ')).to.be(
|
||||
''
|
||||
);
|
||||
await PageObjects.unifiedFieldList.toggleSidebarSection('empty');
|
||||
expect(
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('empty')).join(', ')
|
||||
).to.be('');
|
||||
|
||||
// Expand Meta section
|
||||
await PageObjects.discover.toggleSidebarSection('meta');
|
||||
expect((await PageObjects.discover.getSidebarSectionFieldNames('meta')).join(', ')).to.be(
|
||||
'_id, _index, _score'
|
||||
);
|
||||
await PageObjects.unifiedFieldList.toggleSidebarSection('meta');
|
||||
expect(
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('meta')).join(', ')
|
||||
).to.be('_id, _index, _score');
|
||||
|
||||
// Expand Unmapped section
|
||||
await PageObjects.discover.toggleSidebarSection('unmapped');
|
||||
await PageObjects.unifiedFieldList.toggleSidebarSection('unmapped');
|
||||
expect(
|
||||
(await PageObjects.discover.getSidebarSectionFieldNames('unmapped')).join(', ')
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('unmapped')).join(', ')
|
||||
).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.'
|
||||
);
|
||||
});
|
||||
|
||||
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.clickFieldListItemAdd('@message');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('@message');
|
||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
|
||||
expect(
|
||||
(await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ')
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ')
|
||||
).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('@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.'
|
||||
);
|
||||
|
||||
await PageObjects.discover.clickFieldListItemRemove('@message');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove('@message');
|
||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
|
||||
await PageObjects.discover.clickFieldListItemAdd('_id');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('_id');
|
||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
await PageObjects.discover.clickFieldListItemAdd('@message');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('@message');
|
||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
|
||||
expect(
|
||||
(await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ')
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ')
|
||||
).to.be('extension, _id, @message');
|
||||
|
||||
expect(
|
||||
(await PageObjects.discover.getSidebarSectionFieldNames('popular')).join(', ')
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('popular')).join(', ')
|
||||
).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.'
|
||||
);
|
||||
});
|
||||
|
@ -358,22 +369,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await kibanaServer.uiSettings.update({ 'discover:enableSql': true });
|
||||
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
|
||||
);
|
||||
|
||||
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.'
|
||||
);
|
||||
|
||||
await PageObjects.discover.clickFieldListItemRemove('extension');
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemRemove('extension');
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
|
||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
||||
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||
'49 selected fields. 51 available fields.'
|
||||
);
|
||||
|
||||
|
@ -385,13 +396,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await monacoEditor.setCodeEditorValue(testQuery);
|
||||
await testSubjects.click('querySubmitButton');
|
||||
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.'
|
||||
);
|
||||
expect(
|
||||
(await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ')
|
||||
(await PageObjects.unifiedFieldList.getSidebarSectionFieldNames('selected')).join(', ')
|
||||
).to.be('@tags, geo.dest, occurred');
|
||||
|
||||
await PageObjects.unifiedSearch.switchDataView(
|
||||
|
@ -401,9 +412,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
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.'
|
||||
);
|
||||
});
|
||||
|
@ -414,25 +425,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield'
|
||||
);
|
||||
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
|
||||
);
|
||||
|
||||
await PageObjects.discover.selectIndexPattern('with-timefield');
|
||||
|
||||
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.'
|
||||
);
|
||||
await testSubjects.missingOrFail(
|
||||
`${PageObjects.discover.getSidebarSectionSelector('available')}-fetchWarning`
|
||||
`${PageObjects.unifiedFieldList.getSidebarSectionSelector('available')}-fetchWarning`
|
||||
);
|
||||
await testSubjects.existOrFail(
|
||||
`${PageObjects.discover.getSidebarSectionSelector(
|
||||
`${PageObjects.unifiedFieldList.getSidebarSectionSelector(
|
||||
'available'
|
||||
)}NoFieldsCallout-noFieldsExist`
|
||||
);
|
||||
|
@ -440,9 +451,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||
|
||||
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
|
||||
);
|
||||
await kibanaServer.importExport.unload(
|
||||
|
@ -459,31 +470,31 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
await PageObjects.discover.selectIndexPattern('without-timefield');
|
||||
|
||||
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.'
|
||||
);
|
||||
|
||||
await PageObjects.discover.selectIndexPattern('with-timefield');
|
||||
|
||||
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.'
|
||||
);
|
||||
await testSubjects.existOrFail(
|
||||
`${PageObjects.discover.getSidebarSectionSelector(
|
||||
`${PageObjects.unifiedFieldList.getSidebarSectionSelector(
|
||||
'available'
|
||||
)}NoFieldsCallout-noFieldsMatch`
|
||||
);
|
||||
|
@ -491,9 +502,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
|
@ -509,25 +520,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('should work when filters change', async () => {
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
||||
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||
INITIAL_FIELD_LIST_SUMMARY
|
||||
);
|
||||
|
||||
await PageObjects.discover.clickFieldListItem('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('extension');
|
||||
expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be(
|
||||
'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 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
|
||||
);
|
||||
|
||||
// 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%');
|
||||
});
|
||||
|
||||
|
@ -538,27 +549,27 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
await PageObjects.discover.selectIndexPattern('indices-stats*');
|
||||
|
||||
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.'
|
||||
);
|
||||
|
||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
|
@ -572,7 +583,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.discover.createAdHocDataView('logstash', true);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
||||
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||
INITIAL_FIELD_LIST_SUMMARY
|
||||
);
|
||||
|
||||
|
@ -586,13 +597,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
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.'
|
||||
);
|
||||
|
||||
let allFields = await PageObjects.discover.getAllFieldNames();
|
||||
let allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||
expect(allFields.includes('_bytes-runtimefield')).to.be(true);
|
||||
|
||||
await PageObjects.discover.editField('_bytes-runtimefield');
|
||||
|
@ -605,25 +616,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
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.'
|
||||
);
|
||||
|
||||
allFields = await PageObjects.discover.getAllFieldNames();
|
||||
allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||
expect(allFields.includes('_bytes-runtimefield2')).to.be(true);
|
||||
expect(allFields.includes('_bytes-runtimefield')).to.be(false);
|
||||
|
||||
await PageObjects.discover.removeField('_bytes-runtimefield');
|
||||
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
|
||||
);
|
||||
|
||||
allFields = await PageObjects.discover.getAllFieldNames();
|
||||
allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||
expect(allFields.includes('_bytes-runtimefield2')).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');
|
||||
|
||||
expect(await PageObjects.discover.getSidebarAriaDescription()).to.be(
|
||||
expect(await PageObjects.unifiedFieldList.getSidebarAriaDescription()).to.be(
|
||||
INITIAL_FIELD_LIST_SUMMARY
|
||||
);
|
||||
|
||||
|
@ -644,13 +655,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
// error in fetching documents because of the invalid runtime field
|
||||
await testSubjects.existOrFail('discoverNoResultsError');
|
||||
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
|
||||
// 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.'
|
||||
);
|
||||
let allFields = await PageObjects.discover.getAllFieldNames();
|
||||
let allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||
expect(allFields.includes('_invalid-runtimefield')).to.be(true);
|
||||
|
||||
await browser.refresh();
|
||||
|
@ -658,13 +669,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await testSubjects.existOrFail('discoverNoResultsError'); // still has error
|
||||
|
||||
// check that the sidebar is rendered event after a refresh
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
allFields = await PageObjects.discover.getAllFieldNames();
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
allFields = await PageObjects.unifiedFieldList.getAllFieldNames();
|
||||
expect(allFields.includes('_invalid-runtimefield')).to.be(true);
|
||||
|
||||
await PageObjects.discover.removeField('_invalid-runtimefield');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
|
||||
await testSubjects.missingOrFail('discoverNoResultsError');
|
||||
});
|
||||
|
@ -678,22 +689,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
await PageObjects.discover.selectIndexPattern('with-timefield');
|
||||
|
||||
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.'
|
||||
);
|
||||
await testSubjects.existOrFail(
|
||||
`${PageObjects.discover.getSidebarSectionSelector(
|
||||
`${PageObjects.unifiedFieldList.getSidebarSectionSelector(
|
||||
'available'
|
||||
)}NoFieldsCallout-noFieldsMatch`
|
||||
);
|
||||
|
@ -704,9 +715,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
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.'
|
||||
);
|
||||
|
||||
|
@ -728,26 +739,28 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
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(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'Document']);
|
||||
|
||||
await PageObjects.discover.clickFieldListItemAdd(newField);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(newField);
|
||||
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(await dataGrid.getHeaderFields()).to.eql(['@timestamp', newField]);
|
||||
|
||||
await PageObjects.discover.removeField(newField);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.discover.waitUntilSidebarHasLoaded();
|
||||
await PageObjects.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
|
||||
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']);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// 1. Create scripted field
|
||||
// 2. See the expected value of the scripted field in Discover doc view
|
||||
// 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
|
||||
// appends closing braces, for exmaple, if you type opening square brace [
|
||||
|
@ -41,6 +41,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'visualize',
|
||||
'discover',
|
||||
'timePicker',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
|
||||
describe('scripted fields', function () {
|
||||
|
@ -154,9 +155,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('should see scripted field value in Discover', async function () {
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName);
|
||||
await retry.try(async function () {
|
||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName);
|
||||
});
|
||||
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 () {
|
||||
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 PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName, '14');
|
||||
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(
|
||||
scriptedPainlessFieldName,
|
||||
'14'
|
||||
);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
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 () {
|
||||
await filterBar.removeAllFilters();
|
||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// verify Lens opens a visualization
|
||||
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 () {
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await retry.try(async function () {
|
||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
});
|
||||
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 () {
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
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 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 () {
|
||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// verify Lens opens a visualization
|
||||
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 () {
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await retry.try(async function () {
|
||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
});
|
||||
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 () {
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
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 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 () {
|
||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// verify Lens opens a visualization
|
||||
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 () {
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await retry.try(async function () {
|
||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
});
|
||||
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 () {
|
||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// verify Lens opens a visualization
|
||||
await retry.waitFor('lens visualization', async () => {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// 1. Create scripted field
|
||||
// 2. See the expected value of the scripted field in Discover doc view
|
||||
// 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
|
||||
// appends closing braces, for exmaple, if you type opening square brace [
|
||||
|
@ -40,6 +40,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'visualize',
|
||||
'discover',
|
||||
'timePicker',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
|
||||
describe('scripted fields', function () {
|
||||
|
@ -142,9 +143,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName);
|
||||
await retry.try(async function () {
|
||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName);
|
||||
});
|
||||
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 () {
|
||||
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 PageObjects.discover.clickFieldListPlusFilter(scriptedPainlessFieldName, '14');
|
||||
await PageObjects.unifiedFieldList.clickFieldListPlusFilter(
|
||||
scriptedPainlessFieldName,
|
||||
'14'
|
||||
);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
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 () {
|
||||
await filterBar.removeAllFilters();
|
||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// verify Lens opens a visualization
|
||||
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.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await retry.try(async function () {
|
||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
});
|
||||
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 () {
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
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 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 () {
|
||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// verify Lens opens a visualization
|
||||
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.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await retry.try(async function () {
|
||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
});
|
||||
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 () {
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
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 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 () {
|
||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// verify Lens opens a visualization
|
||||
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.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||
|
||||
await PageObjects.discover.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem(scriptedPainlessFieldName2);
|
||||
await retry.try(async function () {
|
||||
await PageObjects.discover.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(scriptedPainlessFieldName2);
|
||||
});
|
||||
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 () {
|
||||
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize(scriptedPainlessFieldName2);
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
// verify Lens opens a visualization
|
||||
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 { WebElementWrapper } from '../services/lib/web_element_wrapper';
|
||||
|
||||
type SidebarSectionName = 'meta' | 'empty' | 'available' | 'unmapped' | 'popular' | 'selected';
|
||||
|
||||
export class DiscoverPageObject extends FtrService {
|
||||
private readonly retry = this.ctx.getService('retry');
|
||||
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 header = this.ctx.getPageObject('header');
|
||||
private readonly unifiedSearch = this.ctx.getPageObject('unifiedSearch');
|
||||
private readonly unifiedFieldList = this.ctx.getPageObject('unifiedFieldList');
|
||||
private readonly browser = this.ctx.getService('browser');
|
||||
private readonly globalNav = this.ctx.getService('globalNav');
|
||||
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(
|
||||
searchName: string,
|
||||
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) {
|
||||
await this.retry.try(async () => {
|
||||
await this.clickFieldListItem(field);
|
||||
await this.unifiedFieldList.clickFieldListItem(field);
|
||||
await this.testSubjects.click(`discoverFieldListPanelEdit-${field}`);
|
||||
await this.find.byClassName('indexPatternFieldEditor__form');
|
||||
});
|
||||
}
|
||||
|
||||
public async removeField(field: string) {
|
||||
await this.clickFieldListItem(field);
|
||||
await this.unifiedFieldList.clickFieldListItem(field);
|
||||
await this.testSubjects.click(`discoverFieldListPanelDelete-${field}`);
|
||||
await this.retry.waitFor('modal to open', async () => {
|
||||
return await this.testSubjects.exists('runtimeFieldDeleteConfirmModal');
|
||||
|
@ -485,71 +466,6 @@ export class DiscoverPageObject extends FtrService {
|
|||
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') {
|
||||
const isLegacyDefault = await this.useLegacyTable();
|
||||
if (isLegacyDefault) {
|
||||
|
@ -558,110 +474,12 @@ export class DiscoverPageObject extends FtrService {
|
|||
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() {
|
||||
const dataView = await this.getCurrentlySelectedDataView();
|
||||
await this.testSubjects.click('discover-dataView-switch-link');
|
||||
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) {
|
||||
await this.testSubjects.click('discover-dataView-switch-link');
|
||||
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) {
|
||||
await this.elasticChart.waitForRenderingCount(renderCount, 'unifiedHistogramChart');
|
||||
}
|
||||
|
@ -886,7 +691,7 @@ export class DiscoverPageObject extends FtrService {
|
|||
* @param fieldName
|
||||
* */
|
||||
public async dragFieldToTable(fieldName: string) {
|
||||
await this.waitUntilSidebarHasLoaded();
|
||||
await this.unifiedFieldList.waitUntilSidebarHasLoaded();
|
||||
|
||||
const from = `dscFieldListPanelField-${fieldName}`;
|
||||
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 { DashboardPageControls } from './dashboard_page_controls';
|
||||
import { UnifiedSearchPageObject } from './unified_search_page';
|
||||
import { UnifiedFieldListPageObject } from './unified_field_list';
|
||||
import { FilesManagementPageObject } from './files_management';
|
||||
|
||||
export const pageObjects = {
|
||||
|
@ -61,5 +62,6 @@ export const pageObjects = {
|
|||
savedObjects: SavedObjectsPageObject,
|
||||
indexPatternFieldEditorObjects: IndexPatternFieldEditorPageObject,
|
||||
unifiedSearch: UnifiedSearchPageObject,
|
||||
unifiedFieldList: UnifiedFieldListPageObject,
|
||||
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 discover = this.ctx.getPageObject('discover');
|
||||
private readonly timePicker = this.ctx.getPageObject('timePicker');
|
||||
private readonly unifiedFieldList = this.ctx.getPageObject('unifiedFieldList');
|
||||
|
||||
async createAndAddTSVBVisualization(name: string) {
|
||||
this.log.debug(`createAndAddTSVBVisualization(${name})`);
|
||||
|
@ -54,7 +55,7 @@ export class DashboardVisualizationsService extends FtrService {
|
|||
|
||||
if (fields) {
|
||||
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';
|
||||
|
||||
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 testSubjects = getService('testSubjects');
|
||||
const toasts = getService('toasts');
|
||||
|
@ -54,7 +61,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
|
|||
});
|
||||
|
||||
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.header.waitUntilLoadingHasFinished();
|
||||
const sessionIds = await getSessionIds();
|
||||
|
|
|
@ -1390,6 +1390,8 @@
|
|||
"@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/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-histogram-plugin": ["src/plugins/unified_histogram"],
|
||||
|
|
|
@ -27,6 +27,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
'share',
|
||||
'spaceSelector',
|
||||
'header',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const appsMenu = getService('appsMenu');
|
||||
|
@ -234,8 +235,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
await PageObjects.common.waitForTopNavToBeVisible();
|
||||
await PageObjects.discover.selectIndexPattern('logstash-*');
|
||||
await setDiscoverTimeRange();
|
||||
await PageObjects.discover.clickFieldListItem('bytes');
|
||||
await PageObjects.discover.expectMissingFieldListItemVisualize('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||
await PageObjects.unifiedFieldList.expectMissingFieldListItemVisualize('bytes');
|
||||
});
|
||||
|
||||
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.waitForTopNavToBeVisible();
|
||||
await setDiscoverTimeRange();
|
||||
await PageObjects.discover.clickFieldListItem('bytes');
|
||||
await PageObjects.discover.expectMissingFieldListItemVisualize('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||
await PageObjects.unifiedFieldList.expectMissingFieldListItemVisualize('bytes');
|
||||
});
|
||||
|
||||
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.waitForTopNavToBeVisible();
|
||||
await setDiscoverTimeRange();
|
||||
await PageObjects.discover.clickFieldListItem('bytes');
|
||||
await PageObjects.discover.expectFieldListItemVisualize('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||
await PageObjects.unifiedFieldList.expectFieldListItemVisualize('bytes');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
'timePicker',
|
||||
'security',
|
||||
'spaceSelector',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const appsMenu = getService('appsMenu');
|
||||
|
@ -84,8 +85,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
basePath: '/s/custom_space',
|
||||
});
|
||||
await setDiscoverTimeRange();
|
||||
await PageObjects.discover.clickFieldListItem('bytes');
|
||||
await PageObjects.discover.expectFieldListItemVisualize('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||
await PageObjects.unifiedFieldList.expectFieldListItemVisualize('bytes');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -154,8 +155,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
basePath: '/s/custom_space',
|
||||
});
|
||||
await setDiscoverTimeRange();
|
||||
await PageObjects.discover.clickFieldListItem('bytes');
|
||||
await PageObjects.discover.expectMissingFieldListItemVisualize('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||
await PageObjects.unifiedFieldList.expectMissingFieldListItemVisualize('bytes');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
'security',
|
||||
'spaceSelector',
|
||||
'header',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const monacoEditor = getService('monacoEditor');
|
||||
|
||||
|
@ -58,13 +59,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('shows "visualize" field button', async () => {
|
||||
await PageObjects.discover.clickFieldListItem('bytes');
|
||||
await PageObjects.discover.expectFieldListItemVisualize('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItem('bytes');
|
||||
await PageObjects.unifiedFieldList.expectFieldListItemVisualize('bytes');
|
||||
});
|
||||
|
||||
it('visualizes field to Lens and loads fields to the dimesion editor', async () => {
|
||||
await PageObjects.discover.findFieldByName('bytes');
|
||||
await PageObjects.discover.clickFieldListItemVisualize('bytes');
|
||||
await PageObjects.unifiedFieldList.findFieldByName('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('bytes');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await retry.try(async () => {
|
||||
const dimensions = await testSubjects.findAll('lns-dimensionTrigger');
|
||||
|
@ -79,8 +80,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
operation: 'is between',
|
||||
value: { from: '3500', to: '4000' },
|
||||
});
|
||||
await PageObjects.discover.findFieldByName('geo.src');
|
||||
await PageObjects.discover.clickFieldListItemVisualize('geo.src');
|
||||
await PageObjects.unifiedFieldList.findFieldByName('geo.src');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('geo.src');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
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 () => {
|
||||
await queryBar.setQuery('machine.os : ios');
|
||||
await queryBar.submitQuery();
|
||||
await PageObjects.discover.findFieldByName('geo.dest');
|
||||
await PageObjects.discover.clickFieldListItemVisualize('geo.dest');
|
||||
await PageObjects.unifiedFieldList.findFieldByName('geo.dest');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('geo.dest');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
expect(await queryBar.getQueryString()).to.equal('machine.os : ios');
|
||||
|
|
|
@ -19,6 +19,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'timeToVisualize',
|
||||
'common',
|
||||
'discover',
|
||||
'unifiedFieldList',
|
||||
]);
|
||||
const elasticChart = getService('elasticChart');
|
||||
const fieldEditor = getService('fieldEditor');
|
||||
|
@ -218,7 +219,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'_bytes-runtimefield',
|
||||
`emit(doc["bytes"].value.toString())`
|
||||
);
|
||||
await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemToggle('_bytes-runtimefield');
|
||||
const newDataViewId = await PageObjects.discover.getCurrentDataViewId();
|
||||
expect(newDataViewId).not.to.equal(prevDataViewId);
|
||||
expect(await PageObjects.unifiedSearch.isAdHocDataView()).to.be(true);
|
||||
|
|
|
@ -9,7 +9,14 @@ import expect from '@kbn/expect';
|
|||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
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 from = 'Sep 22, 2015 @ 00: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 () => {
|
||||
await PageObjects.discover.selectIndexPattern('geo_shapes*');
|
||||
await PageObjects.discover.clickFieldListItemVisualize('geometry');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('geometry');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.maps.waitForLayersToLoad();
|
||||
const doesLayerExist = await PageObjects.maps.doesLayerExist('geo_shapes*');
|
||||
|
@ -51,7 +58,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
await queryBar.submitQuery();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
await PageObjects.discover.clickFieldListItemVisualize('geo.coordinates');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemVisualize('geo.coordinates');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.maps.waitForLayersToLoad();
|
||||
const doesLayerExist = await PageObjects.maps.doesLayerExist('logstash-*');
|
||||
|
|
|
@ -10,7 +10,14 @@ import { FtrProviderContext } from '../../ftr_provider_context';
|
|||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
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 log = getService('log');
|
||||
|
||||
|
@ -28,7 +35,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('appears correctly in discover', async function () {
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
await PageObjects.discover.clickFieldListItemAdd('histogram-content');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('histogram-content');
|
||||
const rowData = await PageObjects.discover.getDocTableIndex(1);
|
||||
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 toasts = getService('toasts');
|
||||
|
||||
const pageObjects = getPageObjects(['discover', 'timePicker']);
|
||||
const pageObjects = getPageObjects(['discover', 'timePicker', 'unifiedFieldList']);
|
||||
|
||||
return {
|
||||
async clickNextButton() {
|
||||
|
@ -1083,7 +1083,7 @@ export function TransformWizardProvider({ getService, getPageObjects }: FtrProvi
|
|||
async assertDiscoverContainField(field: string) {
|
||||
await pageObjects.discover.isDiscoverAppOnScreen();
|
||||
await retry.tryForTime(60 * 1000, async () => {
|
||||
const allFields = await pageObjects.discover.getAllFieldNames();
|
||||
const allFields = await pageObjects.unifiedFieldList.getAllFieldNames();
|
||||
if (Array.isArray(allFields)) {
|
||||
expect(allFields).to.contain(
|
||||
field,
|
||||
|
|
|
@ -5527,6 +5527,10 @@
|
|||
version "0.0.0"
|
||||
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":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue