convert ftr runners into TS (#110057) (#110139)

Co-authored-by: Mikhail Shustov <restrry@gmail.com>
This commit is contained in:
Kibana Machine 2021-08-25 18:31:33 -04:00 committed by GitHub
parent bc8bbd9580
commit 923bf4090b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 100 additions and 53 deletions

View file

@ -8,6 +8,6 @@
export { runKibanaServer } from './run_kibana_server';
export { runElasticsearch } from './run_elasticsearch';
export { runFtr, hasTests, assertNoneExcluded } from './run_ftr';
export { runFtr, hasTests, assertNoneExcluded, CreateFtrOptions, CreateFtrParams } from './run_ftr';
export { KIBANA_ROOT, KIBANA_FTR_SCRIPT, FUNCTIONAL_CONFIG_PATH, API_CONFIG_PATH } from './paths';
export { runCli } from './run_cli';

View file

@ -10,16 +10,18 @@ import { inspect } from 'util';
import chalk from 'chalk';
import getopts from 'getopts';
/* eslint-disable no-console */
export class CliError extends Error {
constructor(message, exitCode = 1) {
constructor(message: string) {
super(message);
this.exitCode = exitCode;
Error.captureStackTrace(this, CliError);
}
}
export async function runCli(getHelpText, run) {
export async function runCli(
getHelpText: () => string,
run: (options: getopts.ParsedOptions) => Promise<void>
) {
try {
const userOptions = getopts(process.argv.slice(2)) || {};
if (userOptions.help) {

View file

@ -14,7 +14,7 @@ import { createTestEsCluster } from '../../es';
interface RunElasticsearchOptions {
log: ToolingLog;
esFrom: string;
esFrom?: string;
}
export async function runElasticsearch({
config,

View file

@ -5,14 +5,37 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ToolingLog } from '@kbn/dev-utils';
import { FunctionalTestRunner, readConfigFile } from '../../functional_test_runner';
import { CliError } from './run_cli';
export interface CreateFtrOptions {
/** installation dir from which to run Kibana */
installDir: string;
log: ToolingLog;
/** Whether to exit test run at the first failure */
bail?: boolean;
grep: string;
updateBaselines?: boolean;
suiteFiles?: {
include?: string[];
exclude?: string[];
};
suiteTags?: {
include?: string[];
exclude?: string[];
};
updateSnapshots?: boolean;
}
export interface CreateFtrParams {
configPath: string;
options: CreateFtrOptions;
}
async function createFtr({
configPath,
options: { installDir, log, bail, grep, updateBaselines, suiteFiles, suiteTags, updateSnapshots },
}) {
}: CreateFtrParams) {
const config = await readConfigFile(log, configPath);
return {
@ -28,18 +51,18 @@ async function createFtr({
updateBaselines,
updateSnapshots,
suiteFiles: {
include: [...suiteFiles.include, ...config.get('suiteFiles.include')],
exclude: [...suiteFiles.exclude, ...config.get('suiteFiles.exclude')],
include: [...(suiteFiles?.include || []), ...config.get('suiteFiles.include')],
exclude: [...(suiteFiles?.exclude || []), ...config.get('suiteFiles.exclude')],
},
suiteTags: {
include: [...suiteTags.include, ...config.get('suiteTags.include')],
exclude: [...suiteTags.exclude, ...config.get('suiteTags.exclude')],
include: [...(suiteTags?.include || []), ...config.get('suiteTags.include')],
exclude: [...(suiteTags?.exclude || []), ...config.get('suiteTags.exclude')],
},
}),
};
}
export async function assertNoneExcluded({ configPath, options }) {
export async function assertNoneExcluded({ configPath, options }: CreateFtrParams) {
const { config, ftr } = await createFtr({ configPath, options });
if (config.get('testRunner')) {
@ -61,7 +84,7 @@ export async function assertNoneExcluded({ configPath, options }) {
}
}
export async function runFtr({ configPath, options }) {
export async function runFtr({ configPath, options }: CreateFtrParams) {
const { ftr } = await createFtr({ configPath, options });
const failureCount = await ftr.run();
@ -72,7 +95,7 @@ export async function runFtr({ configPath, options }) {
}
}
export async function hasTests({ configPath, options }) {
export async function hasTests({ configPath, options }: CreateFtrParams) {
const { ftr, config } = await createFtr({ configPath, options });
if (config.get('testRunner')) {

View file

@ -5,11 +5,12 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ProcRunner } from '@kbn/dev-utils';
import { resolve, relative } from 'path';
import { KIBANA_ROOT, KIBANA_EXEC, KIBANA_EXEC_PATH } from './paths';
import type { Config } from '../../functional_test_runner';
function extendNodeOptions(installDir) {
function extendNodeOptions(installDir?: string) {
if (!installDir) {
return {};
}
@ -26,7 +27,15 @@ function extendNodeOptions(installDir) {
};
}
export async function runKibanaServer({ procs, config, options }) {
export async function runKibanaServer({
procs,
config,
options,
}: {
procs: ProcRunner;
config: Config;
options: { installDir?: string; extraKbnOpts?: string[] };
}) {
const { installDir } = options;
const runOptions = config.get('kbnTestServer.runOptions');
const env = config.get('kbnTestServer.env');
@ -45,7 +54,7 @@ export async function runKibanaServer({ procs, config, options }) {
});
}
function getKibanaCmd(installDir) {
function getKibanaCmd(installDir?: string) {
if (installDir) {
return process.platform.startsWith('win')
? resolve(installDir, 'bin/kibana.bat')
@ -61,14 +70,17 @@ function getKibanaCmd(installDir) {
* passed, we run from source code. We also allow passing in extra
* Kibana server options, so we tack those on here.
*/
function collectCliArgs(config, { installDir, extraKbnOpts }) {
const buildArgs = config.get('kbnTestServer.buildArgs') || [];
const sourceArgs = config.get('kbnTestServer.sourceArgs') || [];
const serverArgs = config.get('kbnTestServer.serverArgs') || [];
function collectCliArgs(
config: Config,
{ installDir, extraKbnOpts }: { installDir?: string; extraKbnOpts?: string[] }
) {
const buildArgs: string[] = config.get('kbnTestServer.buildArgs') || [];
const sourceArgs: string[] = config.get('kbnTestServer.sourceArgs') || [];
const serverArgs: string[] = config.get('kbnTestServer.serverArgs') || [];
return pipe(
serverArgs,
(args) => (installDir ? args.filter((a) => a !== '--oss') : args),
(args) => (installDir ? args.filter((a: string) => a !== '--oss') : args),
(args) => (installDir ? [...buildArgs, ...args] : [KIBANA_EXEC_PATH, ...sourceArgs, ...args]),
(args) => args.concat(extraKbnOpts || [])
);
@ -78,7 +90,7 @@ function collectCliArgs(config, { installDir, extraKbnOpts }) {
* Filter the cli args to remove duplications and
* overridden options
*/
function filterCliArgs(args) {
function filterCliArgs(args: string[]) {
return args.reduce((acc, val, ind) => {
// If original argv has a later basepath setting, skip this val.
if (isBasePathSettingOverridden(args, val, ind)) {
@ -95,7 +107,7 @@ function filterCliArgs(args) {
}
return [...acc, val];
}, []);
}, [] as string[]);
}
/**
@ -103,7 +115,7 @@ function filterCliArgs(args) {
* previous function. The first function's input
* is the arr array.
*/
function pipe(arr, ...fns) {
function pipe(arr: any[], ...fns: Array<(...args: any[]) => any>) {
return fns.reduce((acc, fn) => {
return fn(acc);
}, arr);
@ -113,16 +125,16 @@ function pipe(arr, ...fns) {
* Checks whether a specific parameter is allowed to appear multiple
* times in the Kibana parameters.
*/
function allowsDuplicate(val) {
function allowsDuplicate(val: string) {
return ['--plugin-path'].includes(val.split('=')[0]);
}
function isBasePathSettingOverridden(args, val, ind) {
function isBasePathSettingOverridden(args: string[], val: string, index: number) {
const key = val.split('=')[0];
const basePathKeys = ['--no-base-path', '--server.basePath'];
if (basePathKeys.includes(key)) {
if (findIndexFrom(args, ++ind, (opt) => basePathKeys.includes(opt.split('=')[0])) > -1) {
if (findIndexFrom(args, ++index, (opt) => basePathKeys.includes(opt.split('=')[0])) > -1) {
return true;
}
}
@ -130,6 +142,6 @@ function isBasePathSettingOverridden(args, val, ind) {
return false;
}
function findIndexFrom(array, index, ...args) {
return [...array].slice(index).findIndex(...args);
function findIndexFrom(array: string[], index: number, predicate: (element: string) => boolean) {
return [...array].slice(index).findIndex(predicate);
}

View file

@ -9,7 +9,7 @@
import { relative } from 'path';
import * as Rx from 'rxjs';
import { startWith, switchMap, take } from 'rxjs/operators';
import { withProcRunner } from '@kbn/dev-utils';
import { withProcRunner, ToolingLog } from '@kbn/dev-utils';
import dedent from 'dedent';
import {
@ -19,13 +19,14 @@ import {
assertNoneExcluded,
hasTests,
KIBANA_FTR_SCRIPT,
CreateFtrOptions,
} from './lib';
import { readConfigFile } from '../functional_test_runner/lib';
const makeSuccessMessage = (options) => {
const makeSuccessMessage = (options: StartServerOptions) => {
const installDirFlag = options.installDir ? ` --kibana-install-dir=${options.installDir}` : '';
const configPaths = Array.isArray(options.config) ? options.config : [options.config];
const configPaths: string[] = Array.isArray(options.config) ? options.config : [options.config];
const pathsMessage = options.useDefaultConfig
? ''
: configPaths
@ -47,14 +48,17 @@ const makeSuccessMessage = (options) => {
/**
* Run servers and tests for each config
* @param {object} options Optional
* @property {string[]} options.configs Array of paths to configs
* @property {function} options.log An instance of the ToolingLog
* @property {string} options.installDir Optional installation dir from which to run Kibana
* @property {boolean} options.bail Whether to exit test run at the first failure
* @property {string} options.esFrom Optionally run from source instead of snapshot
*/
export async function runTests(options) {
interface RunTestsParams extends CreateFtrOptions {
/** Array of paths to configs */
configs: string[];
/** run from source instead of snapshot */
esFrom?: string;
createLogger: () => ToolingLog;
extraKbnOpts: string[];
assertNoneExcluded: boolean;
}
export async function runTests(options: RunTestsParams) {
if (!process.env.KBN_NP_PLUGINS_BUILT && !options.assertNoneExcluded) {
const log = options.createLogger();
log.warning('❗️❗️❗️');
@ -88,6 +92,7 @@ export async function runTests(options) {
continue;
}
// eslint-disable-next-line no-console
console.log(`--- Running ${relative(process.cwd(), configPath)}`);
await withProcRunner(log, async (procs) => {
@ -117,15 +122,20 @@ export async function runTests(options) {
}
}
/**
* Start only servers using single config
* @param {object} options Optional
* @property {string} options.config Path to a config file
* @property {function} options.log An instance of the ToolingLog
* @property {string} options.installDir Optional installation dir from which to run Kibana
* @property {string} options.esFrom Optionally run from source instead of snapshot
*/
export async function startServers(options) {
interface StartServerOptions {
/** Path to a config file */
config: string;
log: ToolingLog;
/** installation dir from which to run Kibana */
installDir?: string;
/** run from source instead of snapshot */
esFrom?: string;
createLogger: () => ToolingLog;
extraKbnOpts: string[];
useDefaultConfig?: boolean;
}
export async function startServers(options: StartServerOptions) {
const log = options.createLogger();
const opts = {
...options,
@ -158,7 +168,7 @@ export async function startServers(options) {
});
}
async function silence(log, milliseconds) {
async function silence(log: ToolingLog, milliseconds: number) {
await log
.getWritten$()
.pipe(

View file

@ -10,7 +10,7 @@
import { format } from 'util';
export function checkMockConsoleLogSnapshot(logMock) {
export function checkMockConsoleLogSnapshot(logMock: jest.Mock) {
const output = logMock.mock.calls
.reduce((acc, args) => `${acc}${format(...args)}\n`, '')
.replace(/(^ at.+[>)\d]$\n?)+/m, ' ...stack trace...');