Skip to content

Commit

Permalink
[kbn-scout] initial package implementation (playwright-test POC) (ela…
Browse files Browse the repository at this point in the history
…stic#194006)

## Summary

This PR introduces a new package, **kbn-scout**, designed to streamline
the setup and execution of Playwright tests for Kibana. The `kbn-scout`
package consolidates server management and testing capabilities by
wrapping both the Kibana/Elasticsearch server launcher and the
Playwright test runner. It includes:

- Test and worker-scoped fixtures for reliable setup across test suites
- Page objects combined into the fixture for Kibana UI interactions
- Configurations for seamless test execution in both local and CI
environments (`Cloud` execution is out of scope)
- This package aims to simplify test setup and enhance modularity,
making it easier to create, run, and maintain deployment-agnostic tests,
that are located in the plugin they actually test.

Tests example is available in `x-pack/plugins/discover_enhanced` plugin
under `ui_tests` folder

How to run:
1) As a single script (servers + tests): 
```
node scripts/scout_test.js --config=x-pack/plugins/discover_enhanced/ui_tests/playwright.config.ts --serverless=es
```

2) Start servers first
```
node scripts/scout_start_servers.js --serverless=es
```
then run tests:
```
npx playwright test --config=x-pack/plugins/discover_enhanced/ui_tests/playwright.config.ts
```
if you have Playwright plugin in IDEA, just use it to run tests files

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
dmlemeshko and kibanamachine authored Nov 26, 2024
1 parent a92103b commit 310d922
Show file tree
Hide file tree
Showing 86 changed files with 3,081 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ packages/kbn-rrule @elastic/response-ops
packages/kbn-rule-data-utils @elastic/security-detections-response @elastic/response-ops @elastic/obs-ux-management-team
packages/kbn-safer-lodash-set @elastic/kibana-security
packages/kbn-saved-objects-settings @elastic/appex-sharedux
packages/kbn-scout @elastic/appex-qa
packages/kbn-screenshotting-server @elastic/appex-sharedux
packages/kbn-search-api-keys-components @elastic/search-kibana
packages/kbn-search-api-keys-server @elastic/search-kibana
Expand Down Expand Up @@ -1552,6 +1553,7 @@ packages/kbn-monaco/src/esql @elastic/kibana-esql
/.eslintignore @elastic/kibana-operations

# QA - Appex QA
/x-pack/plugins/discover_enhanced/ui_tests/ @elastic/appex-qa # temporarily
/x-pack/test/functional/fixtures/package_registry_config.yml @elastic/appex-qa # No usages found
/x-pack/test/functional/fixtures/kbn_archiver/packaging.json @elastic/appex-qa # No usages found
/x-pack/test/functional/es_archives/filebeat @elastic/appex-qa
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ x-pack/test/security_api_integration/plugins/audit_log/audit.log
.ftr
role_users.json

# ignore Scout temp directory
.scout

.devcontainer/.env

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,7 @@
"@kbn/repo-path": "link:packages/kbn-repo-path",
"@kbn/repo-source-classifier": "link:packages/kbn-repo-source-classifier",
"@kbn/repo-source-classifier-cli": "link:packages/kbn-repo-source-classifier-cli",
"@kbn/scout": "link:packages/kbn-scout",
"@kbn/security-api-integration-helpers": "link:x-pack/test/security_api_integration/packages/helpers",
"@kbn/serverless-storybook-config": "link:packages/serverless/storybook/config",
"@kbn/some-dev-log": "link:packages/kbn-some-dev-log",
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-repo-source-classifier/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,6 @@ export const TEST_DIR = new Set([
'storybook',
'.storybook',
'integration_tests',
'ui_tests',
...RANDOM_TEST_FILE_NAMES,
]);
9 changes: 9 additions & 0 deletions packages/kbn-scout/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @kbn/scout

The package is designed to streamline the setup and execution of Playwright tests for Kibana. It consolidates server management and testing capabilities by wrapping both the Kibana/Elasticsearch server launcher and the Playwright test runner. It includes:

- core test and worker-scoped fixtures for reliable setup across test suites
- page objects combined into the fixture for for core Kibana apps UI interactions
- configurations for seamless test execution in both local and CI environments

This package aims to simplify test setup and enhance modularity, making it easier to create, run, and maintain deployment-agnostic tests, that are located in the plugin they actually test.
19 changes: 19 additions & 0 deletions packages/kbn-scout/index.ts
Original file line number Diff line number Diff line change
@@ -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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { startServersCli, runTestsCli } from './src/cli';
export { expect, test, createPlaywrightConfig, createLazyPageObject } from './src/playwright';
export type {
ScoutPage,
ScoutPlaywrightOptions,
ScoutTestOptions,
PageObjects,
ScoutTestFixtures,
ScoutWorkerFixtures,
} from './src/playwright';
14 changes: 14 additions & 0 deletions packages/kbn-scout/jest.config.js
Original file line number Diff line number Diff line change
@@ -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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

module.exports = {
preset: '@kbn/test/jest_node',
rootDir: '../..',
roots: ['<rootDir>/packages/kbn-scout'],
};
6 changes: 6 additions & 0 deletions packages/kbn-scout/kibana.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "test-helper",
"id": "@kbn/scout",
"owner": "@elastic/appex-qa",
"devOnly": true
}
6 changes: 6 additions & 0 deletions packages/kbn-scout/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "@kbn/scout",
"private": true,
"version": "1.0.0",
"license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0"
}
11 changes: 11 additions & 0 deletions packages/kbn-scout/src/cli/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { runTestsCli } from './run_tests_cli';
export { startServersCli } from './start_servers_cli';
39 changes: 39 additions & 0 deletions packages/kbn-scout/src/cli/run_tests_cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { run } from '@kbn/dev-cli-runner';
import { initLogsDir } from '@kbn/test';
import { TEST_FLAG_OPTIONS, parseTestFlags, runTests } from '../playwright/runner';

/**
* Start servers and run the tests
*/
export function runTestsCli() {
run(
async ({ flagsReader, log }) => {
const options = await parseTestFlags(flagsReader);

if (options.logsDir) {
initLogsDir(log, options.logsDir);
}

await runTests(log, options);
},
{
description: `Run Scout UI Tests`,
usage: `
Usage:
node scripts/scout_test --help
node scripts/scout_test --stateful --config <playwright_config_path>
node scripts/scout_test --serverless=es --headed --config <playwright_config_path>
`,
flags: TEST_FLAG_OPTIONS,
}
);
}
34 changes: 34 additions & 0 deletions packages/kbn-scout/src/cli/start_servers_cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { run } from '@kbn/dev-cli-runner';

import { initLogsDir } from '@kbn/test';

import { startServers, parseServerFlags, SERVER_FLAG_OPTIONS } from '../servers';

/**
* Start servers
*/
export function startServersCli() {
run(
async ({ flagsReader: flags, log }) => {
const options = parseServerFlags(flags);

if (options.logsDir) {
initLogsDir(log, options.logsDir);
}

await startServers(log, options);
},
{
flags: SERVER_FLAG_OPTIONS,
}
);
}
16 changes: 16 additions & 0 deletions packages/kbn-scout/src/common/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { Role } from '@kbn/test/src/auth/types';

export const PROJECT_DEFAULT_ROLES = new Map<string, Role>([
['es', 'developer'],
['security', 'editor'],
['oblt', 'editor'],
]);
12 changes: 12 additions & 0 deletions packages/kbn-scout/src/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export * from './services';
export * from './constants';
export * from './utils';
58 changes: 58 additions & 0 deletions packages/kbn-scout/src/common/services/clients.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { KbnClient, createEsClientForTesting } from '@kbn/test';
import type { ToolingLog } from '@kbn/tooling-log';
import { ScoutServerConfig } from '../../types';
import { serviceLoadedMsg } from '../../playwright/utils';

interface ClientOptions {
serviceName: string;
url: string;
username: string;
password: string;
log: ToolingLog;
}

function createClientUrlWithAuth({ serviceName, url, username, password, log }: ClientOptions) {
const clientUrl = new URL(url);
clientUrl.username = username;
clientUrl.password = password;

log.debug(serviceLoadedMsg(`${serviceName}client`));
return clientUrl.toString();
}

export function createEsClient(config: ScoutServerConfig, log: ToolingLog) {
const { username, password } = config.auth;
const elasticsearchUrl = createClientUrlWithAuth({
serviceName: 'Es',
url: config.hosts.elasticsearch,
username,
password,
log,
});

return createEsClientForTesting({
esUrl: elasticsearchUrl,
authOverride: { username, password },
});
}

export function createKbnClient(config: ScoutServerConfig, log: ToolingLog) {
const kibanaUrl = createClientUrlWithAuth({
serviceName: 'Kbn',
url: config.hosts.kibana,
username: config.auth.username,
password: config.auth.password,
log,
});

return new KbnClient({ log, url: kibanaUrl });
}
29 changes: 29 additions & 0 deletions packages/kbn-scout/src/common/services/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import path from 'path';
import fs from 'fs';
import { ToolingLog } from '@kbn/tooling-log';
import { ScoutServerConfig } from '../../types';
import { serviceLoadedMsg } from '../../playwright/utils';

export function createScoutConfig(configDir: string, configName: string, log: ToolingLog) {
if (!configDir || !fs.existsSync(configDir)) {
throw new Error(`Directory with servers configuration is missing`);
}

const configPath = path.join(configDir, `${configName}.json`);
log.info(`Reading test servers confiuration from file: ${configPath}`);

const config = JSON.parse(fs.readFileSync(configPath, 'utf-8')) as ScoutServerConfig;

log.debug(serviceLoadedMsg('config'));

return config;
}
28 changes: 28 additions & 0 deletions packages/kbn-scout/src/common/services/es_archiver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { Client } from '@elastic/elasticsearch';
import { EsArchiver } from '@kbn/es-archiver';
import { REPO_ROOT } from '@kbn/repo-info';
import type { KbnClient } from '@kbn/test';
import type { ToolingLog } from '@kbn/tooling-log';
import { serviceLoadedMsg } from '../../playwright/utils';

export function createEsArchiver(esClient: Client, kbnClient: KbnClient, log: ToolingLog) {
const esArchiver = new EsArchiver({
log,
client: esClient,
kbnClient,
baseDir: REPO_ROOT,
});

log.debug(serviceLoadedMsg('esArchiver'));

return esArchiver;
}
17 changes: 17 additions & 0 deletions packages/kbn-scout/src/common/services/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { createEsClient, createKbnClient } from './clients';
export { createScoutConfig } from './config';
export { createEsArchiver } from './es_archiver';
export { createKbnUrl } from './kibana_url';
export { createSamlSessionManager } from './saml_auth';
export { createLogger } from './logger';

export type { KibanaUrl } from './kibana_url';
Loading

0 comments on commit 310d922

Please sign in to comment.