mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Search Profiler] Enable functional tests for serverless (#172656)
## Summary This PR adds a test that profiles a simple query with a test index to stateful and enables 2 tests for serverless (loading a query from url and profiling a simple query with a test index).
This commit is contained in:
parent
387cb38bd9
commit
7faa488a13
9 changed files with 222 additions and 33 deletions
|
@ -6,26 +6,27 @@
|
|||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { compressToEncodedURIComponent } from 'lz-string';
|
||||
import { asyncForEach } from '@kbn/std';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
const testIndex = 'test-index';
|
||||
const testQuery = {
|
||||
query: {
|
||||
match_all: {},
|
||||
},
|
||||
};
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
const PageObjects = getPageObjects(['common']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const aceEditor = getService('aceEditor');
|
||||
const PageObjects = getPageObjects(['common', 'searchProfiler']);
|
||||
const retry = getService('retry');
|
||||
const security = getService('security');
|
||||
const es = getService('es');
|
||||
const log = getService('log');
|
||||
|
||||
const editorTestSubjectSelector = 'searchProfilerEditor';
|
||||
|
||||
describe('Search Profiler Editor', () => {
|
||||
before(async () => {
|
||||
await security.testUser.setRoles(['global_devtools_read']);
|
||||
await PageObjects.common.navigateToApp('searchProfiler');
|
||||
expect(await testSubjects.exists('searchProfilerEditor')).to.be(true);
|
||||
expect(await PageObjects.searchProfiler.editorExists()).to.be(true);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
|
@ -36,7 +37,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
// The below inputs are written to work _with_ ace's autocomplete unlike console's unit test
|
||||
// counterparts in src/legacy/core_plugins/console/public/tests/src/editor.test.js
|
||||
|
||||
const okInput = [
|
||||
const okInputs = [
|
||||
`{
|
||||
"query": {
|
||||
"match_all": {}`,
|
||||
|
@ -46,7 +47,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
"test": """{ "more": "json" }"""`,
|
||||
];
|
||||
|
||||
const notOkInput = [
|
||||
const notOkInputs = [
|
||||
`{
|
||||
"query": {
|
||||
"match_all": {
|
||||
|
@ -59,24 +60,24 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
|
||||
const expectHasParseErrorsToBe = (expectation: boolean) => async (inputs: string[]) => {
|
||||
for (const input of inputs) {
|
||||
await aceEditor.setValue(editorTestSubjectSelector, input);
|
||||
await PageObjects.searchProfiler.setQuery(input);
|
||||
|
||||
await retry.waitFor(
|
||||
`parser errors to match expectation: HAS ${expectation ? 'ERRORS' : 'NO ERRORS'}`,
|
||||
async () => {
|
||||
const actual = await aceEditor.hasParseErrors(editorTestSubjectSelector);
|
||||
const actual = await PageObjects.searchProfiler.editorHasParseErrors();
|
||||
return expectation === actual;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
await expectHasParseErrorsToBe(false)(okInput);
|
||||
await expectHasParseErrorsToBe(true)(notOkInput);
|
||||
await expectHasParseErrorsToBe(false)(okInputs);
|
||||
await expectHasParseErrorsToBe(true)(notOkInputs);
|
||||
});
|
||||
|
||||
it('supports pre-configured search query', async () => {
|
||||
const searchQuery = {
|
||||
const query = {
|
||||
query: {
|
||||
bool: {
|
||||
should: [
|
||||
|
@ -106,24 +107,21 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
// this index name is just an input placeholder and does not exist
|
||||
const indexName = 'my_index';
|
||||
|
||||
const searchQueryURI = compressToEncodedURIComponent(JSON.stringify(searchQuery, null, 2));
|
||||
|
||||
await PageObjects.common.navigateToUrl(
|
||||
'searchProfiler',
|
||||
`/searchprofiler?index=${indexName}&load_from=${searchQueryURI}`,
|
||||
PageObjects.searchProfiler.getUrlWithIndexAndQuery({ indexName, query }),
|
||||
{
|
||||
useActualUrl: true,
|
||||
}
|
||||
);
|
||||
|
||||
const indexInput = await testSubjects.find('indexName');
|
||||
const indexInputValue = await indexInput.getAttribute('value');
|
||||
const indexInputValue = await PageObjects.searchProfiler.getIndexName();
|
||||
|
||||
expect(indexInputValue).to.eql(indexName);
|
||||
|
||||
await retry.try(async () => {
|
||||
const searchProfilerInput = JSON.parse(await aceEditor.getValue('searchProfilerEditor'));
|
||||
expect(searchProfilerInput).to.eql(searchQuery);
|
||||
const searchProfilerInput = await PageObjects.searchProfiler.getQuery();
|
||||
expect(searchProfilerInput).to.eql(query);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -148,23 +146,35 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('returns error if profile is executed with no valid indices', async () => {
|
||||
const input = {
|
||||
query: {
|
||||
match_all: {},
|
||||
},
|
||||
};
|
||||
await PageObjects.searchProfiler.setIndexName('_all');
|
||||
await PageObjects.searchProfiler.setQuery(testQuery);
|
||||
|
||||
await testSubjects.setValue('indexName', '_all');
|
||||
await aceEditor.setValue(editorTestSubjectSelector, JSON.stringify(input));
|
||||
|
||||
await testSubjects.click('profileButton');
|
||||
await PageObjects.searchProfiler.clickProfileButton();
|
||||
|
||||
await retry.waitFor('notification renders', async () => {
|
||||
const notification = await testSubjects.find('noShardsNotification');
|
||||
const notificationText = await notification.getVisibleText();
|
||||
return notificationText.includes('Unable to profile');
|
||||
return await PageObjects.searchProfiler.editorHasErrorNotification();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('With a test index', () => {
|
||||
before(async () => {
|
||||
await es.indices.create({ index: testIndex });
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await es.indices.delete({ index: testIndex });
|
||||
});
|
||||
|
||||
it('profiles a simple query', async () => {
|
||||
await PageObjects.searchProfiler.setIndexName(testIndex);
|
||||
await PageObjects.searchProfiler.setQuery(testQuery);
|
||||
|
||||
await PageObjects.searchProfiler.clickProfileButton();
|
||||
|
||||
const content = await PageObjects.searchProfiler.getProfileContent();
|
||||
expect(content).to.contain(testIndex);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import { UpgradeAssistantPageObject } from './upgrade_assistant_page';
|
|||
import { UptimePageObject } from './uptime_page';
|
||||
import { UserProfilePageProvider } from './user_profile_page';
|
||||
import { WatcherPageObject } from './watcher_page';
|
||||
import { SearchProfilerPageProvider } from './search_profiler_page';
|
||||
|
||||
// just like services, PageObjects are defined as a map of
|
||||
// names to Providers. Merge in Kibana's or pick specific ones
|
||||
|
@ -87,6 +88,7 @@ export const pageObjects = {
|
|||
reporting: ReportingPageObject,
|
||||
roleMappings: RoleMappingsPageProvider,
|
||||
rollup: RollupPageObject,
|
||||
searchProfiler: SearchProfilerPageProvider,
|
||||
searchSessionsManagement: SearchSessionsPageProvider,
|
||||
security: SecurityPageObject,
|
||||
shareSavedObjectsToSpace: ShareSavedObjectsToSpacePageProvider,
|
||||
|
|
54
x-pack/test/functional/page_objects/search_profiler_page.ts
Normal file
54
x-pack/test/functional/page_objects/search_profiler_page.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 { compressToEncodedURIComponent } from 'lz-string';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export function SearchProfilerPageProvider({ getService }: FtrProviderContext) {
|
||||
const find = getService('find');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const aceEditor = getService('aceEditor');
|
||||
const editorTestSubjectSelector = 'searchProfilerEditor';
|
||||
|
||||
return {
|
||||
async editorExists() {
|
||||
return await testSubjects.exists(editorTestSubjectSelector);
|
||||
},
|
||||
async setQuery(query: any) {
|
||||
await aceEditor.setValue(editorTestSubjectSelector, JSON.stringify(query));
|
||||
},
|
||||
async getQuery() {
|
||||
return JSON.parse(await aceEditor.getValue(editorTestSubjectSelector));
|
||||
},
|
||||
async setIndexName(indexName: string) {
|
||||
await testSubjects.setValue('indexName', indexName);
|
||||
},
|
||||
async getIndexName() {
|
||||
const indexInput = await testSubjects.find('indexName');
|
||||
return await indexInput.getAttribute('value');
|
||||
},
|
||||
async clickProfileButton() {
|
||||
await testSubjects.click('profileButton');
|
||||
},
|
||||
async getProfileContent() {
|
||||
const profileTree = await find.byClassName('prfDevTool__main__profiletree');
|
||||
return profileTree.getVisibleText();
|
||||
},
|
||||
getUrlWithIndexAndQuery({ indexName, query }: { indexName: string; query: any }) {
|
||||
const searchQueryURI = compressToEncodedURIComponent(JSON.stringify(query, null, 2));
|
||||
return `/searchprofiler?index=${indexName}&load_from=${searchQueryURI}`;
|
||||
},
|
||||
async editorHasParseErrors() {
|
||||
return await aceEditor.hasParseErrors(editorTestSubjectSelector);
|
||||
},
|
||||
async editorHasErrorNotification() {
|
||||
const notification = await testSubjects.find('noShardsNotification');
|
||||
const text = await notification.getVisibleText();
|
||||
return text.includes('Unable to profile');
|
||||
},
|
||||
};
|
||||
}
|
|
@ -103,6 +103,10 @@ export function createTestConfig(options: CreateTestConfigOptions) {
|
|||
pathname: '/app/discover',
|
||||
hash: '/context',
|
||||
},
|
||||
searchProfiler: {
|
||||
pathname: '/app/dev_tools',
|
||||
hash: '/searchprofiler',
|
||||
},
|
||||
},
|
||||
// choose where screenshots should be saved
|
||||
screenshots: {
|
||||
|
|
|
@ -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 { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default ({ loadTestFile }: FtrProviderContext) => {
|
||||
describe('Serverless Common UI - Dev Tools', function () {
|
||||
loadTestFile(require.resolve('./search_profiler'));
|
||||
});
|
||||
};
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
const testIndex = 'test-index';
|
||||
const testQuery = {
|
||||
query: {
|
||||
match_all: {},
|
||||
},
|
||||
};
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
const PageObjects = getPageObjects(['svlCommonPage', 'common', 'searchProfiler']);
|
||||
const retry = getService('retry');
|
||||
const es = getService('es');
|
||||
|
||||
describe('Search Profiler Editor', () => {
|
||||
before(async () => {
|
||||
await PageObjects.svlCommonPage.login();
|
||||
await PageObjects.common.navigateToApp('searchProfiler');
|
||||
expect(await PageObjects.searchProfiler.editorExists()).to.be(true);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await PageObjects.svlCommonPage.forceLogout();
|
||||
});
|
||||
|
||||
it('supports pre-configured search query', async () => {
|
||||
const query = {
|
||||
query: {
|
||||
bool: {
|
||||
should: [
|
||||
{
|
||||
match: {
|
||||
name: 'fred',
|
||||
},
|
||||
},
|
||||
{
|
||||
terms: {
|
||||
name: ['sue', 'sally'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
aggs: {
|
||||
stats: {
|
||||
stats: {
|
||||
field: 'price',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Since we're not actually running the query in the test,
|
||||
// this index name is just an input placeholder and does not exist
|
||||
const indexName = 'my_index';
|
||||
|
||||
await PageObjects.common.navigateToUrl(
|
||||
'searchProfiler',
|
||||
PageObjects.searchProfiler.getUrlWithIndexAndQuery({ indexName, query }),
|
||||
{
|
||||
useActualUrl: true,
|
||||
}
|
||||
);
|
||||
|
||||
const indexInputValue = await PageObjects.searchProfiler.getIndexName();
|
||||
|
||||
expect(indexInputValue).to.eql(indexName);
|
||||
|
||||
await retry.try(async () => {
|
||||
const searchProfilerInput = await PageObjects.searchProfiler.getQuery();
|
||||
expect(searchProfilerInput).to.eql(query);
|
||||
});
|
||||
});
|
||||
|
||||
describe('With a test index', () => {
|
||||
before(async () => {
|
||||
await es.indices.create({ index: testIndex });
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await es.indices.delete({ index: testIndex });
|
||||
});
|
||||
|
||||
it('profiles a simple query', async () => {
|
||||
await PageObjects.searchProfiler.setIndexName(testIndex);
|
||||
await PageObjects.searchProfiler.setQuery(testQuery);
|
||||
|
||||
await PageObjects.searchProfiler.clickProfileButton();
|
||||
|
||||
const content = await PageObjects.searchProfiler.getProfileContent();
|
||||
expect(content).to.contain(testIndex);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -15,6 +15,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [
|
||||
require.resolve('../../common/home_page'),
|
||||
require.resolve('../../common/management'),
|
||||
require.resolve('../../common/dev_tools'),
|
||||
require.resolve('../../common/platform_security'),
|
||||
require.resolve('../../common/reporting'),
|
||||
require.resolve('../../common/grok_debugger'),
|
||||
|
|
|
@ -15,6 +15,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [
|
||||
require.resolve('../../common/home_page'),
|
||||
require.resolve('../../common/management'),
|
||||
require.resolve('../../common/dev_tools'),
|
||||
require.resolve('../../common/platform_security'),
|
||||
require.resolve('../../common/reporting'),
|
||||
require.resolve('../../common/console'),
|
||||
|
|
|
@ -15,6 +15,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [
|
||||
require.resolve('../../common/home_page'),
|
||||
require.resolve('../../common/management'),
|
||||
require.resolve('../../common/dev_tools'),
|
||||
require.resolve('../../common/platform_security'),
|
||||
require.resolve('../../common/reporting'),
|
||||
require.resolve('../../common/grok_debugger'),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue