UNPKG

@angular/benchpress

Version:

Benchpress - a framework for e2e performance tests

95 lines 14.6 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { Injector } from '@angular/core'; import { Options } from './common_options'; import { Metric } from './metric'; import { MultiMetric } from './metric/multi_metric'; import { PerflogMetric } from './metric/perflog_metric'; import { UserMetric } from './metric/user_metric'; import { Reporter } from './reporter'; import { ConsoleReporter } from './reporter/console_reporter'; import { MultiReporter } from './reporter/multi_reporter'; import { SampleDescription } from './sample_description'; import { Sampler } from './sampler'; import { Validator } from './validator'; import { RegressionSlopeValidator } from './validator/regression_slope_validator'; import { SizeValidator } from './validator/size_validator'; import { WebDriverAdapter } from './web_driver_adapter'; import { WebDriverExtension } from './web_driver_extension'; import { ChromeDriverExtension } from './webdriver/chrome_driver_extension'; import { FirefoxDriverExtension } from './webdriver/firefox_driver_extension'; import { IOsDriverExtension } from './webdriver/ios_driver_extension'; /** * The Runner is the main entry point for executing a sample run. * It provides defaults, creates the injector and calls the sampler. */ export class Runner { constructor(_defaultProviders = []) { this._defaultProviders = _defaultProviders; } sample({ id, execute, prepare, microMetrics, providers, userMetrics }) { const sampleProviders = [ _DEFAULT_PROVIDERS, this._defaultProviders, { provide: Options.SAMPLE_ID, useValue: id }, { provide: Options.EXECUTE, useValue: execute } ]; if (prepare != null) { sampleProviders.push({ provide: Options.PREPARE, useValue: prepare }); } if (microMetrics != null) { sampleProviders.push({ provide: Options.MICRO_METRICS, useValue: microMetrics }); } if (userMetrics != null) { sampleProviders.push({ provide: Options.USER_METRICS, useValue: userMetrics }); } if (providers != null) { sampleProviders.push(providers); } const inj = Injector.create(sampleProviders); const adapter = inj.get(WebDriverAdapter); return Promise .all([adapter.capabilities(), adapter.executeScript('return window.navigator.userAgent;')]) .then((args) => { const capabilities = args[0]; const userAgent = args[1]; // This might still create instances twice. We are creating a new injector with all the // providers. // Only WebDriverAdapter is reused. // TODO(vsavkin): consider changing it when toAsyncFactory is added back or when child // injectors are handled better. const injector = Injector.create([ sampleProviders, { provide: Options.CAPABILITIES, useValue: capabilities }, { provide: Options.USER_AGENT, useValue: userAgent }, { provide: WebDriverAdapter, useValue: adapter } ]); // TODO: With TypeScript 2.5 injector.get does not infer correctly the // return type. Remove 'any' and investigate the issue. const sampler = injector.get(Sampler); return sampler.sample(); }); } } const _DEFAULT_PROVIDERS = [ Options.DEFAULT_PROVIDERS, Sampler.PROVIDERS, ConsoleReporter.PROVIDERS, RegressionSlopeValidator.PROVIDERS, SizeValidator.PROVIDERS, ChromeDriverExtension.PROVIDERS, FirefoxDriverExtension.PROVIDERS, IOsDriverExtension.PROVIDERS, PerflogMetric.PROVIDERS, UserMetric.PROVIDERS, SampleDescription.PROVIDERS, MultiReporter.provideWith([ConsoleReporter]), MultiMetric.provideWith([PerflogMetric, UserMetric]), { provide: Reporter, useExisting: MultiReporter }, { provide: Validator, useExisting: RegressionSlopeValidator }, WebDriverExtension.provideFirstSupported([ChromeDriverExtension, FirefoxDriverExtension, IOsDriverExtension]), { provide: Metric, useExisting: MultiMetric }, ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVubmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvYmVuY2hwcmVzcy9zcmMvcnVubmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBQyxRQUFRLEVBQWlCLE1BQU0sZUFBZSxDQUFDO0FBRXZELE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUNsRCxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDdEQsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQ2hELE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxZQUFZLENBQUM7QUFDcEMsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLDZCQUE2QixDQUFDO0FBQzVELE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RCxPQUFPLEVBQUMsT0FBTyxFQUFjLE1BQU0sV0FBVyxDQUFDO0FBQy9DLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFDdEMsT0FBTyxFQUFDLHdCQUF3QixFQUFDLE1BQU0sd0NBQXdDLENBQUM7QUFDaEYsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBQ3pELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQ3RELE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQzFELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLHFDQUFxQyxDQUFDO0FBQzFFLE9BQU8sRUFBQyxz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QXdCLENBQUMsU0FBUztJQUNsQyxhQUFhLENBQUMsU0FBUztJQUN2QixxQkFBcUIsQ0FBQyxTQUFTO0lBQy9CLHNCQUFzQixDQUFDLFNBQVM7SUFDaEMsa0JBQWtCLENBQUMsU0FBUztJQUM1QixhQUFhLENBQUMsU0FBUztJQUN2QixVQUFVLENBQUMsU0FBUztJQUNwQixpQkFBaUIsQ0FBQyxTQUFTO0lBQzNCLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM1QyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUMsYUFBYSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3BELEVBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFDO0lBQy9DLEVBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsd0JBQXdCLEVBQUM7SUFDM0Qsa0JBQWtCLENBQUMscUJBQXFCLENBQ3BDLENBQUMscUJBQXFCLEVBQUUsc0JBQXNCLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztJQUN4RSxFQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBQztDQUM1QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7SW5qZWN0b3IsIFN0YXRpY1Byb3ZpZGVyfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtPcHRpb25zfSBmcm9tICcuL2NvbW1vbl9vcHRpb25zJztcbmltcG9ydCB7TWV0cmljfSBmcm9tICcuL21ldHJpYyc7XG5pbXBvcnQge011bHRpTWV0cmljfSBmcm9tICcuL21ldHJpYy9tdWx0aV9tZXRyaWMnO1xuaW1wb3J0IHtQZXJmbG9nTWV0cmljfSBmcm9tICcuL21ldHJpYy9wZXJmbG9nX21ldHJpYyc7XG5pbXBvcnQge1VzZXJNZXRyaWN9IGZyb20gJy4vbWV0cmljL3VzZXJfbWV0cmljJztcbmltcG9ydCB7UmVwb3J0ZXJ9IGZyb20gJy4vcmVwb3J0ZXInO1xuaW1wb3J0IHtDb25zb2xlUmVwb3J0ZXJ9IGZyb20gJy4vcmVwb3J0ZXIvY29uc29sZV9yZXBvcnRlcic7XG5pbXBvcnQge011bHRpUmVwb3J0ZXJ9IGZyb20gJy4vcmVwb3J0ZXIvbXVsdGlfcmVwb3J0ZXInO1xuaW1wb3J0IHtTYW1wbGVEZXNjcmlwdGlvbn0gZnJvbSAnLi9zYW1wbGVfZGVzY3JpcHRpb24nO1xuaW1wb3J0IHtTYW1wbGVyLCBTYW1wbGVTdGF0ZX0gZnJvbSAnLi9zYW1wbGVyJztcbmltcG9ydCB7VmFsaWRhdG9yfSBmcm9tICcuL3ZhbGlkYXRvcic7XG5pbXBvcnQge1JlZ3Jlc3Npb25TbG9wZVZhbGlkYXRvcn0gZnJvbSAnLi92YWxpZGF0b3IvcmVncmVzc2lvbl9zbG9wZV92YWxpZGF0b3InO1xuaW1wb3J0IHtTaXplVmFsaWRhdG9yfSBmcm9tICcuL3ZhbGlkYXRvci9zaXplX3ZhbGlkYXRvcic7XG5pbXBvcnQge1dlYkRyaXZlckFkYXB0ZXJ9IGZyb20gJy4vd2ViX2RyaXZlcl9hZGFwdGVyJztcbmltcG9ydCB7V2ViRHJpdmVyRXh0ZW5zaW9ufSBmcm9tICcuL3dlYl9kcml2ZXJfZXh0ZW5zaW9uJztcbmltcG9ydCB7Q2hyb21lRHJpdmVyRXh0ZW5zaW9ufSBmcm9tICcuL3dlYmRyaXZlci9jaHJvbWVfZHJpdmVyX2V4dGVuc2lvbic7XG5pbXBvcnQge0ZpcmVmb3hEcml2ZXJFeHRlbnNpb259IGZyb20gJy4vd2ViZHJpdmVyL2ZpcmVmb3hfZHJpdmVyX2V4dGVuc2lvbic7XG5pbXBvcnQge0lPc0RyaXZlckV4dGVuc2lvbn0gZnJvbSAnLi93ZWJkcml2ZXIvaW9zX2RyaXZlcl9leHRlbnNpb24nO1xuXG5cblxuLyoqXG4gKiBUaGUgUnVubmVyIGlzIHRoZSBtYWluIGVudHJ5IHBvaW50IGZvciBleGVjdXRpbmcgYSBzYW1wbGUgcnVuLlxuICogSXQgcHJvdmlkZXMgZGVmYXVsdHMsIGNyZWF0ZXMgdGhlIGluamVjdG9yIGFuZCBjYWxscyB0aGUgc2FtcGxlci5cbiAqL1xuZXhwb3J0IGNsYXNzIFJ1bm5lciB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgX2RlZmF1bHRQcm92aWRlcnM6IFN0YXRpY1Byb3ZpZGVyW10gPSBbXSkge31cblxuICBzYW1wbGUoe2lkLCBleGVjdXRlLCBwcmVwYXJlLCBtaWNyb01ldHJpY3MsIHByb3ZpZGVycywgdXNlck1ldHJpY3N9OiB7XG4gICAgaWQ6IHN0cmluZyxcbiAgICBleGVjdXRlPzogRnVuY3Rpb24sXG4gICAgcHJlcGFyZT86IEZ1bmN0aW9uLFxuICAgIG1pY3JvTWV0cmljcz86IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9LFxuICAgIHByb3ZpZGVycz86IFN0YXRpY1Byb3ZpZGVyW10sXG4gICAgdXNlck1ldHJpY3M/OiB7W2tleTogc3RyaW5nXTogc3RyaW5nfVxuICB9KTogUHJvbWlzZTxTYW1wbGVTdGF0ZT4ge1xuICAgIGNvbnN0IHNhbXBsZVByb3ZpZGVyczogU3RhdGljUHJvdmlkZXJbXSA9IFtcbiAgICAgIF9ERUZBVUxUX1BST1ZJREVSUywgdGhpcy5fZGVmYXVsdFByb3ZpZGVycywge3Byb3ZpZGU6IE9wdGlvbnMuU0FNUExFX0lELCB1c2VWYWx1ZTogaWR9LFxuICAgICAge3Byb3ZpZGU6IE9wdGlvbnMuRVhFQ1VURSwgdXNlVmFsdWU6IGV4ZWN1dGV9XG4gICAgXTtcbiAgICBpZiAocHJlcGFyZSAhPSBudWxsKSB7XG4gICAgICBzYW1wbGVQcm92aWRlcnMucHVzaCh7cHJvdmlkZTogT3B0aW9ucy5QUkVQQVJFLCB1c2VWYWx1ZTogcHJlcGFyZX0pO1xuICAgIH1cbiAgICBpZiAobWljcm9NZXRyaWNzICE9IG51bGwpIHtcbiAgICAgIHNhbXBsZVByb3ZpZGVycy5wdXNoKHtwcm92aWRlOiBPcHRpb25zLk1JQ1JPX01FVFJJQ1MsIHVzZVZhbHVlOiBtaWNyb01ldHJpY3N9KTtcbiAgICB9XG4gICAgaWYgKHVzZXJNZXRyaWNzICE9IG51bGwpIHtcbiAgICAgIHNhbXBsZVByb3ZpZGVycy5wdXNoKHtwcm92aWRlOiBPcHRpb25zLlVTRVJfTUVUUklDUywgdXNlVmFsdWU6IHVzZXJNZXRyaWNzfSk7XG4gICAgfVxuICAgIGlmIChwcm92aWRlcnMgIT0gbnVsbCkge1xuICAgICAgc2FtcGxlUHJvdmlkZXJzLnB1c2gocHJvdmlkZXJzKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbmogPSBJbmplY3Rvci5jcmVhdGUoc2FtcGxlUHJvdmlkZXJzKTtcbiAgICBjb25zdCBhZGFwdGVyOiBXZWJEcml2ZXJBZGFwdGVyID0gaW5qLmdldChXZWJEcml2ZXJBZGFwdGVyKTtcblxuICAgIHJldHVybiBQcm9taXNlXG4gICAgICAgIC5hbGwoW2FkYXB0ZXIuY2FwYWJpbGl0aWVzKCksIGFkYXB0ZXIuZXhlY3V0ZVNjcmlwdCgncmV0dXJuIHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50OycpXSlcbiAgICAgICAgLnRoZW4oKGFyZ3MpID0+IHtcbiAgICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBhcmdzWzBdO1xuICAgICAgICAgIGNvbnN0IHVzZXJBZ2VudCA9IGFyZ3NbMV07XG5cbiAgICAgICAgICAvLyBUaGlzIG1pZ2h0IHN0aWxsIGNyZWF0ZSBpbnN0YW5jZXMgdHdpY2UuIFdlIGFyZSBjcmVhdGluZyBhIG5ldyBpbmplY3RvciB3aXRoIGFsbCB0aGVcbiAgICAgICAgICAvLyBwcm92aWRlcnMuXG4gICAgICAgICAgLy8gT25seSBXZWJEcml2ZXJBZGFwdGVyIGlzIHJldXNlZC5cbiAgICAgICAgICAvLyBUT0RPKHZzYXZraW4pOiBjb25zaWRlciBjaGFuZ2luZyBpdCB3aGVuIHRvQXN5bmNGYWN0b3J5IGlzIGFkZGVkIGJhY2sgb3Igd2hlbiBjaGlsZFxuICAgICAgICAgIC8vIGluamVjdG9ycyBhcmUgaGFuZGxlZCBiZXR0ZXIuXG4gICAgICAgICAgY29uc3QgaW5qZWN0b3IgPSBJbmplY3Rvci5jcmVhdGUoW1xuICAgICAgICAgICAgc2FtcGxlUHJvdmlkZXJzLCB7cHJvdmlkZTogT3B0aW9ucy5DQVBBQklMSVRJRVMsIHVzZVZhbHVlOiBjYXBhYmlsaXRpZXN9LFxuICAgICAgICAgICAge3Byb3ZpZGU6IE9wdGlvbnMuVVNFUl9BR0VOVCwgdXNlVmFsdWU6IHVzZXJBZ2VudH0sXG4gICAgICAgICAgICB7cHJvdmlkZTogV2ViRHJpdmVyQWRhcHRlciwgdXNlVmFsdWU6IGFkYXB0ZXJ9XG4gICAgICAgICAgXSk7XG5cbiAgICAgICAgICAvLyBUT0RPOiBXaXRoIFR5cGVTY3JpcHQgMi41IGluamVjdG9yLmdldCBkb2VzIG5vdCBpbmZlciBjb3JyZWN0bHkgdGhlXG4gICAgICAgICAgLy8gcmV0dXJuIHR5cGUuIFJlbW92ZSAnYW55JyBhbmQgaW52ZXN0aWdhdGUgdGhlIGlzc3VlLlxuICAgICAgICAgIGNvbnN0IHNhbXBsZXIgPSBpbmplY3Rvci5nZXQoU2FtcGxlcikgYXMgYW55O1xuICAgICAgICAgIHJldHVybiBzYW1wbGVyLnNhbXBsZSgpO1xuICAgICAgICB9KTtcbiAgfVxufVxuXG5jb25zdCBfREVGQVVMVF9QUk9WSURFUlMgPSBbXG4gIE9wdGlvbnMuREVGQVVMVF9QUk9WSURFUlMsXG4gIFNhbXBsZXIuUFJPVklERVJTLFxuICBDb25zb2xlUmVwb3J0ZXIuUFJPVklERVJTLFxuICBSZWdyZXNzaW9uU2xvcGVWYWxpZGF0b3IuUFJPVklERVJTLFxuICBTaXplVmFsaWRhdG9yLlBST1ZJREVSUyxcbiAgQ2hyb21lRHJpdmVyRXh0ZW5zaW9uLlBST1ZJREVSUyxcbiAgRmlyZWZveERyaXZlckV4dGVuc2lvbi5QUk9WSURFUlMsXG4gIElPc0RyaXZlckV4dGVuc2lvbi5QUk9WSURFUlMsXG4gIFBlcmZsb2dNZXRyaWMuUFJPVklERVJTLFxuICBVc2VyTWV0cmljLlBST1ZJREVSUyxcbiAgU2FtcGxlRGVzY3JpcHRpb24uUFJPVklERVJTLFxuICBNdWx0aVJlcG9ydGVyLnByb3ZpZGVXaXRoKFtDb25zb2xlUmVwb3J0ZXJdKSxcbiAgTXVsdGlNZXRyaWMucHJvdmlkZVdpdGgoW1BlcmZsb2dNZXRyaWMsIFVzZXJNZXRyaWNdKSxcbiAge3Byb3ZpZGU6IFJlcG9ydGVyLCB1c2VFeGlzdGluZzogTXVsdGlSZXBvcnRlcn0sXG4gIHtwcm92aWRlOiBWYWxpZGF0b3IsIHVzZUV4aXN0aW5nOiBSZWdyZXNzaW9uU2xvcGVWYWxpZGF0b3J9LFxuICBXZWJEcml2ZXJFeHRlbnNpb24ucHJvdmlkZUZpcnN0U3VwcG9ydGVkKFxuICAgICAgW0Nocm9tZURyaXZlckV4dGVuc2lvbiwgRmlyZWZveERyaXZlckV4dGVuc2lvbiwgSU9zRHJpdmVyRXh0ZW5zaW9uXSksXG4gIHtwcm92aWRlOiBNZXRyaWMsIHVzZUV4aXN0aW5nOiBNdWx0aU1ldHJpY30sXG5dO1xuIl19