[Data Discovery] Run example plugin functional tests in Serverless (#163411)

## Summary

> [!IMPORTANT]  
> These tests currently do not run in "real" Serverless and only run in
"local" Serverless (what we use in CI). Additional work will need to be
done to allow these tests to be run in an actual Serverless environment,
since they required `config.ts` changes which are only loaded when
running locally.

This PR copies the Data Discovery example plugin functional tests to
`test_serverless` and adds support for running them against the Search
project.

It also adds support for running functional tests against example
plugins in general in Serverless ("local" Serverless only currently).

In the future these should run as deployment-agnostic tests, but support
does not yet exist (see #161574), so in the meantime they've been
duplicated and modified in place. I've left `TODO` comments where test
files have been modified so we know what needs to be addressed once they
are converted to deployment-agnostic tests.

Part of #162347.

### Checklist

- [ ] ~Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)~
- [ ]
~[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials~
- [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
- [ ] ~Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard
accessibility](https://webaim.org/techniques/keyboard/))~
- [ ] ~Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))~
- [ ] ~If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~
- [ ] ~This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))~
- [ ] ~This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)~

### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Dzmitry Lemechko <dzmitry.lemechko@elastic.co>
This commit is contained in:
Davis McPhee 2023-08-31 10:23:05 -03:00 committed by GitHub
parent a62d9a90f5
commit b4bfb2a2dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 1502 additions and 0 deletions

View file

@ -90,10 +90,13 @@ disabled:
- x-pack/test_serverless/functional/test_suites/common/config.ts
- x-pack/test_serverless/functional/test_suites/observability/config.ts
- x-pack/test_serverless/functional/test_suites/observability/config.feature_flags.ts
- x-pack/test_serverless/functional/test_suites/observability/config.examples.ts
- x-pack/test_serverless/functional/test_suites/search/config.ts
- x-pack/test_serverless/functional/test_suites/search/config.feature_flags.ts
- x-pack/test_serverless/functional/test_suites/search/config.examples.ts
- x-pack/test_serverless/functional/test_suites/security/config.ts
- x-pack/test_serverless/functional/test_suites/security/config.feature_flags.ts
- x-pack/test_serverless/functional/test_suites/security/config.examples.ts
defaultQueue: 'n2-4-spot'
enabled:

View file

@ -69,6 +69,19 @@ steps:
- exit_status: '-1'
limit: 3
- command: SERVERLESS_ENVIRONMENT=observability.examples .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Observability Examples Tests'
agents:
queue: n2-4-spot
depends_on: build
timeout_in_minutes: 40
soft_fail:
- exit_status: 10
retry:
automatic:
- exit_status: '-1'
limit: 3
- command: SERVERLESS_ENVIRONMENT=search .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Search Tests'
agents:
@ -82,6 +95,19 @@ steps:
- exit_status: '-1'
limit: 3
- command: SERVERLESS_ENVIRONMENT=search.examples .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Search Examples Tests'
agents:
queue: n2-4-spot
depends_on: build
timeout_in_minutes: 40
soft_fail:
- exit_status: 10
retry:
automatic:
- exit_status: '-1'
limit: 3
- command: SERVERLESS_ENVIRONMENT=security .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Security Tests'
agents:
@ -95,6 +121,19 @@ steps:
- exit_status: '-1'
limit: 3
- command: SERVERLESS_ENVIRONMENT=security.examples .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Security Examples Tests'
agents:
queue: n2-4-spot
depends_on: build
timeout_in_minutes: 40
soft_fail:
- exit_status: 10
retry:
automatic:
- exit_status: '-1'
limit: 3
- command: .buildkite/scripts/steps/functional/security_serverless.sh
label: 'Serverless Security Cypress Tests'
agents:

View file

@ -34,6 +34,19 @@ steps:
- exit_status: '*'
limit: 1
- command: SERVERLESS_ENVIRONMENT=observability.examples .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Observability Examples Tests'
agents:
queue: n2-4-spot
depends_on: build
timeout_in_minutes: 40
retry:
automatic:
- exit_status: '-1'
limit: 3
- exit_status: '*'
limit: 1
- command: SERVERLESS_ENVIRONMENT=search .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Search Tests'
agents:
@ -47,6 +60,19 @@ steps:
- exit_status: '*'
limit: 1
- command: SERVERLESS_ENVIRONMENT=search.examples .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Search Examples Tests'
agents:
queue: n2-4-spot
depends_on: build
timeout_in_minutes: 40
retry:
automatic:
- exit_status: '-1'
limit: 3
- exit_status: '*'
limit: 1
- command: SERVERLESS_ENVIRONMENT=security .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Security Tests'
agents:
@ -60,6 +86,19 @@ steps:
- exit_status: '*'
limit: 1
- command: SERVERLESS_ENVIRONMENT=security.examples .buildkite/scripts/steps/functional/serverless_ftr.sh
label: 'Serverless Security Examples Tests'
agents:
queue: n2-4-spot
depends_on: build
timeout_in_minutes: 40
retry:
automatic:
- exit_status: '-1'
limit: 3
- exit_status: '*'
limit: 1
- command: .buildkite/scripts/steps/functional/security_serverless.sh
label: 'Serverless Security Cypress Tests'
agents:

View file

@ -12,6 +12,10 @@ if [[ "$SERVERLESS_ENVIRONMENT" == "search" ]]; then
"x-pack/test_serverless/api_integration/test_suites/search/config.feature_flags.ts"
"x-pack/test_serverless/functional/test_suites/search/config.ts"
)
elif [[ "$SERVERLESS_ENVIRONMENT" == "search.examples" ]]; then
SERVERLESS_CONFIGS=(
"x-pack/test_serverless/functional/test_suites/search/config.examples.ts"
)
elif [[ "$SERVERLESS_ENVIRONMENT" == "observability" ]]; then
SERVERLESS_CONFIGS=(
"x-pack/test_serverless/api_integration/test_suites/observability/config.ts"
@ -19,12 +23,20 @@ elif [[ "$SERVERLESS_ENVIRONMENT" == "observability" ]]; then
"x-pack/test_serverless/functional/test_suites/observability/config.ts"
"x-pack/test_serverless/functional/test_suites/observability/cypress/config_headless.ts"
)
elif [[ "$SERVERLESS_ENVIRONMENT" == "observability.examples" ]]; then
SERVERLESS_CONFIGS=(
"x-pack/test_serverless/functional/test_suites/observability/config.examples.ts"
)
elif [[ "$SERVERLESS_ENVIRONMENT" == "security" ]]; then
SERVERLESS_CONFIGS=(
"x-pack/test_serverless/api_integration/test_suites/security/config.ts"
"x-pack/test_serverless/api_integration/test_suites/security/config.feature_flags.ts"
"x-pack/test_serverless/functional/test_suites/security/config.ts"
)
elif [[ "$SERVERLESS_ENVIRONMENT" == "security.examples" ]]; then
SERVERLESS_CONFIGS=(
"x-pack/test_serverless/functional/test_suites/security/config.examples.ts"
)
fi
EXIT_CODE=0

7
.github/CODEOWNERS vendored
View file

@ -834,6 +834,13 @@ packages/kbn-yarn-lock-validator @elastic/kibana-operations
/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests @elastic/kibana-data-discovery
/x-pack/test_serverless/api_integration/test_suites/common/search_oss @elastic/kibana-data-discovery
/x-pack/test_serverless/api_integration/test_suites/common/search_xpack @elastic/kibana-data-discovery
/x-pack/test_serverless/functional/test_suites/common/examples/data_view_field_editor_example @elastic/kibana-data-discovery
/x-pack/test_serverless/functional/test_suites/common/examples/discover_customization_examples @elastic/kibana-data-discovery
/x-pack/test_serverless/functional/test_suites/common/examples/field_formats @elastic/kibana-data-discovery
/x-pack/test_serverless/functional/test_suites/common/examples/partial_results @elastic/kibana-data-discovery
/x-pack/test_serverless/functional/test_suites/common/examples/search @elastic/kibana-data-discovery
/x-pack/test_serverless/functional/test_suites/common/examples/search_examples @elastic/kibana-data-discovery
/x-pack/test_serverless/functional/test_suites/common/examples/unified_field_list_examples @elastic/kibana-data-discovery
# Visualizations
/src/plugins/visualize/ @elastic/kibana-visualizations

View file

@ -27,6 +27,7 @@ export function createTestConfig(options: CreateTestConfigOptions) {
serverArgs: [
...svlSharedConfig.get('kbnTestServer.serverArgs'),
`--serverless=${options.serverlessProject}`,
...(options.kbnServerArgs ?? []),
],
},
testFiles: options.testFiles,

View file

@ -0,0 +1,231 @@
{
"type": "doc",
"value": {
"id": "index-pattern:histogram-test",
"index": ".kibana_analytics_1",
"source": {
"index-pattern": {
"fieldAttrs": "{}",
"title": "histogram-test",
"sourceFilters": "[]",
"fields": "[]",
"fieldFormatMap": "{}",
"typeMeta": "{}",
"runtimeFieldMap": "{}",
"name": "histogram-test"
},
"type": "index-pattern",
"references": [],
"managed": false,
"namespaces": [
"default"
],
"coreMigrationVersion": "8.8.0",
"typeMigrationVersion": "8.0.0",
"updated_at": "2023-08-05T05:41:10.360Z",
"created_at": "2023-08-05T05:41:10.360Z"
}
}
}
{
"type": "doc",
"value": {
"id": "5e69404d93193e4074f0ec1a",
"index": "histogram-test",
"source": {
"histogram-title": "incididunt reprehenderit mollit",
"histogram-content": {
"values": [
0.3,
1,
3,
4.2,
4.8
],
"counts": [
237,
170,
33,
149,
241
]
}
}
}
}
{
"type": "doc",
"value": {
"id": "5e69408f2fc61f57fd5bc762",
"index": "histogram-test",
"source": {
"histogram-title": "culpa cillum ullamco",
"histogram-content": {
"values": [
0.5,
1,
1.2,
1.3,
2.8,
3.9,
4.3
],
"counts": [
113,
197,
20,
66,
20,
39,
178
]
}
}
}
}
{
"type": "doc",
"value": {
"id": "5e6940b979b57ad343114cc3",
"index": "histogram-test",
"source": {
"histogram-title": "enim veniam et",
"histogram-content": {
"values": [
3.7,
4.2
],
"counts": [
227,
141
]
}
}
}
}
{
"type": "doc",
"value": {
"id": "5e6940d3e95de786eeb7586d",
"index": "histogram-test",
"source": {
"histogram-title": "est incididunt sunt",
"histogram-content": {
"values": [
1.8,
2.4,
2.6,
4.9
],
"counts": [
92,
101,
122,
244
]
}
}
}
}
{
"type": "doc",
"value": {
"id": "5e694119fb2f956a822b93b9",
"index": "histogram-test",
"source": {
"histogram-title": "qui qui tempor",
"histogram-content": {
"values": [
0.5,
2.1,
2.7,
3,
3.2,
3.5,
4.2,
5
],
"counts": [
210,
168,
182,
181,
97,
164,
77,
2
]
}
}
}
}
{
"type": "doc",
"value": {
"id": "5e694145ad3c741aa12d6e8e",
"index": "histogram-test",
"source": {
"histogram-title": "ullamco nisi sunt",
"histogram-content": {
"values": [
1.7,
4.5,
4.8
],
"counts": [
74,
146,
141
]
}
}
}
}
{
"type": "doc",
"value": {
"id": "5e694159d909d9d99b5e12d1",
"index": "histogram-test",
"source": {
"histogram-title": "magna eu incididunt",
"histogram-content": {
"values": [
1,
3.4,
4.8
],
"counts": [
103,
205,
11
]
}
}
}
}
{
"type": "doc",
"value": {
"id": "5e694159d909d9d99b5e12d1",
"index": "histogram-test",
"source": {
"histogram-title": "single value",
"histogram-content": {
"values": [
1
],
"counts": [
1
]
}
}
}
}

View file

@ -0,0 +1,30 @@
{
"type": "index",
"value": {
"aliases": {},
"index": "histogram-test",
"mappings": {
"properties": {
"histogram-title": {
"fields": {
"keyword": {
"ignore_above": 256,
"type": "keyword"
}
},
"type": "text"
},
"histogram-content": {
"type": "histogram"
}
}
},
"settings": {
"index": {
"auto_expand_replicas": "0-1",
"number_of_replicas": "0",
"number_of_shards": "1"
}
}
}
}

View file

@ -0,0 +1,45 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
// TODO: Changed from PluginFunctionalProviderContext to FtrProviderContext in Serverless
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const find = getService('find');
describe('', () => {
it('finds a data view', async () => {
await testSubjects.existOrFail('dataViewTitle');
});
it('opens the field editor', async () => {
await testSubjects.click('addField');
await testSubjects.existOrFail('flyoutTitle');
await testSubjects.click('closeFlyoutButton');
});
it('uses preconfigured options for a new field', async () => {
// find the checkbox label and click it - `testSubjects.setCheckbox()` is not working for our checkbox
const controlWrapper = await testSubjects.find('preconfiguredControlWrapper');
const control = await find.descendantDisplayedByCssSelector('label', controlWrapper);
await control.click();
await testSubjects.click('addField');
await testSubjects.existOrFail('flyoutTitle');
const nameField = await testSubjects.find('nameField');
const nameInput = await find.descendantDisplayedByCssSelector(
'[data-test-subj=input]',
nameField
);
expect(await nameInput.getAttribute('value')).to.equal('demotestfield');
});
});
}

View file

@ -0,0 +1,52 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
// TODO: Changed from PluginFunctionalProviderContext to FtrProviderContext in Serverless
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) {
const browser = getService('browser');
const es = getService('es');
const PageObjects = getPageObjects(['common', 'header', 'settings', 'svlCommonNavigation']);
const testSubjects = getService('testSubjects');
const find = getService('find');
const retry = getService('retry');
const kibanaServer = getService('kibanaServer');
describe('data view field editor example', function () {
before(async () => {
// TODO: emptyKibanaIndex fails in Serverless with
// "index_not_found_exception: no such index [.kibana_ingest]",
// so it was switched to `savedObjects.cleanStandardList()`
await kibanaServer.savedObjects.cleanStandardList();
await browser.setWindowSize(1300, 900);
await es.transport.request({
path: '/blogs/_doc',
method: 'POST',
body: { user: 'matt', message: 20 },
});
// TODO: Navigation to Data View Management is different in Serverless
await PageObjects.common.navigateToApp('management');
await retry.waitFor('data views link', async () => {
if (await testSubjects.exists('app-card-dataViews')) {
await testSubjects.click('app-card-dataViews');
return true;
}
if (await find.existsByCssSelector('[href*="/dataViews"]')) {
await find.clickByCssSelector('[href*="/dataViews"]');
return true;
}
return false;
});
await PageObjects.settings.createIndexPattern('blogs', null);
await PageObjects.common.navigateToApp('dataViewFieldEditorExample');
});
loadTestFile(require.resolve('./data_view_field_editor_example'));
});
}

View file

@ -0,0 +1,99 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import type { FtrProviderContext } from '../../../../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';
export default ({ getService, getPageObjects }: FtrProviderContext) => {
const PageObjects = getPageObjects(['common', 'timePicker', 'header']);
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const dataGrid = getService('dataGrid');
const defaultSettings = { defaultIndex: 'logstash-*' };
describe('Customizations', () => {
before(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover');
await kibanaServer.uiSettings.replace(defaultSettings);
await PageObjects.common.navigateToApp('home');
const currentUrl = await browser.getCurrentUrl();
const customizationUrl =
currentUrl.substring(0, currentUrl.indexOf('/app/home')) +
'/app/discoverCustomizationExamples';
await browser.get(customizationUrl);
await PageObjects.timePicker.setAbsoluteRange(TEST_START_TIME, TEST_END_TIME);
await PageObjects.header.waitUntilLoadingHasFinished();
});
after(async () => {
await kibanaServer.uiSettings.unset('defaultIndex');
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.savedObjects.cleanStandardList();
});
it('Top nav', async () => {
await testSubjects.existOrFail('customOptionsButton');
await testSubjects.existOrFail('shareTopNavButton');
await testSubjects.existOrFail('documentExplorerButton');
await testSubjects.missingOrFail('discoverNewButton');
await testSubjects.missingOrFail('discoverOpenButton');
await testSubjects.click('customOptionsButton');
await testSubjects.existOrFail('customOptionsPopover');
await testSubjects.click('customOptionsButton');
await testSubjects.missingOrFail('customOptionsPopover');
});
it('Search bar', async () => {
await testSubjects.click('logsViewSelectorButton');
await testSubjects.click('logsViewSelectorOption-ASavedSearch');
await PageObjects.header.waitUntilLoadingHasFinished();
const { title, description } = await PageObjects.common.getSharedItemTitleAndDescription();
const expected = {
title: 'A Saved Search',
description: 'A Saved Search Description',
};
expect(title).to.eql(expected.title);
expect(description).to.eql(expected.description);
});
it('Search bar Prepend Filters exists and should apply filter properly', async () => {
// Validate custom filters are present
await testSubjects.existOrFail('customPrependedFilter');
await testSubjects.click('customPrependedFilter');
await testSubjects.existOrFail('optionsList-control-selection-exists');
// Retrieve option list popover
const optionsListControl = await testSubjects.find('optionsList-control-popover');
const optionsItems = await optionsListControl.findAllByCssSelector(
'[data-test-subj*="optionsList-control-selection-"]'
);
// Retrieve second item in the options along with the count of documents
const item = optionsItems[1];
const countBadge = await item.findByCssSelector(
'[data-test-subj="optionsList-document-count-badge"]'
);
const documentsCount = parseInt(await countBadge.getVisibleText(), 10);
// Click the item to apply filter
await item.click();
await PageObjects.header.waitUntilLoadingHasFinished();
// Validate that filter is applied
const rows = await dataGrid.getDocTableRows();
await expect(documentsCount).to.eql(rows.length);
});
});
};

View file

@ -0,0 +1,14 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Discover customization examples', () => {
loadTestFile(require.resolve('./customizations'));
});
}

View file

@ -0,0 +1,38 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common']);
describe('Field formats example', function () {
before(async () => {
await PageObjects.common.navigateToApp('fieldFormatsExample');
});
it('renders field formats example 1', async () => {
const formattedValues = await Promise.all(
(
await testSubjects.findAll('example1 sample formatted')
).map((wrapper) => wrapper.getVisibleText())
);
expect(formattedValues).to.eql(['1000.00B', '97.66KB', '95.37MB']);
});
it('renders field formats example 2', async () => {
const formattedValues = await Promise.all(
(
await testSubjects.findAll('example2 sample formatted')
).map((wrapper) => wrapper.getVisibleText())
);
expect(formattedValues).to.eql(['$1,000.00', '$100,000.00', '$100,000,000.00']);
});
});
}

View file

@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common']);
describe('Partial Results Example', function () {
before(async () => {
await PageObjects.common.navigateToApp('partialResultsExample');
const element = await testSubjects.find('example-help');
await element.click();
await element.click();
await element.click();
});
it('should trace mouse events', async () => {
const events = await Promise.all(
(
await testSubjects.findAll('example-column-event')
).map((wrapper) => wrapper.getVisibleText())
);
expect(events).to.eql(['mousedown', 'mouseup', 'click']);
});
it('should keep track of the events number', async () => {
const counters = await Promise.all(
(
await testSubjects.findAll('example-column-count')
).map((wrapper) => wrapper.getVisibleText())
);
expect(counters).to.eql(['3', '3', '3']);
});
});
}

View file

@ -0,0 +1,14 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Search examples', () => {
loadTestFile(require.resolve('./warnings'));
});
}

View file

@ -0,0 +1,204 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { estypes } from '@elastic/elasticsearch';
import expect from '@kbn/expect';
import { asyncForEach } from '@kbn/std';
import assert from 'assert';
import type { WebElementWrapper } from '../../../../../../../test/functional/services/lib/web_element_wrapper';
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const PageObjects = getPageObjects(['common', 'timePicker']);
const testSubjects = getService('testSubjects');
const find = getService('find');
const retry = getService('retry');
const es = getService('es');
const log = getService('log');
const indexPatterns = getService('indexPatterns');
const comboBox = getService('comboBox');
const kibanaServer = getService('kibanaServer');
const esArchiver = getService('esArchiver');
describe('handling warnings with search source fetch', function () {
const dataViewTitle = 'sample-01,sample-01-rollup';
const fromTime = 'Jun 17, 2022 @ 00:00:00.000';
const toTime = 'Jun 23, 2022 @ 00:00:00.000';
const testArchive = 'test/functional/fixtures/es_archiver/search/downsampled';
const testIndex = 'sample-01';
const testRollupIndex = 'sample-01-rollup';
const testRollupField = 'kubernetes.container.memory.usage.bytes';
const toastsSelector = '[data-test-subj=globalToastList] [data-test-subj=euiToastHeader]';
const shardFailureType = 'unsupported_aggregation_on_downsampled_index';
const shardFailureReason = `Field [${testRollupField}] of type [aggregate_metric_double] is not supported for aggregation [percentiles]`;
const getTestJson = async (tabTestSubj: string, codeTestSubj: string) => {
log.info(`switch to ${tabTestSubj} tab...`);
await testSubjects.click(tabTestSubj);
const block = await testSubjects.find(codeTestSubj);
const testText = (await block.getVisibleText()).trim();
return testText && JSON.parse(testText);
};
before(async () => {
// create rollup data
log.info(`loading ${testIndex} index...`);
await esArchiver.loadIfNeeded(testArchive);
log.info(`add write block to ${testIndex} index...`);
await es.indices.addBlock({ index: testIndex, block: 'write' });
try {
log.info(`rolling up ${testIndex} index...`);
// es client currently does not have method for downsample
await es.transport.request<void>({
method: 'POST',
path: '/sample-01/_downsample/sample-01-rollup',
body: { fixed_interval: '1h' },
});
} catch (err) {
log.info(`ignoring resource_already_exists_exception...`);
if (!err.message.match(/resource_already_exists_exception/)) {
throw err;
}
}
log.info(`creating ${dataViewTitle} data view...`);
await indexPatterns.create(
{
title: dataViewTitle,
timeFieldName: '@timestamp',
},
{ override: true }
);
await kibanaServer.uiSettings.update({
'dateFormat:tz': 'UTC',
defaultIndex: '0ae0bc7a-e4ca-405c-ab67-f2b5913f2a51',
'timepicker:timeDefaults': '{ "from": "now-1y", "to": "now" }',
});
await PageObjects.common.navigateToApp('searchExamples');
});
beforeEach(async () => {
await comboBox.setCustom('dataViewSelector', dataViewTitle);
await comboBox.set('searchMetricField', testRollupField);
await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
});
after(async () => {
await es.indices.delete({ index: [testIndex, testRollupIndex] });
await kibanaServer.savedObjects.cleanStandardList();
await kibanaServer.uiSettings.replace({});
});
afterEach(async () => {
await PageObjects.common.clearAllToasts();
});
it('shows shard failure warning notifications by default', async () => {
await testSubjects.click('searchSourceWithOther');
// wait for response - toasts appear before the response is rendered
let response: estypes.SearchResponse | undefined;
await retry.try(async () => {
response = await getTestJson('responseTab', 'responseCodeBlock');
expect(response).not.to.eql({});
});
// toasts
const toasts = await find.allByCssSelector(toastsSelector);
expect(toasts.length).to.be(2);
const expects = ['2 of 4 shards failed', 'Query result'];
await asyncForEach(toasts, async (t, index) => {
expect(await t.getVisibleText()).to.eql(expects[index]);
});
// click "see full error" button in the toast
const [openShardModalButton] = await testSubjects.findAll('openShardFailureModalBtn');
await openShardModalButton.click();
const modalHeader = await testSubjects.find('shardFailureModalTitle');
expect(await modalHeader.getVisibleText()).to.be('2 of 4 shards failed');
// request
await testSubjects.click('shardFailuresModalRequestButton');
const requestBlock = await testSubjects.find('shardsFailedModalRequestBlock');
expect(await requestBlock.getVisibleText()).to.contain(testRollupField);
// response
await testSubjects.click('shardFailuresModalResponseButton');
const responseBlock = await testSubjects.find('shardsFailedModalResponseBlock');
expect(await responseBlock.getVisibleText()).to.contain(shardFailureReason);
await testSubjects.click('closeShardFailureModal');
// response tab
assert(response && response._shards.failures);
expect(response._shards.total).to.be(4);
expect(response._shards.successful).to.be(2);
expect(response._shards.skipped).to.be(0);
expect(response._shards.failed).to.be(2);
expect(response._shards.failures.length).to.equal(1);
expect(response._shards.failures[0].index).to.equal(testRollupIndex);
expect(response._shards.failures[0].reason.type).to.equal(shardFailureType);
expect(response._shards.failures[0].reason.reason).to.equal(shardFailureReason);
// warnings tab
const warnings = await getTestJson('warningsTab', 'warningsCodeBlock');
expect(warnings).to.eql([]);
});
it('able to handle shard failure warnings and prevent default notifications', async () => {
await testSubjects.click('searchSourceWithoutOther');
// wait for toasts - toasts appear after the response is rendered
let toasts: WebElementWrapper[] = [];
await retry.try(async () => {
toasts = await find.allByCssSelector(toastsSelector);
expect(toasts.length).to.be(2);
});
const expects = ['Query result', '2 of 4 shards failed'];
await asyncForEach(toasts, async (t, index) => {
expect(await t.getVisibleText()).to.eql(expects[index]);
});
// click "see full error" button in the toast
const [openShardModalButton] = await testSubjects.findAll('openShardFailureModalBtn');
await openShardModalButton.click();
const modalHeader = await testSubjects.find('shardFailureModalTitle');
expect(await modalHeader.getVisibleText()).to.be('2 of 4 shards failed');
// request
await testSubjects.click('shardFailuresModalRequestButton');
const requestBlock = await testSubjects.find('shardsFailedModalRequestBlock');
expect(await requestBlock.getVisibleText()).to.contain(testRollupField);
// response
await testSubjects.click('shardFailuresModalResponseButton');
const responseBlock = await testSubjects.find('shardsFailedModalResponseBlock');
expect(await responseBlock.getVisibleText()).to.contain(shardFailureReason);
await testSubjects.click('closeShardFailureModal');
// response tab
const response = await getTestJson('responseTab', 'responseCodeBlock');
expect(response._shards.total).to.be(4);
expect(response._shards.successful).to.be(2);
expect(response._shards.skipped).to.be(0);
expect(response._shards.failed).to.be(2);
expect(response._shards.failures.length).to.equal(1);
expect(response._shards.failures[0].index).to.equal(testRollupIndex);
expect(response._shards.failures[0].reason.type).to.equal(shardFailureType);
expect(response._shards.failures[0].reason.reason).to.equal(shardFailureReason);
// warnings tab
const warnings = await getTestJson('warningsTab', 'warningsCodeBlock');
expect(warnings).to.eql([
{
type: 'shard_failure',
message: '2 of 4 shards failed',
reason: { reason: shardFailureReason, type: shardFailureType },
text: 'The data might be incomplete or wrong.',
},
]);
});
});
}

View file

@ -0,0 +1,43 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
// TODO: Changed from PluginFunctionalProviderContext to FtrProviderContext in Serverless
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService, loadTestFile }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
describe('search examples', function () {
before(async () => {
// TODO: emptyKibanaIndex fails in Serverless with
// "index_not_found_exception: no such index [.kibana_ingest]",
// so it was switched to `savedObjects.cleanStandardList()`
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/lens/lens_basic.json'
); // need at least one index pattern
});
after(async () => {
await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional');
await kibanaServer.importExport.unload(
'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json'
);
});
// TODO: Removed `search_session_example` since
// search sessions are not supported in Serverless
loadTestFile(require.resolve('./search_example'));
// TODO: Removed `search_sessions_cache` since
// search sessions are not supported in Serverless
loadTestFile(require.resolve('./partial_results_example'));
// TODO: Removed `sql_search_example` since
// SQL is not supported in Serverless
});
}

View 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common']);
const retry = getService('retry');
describe('Partial results example', () => {
before(async () => {
await PageObjects.common.navigateToApp('searchExamples');
await testSubjects.click('/search');
});
it('should update a progress bar', async () => {
await testSubjects.click('responseTab');
const progressBar = await testSubjects.find('progressBar');
const value = await progressBar.getAttribute('value');
expect(value).to.be('0');
await testSubjects.click('requestFibonacci');
await retry.waitFor('update progress bar', async () => {
const newValue = await progressBar.getAttribute('value');
return parseFloat(newValue) > 0;
});
});
});
}

View file

@ -0,0 +1,97 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common', 'timePicker']);
const retry = getService('retry');
const comboBox = getService('comboBox');
const toasts = getService('toasts');
describe('Search example', () => {
describe('with bfetch', () => {
testSearchExample();
});
describe('no bfetch', () => {
const kibanaServer = getService('kibanaServer');
before(async () => {
await kibanaServer.uiSettings.replace({
'bfetch:disable': true,
});
});
after(async () => {
await kibanaServer.uiSettings.unset('bfetch:disable');
});
testSearchExample();
});
const appId = 'searchExamples';
function testSearchExample() {
before(async function () {
await PageObjects.common.navigateToApp(appId, { insertTimestamp: false });
await comboBox.setCustom('dataViewSelector', 'logstash-*');
await comboBox.set('searchBucketField', 'geo.src');
await comboBox.set('searchMetricField', 'memory');
await PageObjects.timePicker.setAbsoluteRange(
'Mar 1, 2015 @ 00:00:00.000',
'Nov 1, 2015 @ 00:00:00.000'
);
});
beforeEach(async () => {
await toasts.dismissAllToasts();
await retry.waitFor('toasts gone', async () => {
return (await toasts.getToastCount()) === 0;
});
});
it('should have an other bucket', async () => {
await testSubjects.click('searchSourceWithOther');
await testSubjects.click('responseTab');
const codeBlock = await testSubjects.find('responseCodeBlock');
await retry.waitFor('get code block', async () => {
const visibleText = await codeBlock.getVisibleText();
const parsedResponse = JSON.parse(visibleText);
const buckets = parsedResponse.aggregations[1].buckets;
return (
buckets.length === 3 && buckets[2].key === '__other__' && buckets[2].doc_count === 9039
);
});
});
it('should not have an other bucket', async () => {
await testSubjects.click('searchSourceWithoutOther');
await testSubjects.click('responseTab');
const codeBlock = await testSubjects.find('responseCodeBlock');
await retry.waitFor('get code block', async () => {
const visibleText = await codeBlock.getVisibleText();
const parsedResponse = JSON.parse(visibleText);
const buckets = parsedResponse.aggregations[1].buckets;
return buckets.length === 2;
});
});
it('should handle warnings', async () => {
await testSubjects.click('searchWithWarning');
await retry.waitFor('', async () => {
const toastCount = await toasts.getToastCount();
return toastCount > 1;
});
const warningToast = await toasts.getToastElement(2);
const textEl = await warningToast.findByTestSubject('euiToastBody');
const text: string = await textEl.getVisibleText();
expect(text).to.contain('Watch out!');
});
}
});
}

View file

@ -0,0 +1,165 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import type { FtrProviderContext } from '../../../../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',
];
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();
});
});
});
};

View file

@ -0,0 +1,182 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import type { FtrProviderContext } from '../../../../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';
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'
);
// TODO: Loading this from `es_archives` in `test_serverless`
// instead since minor modifications were required
await esArchiver.loadIfNeeded(
'x-pack/test_serverless/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');
// TODO: Loading this from `es_archives` in `test_serverless`
// instead since minor modifications were required
await esArchiver.unload(
'x-pack/test_serverless/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%'
);
});
// TODO: Scripted fields tests dropped since they're not supported in Serverless
it('should return examples for non-aggregatable or geo fields', async () => {
await PageObjects.unifiedFieldList.clickFieldListItem('geo.coordinates');
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();
});
});
});
};

View file

@ -0,0 +1,15 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Unified Field List Examples', () => {
loadTestFile(require.resolve('./field_stats'));
loadTestFile(require.resolve('./existing_fields'));
});
}

View file

@ -0,0 +1,21 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('serverless examples UI', function () {
this.tags('skipMKI');
loadTestFile(require.resolve('./examples/data_view_field_editor_example'));
loadTestFile(require.resolve('./examples/discover_customization_examples'));
loadTestFile(require.resolve('./examples/field_formats'));
loadTestFile(require.resolve('./examples/partial_results'));
loadTestFile(require.resolve('./examples/search'));
loadTestFile(require.resolve('./examples/search_examples'));
loadTestFile(require.resolve('./examples/unified_field_list_examples'));
});
}

View file

@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { REPO_ROOT } from '@kbn/repo-info';
import { findTestPluginPaths } from '@kbn/test';
import { resolve } from 'path';
import { createTestConfig } from '../../config.base';
export default createTestConfig({
serverlessProject: 'oblt',
testFiles: [require.resolve('../common/index.examples')],
junit: {
reportName: 'Serverless Observability Examples Functional Tests',
},
kbnServerArgs: findTestPluginPaths([
resolve(REPO_ROOT, 'examples'),
resolve(REPO_ROOT, 'x-pack/examples'),
]),
});

View file

@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { REPO_ROOT } from '@kbn/repo-info';
import { findTestPluginPaths } from '@kbn/test';
import { resolve } from 'path';
import { createTestConfig } from '../../config.base';
export default createTestConfig({
serverlessProject: 'es',
testFiles: [require.resolve('../common/index.examples')],
junit: {
reportName: 'Serverless Search Examples Functional Tests',
},
kbnServerArgs: findTestPluginPaths([
resolve(REPO_ROOT, 'examples'),
resolve(REPO_ROOT, 'x-pack/examples'),
]),
});

View file

@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { REPO_ROOT } from '@kbn/repo-info';
import { findTestPluginPaths } from '@kbn/test';
import { resolve } from 'path';
import { createTestConfig } from '../../config.base';
export default createTestConfig({
serverlessProject: 'security',
testFiles: [require.resolve('../common/index.examples')],
junit: {
reportName: 'Serverless Security Examples Functional Tests',
},
kbnServerArgs: findTestPluginPaths([
resolve(REPO_ROOT, 'examples'),
resolve(REPO_ROOT, 'x-pack/examples'),
]),
});

View file

@ -45,6 +45,7 @@
"@kbn/cases-plugin",
"@kbn/test-subj-selector",
"@kbn/core-http-common",
"@kbn/std",
"@kbn/data-views-plugin",
"@kbn/core-saved-objects-server",
"@kbn/security-api-integration-helpers",