Automate serverless screenshots (#165524)

Co-authored-by: Robert Oskamp <robert.oskamp@elastic.co>
This commit is contained in:
Lisa Cawley 2023-09-12 07:35:34 -07:00 committed by GitHub
parent 5a3a3c8039
commit bfa334c500
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 277 additions and 23 deletions

View file

@ -94,6 +94,7 @@ disabled:
- 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/search/config.screenshots.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

View file

@ -17,15 +17,17 @@ export function ActionsAPIServiceProvider({ getService }: FtrProviderContext) {
config,
secrets,
connectorTypeId,
additionalRequestHeaders,
}: {
name: string;
config: Record<string, unknown>;
secrets: Record<string, unknown>;
connectorTypeId: string;
additionalRequestHeaders?: object;
}) {
const { body: createdAction } = await kbnSupertest
.post(`/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.set({ ...additionalRequestHeaders, 'kbn-xsrf': 'foo' })
.send({
name,
config,
@ -37,24 +39,24 @@ export function ActionsAPIServiceProvider({ getService }: FtrProviderContext) {
return createdAction;
},
async deleteConnector(id: string) {
async deleteConnector(id: string, additionalRequestHeaders?: object) {
log.debug(`Deleting connector with id '${id}'...`);
const rsp = kbnSupertest
.delete(`/api/actions/connector/${id}`)
.set('kbn-xsrf', 'foo')
.set({ ...additionalRequestHeaders, 'kbn-xsrf': 'foo' })
.expect(204, '');
log.debug('> Connector deleted.');
return rsp;
},
async deleteAllConnectors() {
async deleteAllConnectors(additionalRequestHeaders?: object) {
const { body } = await kbnSupertest
.get(`/api/actions/connectors`)
.set('kbn-xsrf', 'foo')
.set({ ...additionalRequestHeaders, 'kbn-xsrf': 'foo' })
.expect(200);
for (const connector of body) {
await this.deleteConnector(connector.id);
await this.deleteConnector(connector.id, additionalRequestHeaders);
}
},
};

View file

@ -56,11 +56,11 @@ export function RulesAPIServiceProvider({ getService }: FtrProviderContext) {
return rsp;
},
async deleteAllRules() {
async deleteAllRules(additionalRequestHeaders?: object) {
log.debug(`Deleting all rules...`);
const { body } = await kbnSupertest
.get(`/api/alerting/rules/_find`)
.set('kbn-xsrf', 'foo')
.set({ ...additionalRequestHeaders, 'kbn-xsrf': 'foo' })
.expect(200);
for (const rule of body.data) {

View file

@ -13,21 +13,30 @@ export function SampleDataTestResourcesServiceProvider({ getService }: FtrProvid
const kibanaServer = getService('kibanaServer');
return {
async installKibanaSampleData(sampleDataId: 'ecommerce' | 'flights' | 'logs') {
await supertest.post(`/api/sample_data/${sampleDataId}`).set('kbn-xsrf', 'true').expect(200);
async installKibanaSampleData(
sampleDataId: 'ecommerce' | 'flights' | 'logs',
additionalRequestHeaders?: object
) {
await supertest
.post(`/api/sample_data/${sampleDataId}`)
.set({ ...additionalRequestHeaders, 'kbn-xsrf': 'true' })
.expect(200);
},
async removeKibanaSampleData(sampleDataId: 'ecommerce' | 'flights' | 'logs') {
async removeKibanaSampleData(
sampleDataId: 'ecommerce' | 'flights' | 'logs',
additionalRequestHeaders?: object
) {
await supertest
.delete(`/api/sample_data/${sampleDataId}`)
.set('kbn-xsrf', 'true')
.set({ ...additionalRequestHeaders, 'kbn-xsrf': 'true' })
.expect(204);
},
async installAllKibanaSampleData() {
await this.installKibanaSampleData('ecommerce');
await this.installKibanaSampleData('flights');
await this.installKibanaSampleData('logs');
async installAllKibanaSampleData(additionalRequestHeaders?: object) {
await this.installKibanaSampleData('ecommerce', additionalRequestHeaders);
await this.installKibanaSampleData('flights', additionalRequestHeaders);
await this.installKibanaSampleData('logs', additionalRequestHeaders);
// Sample data is shifted to be relative to current time
// This means that a static timerange will return different documents
@ -46,10 +55,10 @@ export function SampleDataTestResourcesServiceProvider({ getService }: FtrProvid
});
},
async removeAllKibanaSampleData() {
await this.removeKibanaSampleData('ecommerce');
await this.removeKibanaSampleData('flights');
await this.removeKibanaSampleData('logs');
async removeAllKibanaSampleData(additionalRequestHeaders?: object) {
await this.removeKibanaSampleData('ecommerce', additionalRequestHeaders);
await this.removeKibanaSampleData('flights', additionalRequestHeaders);
await this.removeKibanaSampleData('logs', additionalRequestHeaders);
},
};
}

View file

@ -10,7 +10,6 @@ import { GenericFtrProviderContext } from '@kbn/test';
import { services as xpackApiIntegrationServices } from '../../../test/api_integration/services';
import { services as svlSharedServices } from '../../shared/services';
import { SvlCommonApiServiceProvider } from './svl_common_api';
import { AlertingApiProvider } from './alerting_api';
import { SamlToolsProvider } from './saml_tools';
import { DataViewApiProvider } from './data_view_api';
@ -20,7 +19,6 @@ export const services = {
...xpackApiIntegrationServices,
...svlSharedServices,
svlCommonApi: SvlCommonApiServiceProvider,
alertingApi: AlertingApiProvider,
samlTools: SamlToolsProvider,
dataViewApi: DataViewApiProvider,

View file

@ -62,6 +62,9 @@ export function createTestConfig(options: CreateTestConfigOptions) {
indexManagement: {
pathname: '/app/management/data/index_management',
},
connectors: {
pathname: '/app/management/insightsAndAlerting/triggersActionsConnectors/',
},
advancedSettings: {
pathname: '/app/management/kibana/settings',
},

View file

@ -13,6 +13,7 @@ import { SvlCommonNavigationServiceProvider } from './svl_common_navigation';
import { SvlObltNavigationServiceProvider } from './svl_oblt_navigation';
import { SvlSearchNavigationServiceProvider } from './svl_search_navigation';
import { SvlSecNavigationServiceProvider } from './svl_sec_navigation';
import { SvlCommonScreenshotsProvider } from './svl_common_screenshots';
export const services = {
...xpackFunctionalServices,
@ -22,4 +23,5 @@ export const services = {
svlObltNavigation: SvlObltNavigationServiceProvider,
svlSearchNavigation: SvlSearchNavigationServiceProvider,
svlSecNavigation: SvlSecNavigationServiceProvider,
svlCommonScreenshots: SvlCommonScreenshotsProvider,
};

View file

@ -0,0 +1,46 @@
/*
* 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 function SvlCommonScreenshotsProvider({ getService }: FtrProviderContext) {
const browser = getService('browser');
const screenshot = getService('screenshots');
const testSubjects = getService('testSubjects');
const DEFAULT_WIDTH = 1920;
const DEFAULT_HEIGHT = 1080;
return {
async takeScreenshot(name: string, subDirectories: string[], width?: number, height?: number) {
await browser.setWindowSize(width ?? DEFAULT_WIDTH, height ?? DEFAULT_HEIGHT);
await new Promise((resolve) => setTimeout(resolve, 1000)); // give components time to resize
await screenshot.take(`${name}_new`, undefined, subDirectories);
await browser.setWindowSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
},
async openKibanaNav() {
if (!(await testSubjects.exists('collapsibleNav'))) {
await testSubjects.click('toggleNavButton');
}
await testSubjects.existOrFail('collapsibleNav');
},
async closeKibanaNav() {
if (await testSubjects.exists('collapsibleNav')) {
await testSubjects.click('toggleNavButton');
}
await testSubjects.missingOrFail('collapsibleNav');
},
async removeFocusFromElement() {
// open and close the Kibana nav to un-focus the last used element
await this.openKibanaNav();
await this.closeKibanaNav();
},
};
}

View 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { createTestConfig } from '../../config.base';
const enabledActionTypes = ['.index', '.server-log'];
export default createTestConfig({
serverlessProject: 'es',
testFiles: [require.resolve('./screenshot_creation')],
kbnServerArgs: [`--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`],
junit: {
reportName: 'Serverless Search Screenshot Creation',
},
});

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 { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Screenshots - serverless search UI', function () {
loadTestFile(require.resolve('./response_ops_docs'));
});
}

View file

@ -0,0 +1,42 @@
/*
* 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 const ECOMMERCE_INDEX_PATTERN = 'kibana_sample_data_ecommerce';
export const FLIGHTS_INDEX_PATTERN = 'kibana_sample_data_flights';
export const LOGS_INDEX_PATTERN = 'kibana_sample_data_logs';
export default function ({ getService, loadTestFile }: FtrProviderContext) {
const browser = getService('browser');
const ml = getService('ml');
const sampleData = getService('sampleData');
const svlCommonApi = getService('svlCommonApi');
describe('response ops docs', function () {
this.tags(['responseOps']);
before(async () => {
await sampleData.testResources.installAllKibanaSampleData(
svlCommonApi.getInternalRequestHeader()
);
await ml.testResources.setKibanaTimeZoneToUTC();
await ml.testResources.disableKibanaAnnouncements();
await browser.setWindowSize(1920, 1080);
});
after(async () => {
await sampleData.testResources.removeAllKibanaSampleData(
svlCommonApi.getInternalRequestHeader()
);
await ml.testResources.resetKibanaTimeZone();
await ml.testResources.resetKibanaAnnouncements();
});
loadTestFile(require.resolve('./stack_connectors'));
});
}

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.
*/
import { FtrProviderContext } from '../../../../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const svlCommonScreenshots = getService('svlCommonScreenshots');
// const browser = getService('browser');
// const find = getService('find');
// const testSubjects = getService('testSubjects');
const screenshotDirectories = ['response_ops_docs', 'stack_connectors'];
const pageObjects = getPageObjects(['common', 'header']);
describe('connectors', function () {
it('connectors list screenshot', async () => {
await pageObjects.common.navigateToApp('connectors');
await pageObjects.header.waitUntilLoadingHasFinished();
await svlCommonScreenshots.takeScreenshot(
'connector-listing',
screenshotDirectories,
1400,
1024
);
// const searchBox = await find.byCssSelector('[data-test-subj="actionsList"] .euiFieldSearch');
// await searchBox.click();
// await searchBox.clearValue();
// await searchBox.type('my actionTypeId:(.index)');
// await searchBox.pressKeys(browser.keys.ENTER);
// const typeFilter = await find.byCssSelector(
// '[data-test-subj="actionsList"] .euiFilterButton'
// );
// await typeFilter.click();
// await commonScreenshots.takeScreenshot(
// 'connector-filter-by-type',
// screenshotDirectories,
// 1400,
// 1024
// );
// const clearSearchButton = await testSubjects.find('clearSearchButton');
// await clearSearchButton.click();
// const checkAllButton = await testSubjects.find('checkboxSelectAll');
// await checkAllButton.click();
// await commonScreenshots.takeScreenshot('connector-delete', screenshotDirectories, 1400, 1024);
});
});
}

View file

@ -0,0 +1,63 @@
/*
* 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, getService }: FtrProviderContext) {
const actions = getService('actions');
const browser = getService('browser');
const es = getService('es');
const rules = getService('rules');
const testIndex = `test-index`;
const svlCommonApi = getService('svlCommonApi');
describe('stack connectors', function () {
before(async () => {
await browser.setWindowSize(1920, 1080);
await actions.api.createConnector({
name: 'server-log-connector',
config: {},
secrets: {},
connectorTypeId: '.server-log',
additionalRequestHeaders: svlCommonApi.getInternalRequestHeader(),
});
await es.indices.create({
index: testIndex,
body: {
mappings: {
properties: {
date_updated: {
type: 'date',
format: 'epoch_millis',
},
},
},
},
});
await actions.api.createConnector({
name: 'my-index-connector',
config: {
index: testIndex,
},
secrets: {},
connectorTypeId: '.index',
additionalRequestHeaders: svlCommonApi.getInternalRequestHeader(),
});
});
after(async () => {
await rules.api.deleteAllRules(svlCommonApi.getInternalRequestHeader());
await actions.api.deleteAllConnectors(svlCommonApi.getInternalRequestHeader());
await es.indices.delete({ index: testIndex });
});
loadTestFile(require.resolve('./connectors'));
// loadTestFile(require.resolve('./connector_types'));
});
}

View file

@ -6,7 +6,10 @@
*/
import { SupertestProvider, SupertestWithoutAuthProvider } from './supertest';
import { SvlCommonApiServiceProvider } from './svl_common_api';
export const services = {
supertest: SupertestProvider,
supertestWithoutAuth: SupertestWithoutAuthProvider,
svlCommonApi: SvlCommonApiServiceProvider,
};

View file

@ -7,7 +7,7 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
import { FtrProviderContext } from '../../functional/ftr_provider_context';
const COMMON_REQUEST_HEADERS = {
'kbn-xsrf': 'some-xsrf-token',