Skip to content

Commit

Permalink
Typescript-ify FTR Remote (#32447)
Browse files Browse the repository at this point in the history
* [ftr] flatten GenericProviderTypes to fix "log" types

* [ftr/remote] typscript-ify

* remove webdriver types, since they're version 3 and we're using version 4

* simplify initWebDriver() function

* keep jest tests in the functional tests as js, mixing jest and mocha types doesn't work
  • Loading branch information
Spencer authored Mar 6, 2019
1 parent 9c37b69 commit a7e1061
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 179 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@
"@types/bluebird": "^3.1.1",
"@types/boom": "^7.2.0",
"@types/chance": "^1.0.0",
"@types/chromedriver": "^2.38.0",
"@types/classnames": "^2.2.3",
"@types/d3": "^3.5.41",
"@types/dedent": "^0.7.0",
Expand Down
17 changes: 11 additions & 6 deletions packages/kbn-test/types/ftr.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
* under the License.
*/

import { DefaultServiceProviders } from '../../../src/functional_test_runner/types';
import { ToolingLog } from '@kbn/dev-utils';
import { Config, Lifecycle } from '../../../src/functional_test_runner/lib';

interface AsyncInstance<T> {
/**
Expand All @@ -39,22 +40,23 @@ type MaybeAsyncInstance<T> = T extends Promise<infer X> ? AsyncInstance<X> & X :
* 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> = {
type ProvidedTypeMap<T extends {}> = {
[K in keyof T]: T[K] extends (...args: any[]) => any
? MaybeAsyncInstance<ReturnType<T[K]>>
: never
: unknown
};

export interface GenericFtrProviderContext<
ServiceProviders extends object,
PageObjectProviders extends object,
ServiceMap = ProvidedTypeMap<ServiceProviders & DefaultServiceProviders>,
ServiceProviders extends {},
PageObjectProviders extends {},
ServiceMap = ProvidedTypeMap<ServiceProviders>,
PageObjectMap = ProvidedTypeMap<PageObjectProviders>
> {
/**
* Determine if a service is avaliable
* @param serviceName
*/
hasService(serviceName: 'config' | 'log' | 'lifecycle'): true;
hasService<K extends keyof ServiceMap>(serviceName: K): serviceName is K;
hasService(serviceName: string): serviceName is keyof ServiceMap;

Expand All @@ -63,6 +65,9 @@ export interface GenericFtrProviderContext<
* outside of a test/hook, then make sure to call its `.init()` method and await it's promise.
* @param serviceName
*/
getService(serviceName: 'config'): Config;
getService(serviceName: 'log'): ToolingLog;
getService(serviceName: 'lifecycle'): Lifecycle;
getService<T extends keyof ServiceMap>(serviceName: T): ServiceMap[T];

/**
Expand Down
27 changes: 0 additions & 27 deletions src/functional_test_runner/types.ts

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,44 @@
* under the License.
*/

export function preventParallelCalls(fn, filter) {
const execQueue = [];
export function preventParallelCalls<C extends void, A, R>(
fn: (this: C, arg: A) => Promise<R>,
filter: (arg: A) => boolean
) {
const execQueue: Task[] = [];

return async function (arg) {
if (filter(arg)) {
return await fn.call(this, arg);
class Task {
public promise: Promise<R>;
private resolve!: (result: R) => void;
private reject!: (error: Error) => void;

constructor(private readonly context: C, private readonly arg: A) {
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}

const task = {
exec: async () => {
try {
task.resolve(await fn.call(this, arg));
} catch (error) {
task.reject(error);
} finally {
execQueue.shift();
if (execQueue.length) {
execQueue[0].exec();
}
public async exec() {
try {
this.resolve(await fn.call(this.context, this.arg));
} catch (error) {
this.reject(error);
} finally {
execQueue.shift();
if (execQueue.length) {
execQueue[0].exec();
}
}
};
}
}

task.promise = new Promise((resolve, reject) => {
task.resolve = resolve;
task.reject = reject;
});
return async function(this: C, arg: A) {
if (filter(arg)) {
return await fn.call(this, arg);
}

const task = new Task(this, arg);
if (execQueue.push(task) === 1) {
// only item in the queue, kick it off
task.exec();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,54 @@
* under the License.
*/

import { FtrProviderContext } from '../../ftr_provider_context';
import { initWebDriver } from './webdriver';

export async function RemoteProvider({ getService }) {
export async function RemoteProvider({ getService }: FtrProviderContext) {
const lifecycle = getService('lifecycle');
const log = getService('log');
const config = getService('config');
const possibleBrowsers = ['chrome', 'firefox', 'ie'];
const browserType = process.env.TEST_BROWSER_TYPE || 'chrome';

if (!possibleBrowsers.includes(browserType)) {
throw new Error(`Unexpected TEST_BROWSER_TYPE "${browserType}". Valid options are ` + possibleBrowsers.join(','));
if (browserType !== 'chrome' && browserType !== 'firefox') {
throw new Error(
`Unexpected TEST_BROWSER_TYPE "${browserType}", only "chrome" and "firefox" are supported`
);
}

const { driver, By, Key, until, LegacyActionSequence } = await initWebDriver({ log, browserType });
const { driver, By, Key, until, LegacyActionSequence } = await initWebDriver(log, browserType);

log.info('Remote initialized');

lifecycle.on('beforeTests', async () => {
// hard coded default, can be overridden per suite using `browser.setWindowSize()`
// and will be automatically reverted after each suite
await driver.manage().window().setRect({ width: 1600, height: 1000 });
await driver
.manage()
.window()
.setRect({ width: 1600, height: 1000 });
});

const windowSizeStack = [];
const windowSizeStack: Array<{ width: number; height: number }> = [];
lifecycle.on('beforeTestSuite', async () => {
windowSizeStack.unshift(await driver.manage().window().getRect());
windowSizeStack.unshift(
await driver
.manage()
.window()
.getRect()
);
});

lifecycle.on('beforeEachTest', async () => {
await driver.manage().setTimeouts({ implicit: config.get('timeouts.find') });
});

lifecycle.on('afterTestSuite', async () => {
const { width, height } = windowSizeStack.shift();
await driver.manage().window().setRect({ width: width, height: height });
const { width, height } = windowSizeStack.shift()!;
await driver
.manage()
.window()
.setRect({ width, height });
});

lifecycle.on('cleanup', async () => await driver.quit());
Expand Down
56 changes: 0 additions & 56 deletions test/functional/services/remote/verbose_remote_logging.js

This file was deleted.

Loading

0 comments on commit a7e1061

Please sign in to comment.