In https://github.com/elastic/kibana/pull/31234 there were some extra changes that I've reverted, like use of the `tsconfig-paths` package to magically rewrite import statements to defy the standard node module resolution algorithm, the inclusion of several unnecessary options in the `test/tsconfig.json` file, and changes of the line-endings in the config files. This also brings a few enhancements from https://github.com/elastic/kibana/pull/30190 including a modularized version of the expect.js types, and options for explicit mappings for the PageObjects and services used in ftr tests.
This commit is contained in:
parent
a7c02d41a0
commit
ba82d027cd
|
@ -401,7 +401,6 @@
|
|||
"ts-jest": "^23.1.4",
|
||||
"ts-loader": "^5.2.2",
|
||||
"ts-node": "^7.0.1",
|
||||
"tsconfig-paths": "^3.8.0",
|
||||
"tslint": "^5.11.0",
|
||||
"tslint-config-prettier": "^1.15.0",
|
||||
"tslint-microsoft-contrib": "^6.0.0",
|
||||
|
|
6
packages/kbn-test/tsconfig.json
Normal file
6
packages/kbn-test/tsconfig.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": [
|
||||
"types/**/*"
|
||||
]
|
||||
}
|
6
packages/kbn-test/types/README.md
Normal file
6
packages/kbn-test/types/README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# @kbn/test/types
|
||||
|
||||
Shared types used by different parts of the tests
|
||||
|
||||
- **`expect.js.d.ts`**: This is a fork of the expect.js types that have been slightly modified to only expose a module type for `import expect from 'expect.js'` statements. The `@types/expect.js` includes types for the `expect` global, which is useful for some uses of the library but conflicts with the jest types we use. Making the type "module only" prevents them from conflicting.
|
||||
- **`ftr.d.ts`**: These types are generic types for using the functional test runner. They are here because we plan to move the functional test runner into the `@kbn/test` package at some point and having them here makes them a lot easier to import from all over the place like we do.
|
225
packages/kbn-test/types/expect.js.d.ts
vendored
Normal file
225
packages/kbn-test/types/expect.js.d.ts
vendored
Normal file
|
@ -0,0 +1,225 @@
|
|||
// tslint:disable
|
||||
|
||||
// Type definitions for expect.js 0.3.1
|
||||
// Project: https://github.com/Automattic/expect.js
|
||||
// Definitions by: Teppei Sato <https://github.com/teppeis>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// License: MIT
|
||||
|
||||
declare module 'expect.js' {
|
||||
function expect(target?: any): Root;
|
||||
|
||||
interface Assertion {
|
||||
/**
|
||||
* Assert typeof / instanceof.
|
||||
*/
|
||||
an: An;
|
||||
/**
|
||||
* Check if the value is truthy
|
||||
*/
|
||||
ok(): void;
|
||||
|
||||
/**
|
||||
* Creates an anonymous function which calls fn with arguments.
|
||||
*/
|
||||
withArgs(...args: any[]): Root;
|
||||
|
||||
/**
|
||||
* Assert that the function throws.
|
||||
*
|
||||
* @param fn callback to match error string against
|
||||
*/
|
||||
throwError(fn?: (exception: any) => void): void;
|
||||
|
||||
/**
|
||||
* Assert that the function throws.
|
||||
*
|
||||
* @param fn callback to match error string against
|
||||
*/
|
||||
throwException(fn?: (exception: any) => void): void;
|
||||
|
||||
/**
|
||||
* Assert that the function throws.
|
||||
*
|
||||
* @param regexp regexp to match error string against
|
||||
*/
|
||||
throwError(regexp: RegExp): void;
|
||||
|
||||
/**
|
||||
* Assert that the function throws.
|
||||
*
|
||||
* @param fn callback to match error string against
|
||||
*/
|
||||
throwException(regexp: RegExp): void;
|
||||
|
||||
/**
|
||||
* Checks if the array is empty.
|
||||
*/
|
||||
empty(): Assertion;
|
||||
|
||||
/**
|
||||
* Checks if the obj exactly equals another.
|
||||
*/
|
||||
equal(obj: any): Assertion;
|
||||
|
||||
/**
|
||||
* Checks if the obj sortof equals another.
|
||||
*/
|
||||
eql(obj: any): Assertion;
|
||||
|
||||
/**
|
||||
* Assert within start to finish (inclusive).
|
||||
*
|
||||
* @param start
|
||||
* @param finish
|
||||
*/
|
||||
within(start: number, finish: number): Assertion;
|
||||
|
||||
/**
|
||||
* Assert typeof.
|
||||
*/
|
||||
a(type: string): Assertion;
|
||||
|
||||
/**
|
||||
* Assert instanceof.
|
||||
*/
|
||||
a(type: Function): Assertion;
|
||||
|
||||
/**
|
||||
* Assert numeric value above n.
|
||||
*/
|
||||
greaterThan(n: number): Assertion;
|
||||
|
||||
/**
|
||||
* Assert numeric value above n.
|
||||
*/
|
||||
above(n: number): Assertion;
|
||||
|
||||
/**
|
||||
* Assert numeric value below n.
|
||||
*/
|
||||
lessThan(n: number): Assertion;
|
||||
|
||||
/**
|
||||
* Assert numeric value below n.
|
||||
*/
|
||||
below(n: number): Assertion;
|
||||
|
||||
/**
|
||||
* Assert string value matches regexp.
|
||||
*
|
||||
* @param regexp
|
||||
*/
|
||||
match(regexp: RegExp): Assertion;
|
||||
|
||||
/**
|
||||
* Assert property "length" exists and has value of n.
|
||||
*
|
||||
* @param n
|
||||
*/
|
||||
length(n: number): Assertion;
|
||||
|
||||
/**
|
||||
* Assert property name exists, with optional val.
|
||||
*
|
||||
* @param name
|
||||
* @param val
|
||||
*/
|
||||
property(name: string, val?: any): Assertion;
|
||||
|
||||
/**
|
||||
* Assert that string contains str.
|
||||
*/
|
||||
contain(str: string): Assertion;
|
||||
string(str: string): Assertion;
|
||||
|
||||
/**
|
||||
* Assert that the array contains obj.
|
||||
*/
|
||||
contain(obj: any): Assertion;
|
||||
string(obj: any): Assertion;
|
||||
|
||||
/**
|
||||
* Assert exact keys or inclusion of keys by using the `.own` modifier.
|
||||
*/
|
||||
key(keys: string[]): Assertion;
|
||||
/**
|
||||
* Assert exact keys or inclusion of keys by using the `.own` modifier.
|
||||
*/
|
||||
key(...keys: string[]): Assertion;
|
||||
/**
|
||||
* Assert exact keys or inclusion of keys by using the `.own` modifier.
|
||||
*/
|
||||
keys(keys: string[]): Assertion;
|
||||
/**
|
||||
* Assert exact keys or inclusion of keys by using the `.own` modifier.
|
||||
*/
|
||||
keys(...keys: string[]): Assertion;
|
||||
|
||||
/**
|
||||
* Assert a failure.
|
||||
*/
|
||||
fail(message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Root extends Assertion {
|
||||
not: Not;
|
||||
to: To;
|
||||
only: Only;
|
||||
have: Have;
|
||||
be: Be;
|
||||
}
|
||||
|
||||
interface Be extends Assertion {
|
||||
/**
|
||||
* Checks if the obj exactly equals another.
|
||||
*/
|
||||
(obj: any): Assertion;
|
||||
|
||||
an: An;
|
||||
}
|
||||
|
||||
interface An extends Assertion {
|
||||
/**
|
||||
* Assert typeof.
|
||||
*/
|
||||
(type: string): Assertion;
|
||||
|
||||
/**
|
||||
* Assert instanceof.
|
||||
*/
|
||||
(type: Function): Assertion;
|
||||
}
|
||||
|
||||
interface Not extends NotBase {
|
||||
to: ToBase;
|
||||
}
|
||||
|
||||
interface NotBase extends Assertion {
|
||||
be: Be;
|
||||
have: Have;
|
||||
include: Assertion;
|
||||
only: Only;
|
||||
}
|
||||
|
||||
interface To extends ToBase {
|
||||
not: NotBase;
|
||||
}
|
||||
|
||||
interface ToBase extends Assertion {
|
||||
be: Be;
|
||||
have: Have;
|
||||
include: Assertion;
|
||||
only: Only;
|
||||
}
|
||||
|
||||
interface Only extends Assertion {
|
||||
have: Have;
|
||||
}
|
||||
|
||||
interface Have extends Assertion {
|
||||
own: Assertion;
|
||||
}
|
||||
|
||||
export default expect;
|
||||
}
|
80
packages/kbn-test/types/ftr.d.ts
vendored
Normal file
80
packages/kbn-test/types/ftr.d.ts
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { DefaultServiceProviders } from '../../../src/functional_test_runner/types';
|
||||
|
||||
interface AsyncInstance<T> {
|
||||
/**
|
||||
* Services that are initialized async are not ready before the tests execute, so you might need
|
||||
* to call `init()` and await the promise it returns before interacting with the service
|
||||
*/
|
||||
init(): Promise<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a provider returns a promise it is initialized as an AsyncInstance that is a
|
||||
* proxy to the eventual result with an added init() method which returns the eventual
|
||||
* result. Automatically unwrap these promises and convert them to AsyncInstances + Instance
|
||||
* types.
|
||||
*/
|
||||
type MaybeAsyncInstance<T> = T extends Promise<infer X> ? AsyncInstance<X> & X : T;
|
||||
|
||||
/**
|
||||
* Convert a map of providers to a map of the instance types they provide, also converting
|
||||
* promise types into the async instances that other providers will receive.
|
||||
*/
|
||||
type ProvidedTypeMap<T extends object> = {
|
||||
[K in keyof T]: T[K] extends (...args: any[]) => any
|
||||
? MaybeAsyncInstance<ReturnType<T[K]>>
|
||||
: never
|
||||
};
|
||||
|
||||
export interface GenericFtrProviderContext<
|
||||
ServiceProviders extends object,
|
||||
PageObjectProviders extends object,
|
||||
ServiceMap = ProvidedTypeMap<ServiceProviders & DefaultServiceProviders>,
|
||||
PageObjectMap = ProvidedTypeMap<PageObjectProviders>
|
||||
> {
|
||||
/**
|
||||
* Determine if a service is avaliable
|
||||
* @param serviceName
|
||||
*/
|
||||
hasService<K extends keyof ServiceMap>(serviceName: K): serviceName is K;
|
||||
hasService(serviceName: string): serviceName is keyof ServiceMap;
|
||||
|
||||
/**
|
||||
* Get the instance of a service, if the service is loaded async and the service needs to be used
|
||||
* outside of a test/hook, then make sure to call its `.init()` method and await it's promise.
|
||||
* @param serviceName
|
||||
*/
|
||||
getService<T extends keyof ServiceMap>(serviceName: T): ServiceMap[T];
|
||||
|
||||
/**
|
||||
* Get a map of PageObjects
|
||||
* @param pageObjects
|
||||
*/
|
||||
getPageObjects<K extends keyof PageObjectMap>(pageObjects: K[]): Pick<PageObjectMap, K>;
|
||||
|
||||
/**
|
||||
* Synchronously load a test file, can be called within a `describe()` block to add
|
||||
* common setup/teardown steps to several suites
|
||||
* @param path
|
||||
*/
|
||||
loadTestFile(path: string): void;
|
||||
}
|
|
@ -25,9 +25,9 @@ import { Project } from './project';
|
|||
|
||||
export const PROJECTS = [
|
||||
new Project(resolve(REPO_ROOT, 'tsconfig.json')),
|
||||
new Project(resolve(REPO_ROOT, 'test/tsconfig.json'), 'kibana/test'),
|
||||
new Project(resolve(REPO_ROOT, 'x-pack/tsconfig.json')),
|
||||
new Project(resolve(REPO_ROOT, 'x-pack/test/tsconfig.json'), 'x-pack/test'),
|
||||
new Project(resolve(REPO_ROOT, 'test/tsconfig.json')),
|
||||
|
||||
// NOTE: using glob.sync rather than glob-all or globby
|
||||
// because it takes less than 10 ms, while the other modules
|
||||
|
|
39
src/es_archiver/es_archiver.d.ts
vendored
Normal file
39
src/es_archiver/es_archiver.d.ts
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { Client } from 'elasticsearch';
|
||||
import { createStats } from './lib/stats';
|
||||
|
||||
export type JsonStats = ReturnType<ReturnType<typeof createStats>['toJSON']>;
|
||||
|
||||
export class EsArchiver {
|
||||
constructor(options: { client: Client; dataDir: string; log: ToolingLog; kibanaUrl: string });
|
||||
public save(
|
||||
name: string,
|
||||
indices: string | string[],
|
||||
options?: { raw?: boolean }
|
||||
): Promise<JsonStats>;
|
||||
public load(name: string, options?: { skipExisting?: boolean }): Promise<JsonStats>;
|
||||
public unload(name: string): Promise<JsonStats>;
|
||||
public rebuildAll(): Promise<void>;
|
||||
public edit(prefix: string, handler: () => Promise<void>): Promise<void>;
|
||||
public loadIfNeeded(name: string): Promise<JsonStats>;
|
||||
public emptyKibanaIndex(): Promise<JsonStats>;
|
||||
}
|
|
@ -17,7 +17,4 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export interface TestWrapper {
|
||||
getService(service: string): any;
|
||||
getPageObjects(pages: string[]): { [name: string]: any };
|
||||
}
|
||||
export { EsArchiver } from './es_archiver';
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
export function createStats(name, log) {
|
||||
const info = (msg, ...args) => log.info(`[${name}] ${msg}`, ...args);
|
||||
const debug = (msg, ...args) => log.debug(`[${name}] ${msg}`, ...args);
|
||||
|
||||
const indices = {};
|
||||
const getOrCreate = index => {
|
||||
if (!indices[index]) {
|
||||
indices[index] = {
|
||||
skipped: false,
|
||||
deleted: false,
|
||||
created: false,
|
||||
archived: false,
|
||||
waitForSnapshot: 0,
|
||||
configDocs: {
|
||||
upgraded: 0,
|
||||
tagged: 0,
|
||||
upToDate: 0,
|
||||
},
|
||||
docs: {
|
||||
indexed: 0,
|
||||
archived: 0,
|
||||
}
|
||||
};
|
||||
}
|
||||
return indices[index];
|
||||
};
|
||||
|
||||
class Stats {
|
||||
skippedIndex(index) {
|
||||
getOrCreate(index).skipped = true;
|
||||
info('Skipped restore for existing index %j', index);
|
||||
}
|
||||
|
||||
waitingForInProgressSnapshot(index) {
|
||||
getOrCreate(index).waitForSnapshot += 1;
|
||||
info('Waiting for snapshot of %j to complete', index);
|
||||
}
|
||||
|
||||
deletedIndex(index) {
|
||||
getOrCreate(index).deleted = true;
|
||||
info('Deleted existing index %j', index);
|
||||
}
|
||||
|
||||
createdIndex(index, metadata) {
|
||||
getOrCreate(index).created = true;
|
||||
info('Created index %j', index);
|
||||
Object.keys(metadata || {}).forEach(name => {
|
||||
debug('%j %s %j', index, name, metadata[name]);
|
||||
});
|
||||
}
|
||||
|
||||
archivedIndex(index, metadata) {
|
||||
getOrCreate(index).archived = true;
|
||||
info('Archived %j', index);
|
||||
Object.keys(metadata || {}).forEach(name => {
|
||||
debug('%j %s %j', index, name, metadata[name]);
|
||||
});
|
||||
}
|
||||
|
||||
indexedDoc(index) {
|
||||
getOrCreate(index).docs.indexed += 1;
|
||||
}
|
||||
|
||||
archivedDoc(index) {
|
||||
getOrCreate(index).docs.archived += 1;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return cloneDeep(indices);
|
||||
}
|
||||
|
||||
forEachIndex(fn) {
|
||||
const clone = this.toJSON();
|
||||
Object.keys(clone).forEach(index => {
|
||||
fn(index, clone[index]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return new Stats();
|
||||
}
|
153
src/es_archiver/lib/stats.ts
Normal file
153
src/es_archiver/lib/stats.ts
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
export interface IndexStats {
|
||||
skipped: boolean;
|
||||
deleted: boolean;
|
||||
created: boolean;
|
||||
archived: boolean;
|
||||
waitForSnapshot: number;
|
||||
configDocs: {
|
||||
upgraded: number;
|
||||
tagged: number;
|
||||
upToDate: number;
|
||||
};
|
||||
docs: {
|
||||
indexed: number;
|
||||
archived: number;
|
||||
};
|
||||
}
|
||||
|
||||
export function createStats(name: string, log: ToolingLog) {
|
||||
const info = (msg: string, ...args: any[]) => log.info(`[${name}] ${msg}`, ...args);
|
||||
const debug = (msg: string, ...args: any[]) => log.debug(`[${name}] ${msg}`, ...args);
|
||||
|
||||
const indices: Record<string, IndexStats> = {};
|
||||
const getOrCreate = (index: string) => {
|
||||
if (!indices[index]) {
|
||||
indices[index] = {
|
||||
skipped: false,
|
||||
deleted: false,
|
||||
created: false,
|
||||
archived: false,
|
||||
waitForSnapshot: 0,
|
||||
configDocs: {
|
||||
upgraded: 0,
|
||||
tagged: 0,
|
||||
upToDate: 0,
|
||||
},
|
||||
docs: {
|
||||
indexed: 0,
|
||||
archived: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
return indices[index];
|
||||
};
|
||||
|
||||
return new class Stats {
|
||||
/**
|
||||
* Record that an index was not restored because it already existed
|
||||
* @param index
|
||||
*/
|
||||
public skippedIndex(index: string) {
|
||||
getOrCreate(index).skipped = true;
|
||||
info('Skipped restore for existing index %j', index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that the esArchiver waited for an index that was in the middle of being snapshotted
|
||||
* @param index
|
||||
*/
|
||||
public waitingForInProgressSnapshot(index: string) {
|
||||
getOrCreate(index).waitForSnapshot += 1;
|
||||
info('Waiting for snapshot of %j to complete', index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that an index was deleted
|
||||
* @param index
|
||||
*/
|
||||
public deletedIndex(index: string) {
|
||||
getOrCreate(index).deleted = true;
|
||||
info('Deleted existing index %j', index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that an index was created
|
||||
* @param index
|
||||
*/
|
||||
public createdIndex(index: string, metadata: Record<string, any> = {}) {
|
||||
getOrCreate(index).created = true;
|
||||
info('Created index %j', index);
|
||||
Object.keys(metadata).forEach(key => {
|
||||
debug('%j %s %j', index, key, metadata[key]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that an index was written to the archives
|
||||
* @param index
|
||||
*/
|
||||
public archivedIndex(index: string, metadata: Record<string, any> = {}) {
|
||||
getOrCreate(index).archived = true;
|
||||
info('Archived %j', index);
|
||||
Object.keys(metadata).forEach(key => {
|
||||
debug('%j %s %j', index, key, metadata[key]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that a document was written to elasticsearch
|
||||
* @param index
|
||||
*/
|
||||
public indexedDoc(index: string) {
|
||||
getOrCreate(index).docs.indexed += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that a document was added to the archives
|
||||
* @param index
|
||||
*/
|
||||
public archivedDoc(index: string) {
|
||||
getOrCreate(index).docs.archived += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a plain object version of the stats by index
|
||||
*/
|
||||
public toJSON() {
|
||||
return cloneDeep(indices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the status for each index
|
||||
* @param fn
|
||||
*/
|
||||
public forEachIndex(fn: (index: string, stats: IndexStats) => void) {
|
||||
const clone = this.toJSON();
|
||||
Object.keys(clone).forEach(index => {
|
||||
fn(index, clone[index]);
|
||||
});
|
||||
}
|
||||
}();
|
||||
}
|
|
@ -75,7 +75,6 @@ const functionalTestRunner = createFunctionalTestRunner({
|
|||
bail: cmd.bail,
|
||||
grep: cmd.grep,
|
||||
invert: cmd.invert,
|
||||
require: `ts-node/register --project tests/tsconfig.json -r tsconfig-paths/register -T "test/**/*.{ts,js}"`
|
||||
},
|
||||
suiteTags: {
|
||||
include: cmd.includeTag,
|
||||
|
|
|
@ -17,20 +17,27 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { get, has, cloneDeep } from 'lodash';
|
||||
import { Schema } from 'joi';
|
||||
import { cloneDeep, get, has } from 'lodash';
|
||||
|
||||
// @ts-ignore internal lodash module is not typed
|
||||
import toPath from 'lodash/internal/toPath';
|
||||
|
||||
import { schema } from './schema';
|
||||
|
||||
const $values = Symbol('values');
|
||||
|
||||
interface Options {
|
||||
settings?: Record<string, any>;
|
||||
primary?: boolean;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export class Config {
|
||||
constructor(options = {}) {
|
||||
const {
|
||||
settings = {},
|
||||
primary = false,
|
||||
path,
|
||||
} = options;
|
||||
private [$values]: Record<string, any>;
|
||||
|
||||
constructor(options: Options) {
|
||||
const { settings = {}, primary = false, path = null } = options || {};
|
||||
|
||||
if (!path) {
|
||||
throw new TypeError('path is a required option');
|
||||
|
@ -41,38 +48,52 @@ export class Config {
|
|||
context: {
|
||||
primary: !!primary,
|
||||
path,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
this[$values] = value;
|
||||
}
|
||||
|
||||
has(key) {
|
||||
function recursiveHasCheck(path, values, schema) {
|
||||
if (!schema._inner) return false;
|
||||
public has(key: string) {
|
||||
function recursiveHasCheck(
|
||||
remainingPath: string[],
|
||||
values: Record<string, any>,
|
||||
childSchema: any
|
||||
): boolean {
|
||||
if (!childSchema._inner) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// normalize child and pattern checks so we can iterate the checks in a single loop
|
||||
const checks = [].concat(
|
||||
const checks: Array<{ test: (k: string) => boolean; schema: Schema }> = [
|
||||
// match children first, they have priority
|
||||
(schema._inner.children || []).map(child => ({
|
||||
test: key => child.key === key,
|
||||
schema: child.schema
|
||||
...(childSchema._inner.children || []).map((child: { key: string; schema: Schema }) => ({
|
||||
test: (k: string) => child.key === k,
|
||||
schema: child.schema,
|
||||
})),
|
||||
|
||||
// match patterns on any key that doesn't match an explicit child
|
||||
(schema._inner.patterns || []).map(pattern => ({
|
||||
test: key => pattern.regex.test(key) && has(values, key),
|
||||
schema: pattern.rule
|
||||
}))
|
||||
);
|
||||
...(childSchema._inner.patterns || []).map((pattern: { regex: RegExp; rule: Schema }) => ({
|
||||
test: (k: string) => pattern.regex.test(k) && has(values, k),
|
||||
schema: pattern.rule,
|
||||
})),
|
||||
];
|
||||
|
||||
for (const check of checks) {
|
||||
if (!check.test(path[0])) {
|
||||
if (!check.test(remainingPath[0])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (path.length > 1) {
|
||||
return recursiveHasCheck(path.slice(1), get(values, path[0]), check.schema);
|
||||
if (remainingPath.length > 1) {
|
||||
return recursiveHasCheck(
|
||||
remainingPath.slice(1),
|
||||
get(values, remainingPath[0]),
|
||||
check.schema
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -82,16 +103,18 @@ export class Config {
|
|||
}
|
||||
|
||||
const path = toPath(key);
|
||||
if (!path.length) return true;
|
||||
if (!path.length) {
|
||||
return true;
|
||||
}
|
||||
return recursiveHasCheck(path, this[$values], schema);
|
||||
}
|
||||
|
||||
get(key, defaultValue) {
|
||||
public get(key: string, defaultValue?: any) {
|
||||
if (!this.has(key)) {
|
||||
throw new Error(`Unknown config key "${key}"`);
|
||||
}
|
||||
|
||||
return cloneDeep(get(this[$values], key, defaultValue), (v) => {
|
||||
return cloneDeep(get(this[$values], key, defaultValue), v => {
|
||||
if (typeof v === 'function') {
|
||||
return v;
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { resolve, dirname } from 'path';
|
||||
|
||||
import Joi from 'joi';
|
||||
|
||||
// valid pattern for ID
|
||||
// enforced camel-case identifiers for consistency
|
||||
const ID_PATTERN = /^[a-zA-Z0-9_]+$/;
|
||||
const INSPECTING = (
|
||||
process.execArgv.includes('--inspect') ||
|
||||
process.execArgv.includes('--inspect-brk')
|
||||
);
|
||||
|
||||
const urlPartsSchema = () => Joi.object().keys({
|
||||
protocol: Joi.string().valid('http', 'https').default('http'),
|
||||
hostname: Joi.string().hostname().default('localhost'),
|
||||
port: Joi.number(),
|
||||
auth: Joi.string().regex(/^[^:]+:.+$/, 'username and password separated by a colon'),
|
||||
username: Joi.string(),
|
||||
password: Joi.string(),
|
||||
pathname: Joi.string().regex(/^\//, 'start with a /'),
|
||||
hash: Joi.string().regex(/^\//, 'start with a /')
|
||||
}).default();
|
||||
|
||||
const appUrlPartsSchema = () => Joi.object().keys({
|
||||
pathname: Joi.string().regex(/^\//, 'start with a /'),
|
||||
hash: Joi.string().regex(/^\//, 'start with a /')
|
||||
}).default();
|
||||
|
||||
const defaultRelativeToConfigPath = path => {
|
||||
const makeDefault = (locals, options) => (
|
||||
resolve(dirname(options.context.path), path)
|
||||
);
|
||||
makeDefault.description = `<config.js directory>/${path}`;
|
||||
return makeDefault;
|
||||
};
|
||||
|
||||
export const schema = Joi.object().keys({
|
||||
testFiles: Joi.array().items(Joi.string()).when('$primary', {
|
||||
is: true,
|
||||
then: Joi.required(),
|
||||
otherwise: Joi.default([]),
|
||||
}),
|
||||
|
||||
excludeTestFiles: Joi.array().items(Joi.string()).default([]),
|
||||
|
||||
suiteTags: Joi.object().keys({
|
||||
include: Joi.array().items(Joi.string()).default([]),
|
||||
exclude: Joi.array().items(Joi.string()).default([]),
|
||||
}).default(),
|
||||
|
||||
services: Joi.object().pattern(
|
||||
ID_PATTERN,
|
||||
Joi.func().required()
|
||||
).default(),
|
||||
|
||||
pageObjects: Joi.object().pattern(
|
||||
ID_PATTERN,
|
||||
Joi.func().required()
|
||||
).default(),
|
||||
|
||||
timeouts: Joi.object().keys({
|
||||
find: Joi.number().default(10000),
|
||||
try: Joi.number().default(120000),
|
||||
waitFor: Joi.number().default(20000),
|
||||
esRequestTimeout: Joi.number().default(30000),
|
||||
kibanaStabilize: Joi.number().default(15000),
|
||||
navigateStatusPageCheck: Joi.number().default(250),
|
||||
|
||||
// Many of our tests use the `exists` functions to determine where the user is. For
|
||||
// example, you'll see a lot of code like:
|
||||
// if (!testSubjects.exists('someElementOnPageA')) {
|
||||
// navigateToPageA();
|
||||
// }
|
||||
// If the element doesn't exist, selenium would wait up to defaultFindTimeout for it to
|
||||
// appear. Because there are many times when we expect it to not be there, we don't want
|
||||
// to wait the full amount of time, or it would greatly slow our tests down. We used to have
|
||||
// this value at 1 second, but this caused flakiness because sometimes the element was deemed missing
|
||||
// only because the page hadn't finished loading.
|
||||
// The best path forward it to prefer functions like `testSubjects.existOrFail` or
|
||||
// `testSubjects.missingOrFail` instead of just the `exists` checks, and be deterministic about
|
||||
// where your user is and what they should click next.
|
||||
waitForExists: Joi.number().default(2500),
|
||||
}).default(),
|
||||
|
||||
mochaOpts: Joi.object().keys({
|
||||
bail: Joi.boolean().default(false),
|
||||
grep: Joi.string(),
|
||||
invert: Joi.boolean().default(false),
|
||||
slow: Joi.number().default(30000),
|
||||
timeout: Joi.number().default(INSPECTING ? Infinity : 360000),
|
||||
ui: Joi.string().default('bdd'),
|
||||
require: Joi.string().default('')
|
||||
}).default(),
|
||||
|
||||
updateBaselines: Joi.boolean().default(false),
|
||||
|
||||
junit: Joi.object().keys({
|
||||
enabled: Joi.boolean().default(!!process.env.CI),
|
||||
reportName: Joi.string(),
|
||||
rootDirectory: Joi.string(),
|
||||
}).default(),
|
||||
|
||||
mochaReporter: Joi.object().keys({
|
||||
captureLogOutput: Joi.boolean().default(!!process.env.CI),
|
||||
}).default(),
|
||||
|
||||
users: Joi.object().pattern(
|
||||
ID_PATTERN,
|
||||
Joi.object().keys({
|
||||
username: Joi.string().required(),
|
||||
password: Joi.string().required(),
|
||||
}).required()
|
||||
),
|
||||
|
||||
servers: Joi.object().keys({
|
||||
kibana: urlPartsSchema(),
|
||||
elasticsearch: urlPartsSchema(),
|
||||
}).default(),
|
||||
|
||||
esTestCluster: Joi.object().keys({
|
||||
license: Joi.string().default('oss'),
|
||||
from: Joi.string().default('snapshot'),
|
||||
serverArgs: Joi.array(),
|
||||
dataArchive: Joi.string(),
|
||||
}).default(),
|
||||
|
||||
kbnTestServer: Joi.object().keys({
|
||||
buildArgs: Joi.array(),
|
||||
sourceArgs: Joi.array(),
|
||||
serverArgs: Joi.array(),
|
||||
}).default(),
|
||||
|
||||
chromedriver: Joi.object().keys({
|
||||
url: Joi.string().uri({ scheme: /https?/ }).default('http://localhost:9515')
|
||||
}).default(),
|
||||
|
||||
firefoxdriver: Joi.object().keys({
|
||||
url: Joi.string().uri({ scheme: /https?/ }).default('http://localhost:2828')
|
||||
}).default(),
|
||||
|
||||
|
||||
// definition of apps that work with `common.navigateToApp()`
|
||||
apps: Joi.object().pattern(
|
||||
ID_PATTERN,
|
||||
appUrlPartsSchema()
|
||||
).default(),
|
||||
|
||||
// settings for the esArchiver module
|
||||
esArchiver: Joi.object().keys({
|
||||
directory: Joi.string().default(defaultRelativeToConfigPath('fixtures/es_archiver')),
|
||||
}).default(),
|
||||
|
||||
// settings for the kibanaServer.uiSettings module
|
||||
uiSettings: Joi.object().keys({
|
||||
defaults: Joi.object().unknown(true)
|
||||
}).default(),
|
||||
|
||||
// settings for the screenshots module
|
||||
screenshots: Joi.object().keys({
|
||||
directory: Joi.string().default(defaultRelativeToConfigPath('screenshots'))
|
||||
}).default(),
|
||||
|
||||
// settings for the failureDebugging module
|
||||
failureDebugging: Joi.object().keys({
|
||||
htmlDirectory: Joi.string().default(defaultRelativeToConfigPath('failure_debug/html'))
|
||||
}).default(),
|
||||
|
||||
// settings for the find service
|
||||
layout: Joi.object().keys({
|
||||
fixedHeaderHeight: Joi.number().default(50),
|
||||
}).default(),
|
||||
}).default();
|
238
src/functional_test_runner/lib/config/schema.ts
Normal file
238
src/functional_test_runner/lib/config/schema.ts
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { dirname, resolve } from 'path';
|
||||
|
||||
import Joi from 'joi';
|
||||
|
||||
// valid pattern for ID
|
||||
// enforced camel-case identifiers for consistency
|
||||
const ID_PATTERN = /^[a-zA-Z0-9_]+$/;
|
||||
const INSPECTING =
|
||||
process.execArgv.includes('--inspect') || process.execArgv.includes('--inspect-brk');
|
||||
|
||||
const urlPartsSchema = () =>
|
||||
Joi.object()
|
||||
.keys({
|
||||
protocol: Joi.string()
|
||||
.valid('http', 'https')
|
||||
.default('http'),
|
||||
hostname: Joi.string()
|
||||
.hostname()
|
||||
.default('localhost'),
|
||||
port: Joi.number(),
|
||||
auth: Joi.string().regex(/^[^:]+:.+$/, 'username and password separated by a colon'),
|
||||
username: Joi.string(),
|
||||
password: Joi.string(),
|
||||
pathname: Joi.string().regex(/^\//, 'start with a /'),
|
||||
hash: Joi.string().regex(/^\//, 'start with a /'),
|
||||
})
|
||||
.default();
|
||||
|
||||
const appUrlPartsSchema = () =>
|
||||
Joi.object()
|
||||
.keys({
|
||||
pathname: Joi.string().regex(/^\//, 'start with a /'),
|
||||
hash: Joi.string().regex(/^\//, 'start with a /'),
|
||||
})
|
||||
.default();
|
||||
|
||||
const defaultRelativeToConfigPath = (path: string) => {
|
||||
const makeDefault: any = (_: any, options: any) => resolve(dirname(options.context.path), path);
|
||||
makeDefault.description = `<config.js directory>/${path}`;
|
||||
return makeDefault;
|
||||
};
|
||||
|
||||
export const schema = Joi.object()
|
||||
.keys({
|
||||
testFiles: Joi.array()
|
||||
.items(Joi.string())
|
||||
.when('$primary', {
|
||||
is: true,
|
||||
then: Joi.required(),
|
||||
otherwise: Joi.any().default([]),
|
||||
}),
|
||||
|
||||
excludeTestFiles: Joi.array()
|
||||
.items(Joi.string())
|
||||
.default([]),
|
||||
|
||||
suiteTags: Joi.object()
|
||||
.keys({
|
||||
include: Joi.array()
|
||||
.items(Joi.string())
|
||||
.default([]),
|
||||
exclude: Joi.array()
|
||||
.items(Joi.string())
|
||||
.default([]),
|
||||
})
|
||||
.default(),
|
||||
|
||||
services: Joi.object()
|
||||
.pattern(ID_PATTERN, Joi.func().required())
|
||||
.default(),
|
||||
|
||||
pageObjects: Joi.object()
|
||||
.pattern(ID_PATTERN, Joi.func().required())
|
||||
.default(),
|
||||
|
||||
timeouts: Joi.object()
|
||||
.keys({
|
||||
find: Joi.number().default(10000),
|
||||
try: Joi.number().default(120000),
|
||||
waitFor: Joi.number().default(20000),
|
||||
esRequestTimeout: Joi.number().default(30000),
|
||||
kibanaStabilize: Joi.number().default(15000),
|
||||
navigateStatusPageCheck: Joi.number().default(250),
|
||||
|
||||
// Many of our tests use the `exists` functions to determine where the user is. For
|
||||
// example, you'll see a lot of code like:
|
||||
// if (!testSubjects.exists('someElementOnPageA')) {
|
||||
// navigateToPageA();
|
||||
// }
|
||||
// If the element doesn't exist, selenium would wait up to defaultFindTimeout for it to
|
||||
// appear. Because there are many times when we expect it to not be there, we don't want
|
||||
// to wait the full amount of time, or it would greatly slow our tests down. We used to have
|
||||
// this value at 1 second, but this caused flakiness because sometimes the element was deemed missing
|
||||
// only because the page hadn't finished loading.
|
||||
// The best path forward it to prefer functions like `testSubjects.existOrFail` or
|
||||
// `testSubjects.missingOrFail` instead of just the `exists` checks, and be deterministic about
|
||||
// where your user is and what they should click next.
|
||||
waitForExists: Joi.number().default(2500),
|
||||
})
|
||||
.default(),
|
||||
|
||||
mochaOpts: Joi.object()
|
||||
.keys({
|
||||
bail: Joi.boolean().default(false),
|
||||
grep: Joi.string(),
|
||||
invert: Joi.boolean().default(false),
|
||||
slow: Joi.number().default(30000),
|
||||
timeout: Joi.number().default(INSPECTING ? Infinity : 360000),
|
||||
ui: Joi.string().default('bdd'),
|
||||
})
|
||||
.default(),
|
||||
|
||||
updateBaselines: Joi.boolean().default(false),
|
||||
|
||||
junit: Joi.object()
|
||||
.keys({
|
||||
enabled: Joi.boolean().default(!!process.env.CI),
|
||||
reportName: Joi.string(),
|
||||
rootDirectory: Joi.string(),
|
||||
})
|
||||
.default(),
|
||||
|
||||
mochaReporter: Joi.object()
|
||||
.keys({
|
||||
captureLogOutput: Joi.boolean().default(!!process.env.CI),
|
||||
})
|
||||
.default(),
|
||||
|
||||
users: Joi.object().pattern(
|
||||
ID_PATTERN,
|
||||
Joi.object()
|
||||
.keys({
|
||||
username: Joi.string().required(),
|
||||
password: Joi.string().required(),
|
||||
})
|
||||
.required()
|
||||
),
|
||||
|
||||
servers: Joi.object()
|
||||
.keys({
|
||||
kibana: urlPartsSchema(),
|
||||
elasticsearch: urlPartsSchema(),
|
||||
})
|
||||
.default(),
|
||||
|
||||
esTestCluster: Joi.object()
|
||||
.keys({
|
||||
license: Joi.string().default('oss'),
|
||||
from: Joi.string().default('snapshot'),
|
||||
serverArgs: Joi.array(),
|
||||
dataArchive: Joi.string(),
|
||||
})
|
||||
.default(),
|
||||
|
||||
kbnTestServer: Joi.object()
|
||||
.keys({
|
||||
buildArgs: Joi.array(),
|
||||
sourceArgs: Joi.array(),
|
||||
serverArgs: Joi.array(),
|
||||
})
|
||||
.default(),
|
||||
|
||||
chromedriver: Joi.object()
|
||||
.keys({
|
||||
url: Joi.string()
|
||||
.uri({ scheme: /https?/ })
|
||||
.default('http://localhost:9515'),
|
||||
})
|
||||
.default(),
|
||||
|
||||
firefoxdriver: Joi.object()
|
||||
.keys({
|
||||
url: Joi.string()
|
||||
.uri({ scheme: /https?/ })
|
||||
.default('http://localhost:2828'),
|
||||
})
|
||||
.default(),
|
||||
|
||||
// definition of apps that work with `common.navigateToApp()`
|
||||
apps: Joi.object()
|
||||
.pattern(ID_PATTERN, appUrlPartsSchema())
|
||||
.default(),
|
||||
|
||||
// settings for the esArchiver module
|
||||
esArchiver: Joi.object()
|
||||
.keys({
|
||||
directory: Joi.string().default(defaultRelativeToConfigPath('fixtures/es_archiver')),
|
||||
})
|
||||
.default(),
|
||||
|
||||
// settings for the kibanaServer.uiSettings module
|
||||
uiSettings: Joi.object()
|
||||
.keys({
|
||||
defaults: Joi.object().unknown(true),
|
||||
})
|
||||
.default(),
|
||||
|
||||
// settings for the screenshots module
|
||||
screenshots: Joi.object()
|
||||
.keys({
|
||||
directory: Joi.string().default(defaultRelativeToConfigPath('screenshots')),
|
||||
})
|
||||
.default(),
|
||||
|
||||
// settings for the failureDebugging module
|
||||
failureDebugging: Joi.object()
|
||||
.keys({
|
||||
htmlDirectory: Joi.string().default(defaultRelativeToConfigPath('failure_debug/html')),
|
||||
})
|
||||
.default(),
|
||||
|
||||
// settings for the find service
|
||||
layout: Joi.object()
|
||||
.keys({
|
||||
fixedHeaderHeight: Joi.number().default(50),
|
||||
})
|
||||
.default(),
|
||||
})
|
||||
.default();
|
|
@ -17,7 +17,5 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { KibanaServerProvider } from './kibana_server';
|
||||
export { EsProvider } from './es';
|
||||
export { EsArchiverProvider } from './es_archiver';
|
||||
export { RetryProvider } from './retry';
|
||||
export { Config } from './config/config';
|
||||
export { Lifecycle } from './lifecycle';
|
|
@ -17,31 +17,34 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
type Listener = (...args: any[]) => Promise<void> | void;
|
||||
export type Lifecycle = ReturnType<typeof createLifecycle>;
|
||||
|
||||
export function createLifecycle() {
|
||||
const listeners = {
|
||||
beforeLoadTests: [],
|
||||
beforeTests: [],
|
||||
beforeTestSuite: [],
|
||||
beforeEachTest: [],
|
||||
afterTestSuite: [],
|
||||
testFailure: [],
|
||||
testHookFailure: [],
|
||||
cleanup: [],
|
||||
phaseStart: [],
|
||||
phaseEnd: [],
|
||||
beforeLoadTests: [] as Listener[],
|
||||
beforeTests: [] as Listener[],
|
||||
beforeTestSuite: [] as Listener[],
|
||||
beforeEachTest: [] as Listener[],
|
||||
afterTestSuite: [] as Listener[],
|
||||
testFailure: [] as Listener[],
|
||||
testHookFailure: [] as Listener[],
|
||||
cleanup: [] as Listener[],
|
||||
phaseStart: [] as Listener[],
|
||||
phaseEnd: [] as Listener[],
|
||||
};
|
||||
|
||||
class Lifecycle {
|
||||
on(name, fn) {
|
||||
return {
|
||||
on(name: keyof typeof listeners, fn: Listener) {
|
||||
if (!listeners[name]) {
|
||||
throw new TypeError(`invalid lifecycle event "${name}"`);
|
||||
}
|
||||
|
||||
listeners[name].push(fn);
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
async trigger(name, ...args) {
|
||||
async trigger(name: keyof typeof listeners, ...args: any[]) {
|
||||
if (!listeners[name]) {
|
||||
throw new TypeError(`invalid lifecycle event "${name}"`);
|
||||
}
|
||||
|
@ -51,16 +54,12 @@ export function createLifecycle() {
|
|||
await this.trigger('phaseStart', name);
|
||||
}
|
||||
|
||||
await Promise.all(listeners[name].map(
|
||||
async fn => await fn(...args)
|
||||
));
|
||||
await Promise.all(listeners[name].map(async fn => await fn(...args)));
|
||||
} finally {
|
||||
if (name !== 'phaseStart' && name !== 'phaseEnd') {
|
||||
await this.trigger('phaseEnd', name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Lifecycle();
|
||||
},
|
||||
};
|
||||
}
|
27
src/functional_test_runner/types.ts
Normal file
27
src/functional_test_runner/types.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { Config, Lifecycle } from './lib';
|
||||
|
||||
export interface DefaultServiceProviders {
|
||||
config(): Config;
|
||||
log(): ToolingLog;
|
||||
lifecycle(): Lifecycle;
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// @ts-ignore
|
||||
|
||||
import expect from 'expect.js';
|
||||
import { CidrMask } from '../cidr_mask';
|
||||
|
||||
|
|
|
@ -19,12 +19,7 @@
|
|||
|
||||
import { format as formatUrl } from 'url';
|
||||
import { OPTIMIZE_BUNDLE_DIR, esTestConfig, kbnTestConfig } from '@kbn/test';
|
||||
import {
|
||||
KibanaServerProvider,
|
||||
EsProvider,
|
||||
EsArchiverProvider,
|
||||
RetryProvider,
|
||||
} from './services';
|
||||
import { services } from './services';
|
||||
|
||||
export default function () {
|
||||
const servers = {
|
||||
|
@ -64,11 +59,6 @@ export default function () {
|
|||
],
|
||||
},
|
||||
|
||||
services: {
|
||||
kibanaServer: KibanaServerProvider,
|
||||
retry: RetryProvider,
|
||||
es: EsProvider,
|
||||
esArchiver: EsArchiverProvider,
|
||||
}
|
||||
services
|
||||
};
|
||||
}
|
||||
|
|
24
test/common/ftr_provider_context.d.ts
vendored
Normal file
24
test/common/ftr_provider_context.d.ts
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { GenericFtrProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
import { services } from './services';
|
||||
|
||||
export type FtrProviderContext = GenericFtrProviderContext<typeof services, {}>;
|
|
@ -22,8 +22,9 @@ import { format as formatUrl } from 'url';
|
|||
import elasticsearch from 'elasticsearch';
|
||||
|
||||
import { DEFAULT_API_VERSION } from '../../../src/core/server/elasticsearch/elasticsearch_config';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export function EsProvider({ getService }) {
|
||||
export function EsProvider({ getService }: FtrProviderContext): elasticsearch.Client {
|
||||
const config = getService('config');
|
||||
|
||||
return new elasticsearch.Client({
|
|
@ -18,11 +18,13 @@
|
|||
*/
|
||||
|
||||
import { format as formatUrl } from 'url';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
import { EsArchiver } from '../../../src/es_archiver';
|
||||
// @ts-ignore not TS yet
|
||||
import * as KibanaServer from './kibana_server';
|
||||
|
||||
export function EsArchiverProvider({ getService, hasService }) {
|
||||
export function EsArchiverProvider({ getService, hasService }: FtrProviderContext): EsArchiver {
|
||||
const config = getService('config');
|
||||
const client = getService('es');
|
||||
const log = getService('log');
|
||||
|
@ -37,7 +39,7 @@ export function EsArchiverProvider({ getService, hasService }) {
|
|||
client,
|
||||
dataDir,
|
||||
log,
|
||||
kibanaUrl: formatUrl(config.get('servers.kibana'))
|
||||
kibanaUrl: formatUrl(config.get('servers.kibana')),
|
||||
});
|
||||
|
||||
if (hasService('kibanaServer')) {
|
31
test/common/services/index.ts
Normal file
31
test/common/services/index.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { EsProvider } from './es';
|
||||
import { EsArchiverProvider } from './es_archiver';
|
||||
// @ts-ignore not TS yet
|
||||
import { KibanaServerProvider } from './kibana_server';
|
||||
import { RetryProvider } from './retry';
|
||||
|
||||
export const services = {
|
||||
es: EsProvider,
|
||||
esArchiver: EsArchiverProvider,
|
||||
kibanaServer: KibanaServerProvider,
|
||||
retry: RetryProvider,
|
||||
};
|
|
@ -17,56 +17,51 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { retryForTruthy } from './retry_for_truthy';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { retryForSuccess } from './retry_for_success';
|
||||
import { retryForTruthy } from './retry_for_truthy';
|
||||
|
||||
export function RetryProvider({ getService }) {
|
||||
export function RetryProvider({ getService }: FtrProviderContext) {
|
||||
const config = getService('config');
|
||||
const log = getService('log');
|
||||
|
||||
return new class Retry {
|
||||
async tryForTime(timeout, block) {
|
||||
public async tryForTime<T>(timeout: number, block: () => Promise<T>) {
|
||||
return await retryForSuccess(log, {
|
||||
timeout,
|
||||
methodName: 'retry.tryForTime',
|
||||
block
|
||||
block,
|
||||
});
|
||||
}
|
||||
|
||||
async try(block) {
|
||||
public async try<T>(block: () => Promise<T>) {
|
||||
return await retryForSuccess(log, {
|
||||
timeout: config.get('timeouts.try'),
|
||||
methodName: 'retry.try',
|
||||
block
|
||||
block,
|
||||
});
|
||||
}
|
||||
|
||||
async tryMethod(object, method, ...args) {
|
||||
return await retryForSuccess(log, {
|
||||
timeout: config.get('timeouts.try'),
|
||||
methodName: 'retry.tryMethod',
|
||||
block: async () => (
|
||||
await object[method](...args)
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
async waitForWithTimeout(description, timeout, block) {
|
||||
public async waitForWithTimeout(
|
||||
description: string,
|
||||
timeout: number,
|
||||
block: () => Promise<boolean>
|
||||
) {
|
||||
await retryForTruthy(log, {
|
||||
timeout,
|
||||
methodName: 'retry.waitForWithTimeout',
|
||||
description,
|
||||
block
|
||||
block,
|
||||
});
|
||||
}
|
||||
|
||||
async waitFor(description, block) {
|
||||
public async waitFor(description: string, block: () => Promise<boolean>) {
|
||||
await retryForTruthy(log, {
|
||||
timeout: config.get('timeouts.waitFor'),
|
||||
methodName: 'retry.waitFor',
|
||||
description,
|
||||
block
|
||||
block,
|
||||
});
|
||||
}
|
||||
};
|
||||
}();
|
||||
}
|
|
@ -17,15 +17,14 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { inspect } from 'util';
|
||||
|
||||
const delay = ms => new Promise(resolve => (
|
||||
setTimeout(resolve, ms)
|
||||
));
|
||||
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
const returnTrue = () => true;
|
||||
|
||||
const defaultOnFailure = (methodName) => (lastError) => {
|
||||
const defaultOnFailure = (methodName: string) => (lastError: Error) => {
|
||||
throw new Error(`${methodName} timeout: ${lastError.stack || lastError.message}`);
|
||||
};
|
||||
|
||||
|
@ -33,51 +32,56 @@ const defaultOnFailure = (methodName) => (lastError) => {
|
|||
* Run a function and return either an error or result
|
||||
* @param {Function} block
|
||||
*/
|
||||
async function runAttempt(block) {
|
||||
async function runAttempt<T>(block: () => Promise<T>): Promise<{ result: T } | { error: Error }> {
|
||||
try {
|
||||
return {
|
||||
result: await block()
|
||||
result: await block(),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
// we rely on error being truthy and throwing falsy values is *allowed*
|
||||
// so we cast falsy values to errors
|
||||
error: error || new Error(`${inspect(error)} thrown`),
|
||||
error: error instanceof Error ? error : new Error(`${inspect(error)} thrown`),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function retryForSuccess(log, {
|
||||
timeout,
|
||||
methodName,
|
||||
block,
|
||||
onFailure = defaultOnFailure(methodName),
|
||||
accept = returnTrue
|
||||
}) {
|
||||
interface Options<T> {
|
||||
timeout: number;
|
||||
methodName: string;
|
||||
block: () => Promise<T>;
|
||||
onFailure?: ReturnType<typeof defaultOnFailure>;
|
||||
accept?: (v: T) => boolean;
|
||||
}
|
||||
|
||||
export async function retryForSuccess<T>(log: ToolingLog, options: Options<T>) {
|
||||
const { timeout, methodName, block, accept = returnTrue } = options;
|
||||
const { onFailure = defaultOnFailure(methodName) } = options;
|
||||
|
||||
const start = Date.now();
|
||||
const retryDelay = 502;
|
||||
let lastError;
|
||||
|
||||
while (true) {
|
||||
if (Date.now() - start > timeout) {
|
||||
if (lastError && Date.now() - start > timeout) {
|
||||
await onFailure(lastError);
|
||||
throw new Error('expected onFailure() option to throw an error');
|
||||
}
|
||||
|
||||
const { result, error } = await runAttempt(block);
|
||||
const attempt = await runAttempt(block);
|
||||
|
||||
if (!error && accept(result)) {
|
||||
return result;
|
||||
if ('result' in attempt && accept(attempt.result)) {
|
||||
return attempt.result;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (lastError && lastError.message === error.message) {
|
||||
if ('error' in attempt) {
|
||||
if (lastError && lastError.message === attempt.error.message) {
|
||||
log.debug(`--- ${methodName} failed again with the same message...`);
|
||||
} else {
|
||||
log.debug(`--- ${methodName} error: ${error.message}`);
|
||||
log.debug(`--- ${methodName} error: ${attempt.error.message}`);
|
||||
}
|
||||
|
||||
lastError = error;
|
||||
lastError = attempt.error;
|
||||
}
|
||||
|
||||
await delay(retryDelay);
|
|
@ -17,19 +17,28 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
|
||||
import { retryForSuccess } from './retry_for_success';
|
||||
|
||||
export async function retryForTruthy(log, {
|
||||
timeout,
|
||||
methodName,
|
||||
description,
|
||||
block
|
||||
}) {
|
||||
interface Options {
|
||||
timeout: number;
|
||||
methodName: string;
|
||||
description: string;
|
||||
block: () => Promise<boolean>;
|
||||
}
|
||||
|
||||
export async function retryForTruthy(
|
||||
log: ToolingLog,
|
||||
{ timeout, methodName, description, block }: Options
|
||||
) {
|
||||
log.debug(`Waiting up to ${timeout}ms for ${description}...`);
|
||||
|
||||
const accept = result => Boolean(result);
|
||||
|
||||
const onFailure = lastError => {
|
||||
await retryForSuccess(log, {
|
||||
timeout,
|
||||
methodName,
|
||||
block,
|
||||
onFailure: lastError => {
|
||||
let msg = `timed out waiting for ${description}`;
|
||||
|
||||
if (lastError) {
|
||||
|
@ -37,13 +46,7 @@ export async function retryForTruthy(log, {
|
|||
}
|
||||
|
||||
throw new Error(msg);
|
||||
};
|
||||
|
||||
await retryForSuccess(log, {
|
||||
timeout,
|
||||
methodName,
|
||||
block,
|
||||
onFailure,
|
||||
accept
|
||||
},
|
||||
accept: result => Boolean(result),
|
||||
});
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
const DEFAULT_REQUEST = `
|
||||
|
||||
|
@ -30,38 +31,39 @@ GET _search
|
|||
|
||||
`.trim();
|
||||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
// tslint:disable-next-line no-default-export
|
||||
export default function({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const retry = getService('retry');
|
||||
const log = getService('log');
|
||||
const PageObjects = getPageObjects(['common', 'console']);
|
||||
|
||||
describe('console app', function describeIndexTests() {
|
||||
before(async function () {
|
||||
before(async () => {
|
||||
log.debug('navigateTo console');
|
||||
await PageObjects.common.navigateToApp('console');
|
||||
});
|
||||
|
||||
it('should show the default request', async function () {
|
||||
it('should show the default request', async () => {
|
||||
// collapse the help pane because we only get the VISIBLE TEXT, not the part that is scrolled
|
||||
await PageObjects.console.collapseHelp();
|
||||
await retry.try(async function () {
|
||||
await retry.try(async () => {
|
||||
const actualRequest = await PageObjects.console.getRequest();
|
||||
log.debug(actualRequest);
|
||||
expect(actualRequest.trim()).to.eql(DEFAULT_REQUEST);
|
||||
});
|
||||
});
|
||||
|
||||
it('default request response should include `"timed_out" : false`', async function () {
|
||||
it('default request response should include `"timed_out" : false`', async () => {
|
||||
const expectedResponseContains = '"timed_out" : false,';
|
||||
await PageObjects.console.clickPlay();
|
||||
await retry.try(async function () {
|
||||
await retry.try(async () => {
|
||||
const actualResponse = await PageObjects.console.getResponse();
|
||||
log.debug(actualResponse);
|
||||
expect(actualResponse).to.contain(expectedResponseContains);
|
||||
});
|
||||
});
|
||||
|
||||
it('settings should allow changing the text size', async function () {
|
||||
it('settings should allow changing the text size', async () => {
|
||||
await PageObjects.console.setFontSizeSetting(20);
|
||||
await retry.try(async () => {
|
||||
// the settings are not applied synchronously, so we retry for a time
|
|
@ -17,12 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import expect from 'expect.js';
|
||||
import { TestWrapper } from 'typings';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
// tslint:disable-next-line:no-default-export
|
||||
export default function({ getService, getPageObjects }: TestWrapper) {
|
||||
export default function({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const log = getService('log');
|
||||
const inspector = getService('inspector');
|
||||
|
|
|
@ -17,50 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
CommonPageProvider,
|
||||
ConsolePageProvider,
|
||||
ShieldPageProvider,
|
||||
ContextPageProvider,
|
||||
DiscoverPageProvider,
|
||||
HeaderPageProvider,
|
||||
HomePageProvider,
|
||||
DashboardPageProvider,
|
||||
VisualizePageProvider,
|
||||
SettingsPageProvider,
|
||||
MonitoringPageProvider,
|
||||
PointSeriesPageProvider,
|
||||
VisualBuilderPageProvider,
|
||||
TimelionPageProvider,
|
||||
SharePageProvider,
|
||||
TimePickerPageProvider,
|
||||
} from './page_objects';
|
||||
|
||||
import {
|
||||
RemoteProvider,
|
||||
FilterBarProvider,
|
||||
QueryBarProvider,
|
||||
FindProvider,
|
||||
TestSubjectsProvider,
|
||||
DocTableProvider,
|
||||
ScreenshotsProvider,
|
||||
DashboardVisualizationProvider,
|
||||
DashboardExpectProvider,
|
||||
FailureDebuggingProvider,
|
||||
VisualizeListingTableProvider,
|
||||
DashboardAddPanelProvider,
|
||||
DashboardPanelActionsProvider,
|
||||
FlyoutProvider,
|
||||
ComboBoxProvider,
|
||||
EmbeddingProvider,
|
||||
RenderableProvider,
|
||||
TableProvider,
|
||||
BrowserProvider,
|
||||
InspectorProvider,
|
||||
PieChartProvider,
|
||||
AppsMenuProvider,
|
||||
GlobalNavProvider,
|
||||
} from './services';
|
||||
import { pageObjects } from './page_objects';
|
||||
import { services } from './services';
|
||||
import { services as commonServiceProviders } from '../common/services';
|
||||
|
||||
export default async function ({ readConfigFile }) {
|
||||
const commonConfig = await readConfigFile(require.resolve('../common/config'));
|
||||
|
@ -79,52 +38,10 @@ export default async function ({ readConfigFile }) {
|
|||
require.resolve('./apps/visualize'),
|
||||
require.resolve('./apps/xpack'),
|
||||
],
|
||||
pageObjects: {
|
||||
common: CommonPageProvider,
|
||||
console: ConsolePageProvider,
|
||||
shield: ShieldPageProvider,
|
||||
context: ContextPageProvider,
|
||||
discover: DiscoverPageProvider,
|
||||
header: HeaderPageProvider,
|
||||
home: HomePageProvider,
|
||||
dashboard: DashboardPageProvider,
|
||||
visualize: VisualizePageProvider,
|
||||
settings: SettingsPageProvider,
|
||||
monitoring: MonitoringPageProvider,
|
||||
pointSeries: PointSeriesPageProvider,
|
||||
visualBuilder: VisualBuilderPageProvider,
|
||||
timelion: TimelionPageProvider,
|
||||
share: SharePageProvider,
|
||||
timePicker: TimePickerPageProvider,
|
||||
},
|
||||
pageObjects,
|
||||
services: {
|
||||
es: commonConfig.get('services.es'),
|
||||
esArchiver: commonConfig.get('services.esArchiver'),
|
||||
kibanaServer: commonConfig.get('services.kibanaServer'),
|
||||
retry: commonConfig.get('services.retry'),
|
||||
__leadfoot__: RemoteProvider,
|
||||
filterBar: FilterBarProvider,
|
||||
queryBar: QueryBarProvider,
|
||||
find: FindProvider,
|
||||
testSubjects: TestSubjectsProvider,
|
||||
docTable: DocTableProvider,
|
||||
screenshots: ScreenshotsProvider,
|
||||
dashboardVisualizations: DashboardVisualizationProvider,
|
||||
dashboardExpect: DashboardExpectProvider,
|
||||
failureDebugging: FailureDebuggingProvider,
|
||||
visualizeListingTable: VisualizeListingTableProvider,
|
||||
dashboardAddPanel: DashboardAddPanelProvider,
|
||||
dashboardPanelActions: DashboardPanelActionsProvider,
|
||||
flyout: FlyoutProvider,
|
||||
comboBox: ComboBoxProvider,
|
||||
embedding: EmbeddingProvider,
|
||||
renderable: RenderableProvider,
|
||||
table: TableProvider,
|
||||
browser: BrowserProvider,
|
||||
pieChart: PieChartProvider,
|
||||
inspector: InspectorProvider,
|
||||
appsMenu: AppsMenuProvider,
|
||||
globalNav: GlobalNavProvider,
|
||||
...commonServiceProviders,
|
||||
...services
|
||||
},
|
||||
servers: commonConfig.get('servers'),
|
||||
|
||||
|
|
29
test/functional/ftr_provider_context.d.ts
vendored
Normal file
29
test/functional/ftr_provider_context.d.ts
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { GenericFtrProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
import { services as CommonServiceProviders } from '../common/services';
|
||||
import { pageObjects as FunctionalPageObjectProviders } from './page_objects';
|
||||
import { services as FunctionalServiceProviders } from './services';
|
||||
|
||||
type ServiceProviders = typeof CommonServiceProviders & typeof FunctionalServiceProviders;
|
||||
type PageObjectProviders = typeof FunctionalPageObjectProviders;
|
||||
|
||||
export type FtrProviderContext = GenericFtrProviderContext<ServiceProviders, PageObjectProviders>;
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { ConsolePageProvider } from './console_page';
|
||||
export { CommonPageProvider } from './common_page';
|
||||
export { ShieldPageProvider } from './shield_page';
|
||||
export { ContextPageProvider } from './context_page';
|
||||
export { DiscoverPageProvider } from './discover_page';
|
||||
export { HeaderPageProvider } from './header_page';
|
||||
export { HomePageProvider } from './home_page';
|
||||
export { DashboardPageProvider } from './dashboard_page';
|
||||
export { VisualizePageProvider } from './visualize_page';
|
||||
export { SettingsPageProvider } from './settings_page';
|
||||
export { MonitoringPageProvider } from './monitoring_page';
|
||||
export { PointSeriesPageProvider } from './point_series_page';
|
||||
export { VisualBuilderPageProvider } from './visual_builder_page';
|
||||
export { TimelionPageProvider } from './timelion_page';
|
||||
export { SharePageProvider } from './share_page';
|
||||
export { TimePickerPageProvider } from './time_picker';
|
70
test/functional/page_objects/index.ts
Normal file
70
test/functional/page_objects/index.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// @ts-ignore not TS yet
|
||||
import { CommonPageProvider } from './common_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { ConsolePageProvider } from './console_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { ContextPageProvider } from './context_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { DashboardPageProvider } from './dashboard_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { DiscoverPageProvider } from './discover_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { HeaderPageProvider } from './header_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { HomePageProvider } from './home_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { MonitoringPageProvider } from './monitoring_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { PointSeriesPageProvider } from './point_series_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { SettingsPageProvider } from './settings_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { SharePageProvider } from './share_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { ShieldPageProvider } from './shield_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { TimePickerPageProvider } from './time_picker';
|
||||
// @ts-ignore not TS yet
|
||||
import { TimelionPageProvider } from './timelion_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { VisualBuilderPageProvider } from './visual_builder_page';
|
||||
// @ts-ignore not TS yet
|
||||
import { VisualizePageProvider } from './visualize_page';
|
||||
|
||||
export const pageObjects = {
|
||||
common: CommonPageProvider,
|
||||
console: ConsolePageProvider,
|
||||
context: ContextPageProvider,
|
||||
dashboard: DashboardPageProvider,
|
||||
discover: DiscoverPageProvider,
|
||||
header: HeaderPageProvider,
|
||||
home: HomePageProvider,
|
||||
monitoring: MonitoringPageProvider,
|
||||
pointSeries: PointSeriesPageProvider,
|
||||
settings: SettingsPageProvider,
|
||||
share: SharePageProvider,
|
||||
shield: ShieldPageProvider,
|
||||
timelion: TimelionPageProvider,
|
||||
timePicker: TimePickerPageProvider,
|
||||
visualBuilder: VisualBuilderPageProvider,
|
||||
visualize: VisualizePageProvider,
|
||||
};
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export function AppsMenuProvider({ getService }) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const globalNav = getService('globalNav');
|
||||
|
||||
return new class AppsMenu {
|
||||
async readLinks() {
|
||||
await this._ensureMenuOpen();
|
||||
const buttons = await testSubjects.findAll('appsMenu appLink');
|
||||
try {
|
||||
return Promise.all(buttons.map(async (element) => ({
|
||||
text: await element.getVisibleText(),
|
||||
href: await element.getProperty('href'),
|
||||
})));
|
||||
} finally {
|
||||
await this._ensureMenuClosed();
|
||||
}
|
||||
}
|
||||
|
||||
async linkExists(name) {
|
||||
return (await this.readLinks()).some(nl => nl.text === name);
|
||||
}
|
||||
|
||||
async clickLink(appTitle) {
|
||||
try {
|
||||
log.debug(`click "${appTitle}" tab`);
|
||||
await this._ensureMenuOpen();
|
||||
const container = await testSubjects.find('appsMenu');
|
||||
const link = await container.findByPartialLinkText(appTitle);
|
||||
await link.click();
|
||||
} finally {
|
||||
await this._ensureMenuClosed();
|
||||
}
|
||||
}
|
||||
|
||||
async _ensureMenuOpen() {
|
||||
if (!await testSubjects.exists('navDrawer&expanded')) {
|
||||
await testSubjects.moveMouseTo('navDrawer');
|
||||
await retry.waitFor('apps drawer open', async () => (
|
||||
await testSubjects.exists('navDrawer&expanded')
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
async _ensureMenuClosed() {
|
||||
await globalNav.moveMouseToLogo();
|
||||
await retry.waitFor('apps drawer closed', async () => (
|
||||
await testSubjects.exists('navDrawer&collapsed')
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
95
test/functional/services/apps_menu.ts
Normal file
95
test/functional/services/apps_menu.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export function AppsMenuProvider({ getService }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const globalNav = getService('globalNav');
|
||||
|
||||
return new class AppsMenu {
|
||||
/**
|
||||
* Get the text and href from each of the links in the apps menu
|
||||
*/
|
||||
public async readLinks() {
|
||||
await this.ensureMenuOpen();
|
||||
const appMenu = await testSubjects.find('navDrawer&expanded appsMenu');
|
||||
const $ = await appMenu.parseDomContent();
|
||||
|
||||
const links: Array<{
|
||||
text: string;
|
||||
href: string;
|
||||
}> = $.findTestSubjects('appLink')
|
||||
.toArray()
|
||||
.map((link: any) => {
|
||||
return {
|
||||
text: $(link).text(),
|
||||
href: $(link).attr('href'),
|
||||
};
|
||||
});
|
||||
|
||||
await this.ensureMenuClosed();
|
||||
return links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an app link with the given name exists
|
||||
* @param name
|
||||
*/
|
||||
public async linkExists(name: string) {
|
||||
return (await this.readLinks()).some(nl => nl.text === name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the app link within the app menu that has the given name
|
||||
* @param name
|
||||
*/
|
||||
public async clickLink(name: string) {
|
||||
try {
|
||||
log.debug(`click "${name}" app link`);
|
||||
await this.ensureMenuOpen();
|
||||
const container = await testSubjects.find('navDrawer&expanded appsMenu');
|
||||
const link = await container.findByPartialLinkText(name);
|
||||
await link.click();
|
||||
} finally {
|
||||
await this.ensureMenuClosed();
|
||||
}
|
||||
}
|
||||
|
||||
private async ensureMenuClosed() {
|
||||
await globalNav.moveMouseToLogo();
|
||||
await retry.waitFor(
|
||||
'apps drawer closed',
|
||||
async () => await testSubjects.exists('navDrawer&collapsed')
|
||||
);
|
||||
}
|
||||
|
||||
private async ensureMenuOpen() {
|
||||
if (!(await testSubjects.exists('navDrawer&expanded'))) {
|
||||
await testSubjects.moveMouseTo('navDrawer');
|
||||
await retry.waitFor(
|
||||
'apps drawer open',
|
||||
async () => await testSubjects.exists('navDrawer&expanded')
|
||||
);
|
||||
}
|
||||
}
|
||||
}();
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { QueryBarProvider } from './query_bar';
|
||||
export { FilterBarProvider } from './filter_bar';
|
||||
export { FindProvider } from './find';
|
||||
export { TestSubjectsProvider } from './test_subjects';
|
||||
export { RemoteProvider } from './remote';
|
||||
export { DocTableProvider } from './doc_table';
|
||||
export { ScreenshotsProvider } from './screenshots';
|
||||
export { FailureDebuggingProvider } from './failure_debugging';
|
||||
export { VisualizeListingTableProvider } from './visualize_listing_table';
|
||||
export { FlyoutProvider } from './flyout';
|
||||
export { EmbeddingProvider } from './embedding';
|
||||
export { ComboBoxProvider } from './combo_box';
|
||||
export { RenderableProvider } from './renderable';
|
||||
export { TableProvider } from './table';
|
||||
export { BrowserProvider } from './browser';
|
||||
export { InspectorProvider } from './inspector';
|
||||
export { AppsMenuProvider } from './apps_menu';
|
||||
export { GlobalNavProvider } from './global_nav';
|
||||
|
||||
export * from './visualizations';
|
||||
export * from './dashboard';
|
89
test/functional/services/index.ts
Normal file
89
test/functional/services/index.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { AppsMenuProvider } from './apps_menu';
|
||||
// @ts-ignore not TS yet
|
||||
import { BrowserProvider } from './browser';
|
||||
// @ts-ignore not TS yet
|
||||
import { ComboBoxProvider } from './combo_box';
|
||||
import {
|
||||
DashboardAddPanelProvider,
|
||||
DashboardExpectProvider,
|
||||
DashboardPanelActionsProvider,
|
||||
DashboardVisualizationProvider,
|
||||
// @ts-ignore not TS yet
|
||||
} from './dashboard';
|
||||
// @ts-ignore not TS yet
|
||||
import { DocTableProvider } from './doc_table';
|
||||
// @ts-ignore not TS yet
|
||||
import { EmbeddingProvider } from './embedding';
|
||||
// @ts-ignore not TS yet
|
||||
import { FailureDebuggingProvider } from './failure_debugging';
|
||||
// @ts-ignore not TS yet
|
||||
import { FilterBarProvider } from './filter_bar';
|
||||
// @ts-ignore not TS yet
|
||||
import { FindProvider } from './find';
|
||||
// @ts-ignore not TS yet
|
||||
import { FlyoutProvider } from './flyout';
|
||||
// @ts-ignore not TS yet
|
||||
import { GlobalNavProvider } from './global_nav';
|
||||
// @ts-ignore not TS yet
|
||||
import { InspectorProvider } from './inspector';
|
||||
// @ts-ignore not TS yet
|
||||
import { QueryBarProvider } from './query_bar';
|
||||
// @ts-ignore not TS yet
|
||||
import { RemoteProvider } from './remote';
|
||||
// @ts-ignore not TS yet
|
||||
import { RenderableProvider } from './renderable';
|
||||
// @ts-ignore not TS yet
|
||||
import { ScreenshotsProvider } from './screenshots';
|
||||
// @ts-ignore not TS yet
|
||||
import { TableProvider } from './table';
|
||||
// @ts-ignore not TS yet
|
||||
import { TestSubjectsProvider } from './test_subjects';
|
||||
// @ts-ignore not TS yet
|
||||
import { PieChartProvider } from './visualizations';
|
||||
// @ts-ignore not TS yet
|
||||
import { VisualizeListingTableProvider } from './visualize_listing_table';
|
||||
|
||||
export const services = {
|
||||
__leadfoot__: RemoteProvider,
|
||||
filterBar: FilterBarProvider,
|
||||
queryBar: QueryBarProvider,
|
||||
find: FindProvider,
|
||||
testSubjects: TestSubjectsProvider,
|
||||
docTable: DocTableProvider,
|
||||
screenshots: ScreenshotsProvider,
|
||||
dashboardVisualizations: DashboardVisualizationProvider,
|
||||
dashboardExpect: DashboardExpectProvider,
|
||||
failureDebugging: FailureDebuggingProvider,
|
||||
visualizeListingTable: VisualizeListingTableProvider,
|
||||
dashboardAddPanel: DashboardAddPanelProvider,
|
||||
dashboardPanelActions: DashboardPanelActionsProvider,
|
||||
flyout: FlyoutProvider,
|
||||
comboBox: ComboBoxProvider,
|
||||
embedding: EmbeddingProvider,
|
||||
renderable: RenderableProvider,
|
||||
table: TableProvider,
|
||||
browser: BrowserProvider,
|
||||
pieChart: PieChartProvider,
|
||||
inspector: InspectorProvider,
|
||||
appsMenu: AppsMenuProvider,
|
||||
globalNav: GlobalNavProvider,
|
||||
};
|
|
@ -1,18 +1,10 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"allowJs": true,
|
||||
"outDir": "target",
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"*":[
|
||||
"*"
|
||||
]
|
||||
},
|
||||
"types": [
|
||||
"node",
|
||||
"mocha"
|
||||
"mocha",
|
||||
"@kbn/test/types/expect.js"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export * from './wrapper';
|
||||
export * from './mocha_decorations';
|
30
test/types/mocha_decorations.d.ts
vendored
Normal file
30
test/types/mocha_decorations.d.ts
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Suite } from 'mocha';
|
||||
|
||||
// tslint:disable-next-line:no-namespace We need to use the namespace here to match the Mocha definition
|
||||
declare module 'mocha' {
|
||||
interface Suite {
|
||||
/**
|
||||
* Assign tags to the test suite to determine in which CI job it should be run.
|
||||
*/
|
||||
tags(tags: string[] | string): void;
|
||||
}
|
||||
}
|
|
@ -47,7 +47,13 @@
|
|||
"downlevelIteration": true,
|
||||
// import tslib helpers rather than inlining helpers for iteration or spreading, for instance
|
||||
"importHelpers": true,
|
||||
"skipLibCheck": true
|
||||
// adding global typings
|
||||
"types": [
|
||||
"node",
|
||||
"jest",
|
||||
"react",
|
||||
"@kbn/test/types/expect.js"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"kibana.d.ts",
|
||||
|
@ -56,7 +62,7 @@
|
|||
"test_utils/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"src/**/__fixtures__/**/*",
|
||||
"src/**/__fixtures__/**/*"
|
||||
// In the build we actually exclude **/public/**/* from this config so that
|
||||
// we can run the TSC on both this and the .browser version of this config
|
||||
// file, but if we did it during development IDEs would not be able to find
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
"declarationDir": "./target/types",
|
||||
"stripInternal": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"declarationMap": true,
|
||||
"types": [
|
||||
"node",
|
||||
"jest"
|
||||
]
|
||||
"declarationMap": true
|
||||
},
|
||||
"include": [
|
||||
"./src/type_exports.ts"
|
||||
|
|
|
@ -30,13 +30,13 @@
|
|||
"@kbn/plugin-helpers": "9.0.2",
|
||||
"@kbn/test": "1.0.0",
|
||||
"@types/angular": "1.6.50",
|
||||
"@types/cheerio": "^0.22.10",
|
||||
"@types/d3-array": "^1.2.1",
|
||||
"@types/d3-scale": "^2.0.0",
|
||||
"@types/d3-shape": "^1.2.2",
|
||||
"@types/d3-shape": "^1.3.1",
|
||||
"@types/d3-time": "^1.0.7",
|
||||
"@types/d3-time-format": "^2.1.0",
|
||||
"@types/elasticsearch": "^5.0.30",
|
||||
"@types/expect.js": "^0.3.29",
|
||||
"@types/graphql": "^0.13.1",
|
||||
"@types/history": "^4.6.2",
|
||||
"@types/jest": "^24.0.9",
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": [
|
||||
"expect.js",
|
||||
"@kbn/test/types/expect.js",
|
||||
"mocha",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*",
|
||||
"**/*"
|
||||
],
|
||||
"exclude": [],
|
||||
}
|
||||
|
|
|
@ -4,14 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export interface EsArchiverOptions {
|
||||
skipExisting?: boolean;
|
||||
}
|
||||
|
||||
export interface EsArchiver {
|
||||
load(archiveName: string, options?: EsArchiverOptions): Promise<void>;
|
||||
unload(archiveName: string): Promise<void>;
|
||||
}
|
||||
import { EsArchiver } from '../../../src/es_archiver';
|
||||
|
||||
export interface KibanaFunctionalTestDefaultProviders {
|
||||
getService(serviceName: 'esArchiver'): EsArchiver;
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
},
|
||||
"types": [
|
||||
"node",
|
||||
"jest"
|
||||
"jest",
|
||||
"@kbn/test/types/expect.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
33
yarn.lock
33
yarn.lock
|
@ -1146,7 +1146,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/chance/-/chance-1.0.1.tgz#c10703020369602c40dd9428cc6e1437027116df"
|
||||
integrity sha512-jtV6Bv/j+xk4gcXeLlESwNc/m/I/dIZA0xrt29g0uKcjyPob8iisj/5z0ARE+Ldfx4MxjNFNECG0z++J7zJgqg==
|
||||
|
||||
"@types/cheerio@*":
|
||||
"@types/cheerio@*", "@types/cheerio@^0.22.10":
|
||||
version "0.22.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.10.tgz#780d552467824be4a241b29510a7873a7432c4a6"
|
||||
integrity sha512-fOM/Jhv51iyugY7KOBZz2ThfT1gwvsGCfWxpLpZDgkGjpEO4Le9cld07OdskikLjDUQJ43dzDaVRSFwQlpdqVg==
|
||||
|
@ -1215,10 +1215,10 @@
|
|||
dependencies:
|
||||
"@types/d3-time" "*"
|
||||
|
||||
"@types/d3-shape@^1.2.2":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.2.3.tgz#cadc9f93a626db9190f306048a650df4ffa4e500"
|
||||
integrity sha512-iP9TcX0EVi+LlX+jK9ceS+yhEz5abTitF+JaO2ugpRE/J+bccaYLe/0/3LETMmdaEkYarIyboZW8OF67Mpnj1w==
|
||||
"@types/d3-shape@^1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.3.1.tgz#1b4f92b7efd7306fe2474dc6ee94c0f0ed2e6ab6"
|
||||
integrity sha512-usqdvUvPJ7AJNwpd2drOzRKs1ELie53p2m2GnPKr076/ADM579jVTJ5dPsoZ5E/CMNWk8lvPWYQSvilpp6jjwg==
|
||||
dependencies:
|
||||
"@types/d3-path" "*"
|
||||
|
||||
|
@ -1304,11 +1304,6 @@
|
|||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/expect.js@^0.3.29":
|
||||
version "0.3.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/expect.js/-/expect.js-0.3.29.tgz#28dd359155b84b8ecb094afc3f4b74c3222dca3b"
|
||||
integrity sha1-KN01kVW4S47LCUr8P0t0wyItyjs=
|
||||
|
||||
"@types/fetch-mock@7.2.1":
|
||||
version "7.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/fetch-mock/-/fetch-mock-7.2.1.tgz#5630999aa75532e00af42a54cbe05e1651f4a080"
|
||||
|
@ -1465,11 +1460,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.32.tgz#121f6917c4389db3923640b2e68de5fa64dda88e"
|
||||
integrity sha512-q9Q6+eUEGwQkv4Sbst3J4PNgDOvpuVuKj79Hl/qnmBMEIPzB5QoFRUtjcgcg2xNUZyYUGXBk5wYIBKHt0A+Mxw==
|
||||
|
||||
"@types/json5@^0.0.29":
|
||||
version "0.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||
|
||||
"@types/json5@^0.0.30":
|
||||
version "0.0.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.30.tgz#44cb52f32a809734ca562e685c6473b5754a7818"
|
||||
|
@ -7074,7 +7064,7 @@ deep-is@~0.1.3:
|
|||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
|
||||
|
||||
deepmerge@2.2.1, deepmerge@^2.0.1:
|
||||
deepmerge@2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||
|
@ -21254,17 +21244,6 @@ ts-node@^7.0.1:
|
|||
source-map-support "^0.5.6"
|
||||
yn "^2.0.0"
|
||||
|
||||
tsconfig-paths@^3.8.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.8.0.tgz#4e34202d5b41958f269cf56b01ed95b853d59f72"
|
||||
integrity sha512-zZEYFo4sjORK8W58ENkRn9s+HmQFkkwydDG7My5s/fnfr2YYCaiyXe/HBUcIgU8epEKOXwiahOO+KZYjiXlWyQ==
|
||||
dependencies:
|
||||
"@types/json5" "^0.0.29"
|
||||
deepmerge "^2.0.1"
|
||||
json5 "^1.0.1"
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@1.9.3, tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.2, tslib@^1.9.3:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
|
||||
|
|
Loading…
Reference in a new issue