[User Experience] Synthetics e2e tests. (#132896)

Co-authored-by: shahzad31 <shahzad.muhammad@elastic.co>
This commit is contained in:
Abdul Wahab Zahid 2022-05-31 18:03:25 +02:00 committed by GitHub
parent ec4d9abbc1
commit eab8ece3fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 17732 additions and 152 deletions

View file

@ -39,7 +39,8 @@ disabled:
# Elastic Synthetics configs
- x-pack/plugins/synthetics/e2e/config.ts
- x-pack/plugins/synthetics/e2e/playwright_run.ts
- x-pack/plugins/synthetics/e2e/synthetics_run.ts
- x-pack/plugins/ux/e2e/synthetics_run.ts
# Configs that exist but weren't running in CI when this file was introduced
- test/visual_regression/config.ts

View file

@ -0,0 +1,11 @@
steps:
- command: .buildkite/scripts/steps/functional/ux_synthetics_e2e.sh
label: 'UX Plugin @elastic/synthetics Tests'
agents:
queue: ci-group-6
depends_on: build
timeout_in_minutes: 120
retry:
automatic:
- exit_status: '*'
limit: 1

View file

@ -108,6 +108,10 @@ const uploadPipeline = (pipelineContent) => {
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/synthetics_plugin.yml'));
}
if (await doAnyChangesMatch([/^x-pack\/plugins\/ux/])) {
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/ux_plugin_e2e.yml'));
}
if (process.env.GITHUB_PR_LABELS.includes('ci:deploy-cloud')) {
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/deploy_cloud.yml'));
}

View file

@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail
source .buildkite/scripts/common/util.sh
.buildkite/scripts/bootstrap.sh
.buildkite/scripts/download_build_artifacts.sh
export JOB=kibana-ux-plugin-synthetics
echo "--- User Experience @elastic/synthetics Tests"
cd "$XPACK_DIR"
checks-reporter-with-killswitch "User Experience plugin @elastic/synthetics Tests" \
node plugins/ux/scripts/e2e.js --kibana-install-dir "$KIBANA_BUILD_LOCATION" ${GREP:+--grep \"${GREP}\"}

View file

@ -77,6 +77,7 @@ it('produces the right watch and ignore list', () => {
<absolute path>/x-pack/plugins/security_solution/scripts,
<absolute path>/x-pack/plugins/security_solution/server/lib/detection_engine/scripts,
<absolute path>/x-pack/plugins/synthetics/e2e,
<absolute path>/x-pack/plugins/ux/e2e,
]
`);
});

View file

@ -67,6 +67,7 @@ export function getServerWatchPaths({ pluginPaths, pluginScanDirs }: Options) {
fromRoot('x-pack/plugins/security_solution/scripts'),
fromRoot('x-pack/plugins/security_solution/server/lib/detection_engine/scripts'),
fromRoot('x-pack/plugins/synthetics/e2e'),
fromRoot('x-pack/plugins/ux/e2e'),
];
return {

View file

@ -70,6 +70,11 @@ export const PROJECTS = [
disableTypeCheck: true,
}),
createProject('x-pack/plugins/ux/e2e/tsconfig.json', {
name: 'ux/synthetics-e2e-tests',
disableTypeCheck: true,
}),
// Glob patterns to be all search at once
...findProjects([
'src/plugins/*/tsconfig.json',

View file

@ -0,0 +1,12 @@
#!/usr/bin/env bash
source test/scripts/jenkins_test_setup_xpack.sh
echo " -> Running User Experience plugin @elastic/synthetics tests"
cd "$XPACK_DIR"
checks-reporter-with-killswitch "User Experience plugin @elastic/synthetics Tests" \
node plugins/ux/scripts/e2e.js
echo ""
echo ""

View file

@ -165,6 +165,15 @@ def functionalXpack(Map params = [:]) {
}
}
whenChanged([
'x-pack/plugins/ux/',
]) {
if (githubPr.isPr()) {
task(kibanaPipeline.functionalTestProcess('xpack-uxPluginSynthetics', './test/scripts/jenkins_ux_synthetics.sh'))
}
}
whenChanged([
'x-pack/plugins/fleet/',
]) {

View file

@ -4,9 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrConfigProviderContext } from '@kbn/test';
import yargs from 'yargs';
import { playwrightRunTests } from './playwright_start';
const { argv } = yargs(process.argv.slice(2))
.option('headless', {
@ -14,6 +13,11 @@ const { argv } = yargs(process.argv.slice(2))
type: 'boolean',
description: 'Start in headless mode',
})
.option('pauseOnError', {
default: false,
type: 'boolean',
description: 'Pause on error',
})
.option('grep', {
default: undefined,
type: 'string',
@ -21,15 +25,4 @@ const { argv } = yargs(process.argv.slice(2))
})
.help();
const { headless, grep } = argv;
async function runE2ETests({ readConfigFile }: FtrConfigProviderContext) {
const kibanaConfig = await readConfigFile(require.resolve('./config.ts'));
return {
...kibanaConfig.getAll(),
testRunner: playwrightRunTests({ headless, match: grep }),
};
}
// eslint-disable-next-line import/no-default-export
export default runE2ETests;
export { argv };

View file

@ -1,62 +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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
/* eslint-disable no-console */
import Url from 'url';
import { run as playwrightRun } from '@elastic/synthetics';
import { createApmUsers } from '@kbn/apm-plugin/scripts/create_apm_users/create_apm_users';
import { esArchiverLoad, esArchiverUnload } from './tasks/es_archiver';
import './journeys';
export function playwrightRunTests({ headless, match }: { headless: boolean; match?: string }) {
return async ({ getService }: any) => {
const results = await playwrightStart(getService, headless, match);
Object.entries(results).forEach(([_journey, result]) => {
if (result.status !== 'succeeded') {
throw new Error('Tests failed');
}
});
};
}
async function playwrightStart(getService: any, headless = true, match?: string) {
console.log('Loading esArchiver...');
const esArchiver = getService('esArchiver');
esArchiverLoad('full_heartbeat');
esArchiverLoad('browser');
const config = getService('config');
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote');
const kibanaUrl = Url.format({
protocol: config.get('servers.kibana.protocol'),
hostname: config.get('servers.kibana.hostname'),
port: config.get('servers.kibana.port'),
});
await createApmUsers({
elasticsearch: { username: 'elastic', password: 'changeme' },
kibana: { hostname: kibanaUrl },
});
const res = await playwrightRun({
params: { kibanaUrl, getService },
playwrightOptions: { headless, chromiumSandbox: false, timeout: 60 * 1000 },
match: match === 'undefined' ? '' : match,
});
console.log('Removing esArchiver...');
esArchiverUnload('full_heartbeat');
esArchiverUnload('browser');
return res;
}

View file

@ -0,0 +1,41 @@
/*
* 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 { FtrConfigProviderContext } from '@kbn/test';
import path from 'path';
import { SyntheticsRunner } from './synthetics_start';
import { argv } from './parse_args_params';
const { headless, grep, pauseOnError } = argv;
async function runE2ETests({ readConfigFile }: FtrConfigProviderContext) {
const kibanaConfig = await readConfigFile(require.resolve('./config.ts'));
return {
...kibanaConfig.getAll(),
testRunner: async ({ getService }: any) => {
const syntheticsRunner = new SyntheticsRunner(getService, {
headless,
match: grep,
pauseOnError,
});
await syntheticsRunner.setup();
const fixturesDir = path.join(__dirname, '../e2e/fixtures/es_archiver/');
await syntheticsRunner.loadTestData(fixturesDir, ['full_heartbeat', 'browser']);
await syntheticsRunner.loadTestFiles(async () => {
require('./journeys');
});
await syntheticsRunner.run();
},
};
}
// eslint-disable-next-line import/no-default-export
export default runE2ETests;

View file

@ -0,0 +1,106 @@
/*
* 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.
*/
/* eslint-disable no-console */
import Url from 'url';
import { run as syntheticsRun } from '@elastic/synthetics';
import { PromiseType } from 'utility-types';
import { createApmUsers } from '@kbn/apm-plugin/scripts/create_apm_users/create_apm_users';
import { esArchiverUnload } from './tasks/es_archiver';
export interface ArgParams {
headless: boolean;
match?: string;
pauseOnError: boolean;
}
export class SyntheticsRunner {
public getService: any;
public kibanaUrl: string;
public testFilesLoaded: boolean = false;
public params: ArgParams;
constructor(getService: any, params: ArgParams) {
this.getService = getService;
this.kibanaUrl = this.getKibanaUrl();
this.params = params;
}
async setup() {
await this.createTestUsers();
}
async createTestUsers() {
await createApmUsers({
elasticsearch: { username: 'elastic', password: 'changeme' },
kibana: { hostname: this.kibanaUrl },
});
}
async loadTestFiles(callback: () => Promise<void>) {
console.log('Loading test files');
await callback();
this.testFilesLoaded = true;
console.log('Successfully loaded test files');
}
async loadTestData(e2eDir: string, dataArchives: string[]) {
console.log('Loading esArchiver...');
const esArchiver = this.getService('esArchiver');
const promises = dataArchives.map((archive) => esArchiver.loadIfNeeded(e2eDir + archive));
await Promise.all([
...promises,
esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote'),
]);
}
getKibanaUrl() {
const config = this.getService('config');
return Url.format({
protocol: config.get('servers.kibana.protocol'),
hostname: config.get('servers.kibana.hostname'),
port: config.get('servers.kibana.port'),
});
}
async run() {
if (!this.testFilesLoaded) {
throw new Error('Test files not loaded');
}
const { headless, match, pauseOnError } = this.params;
const results = await syntheticsRun({
params: { kibanaUrl: this.kibanaUrl, getService: this.getService },
playwrightOptions: { headless, chromiumSandbox: false, timeout: 60 * 1000 },
match: match === 'undefined' ? '' : match,
pauseOnError,
});
await this.assertResults(results);
}
assertResults(results: PromiseType<ReturnType<typeof syntheticsRun>>) {
Object.entries(results).forEach(([_journey, result]) => {
if (result.status !== 'succeeded') {
throw new Error('Tests failed');
}
});
}
cleanUp() {
console.log('Removing esArchiver...');
esArchiverUnload('full_heartbeat');
esArchiverUnload('browser');
}
}

View file

@ -0,0 +1,89 @@
/*
* 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.
*/
/* eslint-disable no-console */
const yargs = require('yargs');
const childProcess = require('child_process');
const { argv } = yargs(process.argv.slice(2))
.option('server', {
default: false,
type: 'boolean',
description: 'Start Elasticsearch and kibana',
})
.option('runner', {
default: false,
type: 'boolean',
description:
'Run all tests (an instance of Elasticsearch and kibana are needs to be available)',
})
.option('open', {
default: false,
type: 'boolean',
description: 'Opens the Synthetics Test Runner',
})
.option('kibana-install-dir', {
default: '',
type: 'string',
description: 'Path to the Kibana install directory',
})
.option('headless', {
default: true,
type: 'boolean',
description: 'Start in headless mode',
})
.option('grep', {
default: undefined,
type: 'string',
description: 'run only journeys with a name or tags that matches the glob',
})
.help();
const { server, runner, open, kibanaInstallDir, headless, grep } = argv;
let ftrScript = 'functional_tests';
if (server) {
ftrScript = 'functional_tests_server';
} else if (runner || open) {
ftrScript = 'functional_test_runner';
}
const config = './synthetics_run.ts';
function executeSyntheticsRunner(dirPath) {
console.log(`Running ${ftrScript} in ${dirPath}`);
if (server) {
childProcess.execSync(
`node ../../../../scripts/${ftrScript} --config ${config} --kibana-install-dir '${kibanaInstallDir}'`,
{
cwd: dirPath,
stdio: 'inherit',
}
);
} else if (runner) {
childProcess.execSync(
`node ../../../../scripts/${ftrScript} --config ${config} --kibana-install-dir '${kibanaInstallDir}' --headless ${headless} --grep '${grep}'`,
{
cwd: dirPath,
stdio: 'inherit',
}
);
} else {
childProcess.execSync(
`node ../../../../scripts/${ftrScript} --config ${config} --kibana-install-dir '${kibanaInstallDir}' --grep '${grep}'`,
{
cwd: dirPath,
stdio: 'inherit',
}
);
}
}
module.exports = {
executeSyntheticsRunner,
};

View file

@ -7,82 +7,9 @@
/* eslint-disable no-console */
const { executeSyntheticsRunner } = require('./base_e2e');
const path = require('path');
const yargs = require('yargs');
const childProcess = require('child_process');
const { argv } = yargs(process.argv.slice(2))
.option('server', {
default: false,
type: 'boolean',
description: 'Start Elasticsearch and kibana',
})
.option('runner', {
default: false,
type: 'boolean',
description:
'Run all tests (an instance of Elasticsearch and kibana are needs to be available)',
})
.option('open', {
default: false,
type: 'boolean',
description: 'Opens the Playwright Test Runner',
})
.option('kibana-install-dir', {
default: '',
type: 'string',
description: 'Path to the Kibana install directory',
})
.option('headless', {
default: true,
type: 'boolean',
description: 'Start in headless mode',
})
.option('grep', {
default: undefined,
type: 'string',
description: 'run only journeys with a name or tags that matches the glob',
})
.help();
const { server, runner, open, kibanaInstallDir, headless, grep } = argv;
const e2eDir = path.join(__dirname, '../e2e');
let ftrScript = 'functional_tests';
if (server) {
ftrScript = 'functional_tests_server';
} else if (runner || open) {
ftrScript = 'functional_test_runner';
}
const config = './playwright_run.ts';
function executeRunner() {
if (server) {
childProcess.execSync(
`node ../../../../scripts/${ftrScript} --config ${config} --kibana-install-dir '${kibanaInstallDir}'`,
{
cwd: e2eDir,
stdio: 'inherit',
}
);
} else if (runner) {
childProcess.execSync(
`node ../../../../scripts/${ftrScript} --config ${config} --kibana-install-dir '${kibanaInstallDir}' --headless ${headless} --grep '${grep}'`,
{
cwd: e2eDir,
stdio: 'inherit',
}
);
} else {
childProcess.execSync(
`node ../../../../scripts/${ftrScript} --config ${config} --kibana-install-dir '${kibanaInstallDir}' --grep '${grep}'`,
{
cwd: e2eDir,
stdio: 'inherit',
}
);
}
}
executeRunner();
executeSyntheticsRunner(e2eDir);

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
/*
* 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.
*/
export * from './url_ux_query.journey';

View file

@ -0,0 +1,49 @@
/*
* 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 { journey, step, expect, before } from '@elastic/synthetics';
import { UXDashboardDatePicker } from '../page_objects/date_picker';
import { byTestId, loginToKibana, waitForLoadingToFinish } from './utils';
journey('UX URL Query', async ({ page, params }) => {
before(async () => {
await waitForLoadingToFinish({ page });
});
const queryParams = {
percentile: '50',
rangeFrom: '2020-05-18T11:51:00.000Z',
rangeTo: '2021-10-30T06:37:15.536Z',
};
const queryString = new URLSearchParams(queryParams).toString();
const baseUrl = `${params.kibanaUrl}/app/ux`;
step('Go to UX Dashboard', async () => {
await page.goto(`${baseUrl}?${queryString}`, {
waitUntil: 'networkidle',
});
await loginToKibana({
page,
user: { username: 'viewer_user', password: 'changeme' },
});
});
step('Set date range', async () => {
const datePickerPage = new UXDashboardDatePicker(page);
await datePickerPage.setDefaultE2eRange();
});
step('Confirm query params', async () => {
const value = await page.$eval(
byTestId('uxPercentileSelect'),
(sel: HTMLInputElement) => sel.value
);
expect(value).toBe(queryParams.percentile);
});
});

View 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { expect, Page } from '@elastic/synthetics';
export async function waitForLoadingToFinish({ page }: { page: Page }) {
while (true) {
if ((await page.$(byTestId('kbnLoadingMessage'))) === null) break;
await page.waitForTimeout(5 * 1000);
}
}
export async function loginToKibana({
page,
user,
}: {
page: Page;
user?: { username: string; password: string };
}) {
await page.fill(
'[data-test-subj=loginUsername]',
user?.username ?? 'elastic',
{
timeout: 60 * 1000,
}
);
await page.fill(
'[data-test-subj=loginPassword]',
user?.password ?? 'changeme'
);
await page.click('[data-test-subj=loginSubmit]');
await waitForLoadingToFinish({ page });
}
export const byTestId = (testId: string) => {
return `[data-test-subj=${testId}]`;
};
export const assertText = async ({
page,
text,
}: {
page: Page;
text: string;
}) => {
await page.waitForSelector(`text=${text}`);
expect(await page.$(`text=${text}`)).toBeTruthy();
};
export const assertNotText = async ({
page,
text,
}: {
page: Page;
text: string;
}) => {
expect(await page.$(`text=${text}`)).toBeFalsy();
};
export const getQuerystring = (params: object) => {
return Object.entries(params)
.map(
([key, value]) =>
encodeURIComponent(key) + '=' + encodeURIComponent(value)
)
.join('&');
};
export const delay = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));

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 { Page } from '@elastic/synthetics';
import { Locator, byTestId } from './utils';
export class UXDashboardFilters {
readonly page: Page;
readonly percentileSelect: Locator;
constructor(page: Page) {
this.page = page;
this.percentileSelect = page.locator(byTestId('uxPercentileSelect'));
}
getPercentileOption(percentile: '50' | '55' | '90' | '95' | '99') {
return this.page.locator(byTestId(`p${percentile}Percentile`));
}
}

View file

@ -0,0 +1,68 @@
/*
* 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 moment from 'moment';
import { Page } from '@elastic/synthetics';
import { Locator, byTestId } from './utils';
const DEFAULT_ABS_START_UTC_DATE = '2022-05-22T19:00:00.000Z';
const DEFAULT_ABS_END_UTC_DATE = '2022-05-22T20:00:00.000Z';
const MOMENT_DATE_INPUT_FORMAT = 'MMM DD, YYYY @ HH:mm:ss:SSS';
export class UXDashboardDatePicker {
readonly page: Page;
readonly dateStarButton: Locator;
readonly dateEndButton: Locator;
readonly datePopupAbsoluteTab: Locator;
readonly dateAbsoluteInput: Locator;
readonly dateApplyButton: Locator;
constructor(page: Page) {
this.page = page;
this.dateStarButton = page.locator('.euiDatePopoverButton--start');
this.dateEndButton = page.locator('.euiDatePopoverButton--end');
this.datePopupAbsoluteTab = page.locator('text=Absolute');
this.dateAbsoluteInput = page.locator(
byTestId('superDatePickerAbsoluteDateInput')
);
this.dateApplyButton = page.locator(
byTestId('superDatePickerApplyTimeButton')
);
}
async setAbsoluteStartDate(dateStr: string) {
await this.dateStarButton.first().click({ timeout: 3 * 60 * 1000 });
await this.datePopupAbsoluteTab.first().click();
await this.dateAbsoluteInput.first().click({ clickCount: 3 }); // clear input
await this.dateAbsoluteInput.first().type(dateStr);
}
async setAbsoluteEndDate(dateStr: string) {
await this.dateEndButton.first().click();
await this.datePopupAbsoluteTab.first().click();
await this.dateAbsoluteInput.first().click({ clickCount: 3 }); // clear input
await this.dateAbsoluteInput.first().type(dateStr);
}
async applyDate() {
await this.dateApplyButton.click();
}
async setDefaultE2eRange() {
const startDateStr = moment(DEFAULT_ABS_START_UTC_DATE).format(
MOMENT_DATE_INPUT_FORMAT
);
await this.setAbsoluteStartDate(startDateStr);
const endDateStr = moment(DEFAULT_ABS_END_UTC_DATE).format(
MOMENT_DATE_INPUT_FORMAT
);
await this.setAbsoluteEndDate(endDateStr);
await this.applyDate();
}
}

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 { Page } from '@elastic/synthetics';
export function loginPageProvider({
page,
isRemote = false,
username = 'elastic',
password = 'changeme',
}: {
page: Page;
isRemote?: boolean;
username?: string;
password?: string;
}) {
return {
async waitForLoadingToFinish() {
while (true) {
if ((await page.$('[data-test-subj=kbnLoadingMessage]')) === null)
break;
await page.waitForTimeout(5 * 1000);
}
},
async loginToKibana(usernameT?: string, passwordT?: string) {
if (isRemote) {
await page.click('text="Log in with Elasticsearch"');
}
await page.fill('[data-test-subj=loginUsername]', usernameT ?? username, {
timeout: 60 * 1000,
});
await page.fill('[data-test-subj=loginPassword]', passwordT ?? password);
await page.click('[data-test-subj=loginSubmit]');
await this.waitForLoadingToFinish();
},
};
}

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 { expect, Page } from '@elastic/synthetics';
export type Locator = ReturnType<Page['locator']>;
export function byTestId(testId: string) {
return `[data-test-subj=${testId}]`;
}
export function utilsPageProvider({ page }: { page: Page }) {
return {
byTestId(testId: string) {
return byTestId(testId);
},
async waitForLoadingToFinish() {
while (true) {
if ((await page.$(this.byTestId('kbnLoadingMessage'))) === null) break;
await page.waitForTimeout(5 * 1000);
}
},
async dismissSyntheticsCallout() {
await page.click('[data-test-subj=uptimeDismissSyntheticsCallout]', {
timeout: 60 * 1000,
});
},
async assertText({ text }: { text: string }) {
await page.waitForSelector(`text=${text}`);
expect(await page.$(`text=${text}`)).toBeTruthy();
},
async fillByTestSubj(dataTestSubj: string, value: string) {
await page.fill(`[data-test-subj=${dataTestSubj}]`, value);
},
async selectByTestSubj(dataTestSubj: string, value: string) {
await page.selectOption(`[data-test-subj=${dataTestSubj}]`, value);
},
async checkByTestSubj(dataTestSubj: string, value: string) {
await page.check(`[data-test-subj=${dataTestSubj}]`);
},
async clickByTestSubj(dataTestSubj: string) {
await page.click(`[data-test-subj=${dataTestSubj}]`);
},
async findByTestSubj(dataTestSubj: string) {
return await page.waitForSelector(`[data-test-subj=${dataTestSubj}]`);
},
async findByText(text: string) {
return await page.waitForSelector(`text=${text}`);
},
};
}

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 { FtrConfigProviderContext } from '@kbn/test';
import { argv } from '@kbn/synthetics-plugin/e2e/parse_args_params';
import { SyntheticsRunner } from '@kbn/synthetics-plugin/e2e/synthetics_start';
import path from 'path';
const { headless, grep, pauseOnError } = argv;
async function runE2ETests({ readConfigFile }: FtrConfigProviderContext) {
const kibanaConfig = await readConfigFile(
require.resolve('@kbn/synthetics-plugin/e2e/config')
);
return {
...kibanaConfig.getAll(),
testRunner: async ({ getService }: any) => {
const syntheticsRunner = new SyntheticsRunner(getService, {
headless,
match: grep,
pauseOnError,
});
await syntheticsRunner.setup();
const fixturesDir = path.join(__dirname, '../e2e/fixtures/');
await syntheticsRunner.loadTestData(fixturesDir, [
'rum_8.0.0',
'rum_test_data',
]);
await syntheticsRunner.loadTestFiles(async () => {
require('./journeys');
});
await syntheticsRunner.run();
},
};
}
// eslint-disable-next-line import/no-default-export
export default runE2ETests;

View file

@ -0,0 +1,20 @@
{
"extends": "../../../../tsconfig.base.json",
"exclude": ["tmp", "target/**/*"],
"include": ["./**/*"],
"compilerOptions": {
"outDir": "target/types",
"types": [ "node"],
},
"references": [
{
"path": "../../apm/tsconfig.json",
},
{
"path": "../../synthetics/e2e/tsconfig.json",
},
{
"path": "../tsconfig.json",
}
]
}

View file

@ -0,0 +1,20 @@
/*
* 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.
*/
/* eslint-disable no-console */
/* eslint-disable @kbn/imports/uniform_imports */
const {
executeSyntheticsRunner,
} = require('../../synthetics/scripts/base_e2e');
const path = require('path');
const e2eDir = path.join(__dirname, '../e2e');
console.log(e2eDir);
executeSyntheticsRunner(e2eDir);