Skip to content

Commit

Permalink
feat: add latest webdriverIO runner (#207)
Browse files Browse the repository at this point in the history
  • Loading branch information
ineedfat authored and Diego Ferreiro Val committed Oct 16, 2019
1 parent 9bf551c commit 7e457b0
Show file tree
Hide file tree
Showing 6 changed files with 491 additions and 7 deletions.
24 changes: 24 additions & 0 deletions packages/@best/runner-webdriverio/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@best/runner-webdriverio",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"version": "4.0.0-alpha8",
"description": "Best Runner (WebdriverIO)",
"keywords": [
"Best",
"Runner",
"performance"
],
"main": "build/index.js",
"dependencies": {
"@best/runner-abstract": "4.0.0-alpha8",
"@best/types": "4.0.0-alpha8",
"deepmerge": "^4.0.0",
"webdriverio": "^5.13.2"
},
"files": [
"build/**/*.js"
]
}
104 changes: 104 additions & 0 deletions packages/@best/runner-webdriverio/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2019, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/

import { RunnerOutputStream } from "@best/console-stream";
import { FrozenGlobalConfig, FrozenProjectConfig, BenchmarkInfo, BenchmarkRuntimeConfig, BenchmarkResults, BenchmarkResultsState, BenchmarkResultsSnapshot } from '@best/types';
import AbstractRunner from '@best/runner-abstract';
import WebdriverBrowser from './webdriver';

declare var BEST: any;
const UPDATE_INTERVAL = 300;


export default class Runner extends AbstractRunner {

async run(benchmarkInfo: BenchmarkInfo, projectConfig: FrozenProjectConfig, globalConfig: FrozenGlobalConfig, runnerLogStream: RunnerOutputStream): Promise<BenchmarkResultsSnapshot> {
const { benchmarkEntry } = benchmarkInfo;
const { useHttp } = projectConfig;

const runtimeOptions = this.getRuntimeOptions(projectConfig);
const state = this.initializeBenchmarkState();

const { url, terminate } = await this.initializeServer(benchmarkEntry, useHttp);
const browser = new WebdriverBrowser(url, projectConfig);

try {
await browser.initialize();
runnerLogStream.onBenchmarkStart(benchmarkEntry);

const { results } = await this.runIterations(browser, state, runtimeOptions, runnerLogStream);
const environment = await this.getEnvironment({ version:browser.version() }, projectConfig, globalConfig);

return { results, environment, benchmarkInfo, projectConfig };
} catch (e) {
runnerLogStream.onBenchmarkError(benchmarkEntry);
throw e;
} finally {
runnerLogStream.onBenchmarkEnd(benchmarkEntry);
await browser.close();
terminate();
}
}

initializeBenchmarkState(): BenchmarkResultsState {
return { executedTime: 0, executedIterations: 0, results: [] };
}

async runIterations(browser: WebdriverBrowser, state: BenchmarkResultsState, runtimeOptions: BenchmarkRuntimeConfig, runnnerLogStream: RunnerOutputStream): Promise<BenchmarkResultsState> {
return runtimeOptions.iterateOnClient
? this.runClientIterations(browser, state, runtimeOptions, runnnerLogStream)
: this.runServerIterations(browser, state, runtimeOptions, runnnerLogStream);
}

async runClientIterations(browser: WebdriverBrowser, state: BenchmarkResultsState, runtimeOptions: BenchmarkRuntimeConfig, runnerLogStream: RunnerOutputStream): Promise<BenchmarkResultsState> {
// Run an iteration to estimate the time it will take
const testResult = await this.runIteration(browser, { iterations: 1 });
const estimatedIterationTime = testResult.aggregate;

const start = Date.now();
// eslint-disable-next-line lwc/no-set-interval
const intervalId = setInterval(() => {
const executing = Date.now() - start;
state.executedTime = executing;
state.executedIterations = Math.round(executing / estimatedIterationTime);
runnerLogStream.updateBenchmarkProgress(state, runtimeOptions);
}, UPDATE_INTERVAL);

await browser.reloadPage();
const { results: [root,] } = await this.runIteration(browser, runtimeOptions);
state.results.push(root);
clearInterval(intervalId);

return state;
}

async runServerIterations(browser: WebdriverBrowser, state: BenchmarkResultsState, runtimeOptions: BenchmarkRuntimeConfig, runnnerLogStream: RunnerOutputStream): Promise<BenchmarkResultsState> {
while (state.executedTime < runtimeOptions.maxDuration || state.executedIterations < runtimeOptions.minSampleCount) {
const start = Date.now();
const { results: [root,] } = await this.runIteration(browser, runtimeOptions);
await browser.reloadPage();
state.executedTime += Date.now() - start;
state.executedIterations++;
if (root) {
state.results.push(root);
}
runnnerLogStream.updateBenchmarkProgress(state, runtimeOptions);
}

return state;
}

async runIteration(browser: WebdriverBrowser, payload: any): Promise<BenchmarkResults> {
return browser.evaluate(async (o: any, done: any) => {
try {
done(await BEST.runBenchmark(o))
} catch(e) {
throw e;
}
}, payload);
}
}
71 changes: 71 additions & 0 deletions packages/@best/runner-webdriverio/src/webdriver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2019, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/

import { FrozenProjectConfig } from '@best/types';
import { remote } from 'webdriverio';
import merge from 'deepmerge';

const DEFAULT_WEBDRIVERIO_OPTIONS = {
capabilities: {
timeouts: { "implicit": 0, "pageLoad": 300000, "script": 120000 },
browserName: "chrome",
},
hostname: "localhost",
port: 4444,
logLevel: "silent",
}

export default class WebdriverBrowser {
pageUrl: string;
projectConfig: FrozenProjectConfig;
browser?: WebdriverIOAsync.BrowserObject;
wdioOpts: any;

constructor(url: string, projectConfig: FrozenProjectConfig) {
this.pageUrl = url;
this.projectConfig = projectConfig;
this.wdioOpts = Object.assign({}, DEFAULT_WEBDRIVERIO_OPTIONS);

// restricting what client config can override
if (this.projectConfig.benchmarkRunnerConfig.webdriverOptions) {
this.wdioOpts.capabilities = merge(this.wdioOpts.capabilities,
this.projectConfig.benchmarkRunnerConfig.webdriverOptions.capabilities || {})
}
}

/**
* Initialize a new browser session and navigate to pageUrl
*/
async initialize() {
this.browser = await remote(this.wdioOpts);
await this.browser.url(this.pageUrl);
}


async close() {
if (this.browser) {
return await this.browser.closeWindow();
}
}

async reloadPage() {
if (this.browser) {
await this.browser.refresh();
}
}

async evaluate(fn: (o: any, done: any) => any, payload: any) {
if(this.browser) {
return await this.browser.executeAsync(fn, payload);
}
return null;
}

version() {
return this.wdioOpts.capabilities ? this.wdioOpts.capabilities.browserVersion : "unknown";
}
}
11 changes: 11 additions & 0 deletions packages/@best/runner-webdriverio/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "../../../tsconfig.settings.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "build"
},
"references": [
{ "path": "../runner-abstract" },
{ "path": "../types" }
]
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{ "path": "./packages/@best/runner-headless" },
{ "path": "./packages/@best/runner-remote" },
{ "path": "./packages/@best/runner-hub" },
// { "path": "./packages/@best/runner-webdriver" },
{ "path": "./packages/@best/runner-webdriverio" },
{ "path": "./packages/@best/runtime" },
{ "path": "./packages/@best/store" },
{ "path": "./packages/@best/store-aws" },
Expand Down
Loading

0 comments on commit 7e457b0

Please sign in to comment.