testcafe 1.14.1 → 1.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/LICENSE +21 -21
- package/bin/testcafe-with-v8-flag-filter.js +0 -0
- package/lib/api/exportable-lib/index.js +49 -49
- package/lib/api/request-hooks/assert-type.js +7 -7
- package/lib/api/request-hooks/hook-method-names.js +9 -9
- package/lib/api/request-hooks/hook.js +32 -32
- package/lib/api/request-hooks/interfaces.js +2 -2
- package/lib/api/request-hooks/request-logger.js +112 -112
- package/lib/api/request-hooks/request-mock/create-request-mock.js +10 -10
- package/lib/api/request-hooks/request-mock/index.js +44 -44
- package/lib/api/request-hooks/request-mock.js +46 -46
- package/lib/api/structure/base-unit.js +11 -11
- package/lib/api/structure/fixture.js +75 -75
- package/lib/api/structure/interfaces.js +2 -2
- package/lib/api/structure/test-file.js +31 -31
- package/lib/api/structure/test-timeout.js +9 -9
- package/lib/api/structure/test.js +85 -85
- package/lib/api/structure/testing-unit.js +89 -89
- package/lib/api/structure/unit-type.js +9 -9
- package/lib/api/test-controller/assertion.js +88 -88
- package/lib/api/test-controller/execution-context.js +82 -82
- package/lib/api/test-controller/index.js +358 -358
- package/lib/api/test-controller/proxy.js +28 -28
- package/lib/api/test-page-url.js +60 -60
- package/lib/api/test-run-tracker.js +68 -68
- package/lib/api/wrap-test-function.js +49 -49
- package/lib/assertions/executor.js +74 -74
- package/lib/assertions/get-fn.js +46 -46
- package/lib/assertions/type.js +20 -20
- package/lib/assets/content-types.js +9 -9
- package/lib/assets/injectables.js +18 -18
- package/lib/browser/connection/command.js +10 -10
- package/lib/browser/connection/error-hints.js +9 -9
- package/lib/browser/connection/gateway.js +159 -159
- package/lib/browser/connection/get-hints.js +33 -33
- package/lib/browser/connection/heartbeat-status.js +8 -8
- package/lib/browser/connection/index.js +328 -328
- package/lib/browser/connection/remotes-queue.js +46 -46
- package/lib/browser/connection/service-routes.js +12 -12
- package/lib/browser/connection/status.js +12 -12
- package/lib/browser/interfaces.js +2 -2
- package/lib/browser/provider/built-in/dedicated/base.js +80 -80
- package/lib/browser/provider/built-in/dedicated/chrome/browser-client.js +204 -204
- package/lib/browser/provider/built-in/dedicated/chrome/build-chrome-args.js +17 -17
- package/lib/browser/provider/built-in/dedicated/chrome/config.js +110 -110
- package/lib/browser/provider/built-in/dedicated/chrome/create-temp-profile.js +45 -45
- package/lib/browser/provider/built-in/dedicated/chrome/elapsed-upperbounds.js +15 -15
- package/lib/browser/provider/built-in/dedicated/chrome/index.js +102 -102
- package/lib/browser/provider/built-in/dedicated/chrome/interfaces.js +2 -2
- package/lib/browser/provider/built-in/dedicated/chrome/local-chrome.js +24 -24
- package/lib/browser/provider/built-in/dedicated/chrome/runtime-info.js +29 -29
- package/lib/browser/provider/built-in/dedicated/edge/index.js +10 -10
- package/lib/browser/provider/built-in/dedicated/edge/runtime-info.js +29 -29
- package/lib/browser/provider/built-in/dedicated/firefox/config.js +33 -33
- package/lib/browser/provider/built-in/dedicated/firefox/create-temp-profile.js +78 -78
- package/lib/browser/provider/built-in/dedicated/firefox/index.js +73 -73
- package/lib/browser/provider/built-in/dedicated/firefox/local-firefox.js +36 -36
- package/lib/browser/provider/built-in/dedicated/firefox/marionette-client/commands.js +13 -13
- package/lib/browser/provider/built-in/dedicated/firefox/marionette-client/index.js +200 -200
- package/lib/browser/provider/built-in/dedicated/firefox/runtime-info.js +17 -17
- package/lib/browser/provider/built-in/index.js +21 -21
- package/lib/browser/provider/built-in/locally-installed.js +30 -30
- package/lib/browser/provider/built-in/path.js +47 -47
- package/lib/browser/provider/built-in/remote.js +58 -58
- package/lib/browser/provider/index.js +303 -303
- package/lib/browser/provider/parse-provider-name.js +16 -16
- package/lib/browser/provider/plugin-host.js +121 -121
- package/lib/browser/provider/pool.js +115 -115
- package/lib/browser/provider/utils/argument-parsing.js +74 -74
- package/lib/browser/provider/utils/browser-starter.js +34 -34
- package/lib/browser/provider/utils/client-functions.js +24 -24
- package/lib/browser/provider/utils/get-maximized-headless-window-size.js +9 -9
- package/lib/cli/argument-parser.js +284 -284
- package/lib/cli/authentication-helper.js +35 -35
- package/lib/cli/cli.js +134 -134
- package/lib/cli/correct-browsers-and-sources.js +40 -40
- package/lib/cli/index.js +19 -19
- package/lib/cli/log.js +43 -43
- package/lib/cli/remotes-wizard.js +36 -36
- package/lib/cli/termination-handler.js +38 -38
- package/lib/client/automation/index.js +34 -16
- package/lib/client/automation/index.min.js +1 -1
- package/lib/client/browser/idle-page/index.html.mustache +35 -35
- package/lib/client/browser/idle-page/logo.svg +86 -86
- package/lib/client/core/index.js +14 -14
- package/lib/client/driver/index.js +46 -16
- package/lib/client/driver/index.min.js +1 -1
- package/lib/client/driver/internal-properties.js +9 -9
- package/lib/client/test-run/iframe.js.mustache +17 -17
- package/lib/client/test-run/index.js.mustache +51 -51
- package/lib/client/ui/index.js +14 -14
- package/lib/client/ui/sprite.svg +42 -42
- package/lib/client-functions/builder-symbol.js +4 -4
- package/lib/client-functions/client-function-builder.js +155 -155
- package/lib/client-functions/replicator.js +61 -61
- package/lib/client-functions/return-single-prop-mode.js +8 -8
- package/lib/client-functions/selector-api-execution-mode.js +20 -20
- package/lib/client-functions/selectors/add-api.js +645 -645
- package/lib/client-functions/selectors/create-snapshot-methods.js +13 -13
- package/lib/client-functions/selectors/prepare-api-args.js +20 -20
- package/lib/client-functions/selectors/selector-attribute-filter.js +22 -22
- package/lib/client-functions/selectors/selector-builder.js +153 -153
- package/lib/client-functions/selectors/selector-text-filter.js +43 -43
- package/lib/client-functions/selectors/snapshot-properties.js +48 -48
- package/lib/client-functions/types.js +18 -18
- package/lib/compiler/babel/format-babel-produced-code.js +10 -10
- package/lib/compiler/babel/get-base-babel-options.js +11 -11
- package/lib/compiler/babel/load-libs.js +63 -63
- package/lib/compiler/babel/preset-stage-2.js +19 -19
- package/lib/compiler/compile-client-function.js +73 -73
- package/lib/compiler/compilers.js +33 -33
- package/lib/compiler/index.js +92 -92
- package/lib/compiler/interfaces.js +2 -2
- package/lib/compiler/test-file/api-based.js +146 -146
- package/lib/compiler/test-file/base.js +36 -36
- package/lib/compiler/test-file/exportble-lib-path.js +5 -5
- package/lib/compiler/test-file/formats/coffeescript/compiler.js +38 -38
- package/lib/compiler/test-file/formats/coffeescript/get-test-list.js +29 -29
- package/lib/compiler/test-file/formats/es-next/compiler.js +42 -42
- package/lib/compiler/test-file/formats/es-next/get-test-list.js +166 -166
- package/lib/compiler/test-file/formats/es-next/is-flow-code.js +7 -7
- package/lib/compiler/test-file/formats/raw.js +85 -85
- package/lib/compiler/test-file/formats/typescript/compiler.js +135 -135
- package/lib/compiler/test-file/formats/typescript/get-test-list.js +185 -185
- package/lib/compiler/test-file/test-file-parser-base.js +214 -214
- package/lib/configuration/configuration-base.js +165 -165
- package/lib/configuration/constants.js +9 -9
- package/lib/configuration/customizable-compilers.js +7 -7
- package/lib/configuration/default-values.js +51 -51
- package/lib/configuration/interfaces.js +2 -2
- package/lib/configuration/option-names.js +53 -53
- package/lib/configuration/option-source.js +9 -9
- package/lib/configuration/option.js +14 -14
- package/lib/configuration/quarantine-option-names.js +8 -8
- package/lib/configuration/run-option-names.js +26 -26
- package/lib/configuration/screenshot-option-names.js +10 -10
- package/lib/configuration/testcafe-configuration.js +163 -163
- package/lib/configuration/types.js +2 -2
- package/lib/configuration/typescript-configuration.js +62 -62
- package/lib/custom-client-scripts/assert-type.js +7 -7
- package/lib/custom-client-scripts/client-script-init.js +2 -2
- package/lib/custom-client-scripts/client-script.js +106 -106
- package/lib/custom-client-scripts/get-code.js +11 -11
- package/lib/custom-client-scripts/get-url.js +6 -6
- package/lib/custom-client-scripts/load.js +15 -15
- package/lib/custom-client-scripts/problematic-scripts.js +2 -2
- package/lib/custom-client-scripts/routing.js +36 -36
- package/lib/custom-client-scripts/utils.js +60 -60
- package/lib/embedding-utils.js +83 -83
- package/lib/errors/create-stack-filter.js +18 -18
- package/lib/errors/error-list.js +26 -26
- package/lib/errors/get-callsite.js +31 -31
- package/lib/errors/internal-modules-prefix.js +8 -8
- package/lib/errors/is-internal-stack-frame.js +45 -45
- package/lib/errors/process-test-fn-error.js +37 -37
- package/lib/errors/runtime/index.js +123 -123
- package/lib/errors/runtime/templates.js +115 -115
- package/lib/errors/runtime/type-assertions.js +112 -112
- package/lib/errors/stack-cleaning-hook.js +64 -64
- package/lib/errors/test-run/formattable-adapter.js +59 -59
- package/lib/errors/test-run/index.js +301 -301
- package/lib/errors/test-run/render-error-template.js +31 -31
- package/lib/errors/test-run/templates.js +91 -91
- package/lib/errors/test-run/utils.js +89 -89
- package/lib/errors/types.js +156 -156
- package/lib/index.js +81 -81
- package/lib/live/bootstrapper.js +43 -43
- package/lib/live/controller.js +107 -107
- package/lib/live/file-watcher/index.js +67 -67
- package/lib/live/file-watcher/modules-graph.js +58 -58
- package/lib/live/keyboard-observer.js +76 -76
- package/lib/live/logger/index.js +64 -64
- package/lib/live/test-run-controller.js +96 -96
- package/lib/live/test-run-state.js +6 -6
- package/lib/live/test-run.js +56 -56
- package/lib/live/test-runner.js +167 -167
- package/lib/load-assets.js +29 -29
- package/lib/notifications/add-rendered-warning.js +16 -16
- package/lib/notifications/debug-logger.js +78 -78
- package/lib/notifications/deprecated.js +24 -24
- package/lib/notifications/information-message.js +9 -9
- package/lib/notifications/warning-log.js +31 -31
- package/lib/notifications/warning-message.js +47 -47
- package/lib/reporter/command/command-formatter.js +120 -109
- package/lib/reporter/command/format-command.js +8 -8
- package/lib/reporter/command/interfaces.js +2 -2
- package/lib/reporter/index.js +319 -314
- package/lib/reporter/interfaces.js +2 -2
- package/lib/reporter/plugin-host.js +135 -135
- package/lib/reporter/plugin-methods.js +12 -12
- package/lib/role/index.js +74 -74
- package/lib/role/marker-symbol.js +7 -7
- package/lib/role/phase.js +9 -9
- package/lib/runner/bootstrapper.js +271 -271
- package/lib/runner/browser-job-result.js +9 -9
- package/lib/runner/browser-job.js +152 -152
- package/lib/runner/browser-set.js +114 -114
- package/lib/runner/fixture-hook-controller.js +85 -85
- package/lib/runner/index.js +449 -449
- package/lib/runner/interfaces.js +2 -2
- package/lib/runner/reporter-stream-controller.js +27 -27
- package/lib/runner/task/index.js +151 -151
- package/lib/runner/task/phase.js +9 -9
- package/lib/runner/test-run-controller.js +165 -165
- package/lib/runner/tested-app.js +72 -72
- package/lib/screenshots/capturer.js +141 -141
- package/lib/screenshots/constants.js +11 -11
- package/lib/screenshots/crop.js +111 -111
- package/lib/screenshots/default-extension.js +4 -4
- package/lib/screenshots/index.js +67 -67
- package/lib/screenshots/utils.js +39 -39
- package/lib/services/compiler/host.js +190 -190
- package/lib/services/compiler/io.js +9 -9
- package/lib/services/compiler/protocol.js +17 -16
- package/lib/services/compiler/service.js +225 -212
- package/lib/services/compiler/test-run-proxy.js +111 -111
- package/lib/services/interfaces.js +2 -2
- package/lib/services/process-title.js +8 -8
- package/lib/services/serialization/prepare-options.js +17 -17
- package/lib/services/serialization/replicator/create-replicator.js +25 -25
- package/lib/services/serialization/replicator/custom-error-transform.js +26 -26
- package/lib/services/serialization/test-structure.js +92 -92
- package/lib/services/utils/ipc/interfaces.js +30 -30
- package/lib/services/utils/ipc/io.js +108 -108
- package/lib/services/utils/ipc/message.js +75 -75
- package/lib/services/utils/ipc/packet.js +55 -55
- package/lib/services/utils/ipc/proxy.js +109 -109
- package/lib/services/utils/ipc/transport.js +64 -64
- package/lib/shared/errors/index.js +382 -382
- package/lib/shared/node-modules-folder-name.js +4 -4
- package/lib/test-run/bookmark.js +90 -90
- package/lib/test-run/browser-console-messages.js +73 -73
- package/lib/test-run/browser-manipulation-queue.js +92 -92
- package/lib/test-run/client-messages.js +9 -9
- package/lib/test-run/commands/actions.js +486 -483
- package/lib/test-run/commands/assertion.js +45 -45
- package/lib/test-run/commands/base.js +14 -14
- package/lib/test-run/commands/browser-manipulation.js +95 -95
- package/lib/test-run/commands/from-object.js +82 -82
- package/lib/test-run/commands/observation.js +61 -61
- package/lib/test-run/commands/options.js +231 -215
- package/lib/test-run/commands/service.js +54 -48
- package/lib/test-run/commands/type.js +65 -64
- package/lib/test-run/commands/utils.js +87 -87
- package/lib/test-run/commands/validations/argument.js +90 -90
- package/lib/test-run/commands/validations/factories.js +47 -47
- package/lib/test-run/commands/validations/initializers.js +44 -44
- package/lib/test-run/debug-log.js +32 -32
- package/lib/test-run/execute-js-expression.js +74 -74
- package/lib/test-run/index.js +823 -799
- package/lib/test-run/marker-symbol.js +7 -7
- package/lib/test-run/observed-callsites-storage.js +17 -17
- package/lib/test-run/phase.js +16 -16
- package/lib/test-run/session-controller.js +104 -104
- package/lib/testcafe.js +118 -118
- package/lib/utils/assignable.js +39 -39
- package/lib/utils/async-event-emitter.js +28 -28
- package/lib/utils/async-queue.js +14 -14
- package/lib/utils/browser-connection-timeouts.js +19 -19
- package/lib/utils/callsite.js +17 -17
- package/lib/utils/check-file-path.js +31 -31
- package/lib/utils/check-url.js +51 -51
- package/lib/utils/convert-to-best-fit-type.js +16 -16
- package/lib/utils/correct-file-path.js +21 -21
- package/lib/utils/define-lazy-property.js +13 -13
- package/lib/utils/delay.js +6 -6
- package/lib/utils/delegated-api.js +44 -44
- package/lib/utils/detect-display.js +6 -6
- package/lib/utils/detect-ffmpeg.js +44 -44
- package/lib/utils/diff/colors.js +29 -29
- package/lib/utils/diff/index.js +52 -52
- package/lib/utils/diff/util.js +23 -23
- package/lib/utils/diff.js +29 -29
- package/lib/utils/escape-user-agent.js +10 -10
- package/lib/utils/flag-list.js +17 -17
- package/lib/utils/get-any-key.js +8 -8
- package/lib/utils/get-browser.js +8 -8
- package/lib/utils/get-common-path.js +34 -34
- package/lib/utils/get-filter-fn.js +40 -40
- package/lib/utils/get-options/base.js +36 -36
- package/lib/utils/get-options/compiler.js +33 -33
- package/lib/utils/get-options/grep.js +15 -15
- package/lib/utils/get-options/index.js +20 -20
- package/lib/utils/get-options/meta.js +22 -22
- package/lib/utils/get-options/quarantine.js +91 -91
- package/lib/utils/get-options/screenshot.js +17 -17
- package/lib/utils/get-options/ssl.js +45 -45
- package/lib/utils/get-options/video.js +10 -10
- package/lib/utils/get-viewport-width.js +17 -17
- package/lib/utils/guard-time-execution.js +10 -10
- package/lib/utils/handle-errors.js +74 -74
- package/lib/utils/handle-tag-args.js +8 -8
- package/lib/utils/http.js +30 -30
- package/lib/utils/is-localhost.js +11 -11
- package/lib/utils/is-password-input.js +11 -0
- package/lib/utils/is-repl.js +10 -10
- package/lib/utils/is-window-in-iframe.js +6 -6
- package/lib/utils/limit-number.js +10 -10
- package/lib/utils/make-reg-exp.js +7 -7
- package/lib/utils/moment-loader.js +20 -20
- package/lib/utils/parse-file-list.js +71 -71
- package/lib/utils/parse-user-agent.js +55 -55
- package/lib/utils/path-pattern.js +114 -114
- package/lib/utils/prepare-reporters.js +30 -30
- package/lib/utils/prerender-callsite.js +18 -18
- package/lib/utils/process.js +119 -119
- package/lib/utils/promisified-functions.js +46 -46
- package/lib/utils/re-executable-promise.js +39 -39
- package/lib/utils/render-callsite-sync.js +29 -29
- package/lib/utils/render-template.js +9 -9
- package/lib/utils/reporter.js +30 -30
- package/lib/utils/resolve-path-relatively-cwd.js +7 -7
- package/lib/utils/string.js +105 -105
- package/lib/utils/temp-directory/cleanup-process/commands.js +7 -7
- package/lib/utils/temp-directory/cleanup-process/index.js +143 -143
- package/lib/utils/temp-directory/cleanup-process/worker.js +58 -58
- package/lib/utils/temp-directory/index.js +87 -87
- package/lib/utils/temp-directory/lockfile.js +56 -56
- package/lib/utils/thennable.js +7 -7
- package/lib/utils/timer.js +15 -15
- package/lib/utils/to-posix-path.js +8 -8
- package/lib/utils/types.js +2 -2
- package/lib/video-recorder/interfaces.js +2 -2
- package/lib/video-recorder/process.js +126 -126
- package/lib/video-recorder/recorder.js +136 -136
- package/lib/video-recorder/test-run-video-recorder.js +69 -69
- package/lib/video-recorder/videos.js +37 -37
- package/package.json +2 -2
- package/ts-defs/index.d.ts +25 -14
- package/ts-defs/selectors.d.ts +16 -5
- package/ts-defs/testcafe-scripts.d.ts +17 -6
package/lib/runner/index.js
CHANGED
|
@@ -1,451 +1,451 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const path_1 = require("path");
|
|
7
|
-
const debug_1 = __importDefault(require("debug"));
|
|
8
|
-
const promisify_event_1 = __importDefault(require("promisify-event"));
|
|
9
|
-
const events_1 = require("events");
|
|
10
|
-
const lodash_1 = require("lodash");
|
|
11
|
-
const bootstrapper_1 = __importDefault(require("./bootstrapper"));
|
|
12
|
-
const reporter_1 = __importDefault(require("../reporter"));
|
|
13
|
-
const task_1 = __importDefault(require("./task"));
|
|
14
|
-
const debug_logger_1 = __importDefault(require("../notifications/debug-logger"));
|
|
15
|
-
const runtime_1 = require("../errors/runtime");
|
|
16
|
-
const types_1 = require("../errors/types");
|
|
17
|
-
const type_assertions_1 = require("../errors/runtime/type-assertions");
|
|
18
|
-
const utils_1 = require("../errors/test-run/utils");
|
|
19
|
-
const detect_ffmpeg_1 = __importDefault(require("../utils/detect-ffmpeg"));
|
|
20
|
-
const check_file_path_1 = __importDefault(require("../utils/check-file-path"));
|
|
21
|
-
const handle_errors_1 = require("../utils/handle-errors");
|
|
22
|
-
const option_names_1 = __importDefault(require("../configuration/option-names"));
|
|
23
|
-
const flag_list_1 = __importDefault(require("../utils/flag-list"));
|
|
24
|
-
const prepare_reporters_1 = __importDefault(require("../utils/prepare-reporters"));
|
|
25
|
-
const load_1 = __importDefault(require("../custom-client-scripts/load"));
|
|
26
|
-
const utils_2 = require("../custom-client-scripts/utils");
|
|
27
|
-
const reporter_stream_controller_1 = __importDefault(require("./reporter-stream-controller"));
|
|
28
|
-
const customizable_compilers_1 = __importDefault(require("../configuration/customizable-compilers"));
|
|
29
|
-
const string_1 = require("../utils/string");
|
|
30
|
-
const is_localhost_1 = __importDefault(require("../utils/is-localhost"));
|
|
31
|
-
const warning_log_1 = __importDefault(require("../notifications/warning-log"));
|
|
32
|
-
const DEBUG_LOGGER = debug_1.default('testcafe:runner');
|
|
33
|
-
class Runner extends events_1.EventEmitter {
|
|
34
|
-
constructor({ proxy, browserConnectionGateway, configuration, compilerService }) {
|
|
35
|
-
super();
|
|
36
|
-
this.proxy = proxy;
|
|
37
|
-
this.bootstrapper = this._createBootstrapper(browserConnectionGateway, compilerService);
|
|
38
|
-
this.pendingTaskPromises = [];
|
|
39
|
-
this.configuration = configuration;
|
|
40
|
-
this.isCli = false;
|
|
41
|
-
this.warningLog = new warning_log_1.default();
|
|
42
|
-
this.compilerService = compilerService;
|
|
43
|
-
this.apiMethodWasCalled = new flag_list_1.default([
|
|
44
|
-
option_names_1.default.src,
|
|
45
|
-
option_names_1.default.browsers,
|
|
46
|
-
option_names_1.default.reporter,
|
|
47
|
-
option_names_1.default.clientScripts
|
|
48
|
-
]);
|
|
49
|
-
}
|
|
50
|
-
_createBootstrapper(browserConnectionGateway, compilerService) {
|
|
51
|
-
return new bootstrapper_1.default({ browserConnectionGateway, compilerService });
|
|
52
|
-
}
|
|
53
|
-
_disposeBrowserSet(browserSet) {
|
|
54
|
-
return browserSet.dispose().catch(e => DEBUG_LOGGER(e));
|
|
55
|
-
}
|
|
56
|
-
_disposeReporters(reporters) {
|
|
57
|
-
return Promise.all(reporters.map(reporter => reporter.dispose().catch(e => DEBUG_LOGGER(e))));
|
|
58
|
-
}
|
|
59
|
-
_disposeTestedApp(testedApp) {
|
|
60
|
-
return testedApp ? testedApp.kill().catch(e => DEBUG_LOGGER(e)) : Promise.resolve();
|
|
61
|
-
}
|
|
62
|
-
async _disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp) {
|
|
63
|
-
task.abort();
|
|
64
|
-
task.unRegisterClientScriptRouting();
|
|
65
|
-
task.clearListeners();
|
|
66
|
-
await this._disposeAssets(browserSet, reporters, testedApp);
|
|
67
|
-
}
|
|
68
|
-
_disposeAssets(browserSet, reporters, testedApp) {
|
|
69
|
-
return Promise.all([
|
|
70
|
-
this._disposeBrowserSet(browserSet),
|
|
71
|
-
this._disposeReporters(reporters),
|
|
72
|
-
this._disposeTestedApp(testedApp)
|
|
73
|
-
]);
|
|
74
|
-
}
|
|
75
|
-
_prepareArrayParameter(array) {
|
|
76
|
-
array = lodash_1.flattenDeep(array);
|
|
77
|
-
if (this.isCli)
|
|
78
|
-
return array.length === 0 ? void 0 : array;
|
|
79
|
-
return array;
|
|
80
|
-
}
|
|
81
|
-
_createCancelablePromise(taskPromise) {
|
|
82
|
-
const promise = taskPromise.then(({ completionPromise }) => completionPromise);
|
|
83
|
-
const removeFromPending = () => lodash_1.pull(this.pendingTaskPromises, promise);
|
|
84
|
-
promise
|
|
85
|
-
.then(removeFromPending)
|
|
86
|
-
.catch(removeFromPending);
|
|
87
|
-
promise.cancel = () => taskPromise
|
|
88
|
-
.then(({ cancelTask }) => cancelTask())
|
|
89
|
-
.then(removeFromPending);
|
|
90
|
-
this.pendingTaskPromises.push(promise);
|
|
91
|
-
return promise;
|
|
92
|
-
}
|
|
93
|
-
// Run task
|
|
94
|
-
_getFailedTestCount(task, reporter) {
|
|
95
|
-
let failedTestCount = reporter.testCount - reporter.passed;
|
|
96
|
-
if (task.opts.stopOnFirstFail && !!failedTestCount)
|
|
97
|
-
failedTestCount = 1;
|
|
98
|
-
return failedTestCount;
|
|
99
|
-
}
|
|
100
|
-
async _getTaskResult(task, browserSet, reporters, testedApp) {
|
|
101
|
-
if (!task.opts.live) {
|
|
102
|
-
task.on('browser-job-done', job => {
|
|
103
|
-
job.browserConnections.forEach(bc => browserSet.releaseConnection(bc));
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
const browserSetErrorPromise = promisify_event_1.default(browserSet, 'error');
|
|
107
|
-
const taskErrorPromise = promisify_event_1.default(task, 'error');
|
|
108
|
-
const streamController = new reporter_stream_controller_1.default(task, reporters);
|
|
109
|
-
const taskDonePromise = task.once('done')
|
|
110
|
-
.then(() => browserSetErrorPromise.cancel())
|
|
111
|
-
.then(() => {
|
|
112
|
-
return Promise.all(reporters.map(reporter => reporter.pendingTaskDonePromise));
|
|
113
|
-
});
|
|
114
|
-
const promises = [
|
|
115
|
-
taskDonePromise,
|
|
116
|
-
browserSetErrorPromise,
|
|
117
|
-
taskErrorPromise
|
|
118
|
-
];
|
|
119
|
-
if (testedApp)
|
|
120
|
-
promises.push(testedApp.errorPromise);
|
|
121
|
-
try {
|
|
122
|
-
await Promise.race(promises);
|
|
123
|
-
}
|
|
124
|
-
catch (err) {
|
|
125
|
-
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp);
|
|
126
|
-
throw err;
|
|
127
|
-
}
|
|
128
|
-
await this._disposeAssets(browserSet, reporters, testedApp);
|
|
129
|
-
if (streamController.multipleStreamError)
|
|
130
|
-
throw streamController.multipleStreamError;
|
|
131
|
-
return this._getFailedTestCount(task, reporters[0]);
|
|
132
|
-
}
|
|
133
|
-
_createTask(tests, browserConnectionGroups, proxy, opts, warningLog) {
|
|
134
|
-
return new task_1.default({
|
|
135
|
-
tests,
|
|
136
|
-
browserConnectionGroups,
|
|
137
|
-
proxy,
|
|
138
|
-
opts,
|
|
139
|
-
runnerWarningLog: warningLog,
|
|
140
|
-
compilerService: this.compilerService
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
_runTask({ reporterPlugins, browserSet, tests, testedApp, options }) {
|
|
144
|
-
const task = this._createTask(tests, browserSet.browserConnectionGroups, this.proxy, options, this.warningLog);
|
|
145
|
-
const reporters = reporterPlugins.map(reporter => new reporter_1.default(reporter.plugin, task, reporter.outStream, reporter.name));
|
|
146
|
-
const completionPromise = this._getTaskResult(task, browserSet, reporters, testedApp);
|
|
147
|
-
let completed = false;
|
|
148
|
-
task.on('start', handle_errors_1.startHandlingTestErrors);
|
|
149
|
-
if (!this.configuration.getOption(option_names_1.default.skipUncaughtErrors)) {
|
|
150
|
-
task.on('test-run-start', handle_errors_1.addRunningTest);
|
|
151
|
-
task.on('test-run-done', handle_errors_1.removeRunningTest);
|
|
152
|
-
}
|
|
153
|
-
task.on('done', handle_errors_1.stopHandlingTestErrors);
|
|
154
|
-
task.on('error', handle_errors_1.stopHandlingTestErrors);
|
|
155
|
-
const onTaskCompleted = () => {
|
|
156
|
-
task.unRegisterClientScriptRouting();
|
|
157
|
-
completed = true;
|
|
158
|
-
};
|
|
159
|
-
completionPromise
|
|
160
|
-
.then(onTaskCompleted)
|
|
161
|
-
.catch(onTaskCompleted);
|
|
162
|
-
const cancelTask = async () => {
|
|
163
|
-
if (!completed)
|
|
164
|
-
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp);
|
|
165
|
-
};
|
|
166
|
-
return { completionPromise, cancelTask };
|
|
167
|
-
}
|
|
168
|
-
_registerAssets(assets) {
|
|
169
|
-
assets.forEach(asset => this.proxy.GET(asset.path, asset.info));
|
|
170
|
-
}
|
|
171
|
-
_validateDebugLogger() {
|
|
172
|
-
const debugLogger = this.configuration.getOption(option_names_1.default.debugLogger);
|
|
173
|
-
const debugLoggerDefinedCorrectly = debugLogger === null || !!debugLogger &&
|
|
174
|
-
['showBreakpoint', 'hideBreakpoint'].every(method => method in debugLogger && lodash_1.isFunction(debugLogger[method]));
|
|
175
|
-
if (!debugLoggerDefinedCorrectly) {
|
|
176
|
-
this.configuration.mergeOptions({
|
|
177
|
-
[option_names_1.default.debugLogger]: debug_logger_1.default
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
_validateSpeedOption() {
|
|
182
|
-
const speed = this.configuration.getOption(option_names_1.default.speed);
|
|
183
|
-
if (speed === void 0)
|
|
184
|
-
return;
|
|
185
|
-
if (typeof speed !== 'number' || isNaN(speed) || speed < 0.01 || speed > 1)
|
|
186
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidSpeedValue);
|
|
187
|
-
}
|
|
188
|
-
_validateConcurrencyOption() {
|
|
189
|
-
const concurrency = this.configuration.getOption(option_names_1.default.concurrency);
|
|
190
|
-
if (concurrency === void 0)
|
|
191
|
-
return;
|
|
192
|
-
if (typeof concurrency !== 'number' || isNaN(concurrency) || concurrency < 1)
|
|
193
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidConcurrencyFactor);
|
|
194
|
-
}
|
|
195
|
-
_validateRequestTimeoutOption(optionName) {
|
|
196
|
-
const requestTimeout = this.configuration.getOption(optionName);
|
|
197
|
-
if (requestTimeout === void 0)
|
|
198
|
-
return;
|
|
199
|
-
type_assertions_1.assertType(type_assertions_1.is.nonNegativeNumber, null, `"${optionName}" option`, requestTimeout);
|
|
200
|
-
}
|
|
201
|
-
_validateProxyBypassOption() {
|
|
202
|
-
let proxyBypass = this.configuration.getOption(option_names_1.default.proxyBypass);
|
|
203
|
-
if (proxyBypass === void 0)
|
|
204
|
-
return;
|
|
205
|
-
type_assertions_1.assertType([type_assertions_1.is.string, type_assertions_1.is.array], null, '"proxyBypass" argument', proxyBypass);
|
|
206
|
-
if (typeof proxyBypass === 'string')
|
|
207
|
-
proxyBypass = [proxyBypass];
|
|
208
|
-
proxyBypass = proxyBypass.reduce((arr, rules) => {
|
|
209
|
-
type_assertions_1.assertType(type_assertions_1.is.string, null, '"proxyBypass" argument', rules);
|
|
210
|
-
return arr.concat(rules.split(','));
|
|
211
|
-
}, []);
|
|
212
|
-
this.configuration.mergeOptions({ proxyBypass });
|
|
213
|
-
}
|
|
214
|
-
_getScreenshotOptions() {
|
|
215
|
-
let { path, pathPattern } = this.configuration.getOption(option_names_1.default.screenshots) || {};
|
|
216
|
-
if (!path)
|
|
217
|
-
path = this.configuration.getOption(option_names_1.default.screenshotPath);
|
|
218
|
-
if (!pathPattern)
|
|
219
|
-
pathPattern = this.configuration.getOption(option_names_1.default.screenshotPathPattern);
|
|
220
|
-
return { path, pathPattern };
|
|
221
|
-
}
|
|
222
|
-
_validateScreenshotOptions() {
|
|
223
|
-
const { path, pathPattern } = this._getScreenshotOptions();
|
|
224
|
-
const disableScreenshots = this.configuration.getOption(option_names_1.default.disableScreenshots) || !path;
|
|
225
|
-
this.configuration.mergeOptions({ [option_names_1.default.disableScreenshots]: disableScreenshots });
|
|
226
|
-
if (disableScreenshots)
|
|
227
|
-
return;
|
|
228
|
-
if (path) {
|
|
229
|
-
this._validateScreenshotPath(path, 'screenshots base directory path');
|
|
230
|
-
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { path: path_1.resolve(path) } });
|
|
231
|
-
}
|
|
232
|
-
if (pathPattern) {
|
|
233
|
-
this._validateScreenshotPath(pathPattern, 'screenshots path pattern');
|
|
234
|
-
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { pathPattern } });
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
async _validateVideoOptions() {
|
|
238
|
-
const videoPath = this.configuration.getOption(option_names_1.default.videoPath);
|
|
239
|
-
const videoEncodingOptions = this.configuration.getOption(option_names_1.default.videoEncodingOptions);
|
|
240
|
-
let videoOptions = this.configuration.getOption(option_names_1.default.videoOptions);
|
|
241
|
-
if (!videoPath) {
|
|
242
|
-
if (videoOptions || videoEncodingOptions)
|
|
243
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotSetVideoOptionsWithoutBaseVideoPathSpecified);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
this.configuration.mergeOptions({ [option_names_1.default.videoPath]: path_1.resolve(videoPath) });
|
|
247
|
-
if (!videoOptions) {
|
|
248
|
-
videoOptions = {};
|
|
249
|
-
this.configuration.mergeOptions({ [option_names_1.default.videoOptions]: videoOptions });
|
|
250
|
-
}
|
|
251
|
-
if (videoOptions.ffmpegPath)
|
|
252
|
-
videoOptions.ffmpegPath = path_1.resolve(videoOptions.ffmpegPath);
|
|
253
|
-
else
|
|
254
|
-
videoOptions.ffmpegPath = await detect_ffmpeg_1.default();
|
|
255
|
-
if (!videoOptions.ffmpegPath)
|
|
256
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotFindFFMPEG);
|
|
257
|
-
}
|
|
258
|
-
_validateCompilerOptions() {
|
|
259
|
-
const compilerOptions = this.configuration.getOption(option_names_1.default.compilerOptions);
|
|
260
|
-
if (!compilerOptions)
|
|
261
|
-
return;
|
|
262
|
-
const specifiedCompilers = Object.keys(compilerOptions);
|
|
263
|
-
const customizedCompilers = Object.keys(customizable_compilers_1.default);
|
|
264
|
-
const wrongCompilers = specifiedCompilers.filter(compiler => !customizedCompilers.includes(compiler));
|
|
265
|
-
if (!wrongCompilers.length)
|
|
266
|
-
return;
|
|
267
|
-
const compilerListStr = string_1.getConcatenatedValuesString(wrongCompilers, void 0, "'");
|
|
268
|
-
const pluralSuffix = string_1.getPluralSuffix(wrongCompilers);
|
|
269
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotCustomizeSpecifiedCompilers, compilerListStr, pluralSuffix);
|
|
270
|
-
}
|
|
271
|
-
_validateRetryTestPagesOption() {
|
|
272
|
-
const retryTestPagesOption = this.configuration.getOption(option_names_1.default.retryTestPages);
|
|
273
|
-
if (!retryTestPagesOption)
|
|
274
|
-
return;
|
|
275
|
-
const ssl = this.configuration.getOption(option_names_1.default.ssl);
|
|
276
|
-
if (ssl)
|
|
277
|
-
return;
|
|
278
|
-
const hostname = this.configuration.getOption(option_names_1.default.hostname);
|
|
279
|
-
if (is_localhost_1.default(hostname))
|
|
280
|
-
return;
|
|
281
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotEnableRetryTestPagesOption);
|
|
282
|
-
}
|
|
283
|
-
async _validateRunOptions() {
|
|
284
|
-
this._validateDebugLogger();
|
|
285
|
-
this._validateScreenshotOptions();
|
|
286
|
-
await this._validateVideoOptions();
|
|
287
|
-
this._validateSpeedOption();
|
|
288
|
-
this._validateConcurrencyOption();
|
|
289
|
-
this._validateProxyBypassOption();
|
|
290
|
-
this._validateCompilerOptions();
|
|
291
|
-
this._validateRetryTestPagesOption();
|
|
292
|
-
this._validateRequestTimeoutOption(option_names_1.default.pageRequestTimeout);
|
|
293
|
-
this._validateRequestTimeoutOption(option_names_1.default.ajaxRequestTimeout);
|
|
294
|
-
}
|
|
295
|
-
_createRunnableConfiguration() {
|
|
296
|
-
return this.bootstrapper
|
|
297
|
-
.createRunnableConfiguration()
|
|
298
|
-
.then(runnableConfiguration => {
|
|
299
|
-
this.emit('done-bootstrapping');
|
|
300
|
-
return runnableConfiguration;
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
_validateScreenshotPath(screenshotPath, pathType) {
|
|
304
|
-
const forbiddenCharsList = check_file_path_1.default(screenshotPath);
|
|
305
|
-
if (forbiddenCharsList.length)
|
|
306
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.forbiddenCharatersInScreenshotPath, screenshotPath, pathType, utils_1.renderForbiddenCharsList(forbiddenCharsList));
|
|
307
|
-
}
|
|
308
|
-
_setBootstrapperOptions() {
|
|
309
|
-
this.configuration.prepare();
|
|
310
|
-
this.configuration.notifyAboutOverriddenOptions();
|
|
311
|
-
this.configuration.notifyAboutDeprecatedOptions(this.warningLog);
|
|
312
|
-
this.bootstrapper.sources = this.configuration.getOption(option_names_1.default.src) || this.bootstrapper.sources;
|
|
313
|
-
this.bootstrapper.browsers = this.configuration.getOption(option_names_1.default.browsers) || this.bootstrapper.browsers;
|
|
314
|
-
this.bootstrapper.concurrency = this.configuration.getOption(option_names_1.default.concurrency);
|
|
315
|
-
this.bootstrapper.appCommand = this.configuration.getOption(option_names_1.default.appCommand) || this.bootstrapper.appCommand;
|
|
316
|
-
this.bootstrapper.appInitDelay = this.configuration.getOption(option_names_1.default.appInitDelay);
|
|
317
|
-
this.bootstrapper.filter = this.configuration.getOption(option_names_1.default.filter) || this.bootstrapper.filter;
|
|
318
|
-
this.bootstrapper.reporters = this.configuration.getOption(option_names_1.default.reporter) || this.bootstrapper.reporters;
|
|
319
|
-
this.bootstrapper.tsConfigPath = this.configuration.getOption(option_names_1.default.tsConfigPath);
|
|
320
|
-
this.bootstrapper.clientScripts = this.configuration.getOption(option_names_1.default.clientScripts) || this.bootstrapper.clientScripts;
|
|
321
|
-
this.bootstrapper.disableMultipleWindows = this.configuration.getOption(option_names_1.default.disableMultipleWindows);
|
|
322
|
-
this.bootstrapper.compilerOptions = this.configuration.getOption(option_names_1.default.compilerOptions);
|
|
323
|
-
this.bootstrapper.browserInitTimeout = this.configuration.getOption(option_names_1.default.browserInitTimeout);
|
|
324
|
-
}
|
|
325
|
-
async _prepareClientScripts(tests, clientScripts) {
|
|
326
|
-
return Promise.all(tests.map(async (test) => {
|
|
327
|
-
if (test.isLegacy)
|
|
328
|
-
return;
|
|
329
|
-
let loadedTestClientScripts = await load_1.default(test.clientScripts, path_1.dirname(test.testFile.filename));
|
|
330
|
-
loadedTestClientScripts = clientScripts.concat(loadedTestClientScripts);
|
|
331
|
-
test.clientScripts = utils_2.setUniqueUrls(loadedTestClientScripts);
|
|
332
|
-
}));
|
|
333
|
-
}
|
|
334
|
-
// API
|
|
335
|
-
embeddingOptions(opts) {
|
|
336
|
-
const { assets, TestRunCtor } = opts;
|
|
337
|
-
this._registerAssets(assets);
|
|
338
|
-
this.configuration.mergeOptions({ TestRunCtor });
|
|
339
|
-
return this;
|
|
340
|
-
}
|
|
341
|
-
src(...sources) {
|
|
342
|
-
if (this.apiMethodWasCalled.src)
|
|
343
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.src);
|
|
344
|
-
sources = this._prepareArrayParameter(sources);
|
|
345
|
-
this.configuration.mergeOptions({ [option_names_1.default.src]: sources });
|
|
346
|
-
this.apiMethodWasCalled.src = true;
|
|
347
|
-
return this;
|
|
348
|
-
}
|
|
349
|
-
browsers(...browsers) {
|
|
350
|
-
if (this.apiMethodWasCalled.browsers)
|
|
351
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.browsers);
|
|
352
|
-
browsers = this._prepareArrayParameter(browsers);
|
|
353
|
-
this.configuration.mergeOptions({ browsers });
|
|
354
|
-
this.apiMethodWasCalled.browsers = true;
|
|
355
|
-
return this;
|
|
356
|
-
}
|
|
357
|
-
concurrency(concurrency) {
|
|
358
|
-
this.configuration.mergeOptions({ concurrency });
|
|
359
|
-
return this;
|
|
360
|
-
}
|
|
361
|
-
reporter(name, output) {
|
|
362
|
-
if (this.apiMethodWasCalled.reporter)
|
|
363
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.reporter);
|
|
364
|
-
let reporters = prepare_reporters_1.default(name, output);
|
|
365
|
-
reporters = this._prepareArrayParameter(reporters);
|
|
366
|
-
this.configuration.mergeOptions({ [option_names_1.default.reporter]: reporters });
|
|
367
|
-
this.apiMethodWasCalled.reporter = true;
|
|
368
|
-
return this;
|
|
369
|
-
}
|
|
370
|
-
filter(filter) {
|
|
371
|
-
this.configuration.mergeOptions({ filter });
|
|
372
|
-
return this;
|
|
373
|
-
}
|
|
374
|
-
useProxy(proxy, proxyBypass) {
|
|
375
|
-
this.configuration.mergeOptions({ proxy, proxyBypass });
|
|
376
|
-
return this;
|
|
377
|
-
}
|
|
378
|
-
screenshots(...options) {
|
|
379
|
-
let fullPage;
|
|
380
|
-
let [path, takeOnFails, pathPattern] = options;
|
|
381
|
-
if (options.length === 1 && options[0] && typeof options[0] === 'object')
|
|
382
|
-
({ path, takeOnFails, pathPattern, fullPage } = options[0]);
|
|
383
|
-
this.configuration.mergeOptions({ screenshots: { path, takeOnFails, pathPattern, fullPage } });
|
|
384
|
-
return this;
|
|
385
|
-
}
|
|
386
|
-
video(path, options, encodingOptions) {
|
|
387
|
-
this.configuration.mergeOptions({
|
|
388
|
-
[option_names_1.default.videoPath]: path,
|
|
389
|
-
[option_names_1.default.videoOptions]: options,
|
|
390
|
-
[option_names_1.default.videoEncodingOptions]: encodingOptions
|
|
391
|
-
});
|
|
392
|
-
return this;
|
|
393
|
-
}
|
|
394
|
-
startApp(command, initDelay) {
|
|
395
|
-
this.configuration.mergeOptions({
|
|
396
|
-
[option_names_1.default.appCommand]: command,
|
|
397
|
-
[option_names_1.default.appInitDelay]: initDelay
|
|
398
|
-
});
|
|
399
|
-
return this;
|
|
400
|
-
}
|
|
401
|
-
tsConfigPath(path) {
|
|
402
|
-
this.configuration.mergeOptions({
|
|
403
|
-
[option_names_1.default.tsConfigPath]: path
|
|
404
|
-
});
|
|
405
|
-
return this;
|
|
406
|
-
}
|
|
407
|
-
clientScripts(...scripts) {
|
|
408
|
-
if (this.apiMethodWasCalled.clientScripts)
|
|
409
|
-
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.clientScripts);
|
|
410
|
-
scripts = this._prepareArrayParameter(scripts);
|
|
411
|
-
this.configuration.mergeOptions({ [option_names_1.default.clientScripts]: scripts });
|
|
412
|
-
this.apiMethodWasCalled.clientScripts = true;
|
|
413
|
-
return this;
|
|
414
|
-
}
|
|
415
|
-
compilerOptions(opts) {
|
|
416
|
-
this.configuration.mergeOptions({
|
|
417
|
-
[option_names_1.default.compilerOptions]: opts
|
|
418
|
-
});
|
|
419
|
-
return this;
|
|
420
|
-
}
|
|
421
|
-
run(options = {}) {
|
|
422
|
-
this.apiMethodWasCalled.reset();
|
|
423
|
-
this.configuration.mergeOptions(options);
|
|
424
|
-
this._setBootstrapperOptions();
|
|
425
|
-
const runTaskPromise = Promise.resolve()
|
|
426
|
-
.then(() => this._validateRunOptions())
|
|
427
|
-
.then(() => this._createRunnableConfiguration())
|
|
428
|
-
.then(async ({ reporterPlugins, browserSet, tests, testedApp, commonClientScripts }) => {
|
|
429
|
-
var _a;
|
|
430
|
-
await this._prepareClientScripts(tests, commonClientScripts);
|
|
431
|
-
const resultOptions = this.configuration.getOptions();
|
|
432
|
-
await ((_a = this.bootstrapper.compilerService) === null || _a === void 0 ? void 0 : _a.setOptions({ value: resultOptions }));
|
|
433
|
-
return this._runTask({ reporterPlugins, browserSet, tests, testedApp, options: resultOptions });
|
|
434
|
-
});
|
|
435
|
-
return this._createCancelablePromise(runTaskPromise);
|
|
436
|
-
}
|
|
437
|
-
async stop() {
|
|
438
|
-
// NOTE: When taskPromise is cancelled, it is removed from
|
|
439
|
-
// the pendingTaskPromises array, which leads to shifting indexes
|
|
440
|
-
// towards the beginning. So, we must copy the array in order to iterate it,
|
|
441
|
-
// or we can perform iteration from the end to the beginning.
|
|
442
|
-
const cancellationPromises = this.pendingTaskPromises.reduceRight((result, taskPromise) => {
|
|
443
|
-
result.push(taskPromise.cancel());
|
|
444
|
-
return result;
|
|
445
|
-
}, []);
|
|
446
|
-
await Promise.all(cancellationPromises);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
exports.default = Runner;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const debug_1 = __importDefault(require("debug"));
|
|
8
|
+
const promisify_event_1 = __importDefault(require("promisify-event"));
|
|
9
|
+
const events_1 = require("events");
|
|
10
|
+
const lodash_1 = require("lodash");
|
|
11
|
+
const bootstrapper_1 = __importDefault(require("./bootstrapper"));
|
|
12
|
+
const reporter_1 = __importDefault(require("../reporter"));
|
|
13
|
+
const task_1 = __importDefault(require("./task"));
|
|
14
|
+
const debug_logger_1 = __importDefault(require("../notifications/debug-logger"));
|
|
15
|
+
const runtime_1 = require("../errors/runtime");
|
|
16
|
+
const types_1 = require("../errors/types");
|
|
17
|
+
const type_assertions_1 = require("../errors/runtime/type-assertions");
|
|
18
|
+
const utils_1 = require("../errors/test-run/utils");
|
|
19
|
+
const detect_ffmpeg_1 = __importDefault(require("../utils/detect-ffmpeg"));
|
|
20
|
+
const check_file_path_1 = __importDefault(require("../utils/check-file-path"));
|
|
21
|
+
const handle_errors_1 = require("../utils/handle-errors");
|
|
22
|
+
const option_names_1 = __importDefault(require("../configuration/option-names"));
|
|
23
|
+
const flag_list_1 = __importDefault(require("../utils/flag-list"));
|
|
24
|
+
const prepare_reporters_1 = __importDefault(require("../utils/prepare-reporters"));
|
|
25
|
+
const load_1 = __importDefault(require("../custom-client-scripts/load"));
|
|
26
|
+
const utils_2 = require("../custom-client-scripts/utils");
|
|
27
|
+
const reporter_stream_controller_1 = __importDefault(require("./reporter-stream-controller"));
|
|
28
|
+
const customizable_compilers_1 = __importDefault(require("../configuration/customizable-compilers"));
|
|
29
|
+
const string_1 = require("../utils/string");
|
|
30
|
+
const is_localhost_1 = __importDefault(require("../utils/is-localhost"));
|
|
31
|
+
const warning_log_1 = __importDefault(require("../notifications/warning-log"));
|
|
32
|
+
const DEBUG_LOGGER = debug_1.default('testcafe:runner');
|
|
33
|
+
class Runner extends events_1.EventEmitter {
|
|
34
|
+
constructor({ proxy, browserConnectionGateway, configuration, compilerService }) {
|
|
35
|
+
super();
|
|
36
|
+
this.proxy = proxy;
|
|
37
|
+
this.bootstrapper = this._createBootstrapper(browserConnectionGateway, compilerService);
|
|
38
|
+
this.pendingTaskPromises = [];
|
|
39
|
+
this.configuration = configuration;
|
|
40
|
+
this.isCli = false;
|
|
41
|
+
this.warningLog = new warning_log_1.default();
|
|
42
|
+
this.compilerService = compilerService;
|
|
43
|
+
this.apiMethodWasCalled = new flag_list_1.default([
|
|
44
|
+
option_names_1.default.src,
|
|
45
|
+
option_names_1.default.browsers,
|
|
46
|
+
option_names_1.default.reporter,
|
|
47
|
+
option_names_1.default.clientScripts
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
_createBootstrapper(browserConnectionGateway, compilerService) {
|
|
51
|
+
return new bootstrapper_1.default({ browserConnectionGateway, compilerService });
|
|
52
|
+
}
|
|
53
|
+
_disposeBrowserSet(browserSet) {
|
|
54
|
+
return browserSet.dispose().catch(e => DEBUG_LOGGER(e));
|
|
55
|
+
}
|
|
56
|
+
_disposeReporters(reporters) {
|
|
57
|
+
return Promise.all(reporters.map(reporter => reporter.dispose().catch(e => DEBUG_LOGGER(e))));
|
|
58
|
+
}
|
|
59
|
+
_disposeTestedApp(testedApp) {
|
|
60
|
+
return testedApp ? testedApp.kill().catch(e => DEBUG_LOGGER(e)) : Promise.resolve();
|
|
61
|
+
}
|
|
62
|
+
async _disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp) {
|
|
63
|
+
task.abort();
|
|
64
|
+
task.unRegisterClientScriptRouting();
|
|
65
|
+
task.clearListeners();
|
|
66
|
+
await this._disposeAssets(browserSet, reporters, testedApp);
|
|
67
|
+
}
|
|
68
|
+
_disposeAssets(browserSet, reporters, testedApp) {
|
|
69
|
+
return Promise.all([
|
|
70
|
+
this._disposeBrowserSet(browserSet),
|
|
71
|
+
this._disposeReporters(reporters),
|
|
72
|
+
this._disposeTestedApp(testedApp)
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
_prepareArrayParameter(array) {
|
|
76
|
+
array = lodash_1.flattenDeep(array);
|
|
77
|
+
if (this.isCli)
|
|
78
|
+
return array.length === 0 ? void 0 : array;
|
|
79
|
+
return array;
|
|
80
|
+
}
|
|
81
|
+
_createCancelablePromise(taskPromise) {
|
|
82
|
+
const promise = taskPromise.then(({ completionPromise }) => completionPromise);
|
|
83
|
+
const removeFromPending = () => lodash_1.pull(this.pendingTaskPromises, promise);
|
|
84
|
+
promise
|
|
85
|
+
.then(removeFromPending)
|
|
86
|
+
.catch(removeFromPending);
|
|
87
|
+
promise.cancel = () => taskPromise
|
|
88
|
+
.then(({ cancelTask }) => cancelTask())
|
|
89
|
+
.then(removeFromPending);
|
|
90
|
+
this.pendingTaskPromises.push(promise);
|
|
91
|
+
return promise;
|
|
92
|
+
}
|
|
93
|
+
// Run task
|
|
94
|
+
_getFailedTestCount(task, reporter) {
|
|
95
|
+
let failedTestCount = reporter.testCount - reporter.passed;
|
|
96
|
+
if (task.opts.stopOnFirstFail && !!failedTestCount)
|
|
97
|
+
failedTestCount = 1;
|
|
98
|
+
return failedTestCount;
|
|
99
|
+
}
|
|
100
|
+
async _getTaskResult(task, browserSet, reporters, testedApp) {
|
|
101
|
+
if (!task.opts.live) {
|
|
102
|
+
task.on('browser-job-done', job => {
|
|
103
|
+
job.browserConnections.forEach(bc => browserSet.releaseConnection(bc));
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const browserSetErrorPromise = promisify_event_1.default(browserSet, 'error');
|
|
107
|
+
const taskErrorPromise = promisify_event_1.default(task, 'error');
|
|
108
|
+
const streamController = new reporter_stream_controller_1.default(task, reporters);
|
|
109
|
+
const taskDonePromise = task.once('done')
|
|
110
|
+
.then(() => browserSetErrorPromise.cancel())
|
|
111
|
+
.then(() => {
|
|
112
|
+
return Promise.all(reporters.map(reporter => reporter.pendingTaskDonePromise));
|
|
113
|
+
});
|
|
114
|
+
const promises = [
|
|
115
|
+
taskDonePromise,
|
|
116
|
+
browserSetErrorPromise,
|
|
117
|
+
taskErrorPromise
|
|
118
|
+
];
|
|
119
|
+
if (testedApp)
|
|
120
|
+
promises.push(testedApp.errorPromise);
|
|
121
|
+
try {
|
|
122
|
+
await Promise.race(promises);
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp);
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
await this._disposeAssets(browserSet, reporters, testedApp);
|
|
129
|
+
if (streamController.multipleStreamError)
|
|
130
|
+
throw streamController.multipleStreamError;
|
|
131
|
+
return this._getFailedTestCount(task, reporters[0]);
|
|
132
|
+
}
|
|
133
|
+
_createTask(tests, browserConnectionGroups, proxy, opts, warningLog) {
|
|
134
|
+
return new task_1.default({
|
|
135
|
+
tests,
|
|
136
|
+
browserConnectionGroups,
|
|
137
|
+
proxy,
|
|
138
|
+
opts,
|
|
139
|
+
runnerWarningLog: warningLog,
|
|
140
|
+
compilerService: this.compilerService
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
_runTask({ reporterPlugins, browserSet, tests, testedApp, options }) {
|
|
144
|
+
const task = this._createTask(tests, browserSet.browserConnectionGroups, this.proxy, options, this.warningLog);
|
|
145
|
+
const reporters = reporterPlugins.map(reporter => new reporter_1.default(reporter.plugin, task, reporter.outStream, reporter.name));
|
|
146
|
+
const completionPromise = this._getTaskResult(task, browserSet, reporters, testedApp);
|
|
147
|
+
let completed = false;
|
|
148
|
+
task.on('start', handle_errors_1.startHandlingTestErrors);
|
|
149
|
+
if (!this.configuration.getOption(option_names_1.default.skipUncaughtErrors)) {
|
|
150
|
+
task.on('test-run-start', handle_errors_1.addRunningTest);
|
|
151
|
+
task.on('test-run-done', handle_errors_1.removeRunningTest);
|
|
152
|
+
}
|
|
153
|
+
task.on('done', handle_errors_1.stopHandlingTestErrors);
|
|
154
|
+
task.on('error', handle_errors_1.stopHandlingTestErrors);
|
|
155
|
+
const onTaskCompleted = () => {
|
|
156
|
+
task.unRegisterClientScriptRouting();
|
|
157
|
+
completed = true;
|
|
158
|
+
};
|
|
159
|
+
completionPromise
|
|
160
|
+
.then(onTaskCompleted)
|
|
161
|
+
.catch(onTaskCompleted);
|
|
162
|
+
const cancelTask = async () => {
|
|
163
|
+
if (!completed)
|
|
164
|
+
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp);
|
|
165
|
+
};
|
|
166
|
+
return { completionPromise, cancelTask };
|
|
167
|
+
}
|
|
168
|
+
_registerAssets(assets) {
|
|
169
|
+
assets.forEach(asset => this.proxy.GET(asset.path, asset.info));
|
|
170
|
+
}
|
|
171
|
+
_validateDebugLogger() {
|
|
172
|
+
const debugLogger = this.configuration.getOption(option_names_1.default.debugLogger);
|
|
173
|
+
const debugLoggerDefinedCorrectly = debugLogger === null || !!debugLogger &&
|
|
174
|
+
['showBreakpoint', 'hideBreakpoint'].every(method => method in debugLogger && lodash_1.isFunction(debugLogger[method]));
|
|
175
|
+
if (!debugLoggerDefinedCorrectly) {
|
|
176
|
+
this.configuration.mergeOptions({
|
|
177
|
+
[option_names_1.default.debugLogger]: debug_logger_1.default
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
_validateSpeedOption() {
|
|
182
|
+
const speed = this.configuration.getOption(option_names_1.default.speed);
|
|
183
|
+
if (speed === void 0)
|
|
184
|
+
return;
|
|
185
|
+
if (typeof speed !== 'number' || isNaN(speed) || speed < 0.01 || speed > 1)
|
|
186
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidSpeedValue);
|
|
187
|
+
}
|
|
188
|
+
_validateConcurrencyOption() {
|
|
189
|
+
const concurrency = this.configuration.getOption(option_names_1.default.concurrency);
|
|
190
|
+
if (concurrency === void 0)
|
|
191
|
+
return;
|
|
192
|
+
if (typeof concurrency !== 'number' || isNaN(concurrency) || concurrency < 1)
|
|
193
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidConcurrencyFactor);
|
|
194
|
+
}
|
|
195
|
+
_validateRequestTimeoutOption(optionName) {
|
|
196
|
+
const requestTimeout = this.configuration.getOption(optionName);
|
|
197
|
+
if (requestTimeout === void 0)
|
|
198
|
+
return;
|
|
199
|
+
type_assertions_1.assertType(type_assertions_1.is.nonNegativeNumber, null, `"${optionName}" option`, requestTimeout);
|
|
200
|
+
}
|
|
201
|
+
_validateProxyBypassOption() {
|
|
202
|
+
let proxyBypass = this.configuration.getOption(option_names_1.default.proxyBypass);
|
|
203
|
+
if (proxyBypass === void 0)
|
|
204
|
+
return;
|
|
205
|
+
type_assertions_1.assertType([type_assertions_1.is.string, type_assertions_1.is.array], null, '"proxyBypass" argument', proxyBypass);
|
|
206
|
+
if (typeof proxyBypass === 'string')
|
|
207
|
+
proxyBypass = [proxyBypass];
|
|
208
|
+
proxyBypass = proxyBypass.reduce((arr, rules) => {
|
|
209
|
+
type_assertions_1.assertType(type_assertions_1.is.string, null, '"proxyBypass" argument', rules);
|
|
210
|
+
return arr.concat(rules.split(','));
|
|
211
|
+
}, []);
|
|
212
|
+
this.configuration.mergeOptions({ proxyBypass });
|
|
213
|
+
}
|
|
214
|
+
_getScreenshotOptions() {
|
|
215
|
+
let { path, pathPattern } = this.configuration.getOption(option_names_1.default.screenshots) || {};
|
|
216
|
+
if (!path)
|
|
217
|
+
path = this.configuration.getOption(option_names_1.default.screenshotPath);
|
|
218
|
+
if (!pathPattern)
|
|
219
|
+
pathPattern = this.configuration.getOption(option_names_1.default.screenshotPathPattern);
|
|
220
|
+
return { path, pathPattern };
|
|
221
|
+
}
|
|
222
|
+
_validateScreenshotOptions() {
|
|
223
|
+
const { path, pathPattern } = this._getScreenshotOptions();
|
|
224
|
+
const disableScreenshots = this.configuration.getOption(option_names_1.default.disableScreenshots) || !path;
|
|
225
|
+
this.configuration.mergeOptions({ [option_names_1.default.disableScreenshots]: disableScreenshots });
|
|
226
|
+
if (disableScreenshots)
|
|
227
|
+
return;
|
|
228
|
+
if (path) {
|
|
229
|
+
this._validateScreenshotPath(path, 'screenshots base directory path');
|
|
230
|
+
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { path: path_1.resolve(path) } });
|
|
231
|
+
}
|
|
232
|
+
if (pathPattern) {
|
|
233
|
+
this._validateScreenshotPath(pathPattern, 'screenshots path pattern');
|
|
234
|
+
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { pathPattern } });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
async _validateVideoOptions() {
|
|
238
|
+
const videoPath = this.configuration.getOption(option_names_1.default.videoPath);
|
|
239
|
+
const videoEncodingOptions = this.configuration.getOption(option_names_1.default.videoEncodingOptions);
|
|
240
|
+
let videoOptions = this.configuration.getOption(option_names_1.default.videoOptions);
|
|
241
|
+
if (!videoPath) {
|
|
242
|
+
if (videoOptions || videoEncodingOptions)
|
|
243
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotSetVideoOptionsWithoutBaseVideoPathSpecified);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
this.configuration.mergeOptions({ [option_names_1.default.videoPath]: path_1.resolve(videoPath) });
|
|
247
|
+
if (!videoOptions) {
|
|
248
|
+
videoOptions = {};
|
|
249
|
+
this.configuration.mergeOptions({ [option_names_1.default.videoOptions]: videoOptions });
|
|
250
|
+
}
|
|
251
|
+
if (videoOptions.ffmpegPath)
|
|
252
|
+
videoOptions.ffmpegPath = path_1.resolve(videoOptions.ffmpegPath);
|
|
253
|
+
else
|
|
254
|
+
videoOptions.ffmpegPath = await detect_ffmpeg_1.default();
|
|
255
|
+
if (!videoOptions.ffmpegPath)
|
|
256
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotFindFFMPEG);
|
|
257
|
+
}
|
|
258
|
+
_validateCompilerOptions() {
|
|
259
|
+
const compilerOptions = this.configuration.getOption(option_names_1.default.compilerOptions);
|
|
260
|
+
if (!compilerOptions)
|
|
261
|
+
return;
|
|
262
|
+
const specifiedCompilers = Object.keys(compilerOptions);
|
|
263
|
+
const customizedCompilers = Object.keys(customizable_compilers_1.default);
|
|
264
|
+
const wrongCompilers = specifiedCompilers.filter(compiler => !customizedCompilers.includes(compiler));
|
|
265
|
+
if (!wrongCompilers.length)
|
|
266
|
+
return;
|
|
267
|
+
const compilerListStr = string_1.getConcatenatedValuesString(wrongCompilers, void 0, "'");
|
|
268
|
+
const pluralSuffix = string_1.getPluralSuffix(wrongCompilers);
|
|
269
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotCustomizeSpecifiedCompilers, compilerListStr, pluralSuffix);
|
|
270
|
+
}
|
|
271
|
+
_validateRetryTestPagesOption() {
|
|
272
|
+
const retryTestPagesOption = this.configuration.getOption(option_names_1.default.retryTestPages);
|
|
273
|
+
if (!retryTestPagesOption)
|
|
274
|
+
return;
|
|
275
|
+
const ssl = this.configuration.getOption(option_names_1.default.ssl);
|
|
276
|
+
if (ssl)
|
|
277
|
+
return;
|
|
278
|
+
const hostname = this.configuration.getOption(option_names_1.default.hostname);
|
|
279
|
+
if (is_localhost_1.default(hostname))
|
|
280
|
+
return;
|
|
281
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotEnableRetryTestPagesOption);
|
|
282
|
+
}
|
|
283
|
+
async _validateRunOptions() {
|
|
284
|
+
this._validateDebugLogger();
|
|
285
|
+
this._validateScreenshotOptions();
|
|
286
|
+
await this._validateVideoOptions();
|
|
287
|
+
this._validateSpeedOption();
|
|
288
|
+
this._validateConcurrencyOption();
|
|
289
|
+
this._validateProxyBypassOption();
|
|
290
|
+
this._validateCompilerOptions();
|
|
291
|
+
this._validateRetryTestPagesOption();
|
|
292
|
+
this._validateRequestTimeoutOption(option_names_1.default.pageRequestTimeout);
|
|
293
|
+
this._validateRequestTimeoutOption(option_names_1.default.ajaxRequestTimeout);
|
|
294
|
+
}
|
|
295
|
+
_createRunnableConfiguration() {
|
|
296
|
+
return this.bootstrapper
|
|
297
|
+
.createRunnableConfiguration()
|
|
298
|
+
.then(runnableConfiguration => {
|
|
299
|
+
this.emit('done-bootstrapping');
|
|
300
|
+
return runnableConfiguration;
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
_validateScreenshotPath(screenshotPath, pathType) {
|
|
304
|
+
const forbiddenCharsList = check_file_path_1.default(screenshotPath);
|
|
305
|
+
if (forbiddenCharsList.length)
|
|
306
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.forbiddenCharatersInScreenshotPath, screenshotPath, pathType, utils_1.renderForbiddenCharsList(forbiddenCharsList));
|
|
307
|
+
}
|
|
308
|
+
_setBootstrapperOptions() {
|
|
309
|
+
this.configuration.prepare();
|
|
310
|
+
this.configuration.notifyAboutOverriddenOptions();
|
|
311
|
+
this.configuration.notifyAboutDeprecatedOptions(this.warningLog);
|
|
312
|
+
this.bootstrapper.sources = this.configuration.getOption(option_names_1.default.src) || this.bootstrapper.sources;
|
|
313
|
+
this.bootstrapper.browsers = this.configuration.getOption(option_names_1.default.browsers) || this.bootstrapper.browsers;
|
|
314
|
+
this.bootstrapper.concurrency = this.configuration.getOption(option_names_1.default.concurrency);
|
|
315
|
+
this.bootstrapper.appCommand = this.configuration.getOption(option_names_1.default.appCommand) || this.bootstrapper.appCommand;
|
|
316
|
+
this.bootstrapper.appInitDelay = this.configuration.getOption(option_names_1.default.appInitDelay);
|
|
317
|
+
this.bootstrapper.filter = this.configuration.getOption(option_names_1.default.filter) || this.bootstrapper.filter;
|
|
318
|
+
this.bootstrapper.reporters = this.configuration.getOption(option_names_1.default.reporter) || this.bootstrapper.reporters;
|
|
319
|
+
this.bootstrapper.tsConfigPath = this.configuration.getOption(option_names_1.default.tsConfigPath);
|
|
320
|
+
this.bootstrapper.clientScripts = this.configuration.getOption(option_names_1.default.clientScripts) || this.bootstrapper.clientScripts;
|
|
321
|
+
this.bootstrapper.disableMultipleWindows = this.configuration.getOption(option_names_1.default.disableMultipleWindows);
|
|
322
|
+
this.bootstrapper.compilerOptions = this.configuration.getOption(option_names_1.default.compilerOptions);
|
|
323
|
+
this.bootstrapper.browserInitTimeout = this.configuration.getOption(option_names_1.default.browserInitTimeout);
|
|
324
|
+
}
|
|
325
|
+
async _prepareClientScripts(tests, clientScripts) {
|
|
326
|
+
return Promise.all(tests.map(async (test) => {
|
|
327
|
+
if (test.isLegacy)
|
|
328
|
+
return;
|
|
329
|
+
let loadedTestClientScripts = await load_1.default(test.clientScripts, path_1.dirname(test.testFile.filename));
|
|
330
|
+
loadedTestClientScripts = clientScripts.concat(loadedTestClientScripts);
|
|
331
|
+
test.clientScripts = utils_2.setUniqueUrls(loadedTestClientScripts);
|
|
332
|
+
}));
|
|
333
|
+
}
|
|
334
|
+
// API
|
|
335
|
+
embeddingOptions(opts) {
|
|
336
|
+
const { assets, TestRunCtor } = opts;
|
|
337
|
+
this._registerAssets(assets);
|
|
338
|
+
this.configuration.mergeOptions({ TestRunCtor });
|
|
339
|
+
return this;
|
|
340
|
+
}
|
|
341
|
+
src(...sources) {
|
|
342
|
+
if (this.apiMethodWasCalled.src)
|
|
343
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.src);
|
|
344
|
+
sources = this._prepareArrayParameter(sources);
|
|
345
|
+
this.configuration.mergeOptions({ [option_names_1.default.src]: sources });
|
|
346
|
+
this.apiMethodWasCalled.src = true;
|
|
347
|
+
return this;
|
|
348
|
+
}
|
|
349
|
+
browsers(...browsers) {
|
|
350
|
+
if (this.apiMethodWasCalled.browsers)
|
|
351
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.browsers);
|
|
352
|
+
browsers = this._prepareArrayParameter(browsers);
|
|
353
|
+
this.configuration.mergeOptions({ browsers });
|
|
354
|
+
this.apiMethodWasCalled.browsers = true;
|
|
355
|
+
return this;
|
|
356
|
+
}
|
|
357
|
+
concurrency(concurrency) {
|
|
358
|
+
this.configuration.mergeOptions({ concurrency });
|
|
359
|
+
return this;
|
|
360
|
+
}
|
|
361
|
+
reporter(name, output) {
|
|
362
|
+
if (this.apiMethodWasCalled.reporter)
|
|
363
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.reporter);
|
|
364
|
+
let reporters = prepare_reporters_1.default(name, output);
|
|
365
|
+
reporters = this._prepareArrayParameter(reporters);
|
|
366
|
+
this.configuration.mergeOptions({ [option_names_1.default.reporter]: reporters });
|
|
367
|
+
this.apiMethodWasCalled.reporter = true;
|
|
368
|
+
return this;
|
|
369
|
+
}
|
|
370
|
+
filter(filter) {
|
|
371
|
+
this.configuration.mergeOptions({ filter });
|
|
372
|
+
return this;
|
|
373
|
+
}
|
|
374
|
+
useProxy(proxy, proxyBypass) {
|
|
375
|
+
this.configuration.mergeOptions({ proxy, proxyBypass });
|
|
376
|
+
return this;
|
|
377
|
+
}
|
|
378
|
+
screenshots(...options) {
|
|
379
|
+
let fullPage;
|
|
380
|
+
let [path, takeOnFails, pathPattern] = options;
|
|
381
|
+
if (options.length === 1 && options[0] && typeof options[0] === 'object')
|
|
382
|
+
({ path, takeOnFails, pathPattern, fullPage } = options[0]);
|
|
383
|
+
this.configuration.mergeOptions({ screenshots: { path, takeOnFails, pathPattern, fullPage } });
|
|
384
|
+
return this;
|
|
385
|
+
}
|
|
386
|
+
video(path, options, encodingOptions) {
|
|
387
|
+
this.configuration.mergeOptions({
|
|
388
|
+
[option_names_1.default.videoPath]: path,
|
|
389
|
+
[option_names_1.default.videoOptions]: options,
|
|
390
|
+
[option_names_1.default.videoEncodingOptions]: encodingOptions
|
|
391
|
+
});
|
|
392
|
+
return this;
|
|
393
|
+
}
|
|
394
|
+
startApp(command, initDelay) {
|
|
395
|
+
this.configuration.mergeOptions({
|
|
396
|
+
[option_names_1.default.appCommand]: command,
|
|
397
|
+
[option_names_1.default.appInitDelay]: initDelay
|
|
398
|
+
});
|
|
399
|
+
return this;
|
|
400
|
+
}
|
|
401
|
+
tsConfigPath(path) {
|
|
402
|
+
this.configuration.mergeOptions({
|
|
403
|
+
[option_names_1.default.tsConfigPath]: path
|
|
404
|
+
});
|
|
405
|
+
return this;
|
|
406
|
+
}
|
|
407
|
+
clientScripts(...scripts) {
|
|
408
|
+
if (this.apiMethodWasCalled.clientScripts)
|
|
409
|
+
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.clientScripts);
|
|
410
|
+
scripts = this._prepareArrayParameter(scripts);
|
|
411
|
+
this.configuration.mergeOptions({ [option_names_1.default.clientScripts]: scripts });
|
|
412
|
+
this.apiMethodWasCalled.clientScripts = true;
|
|
413
|
+
return this;
|
|
414
|
+
}
|
|
415
|
+
compilerOptions(opts) {
|
|
416
|
+
this.configuration.mergeOptions({
|
|
417
|
+
[option_names_1.default.compilerOptions]: opts
|
|
418
|
+
});
|
|
419
|
+
return this;
|
|
420
|
+
}
|
|
421
|
+
run(options = {}) {
|
|
422
|
+
this.apiMethodWasCalled.reset();
|
|
423
|
+
this.configuration.mergeOptions(options);
|
|
424
|
+
this._setBootstrapperOptions();
|
|
425
|
+
const runTaskPromise = Promise.resolve()
|
|
426
|
+
.then(() => this._validateRunOptions())
|
|
427
|
+
.then(() => this._createRunnableConfiguration())
|
|
428
|
+
.then(async ({ reporterPlugins, browserSet, tests, testedApp, commonClientScripts }) => {
|
|
429
|
+
var _a;
|
|
430
|
+
await this._prepareClientScripts(tests, commonClientScripts);
|
|
431
|
+
const resultOptions = this.configuration.getOptions();
|
|
432
|
+
await ((_a = this.bootstrapper.compilerService) === null || _a === void 0 ? void 0 : _a.setOptions({ value: resultOptions }));
|
|
433
|
+
return this._runTask({ reporterPlugins, browserSet, tests, testedApp, options: resultOptions });
|
|
434
|
+
});
|
|
435
|
+
return this._createCancelablePromise(runTaskPromise);
|
|
436
|
+
}
|
|
437
|
+
async stop() {
|
|
438
|
+
// NOTE: When taskPromise is cancelled, it is removed from
|
|
439
|
+
// the pendingTaskPromises array, which leads to shifting indexes
|
|
440
|
+
// towards the beginning. So, we must copy the array in order to iterate it,
|
|
441
|
+
// or we can perform iteration from the end to the beginning.
|
|
442
|
+
const cancellationPromises = this.pendingTaskPromises.reduceRight((result, taskPromise) => {
|
|
443
|
+
result.push(taskPromise.cancel());
|
|
444
|
+
return result;
|
|
445
|
+
}, []);
|
|
446
|
+
await Promise.all(cancellationPromises);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
exports.default = Runner;
|
|
450
450
|
module.exports = exports.default;
|
|
451
451
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVubmVyL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0JBQXVEO0FBQ3ZELGtEQUEwQjtBQUMxQixzRUFBNkM7QUFDN0MsbUNBQXNDO0FBQ3RDLG1DQUlnQjtBQUVoQixrRUFBMEM7QUFDMUMsMkRBQW1DO0FBQ25DLGtEQUEwQjtBQUMxQixpRkFBK0Q7QUFDL0QsK0NBQWlEO0FBQ2pELDJDQUFpRDtBQUNqRCx1RUFBbUU7QUFDbkUsb0RBQW9FO0FBQ3BFLDJFQUFrRDtBQUNsRCwrRUFBcUQ7QUFDckQsMERBS2dDO0FBRWhDLGlGQUF5RDtBQUN6RCxtRUFBMEM7QUFDMUMsbUZBQTBEO0FBQzFELHlFQUE4RDtBQUM5RCwwREFBK0Q7QUFDL0QsOEZBQW9FO0FBQ3BFLHFHQUE0RTtBQUM1RSw0Q0FBK0U7QUFDL0UseUVBQWdEO0FBQ2hELCtFQUFzRDtBQUV0RCxNQUFNLFlBQVksR0FBRyxlQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUU5QyxNQUFxQixNQUFPLFNBQVEscUJBQVk7SUFDNUMsWUFBYSxFQUFFLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFO1FBQzVFLEtBQUssRUFBRSxDQUFDO1FBRVIsSUFBSSxDQUFDLEtBQUssR0FBaUIsS0FBSyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxZQUFZLEdBQVUsSUFBSSxDQUFDLG1CQUFtQixDQUFDLHdCQUF3QixFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQy9GLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDLGFBQWEsR0FBUyxhQUFhLENBQUM7UUFDekMsSUFBSSxDQUFDLEtBQUssR0FBaUIsS0FBSyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxVQUFVLEdBQVksSUFBSSxxQkFBVSxFQUFFLENBQUM7UUFDNUMsSUFBSSxDQUFDLGVBQWUsR0FB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QUM7WUFFdEQsYUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLGVBQWUsMENBQUUsVUFBVSxDQUFDLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxFQUFDLENBQUM7WUFFOUUsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQ3BHLENBQUMsQ0FBQyxDQUFDO1FBRVAsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJO1FBQ04sMERBQTBEO1FBQzFELGlFQUFpRTtRQUNqRSw0RUFBNEU7UUFDNUUsNkRBQTZEO1FBQzdELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsRUFBRTtZQUN0RixNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBRWxDLE9BQU8sTUFBTSxDQUFDO1FBQ2xCLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVQLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBQzVDLENBQUM7Q0FDSjtBQXpqQkQseUJBeWpCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJlc29sdmUgYXMgcmVzb2x2ZVBhdGgsIGRpcm5hbWUgfSBmcm9tICdwYXRoJztcbmltcG9ydCBkZWJ1ZyBmcm9tICdkZWJ1Zyc7XG5pbXBvcnQgcHJvbWlzaWZ5RXZlbnQgZnJvbSAncHJvbWlzaWZ5LWV2ZW50JztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQge1xuICAgIGZsYXR0ZW5EZWVwIGFzIGZsYXR0ZW4sXG4gICAgcHVsbCBhcyByZW1vdmUsXG4gICAgaXNGdW5jdGlvblxufSBmcm9tICdsb2Rhc2gnO1xuXG5pbXBvcnQgQm9vdHN0cmFwcGVyIGZyb20gJy4vYm9vdHN0cmFwcGVyJztcbmltcG9ydCBSZXBvcnRlciBmcm9tICcuLi9yZXBvcnRlcic7XG5pbXBvcnQgVGFzayBmcm9tICcuL3Rhc2snO1xuaW1wb3J0IGRlZmF1bHREZWJ1Z0xvZ2dlciBmcm9tICcuLi9ub3RpZmljYXRpb25zL2RlYnVnLWxvZ2dlcic7XG5pbXBvcnQgeyBHZW5lcmFsRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMvcnVudGltZSc7XG5pbXBvcnQgeyBSVU5USU1FX0VSUk9SUyB9IGZyb20gJy4uL2Vycm9ycy90eXBlcyc7XG5pbXBvcnQgeyBhc3NlcnRUeXBlLCBpcyB9IGZyb20gJy4uL2Vycm9ycy9ydW50aW1lL3R5cGUtYXNzZXJ0aW9ucyc7XG5pbXBvcnQgeyByZW5kZXJGb3JiaWRkZW5DaGFyc0xpc3QgfSBmcm9tICcuLi9lcnJvcnMvdGVzdC1ydW4vdXRpbHMnO1xuaW1wb3J0IGRldGVjdEZGTVBFRyBmcm9tICcuLi91dGlscy9kZXRlY3QtZmZtcGVnJztcbmltcG9ydCBjaGVja0ZpbGVQYXRoIGZyb20gJy4uL3V0aWxzL2NoZWNrLWZpbGUtcGF0aCc7XG5pbXBvcnQge1xuICAgIGFkZFJ1bm5pbmdUZXN0LFxuICAgIHJlbW92ZVJ1bm5pbmdUZXN0LFxuICAgIHN0YXJ0SGFuZGxpbmdUZXN0RXJyb3JzLFxuICAgIHN0b3BIYW5kbGluZ1Rlc3RFcnJvcnNcbn0gZnJvbSAnLi4vdXRpbHMvaGFuZGxlLWVycm9ycyc7XG5cbmltcG9ydCBPUFRJT05fTkFNRVMgZnJvbSAnLi4vY29uZmlndXJhdGlvbi9vcHRpb24tbmFtZXMnO1xuaW1wb3J0IEZsYWdMaXN0IGZyb20gJy4uL3V0aWxzL2ZsYWctbGlzdCc7XG5pbXBvcnQgcHJlcGFyZVJlcG9ydGVycyBmcm9tICcuLi91dGlscy9wcmVwYXJlLXJlcG9ydGVycyc7XG5pbXBvcnQgbG9hZENsaWVudFNjcmlwdHMgZnJvbSAnLi4vY3VzdG9tLWNsaWVudC1zY3JpcHRzL2xvYWQnO1xuaW1wb3J0IHsgc2V0VW5pcXVlVXJscyB9IGZyb20gJy4uL2N1c3RvbS1jbGllbnQtc2NyaXB0cy91dGlscyc7XG5pbXBvcnQgUmVwb3J0ZXJTdHJlYW1Db250cm9sbGVyIGZyb20gJy4vcmVwb3J0ZXItc3RyZWFtLWNvbnRyb2xsZXInO1xuaW1wb3J0IEN1c3RvbWl6YWJsZUNvbXBpbGVycyBmcm9tICcuLi9jb25maWd1cmF0aW9uL2N1c3RvbWl6YWJsZS1jb21waWxlcnMnO1xuaW1wb3J0IHsgZ2V0Q29uY2F0ZW5hdGVkVmFsdWVzU3RyaW5nLCBnZXRQbHVyYWxTdWZmaXggfSBmcm9tICcuLi91dGlscy9zdHJpbmcnO1xuaW1wb3J0IGlzTG9jYWxob3N0IGZyb20gJy4uL3V0aWxzL2lzLWxvY2FsaG9zdCc7XG5pbXBvcnQgV2FybmluZ0xvZyBmcm9tICcuLi9ub3RpZmljYXRpb25zL3dhcm5pbmctbG9nJztcblxuY29uc3QgREVCVUdfTE9HR0VSID0gZGVidWcoJ3Rlc3RjYWZlOnJ1bm5lcicpO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSdW5uZXIgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICAgIGNvbnN0cnVjdG9yICh7IHByb3h5LCBicm93c2VyQ29ubmVjdGlvbkdhdGV3YXksIGNvbmZpZ3VyYXRpb24sIGNvbXBpbGVyU2VydmljZSB9KSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5wcm94eSAgICAgICAgICAgICAgID0gcHJveHk7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyICAgICAgICA9IHRoaXMuX2NyZWF0ZUJvb3RzdHJhcHBlcihicm93c2VyQ29ubmVjdGlvbkdhdGV3YXksIGNvbXBpbGVyU2VydmljZSk7XG4gICAgICAgIHRoaXMucGVuZGluZ1Rhc2tQcm9taXNlcyA9IFtdO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24gICAgICAgPSBjb25maWd1cmF0aW9uO1xuICAgICAgICB0aGlzLmlzQ2xpICAgICAgICAgICAgICAgPSBmYWxzZTtcbiAgICAgICAgdGhpcy53YXJuaW5nTG9nICAgICAgICAgID0gbmV3IFdhcm5pbmdMb2coKTtcbiAgICAgICAgdGhpcy5jb21waWxlclNlcnZpY2UgICAgID0gY29tcGlsZXJTZXJ2aWNlO1xuXG4gICAgICAgIHRoaXMuYXBpTWV0aG9kV2FzQ2FsbGVkID0gbmV3IEZsYWdMaXN0KFtcbiAgICAgICAgICAgIE9QVElPTl9OQU1FUy5zcmMsXG4gICAgICAgICAgICBPUFRJT05fTkFNRVMuYnJvd3NlcnMsXG4gICAgICAgICAgICBPUFRJT05fTkFNRVMucmVwb3J0ZXIsXG4gICAgICAgICAgICBPUFRJT05fTkFNRVMuY2xpZW50U2NyaXB0c1xuICAgICAgICBdKTtcbiAgICB9XG5cbiAgICBfY3JlYXRlQm9vdHN0cmFwcGVyIChicm93c2VyQ29ubmVjdGlvbkdhdGV3YXksIGNvbXBpbGVyU2VydmljZSkge1xuICAgICAgICByZXR1cm4gbmV3IEJvb3RzdHJhcHBlcih7IGJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSwgY29tcGlsZXJTZXJ2aWNlIH0pO1xuICAgIH1cblxuICAgIF9kaXNwb3NlQnJvd3NlclNldCAoYnJvd3NlclNldCkge1xuICAgICAgICByZXR1cm4gYnJvd3NlclNldC5kaXNwb3NlKCkuY2F0Y2goZSA9PiBERUJVR19MT0dHRVIoZSkpO1xuICAgIH1cblxuICAgIF9kaXNwb3NlUmVwb3J0ZXJzIChyZXBvcnRlcnMpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHJlcG9ydGVycy5tYXAocmVwb3J0ZXIgPT4gcmVwb3J0ZXIuZGlzcG9zZSgpLmNhdGNoKGUgPT4gREVCVUdfTE9HR0VSKGUpKSkpO1xuICAgIH1cblxuICAgIF9kaXNwb3NlVGVzdGVkQXBwICh0ZXN0ZWRBcHApIHtcbiAgICAgICAgcmV0dXJuIHRlc3RlZEFwcCA/IHRlc3RlZEFwcC5raWxsKCkuY2F0Y2goZSA9PiBERUJVR19MT0dHRVIoZSkpIDogUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2Rpc3Bvc2VUYXNrQW5kUmVsYXRlZEFzc2V0cyAodGFzaywgYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApIHtcbiAgICAgICAgdGFzay5hYm9ydCgpO1xuICAgICAgICB0YXNrLnVuUmVnaXN0ZXJDbGllbnRTY3JpcHRSb3V0aW5nKCk7XG4gICAgICAgIHRhc2suY2xlYXJMaXN0ZW5lcnMoKTtcblxuICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlQXNzZXRzKGJyb3dzZXJTZXQsIHJlcG9ydGVycywgdGVzdGVkQXBwKTtcbiAgICB9XG5cbiAgICBfZGlzcG9zZUFzc2V0cyAoYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgIHRoaXMuX2Rpc3Bvc2VCcm93c2VyU2V0KGJyb3dzZXJTZXQpLFxuICAgICAgICAgICAgdGhpcy5fZGlzcG9zZVJlcG9ydGVycyhyZXBvcnRlcnMpLFxuICAgICAgICAgICAgdGhpcy5fZGlzcG9zZVRlc3RlZEFwcCh0ZXN0ZWRBcHApXG4gICAgICAgIF0pO1xuICAgIH1cblxuICAgIF9wcmVwYXJlQXJyYXlQYXJhbWV0ZXIgKGFycmF5KSB7XG4gICAgICAgIGFycmF5ID0gZmxhdHRlbihhcnJheSk7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNDbGkpXG4gICAgICAgICAgICByZXR1cm4gYXJyYXkubGVuZ3RoID09PSAwID8gdm9pZCAwIDogYXJyYXk7XG5cbiAgICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIF9jcmVhdGVDYW5jZWxhYmxlUHJvbWlzZSAodGFza1Byb21pc2UpIHtcbiAgICAgICAgY29uc3QgcHJvbWlzZSAgICAgICAgICAgPSB0YXNrUHJvbWlzZS50aGVuKCh7IGNvbXBsZXRpb25Qcm9taXNlIH0pID0+IGNvbXBsZXRpb25Qcm9taXNlKTtcbiAgICAgICAgY29uc3QgcmVtb3ZlRnJvbVBlbmRpbmcgPSAoKSA9PiByZW1vdmUodGhpcy5wZW5kaW5nVGFza1Byb21pc2VzLCBwcm9taXNlKTtcblxuICAgICAgICBwcm9taXNlXG4gICAgICAgICAgICAudGhlbihyZW1vdmVGcm9tUGVuZGluZylcbiAgICAgICAgICAgIC5jYXRjaChyZW1vdmVGcm9tUGVuZGluZyk7XG5cbiAgICAgICAgcHJvbWlzZS5jYW5jZWwgPSAoKSA9PiB0YXNrUHJvbWlzZVxuICAgICAgICAgICAgLnRoZW4oKHsgY2FuY2VsVGFzayB9KSA9PiBjYW5jZWxUYXNrKCkpXG4gICAgICAgICAgICAudGhlbihyZW1vdmVGcm9tUGVuZGluZyk7XG5cbiAgICAgICAgdGhpcy5wZW5kaW5nVGFza1Byb21pc2VzLnB1c2gocHJvbWlzZSk7XG5cbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgLy8gUnVuIHRhc2tcbiAgICBfZ2V0RmFpbGVkVGVzdENvdW50ICh0YXNrLCByZXBvcnRlcikge1xuICAgICAgICBsZXQgZmFpbGVkVGVzdENvdW50ID0gcmVwb3J0ZXIudGVzdENvdW50IC0gcmVwb3J0ZXIucGFzc2VkO1xuXG4gICAgICAgIGlmICh0YXNrLm9wdHMuc3RvcE9uRmlyc3RGYWlsICYmICEhZmFpbGVkVGVzdENvdW50KVxuICAgICAgICAgICAgZmFpbGVkVGVzdENvdW50ID0gMTtcblxuICAgICAgICByZXR1cm4gZmFpbGVkVGVzdENvdW50O1xuICAgIH1cblxuICAgIGFzeW5jIF9nZXRUYXNrUmVzdWx0ICh0YXNrLCBicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCkge1xuICAgICAgICBpZiAoIXRhc2sub3B0cy5saXZlKSB7XG4gICAgICAgICAgICB0YXNrLm9uKCdicm93c2VyLWpvYi1kb25lJywgam9iID0+IHtcbiAgICAgICAgICAgICAgICBqb2IuYnJvd3NlckNvbm5lY3Rpb25zLmZvckVhY2goYmMgPT4gYnJvd3NlclNldC5yZWxlYXNlQ29ubmVjdGlvbihiYykpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBicm93c2VyU2V0RXJyb3JQcm9taXNlID0gcHJvbWlzaWZ5RXZlbnQoYnJvd3NlclNldCwgJ2Vycm9yJyk7XG4gICAgICAgIGNvbnN0IHRhc2tFcnJvclByb21pc2UgICAgICAgPSBwcm9taXNpZnlFdmVudCh0YXNrLCAnZXJyb3InKTtcbiAgICAgICAgY29uc3Qgc3RyZWFtQ29udHJvbGxlciAgICAgICA9IG5ldyBSZXBvcnRlclN0cmVhbUNvbnRyb2xsZXIodGFzaywgcmVwb3J0ZXJzKTtcblxuICAgICAgICBjb25zdCB0YXNrRG9uZVByb21pc2UgPSB0YXNrLm9uY2UoJ2RvbmUnKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gYnJvd3NlclNldEVycm9yUHJvbWlzZS5jYW5jZWwoKSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVwb3J0ZXJzLm1hcChyZXBvcnRlciA9PiByZXBvcnRlci5wZW5kaW5nVGFza0RvbmVQcm9taXNlKSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtcbiAgICAgICAgICAgIHRhc2tEb25lUHJvbWlzZSxcbiAgICAgICAgICAgIGJyb3dzZXJTZXRFcnJvclByb21pc2UsXG4gICAgICAgICAgICB0YXNrRXJyb3JQcm9taXNlXG4gICAgICAgIF07XG5cbiAgICAgICAgaWYgKHRlc3RlZEFwcClcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGVzdGVkQXBwLmVycm9yUHJvbWlzZSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UucmFjZShwcm9taXNlcyk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fZGlzcG9zZVRhc2tBbmRSZWxhdGVkQXNzZXRzKHRhc2ssIGJyb3dzZXJTZXQsIHJlcG9ydGVycywgdGVzdGVkQXBwKTtcblxuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5fZGlzcG9zZUFzc2V0cyhicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCk7XG5cbiAgICAgICAgaWYgKHN0cmVhbUNvbnRyb2xsZXIubXVsdGlwbGVTdHJlYW1FcnJvcilcbiAgICAgICAgICAgIHRocm93IHN0cmVhbUNvbnRyb2xsZXIubXVsdGlwbGVTdHJlYW1FcnJvcjtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0RmFpbGVkVGVzdENvdW50KHRhc2ssIHJlcG9ydGVyc1swXSk7XG4gICAgfVxuXG4gICAgX2NyZWF0ZVRhc2sgKHRlc3RzLCBicm93c2VyQ29ubmVjdGlvbkdyb3VwcywgcHJveHksIG9wdHMsIHdhcm5pbmdMb2cpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUYXNrKHtcbiAgICAgICAgICAgIHRlc3RzLFxuICAgICAgICAgICAgYnJvd3NlckNvbm5lY3Rpb25Hcm91cHMsXG4gICAgICAgICAgICBwcm94eSxcbiAgICAgICAgICAgIG9wdHMsXG4gICAgICAgICAgICBydW5uZXJXYXJuaW5nTG9nOiB3YXJuaW5nTG9nLFxuICAgICAgICAgICAgY29tcGlsZXJTZXJ2aWNlOiAgdGhpcy5jb21waWxlclNlcnZpY2VcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgX3J1blRhc2sgKHsgcmVwb3J0ZXJQbHVnaW5zLCBicm93c2VyU2V0LCB0ZXN0cywgdGVzdGVkQXBwLCBvcHRpb25zIH0pIHtcbiAgICAgICAgY29uc3QgdGFzayAgICAgICAgICAgICAgPSB0aGlzLl9jcmVhdGVUYXNrKHRlc3RzLCBicm93c2VyU2V0LmJyb3dzZXJDb25uZWN0aW9uR3JvdXBzLCB0aGlzLnByb3h5LCBvcHRpb25zLCB0aGlzLndhcm5pbmdMb2cpO1xuICAgICAgICBjb25zdCByZXBvcnRlcnMgICAgICAgICA9IHJlcG9ydGVyUGx1Z2lucy5tYXAocmVwb3J0ZXIgPT4gbmV3IFJlcG9ydGVyKHJlcG9ydGVyLnBsdWdpbiwgdGFzaywgcmVwb3J0ZXIub3V0U3RyZWFtLCByZXBvcnRlci5uYW1lKSk7XG4gICAgICAgIGNvbnN0IGNvbXBsZXRpb25Qcm9taXNlID0gdGhpcy5fZ2V0VGFza1Jlc3VsdCh0YXNrLCBicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCk7XG4gICAgICAgIGxldCBjb21wbGV0ZWQgICAgICAgICAgID0gZmFsc2U7XG5cbiAgICAgICAgdGFzay5vbignc3RhcnQnLCBzdGFydEhhbmRsaW5nVGVzdEVycm9ycyk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5za2lwVW5jYXVnaHRFcnJvcnMpKSB7XG4gICAgICAgICAgICB0YXNrLm9uKCd0ZXN0LXJ1bi1zdGFydCcsIGFkZFJ1bm5pbmdUZXN0KTtcbiAgICAgICAgICAgIHRhc2sub24oJ3Rlc3QtcnVuLWRvbmUnLCByZW1vdmVSdW5uaW5nVGVzdCk7XG4gICAgICAgIH1cblxuICAgICAgICB0YXNrLm9uKCdkb25lJywgc3RvcEhhbmRsaW5nVGVzdEVycm9ycyk7XG5cbiAgICAgICAgdGFzay5vbignZXJyb3InLCBzdG9wSGFuZGxpbmdUZXN0RXJyb3JzKTtcblxuICAgICAgICBjb25zdCBvblRhc2tDb21wbGV0ZWQgPSAoKSA9PiB7XG4gICAgICAgICAgICB0YXNrLnVuUmVnaXN0ZXJDbGllbnRTY3JpcHRSb3V0aW5nKCk7XG5cbiAgICAgICAgICAgIGNvbXBsZXRlZCA9IHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29tcGxldGlvblByb21pc2VcbiAgICAgICAgICAgIC50aGVuKG9uVGFza0NvbXBsZXRlZClcbiAgICAgICAgICAgIC5jYXRjaChvblRhc2tDb21wbGV0ZWQpO1xuXG4gICAgICAgIGNvbnN0IGNhbmNlbFRhc2sgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWNvbXBsZXRlZClcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlVGFza0FuZFJlbGF0ZWRBc3NldHModGFzaywgYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB7IGNvbXBsZXRpb25Qcm9taXNlLCBjYW5jZWxUYXNrIH07XG4gICAgfVxuXG4gICAgX3JlZ2lzdGVyQXNzZXRzIChhc3NldHMpIHtcbiAgICAgICAgYXNzZXRzLmZvckVhY2goYXNzZXQgPT4gdGhpcy5wcm94eS5HRVQoYXNzZXQucGF0aCwgYXNzZXQuaW5mbykpO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZURlYnVnTG9nZ2VyICgpIHtcbiAgICAgICAgY29uc3QgZGVidWdMb2dnZXIgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5kZWJ1Z0xvZ2dlcik7XG5cbiAgICAgICAgY29uc3QgZGVidWdMb2dnZXJEZWZpbmVkQ29ycmVjdGx5ID0gZGVidWdMb2dnZXIgPT09IG51bGwgfHwgISFkZWJ1Z0xvZ2dlciAmJlxuICAgICAgICAgICAgWydzaG93QnJlYWtwb2ludCcsICdoaWRlQnJlYWtwb2ludCddLmV2ZXJ5KG1ldGhvZCA9PiBtZXRob2QgaW4gZGVidWdMb2dnZXIgJiYgaXNGdW5jdGlvbihkZWJ1Z0xvZ2dlclttZXRob2RdKSk7XG5cbiAgICAgICAgaWYgKCFkZWJ1Z0xvZ2dlckRlZmluZWRDb3JyZWN0bHkpIHtcbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoe1xuICAgICAgICAgICAgICAgIFtPUFRJT05fTkFNRVMuZGVidWdMb2dnZXJdOiBkZWZhdWx0RGVidWdMb2dnZXJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlU3BlZWRPcHRpb24gKCkge1xuICAgICAgICBjb25zdCBzcGVlZCA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnNwZWVkKTtcblxuICAgICAgICBpZiAoc3BlZWQgPT09IHZvaWQgMClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBpZiAodHlwZW9mIHNwZWVkICE9PSAnbnVtYmVyJyB8fCBpc05hTihzcGVlZCkgfHwgc3BlZWQgPCAwLjAxIHx8IHNwZWVkID4gMSlcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuaW52YWxpZFNwZWVkVmFsdWUpO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZUNvbmN1cnJlbmN5T3B0aW9uICgpIHtcbiAgICAgICAgY29uc3QgY29uY3VycmVuY3kgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5jb25jdXJyZW5jeSk7XG5cbiAgICAgICAgaWYgKGNvbmN1cnJlbmN5ID09PSB2b2lkIDApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25jdXJyZW5jeSAhPT0gJ251bWJlcicgfHwgaXNOYU4oY29uY3VycmVuY3kpIHx8IGNvbmN1cnJlbmN5IDwgMSlcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuaW52YWxpZENvbmN1cnJlbmN5RmFjdG9yKTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVSZXF1ZXN0VGltZW91dE9wdGlvbiAob3B0aW9uTmFtZSkge1xuICAgICAgICBjb25zdCByZXF1ZXN0VGltZW91dCA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24ob3B0aW9uTmFtZSk7XG5cbiAgICAgICAgaWYgKHJlcXVlc3RUaW1lb3V0ID09PSB2b2lkIDApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgYXNzZXJ0VHlwZShpcy5ub25OZWdhdGl2ZU51bWJlciwgbnVsbCwgYFwiJHtvcHRpb25OYW1lfVwiIG9wdGlvbmAsIHJlcXVlc3RUaW1lb3V0KTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVQcm94eUJ5cGFzc09wdGlvbiAoKSB7XG4gICAgICAgIGxldCBwcm94eUJ5cGFzcyA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnByb3h5QnlwYXNzKTtcblxuICAgICAgICBpZiAocHJveHlCeXBhc3MgPT09IHZvaWQgMClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBhc3NlcnRUeXBlKFsgaXMuc3RyaW5nLCBpcy5hcnJheSBdLCBudWxsLCAnXCJwcm94eUJ5cGFzc1wiIGFyZ3VtZW50JywgcHJveHlCeXBhc3MpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcHJveHlCeXBhc3MgPT09ICdzdHJpbmcnKVxuICAgICAgICAgICAgcHJveHlCeXBhc3MgPSBbcHJveHlCeXBhc3NdO1xuXG4gICAgICAgIHByb3h5QnlwYXNzID0gcHJveHlCeXBhc3MucmVkdWNlKChhcnIsIHJ1bGVzKSA9PiB7XG4gICAgICAgICAgICBhc3NlcnRUeXBlKGlzLnN0cmluZywgbnVsbCwgJ1wicHJveHlCeXBhc3NcIiBhcmd1bWVudCcsIHJ1bGVzKTtcblxuICAgICAgICAgICAgcmV0dXJuIGFyci5jb25jYXQocnVsZXMuc3BsaXQoJywnKSk7XG4gICAgICAgIH0sIFtdKTtcblxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgcHJveHlCeXBhc3MgfSk7XG4gICAgfVxuXG4gICAgX2dldFNjcmVlbnNob3RPcHRpb25zICgpIHtcbiAgICAgICAgbGV0IHsgcGF0aCwgcGF0aFBhdHRlcm4gfSA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnNjcmVlbnNob3RzKSB8fCB7fTtcblxuICAgICAgICBpZiAoIXBhdGgpXG4gICAgICAgICAgICBwYXRoID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc2NyZWVuc2hvdFBhdGgpO1xuXG4gICAgICAgIGlmICghcGF0aFBhdHRlcm4pXG4gICAgICAgICAgICBwYXRoUGF0dGVybiA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnNjcmVlbnNob3RQYXRoUGF0dGVybik7XG5cbiAgICAgICAgcmV0dXJuIHsgcGF0aCwgcGF0aFBhdHRlcm4gfTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVTY3JlZW5zaG90T3B0aW9ucyAoKSB7XG4gICAgICAgIGNvbnN0IHsgcGF0aCwgcGF0aFBhdHRlcm4gfSA9IHRoaXMuX2dldFNjcmVlbnNob3RPcHRpb25zKCk7XG5cbiAgICAgICAgY29uc3QgZGlzYWJsZVNjcmVlbnNob3RzID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuZGlzYWJsZVNjcmVlbnNob3RzKSB8fCAhcGF0aDtcblxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy5kaXNhYmxlU2NyZWVuc2hvdHNdOiBkaXNhYmxlU2NyZWVuc2hvdHMgfSk7XG5cbiAgICAgICAgaWYgKGRpc2FibGVTY3JlZW5zaG90cylcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBpZiAocGF0aCkge1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdGVTY3JlZW5zaG90UGF0aChwYXRoLCAnc2NyZWVuc2hvdHMgYmFzZSBkaXJlY3RvcnkgcGF0aCcpO1xuXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy5zY3JlZW5zaG90c106IHsgcGF0aDogcmVzb2x2ZVBhdGgocGF0aCkgfSB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXRoUGF0dGVybikge1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdGVTY3JlZW5zaG90UGF0aChwYXRoUGF0dGVybiwgJ3NjcmVlbnNob3RzIHBhdGggcGF0dGVybicpO1xuXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy5zY3JlZW5zaG90c106IHsgcGF0aFBhdHRlcm4gfSB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIF92YWxpZGF0ZVZpZGVvT3B0aW9ucyAoKSB7XG4gICAgICAgIGNvbnN0IHZpZGVvUGF0aCAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMudmlkZW9QYXRoKTtcbiAgICAgICAgY29uc3QgdmlkZW9FbmNvZGluZ09wdGlvbnMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy52aWRlb0VuY29kaW5nT3B0aW9ucyk7XG5cbiAgICAgICAgbGV0IHZpZGVvT3B0aW9ucyA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnZpZGVvT3B0aW9ucyk7XG5cbiAgICAgICAgaWYgKCF2aWRlb1BhdGgpIHtcbiAgICAgICAgICAgIGlmICh2aWRlb09wdGlvbnMgfHwgdmlkZW9FbmNvZGluZ09wdGlvbnMpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5jYW5ub3RTZXRWaWRlb09wdGlvbnNXaXRob3V0QmFzZVZpZGVvUGF0aFNwZWNpZmllZCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBbT1BUSU9OX05BTUVTLnZpZGVvUGF0aF06IHJlc29sdmVQYXRoKHZpZGVvUGF0aCkgfSk7XG5cbiAgICAgICAgaWYgKCF2aWRlb09wdGlvbnMpIHtcbiAgICAgICAgICAgIHZpZGVvT3B0aW9ucyA9IHt9O1xuXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgW09QVElPTl9OQU1FUy52aWRlb09wdGlvbnNdOiB2aWRlb09wdGlvbnMgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmlkZW9PcHRpb25zLmZmbXBlZ1BhdGgpXG4gICAgICAgICAgICB2aWRlb09wdGlvbnMuZmZtcGVnUGF0aCA9IHJlc29sdmVQYXRoKHZpZGVvT3B0aW9ucy5mZm1wZWdQYXRoKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdmlkZW9PcHRpb25zLmZmbXBlZ1BhdGggPSBhd2FpdCBkZXRlY3RGRk1QRUcoKTtcblxuICAgICAgICBpZiAoIXZpZGVvT3B0aW9ucy5mZm1wZWdQYXRoKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5jYW5ub3RGaW5kRkZNUEVHKTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVDb21waWxlck9wdGlvbnMgKCkge1xuICAgICAgICBjb25zdCBjb21waWxlck9wdGlvbnMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5jb21waWxlck9wdGlvbnMpO1xuXG4gICAgICAgIGlmICghY29tcGlsZXJPcHRpb25zKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHNwZWNpZmllZENvbXBpbGVycyAgPSBPYmplY3Qua2V5cyhjb21waWxlck9wdGlvbnMpO1xuICAgICAgICBjb25zdCBjdXN0b21pemVkQ29tcGlsZXJzID0gT2JqZWN0LmtleXMoQ3VzdG9taXphYmxlQ29tcGlsZXJzKTtcbiAgICAgICAgY29uc3Qgd3JvbmdDb21waWxlcnMgICAgICA9IHNwZWNpZmllZENvbXBpbGVycy5maWx0ZXIoY29tcGlsZXIgPT4gIWN1c3RvbWl6ZWRDb21waWxlcnMuaW5jbHVkZXMoY29tcGlsZXIpKTtcblxuICAgICAgICBpZiAoIXdyb25nQ29tcGlsZXJzLmxlbmd0aClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBjb21waWxlckxpc3RTdHIgPSBnZXRDb25jYXRlbmF0ZWRWYWx1ZXNTdHJpbmcod3JvbmdDb21waWxlcnMsIHZvaWQgMCwgXCInXCIpO1xuICAgICAgICBjb25zdCBwbHVyYWxTdWZmaXggICAgPSBnZXRQbHVyYWxTdWZmaXgod3JvbmdDb21waWxlcnMpO1xuXG4gICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuY2Fubm90Q3VzdG9taXplU3BlY2lmaWVkQ29tcGlsZXJzLCBjb21waWxlckxpc3RTdHIsIHBsdXJhbFN1ZmZpeCk7XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlUmV0cnlUZXN0UGFnZXNPcHRpb24gKCkge1xuICAgICAgICBjb25zdCByZXRyeVRlc3RQYWdlc09wdGlvbiA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnJldHJ5VGVzdFBhZ2VzKTtcblxuICAgICAgICBpZiAoIXJldHJ5VGVzdFBhZ2VzT3B0aW9uKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHNzbCA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnNzbCk7XG5cbiAgICAgICAgaWYgKHNzbClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBob3N0bmFtZSA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmhvc3RuYW1lKTtcblxuICAgICAgICBpZiAoaXNMb2NhbGhvc3QoaG9zdG5hbWUpKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuY2Fubm90RW5hYmxlUmV0cnlUZXN0UGFnZXNPcHRpb24pO1xuICAgIH1cblxuICAgIGFzeW5jIF92YWxpZGF0ZVJ1bk9wdGlvbnMgKCkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZURlYnVnTG9nZ2VyKCk7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlU2NyZWVuc2hvdE9wdGlvbnMoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fdmFsaWRhdGVWaWRlb09wdGlvbnMoKTtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVTcGVlZE9wdGlvbigpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZUNvbmN1cnJlbmN5T3B0aW9uKCk7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlUHJveHlCeXBhc3NPcHRpb24oKTtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVDb21waWxlck9wdGlvbnMoKTtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVSZXRyeVRlc3RQYWdlc09wdGlvbigpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZVJlcXVlc3RUaW1lb3V0T3B0aW9uKE9QVElPTl9OQU1FUy5wYWdlUmVxdWVzdFRpbWVvdXQpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZVJlcXVlc3RUaW1lb3V0T3B0aW9uKE9QVElPTl9OQU1FUy5hamF4UmVxdWVzdFRpbWVvdXQpO1xuICAgIH1cblxuICAgIF9jcmVhdGVSdW5uYWJsZUNvbmZpZ3VyYXRpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5ib290c3RyYXBwZXJcbiAgICAgICAgICAgIC5jcmVhdGVSdW5uYWJsZUNvbmZpZ3VyYXRpb24oKVxuICAgICAgICAgICAgLnRoZW4ocnVubmFibGVDb25maWd1cmF0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXQoJ2RvbmUtYm9vdHN0cmFwcGluZycpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJ1bm5hYmxlQ29uZmlndXJhdGlvbjtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZVNjcmVlbnNob3RQYXRoIChzY3JlZW5zaG90UGF0aCwgcGF0aFR5cGUpIHtcbiAgICAgICAgY29uc3QgZm9yYmlkZGVuQ2hhcnNMaXN0ID0gY2hlY2tGaWxlUGF0aChzY3JlZW5zaG90UGF0aCk7XG5cbiAgICAgICAgaWYgKGZvcmJpZGRlbkNoYXJzTGlzdC5sZW5ndGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLmZvcmJpZGRlbkNoYXJhdGVyc0luU2NyZWVuc2hvdFBhdGgsIHNjcmVlbnNob3RQYXRoLCBwYXRoVHlwZSwgcmVuZGVyRm9yYmlkZGVuQ2hhcnNMaXN0KGZvcmJpZGRlbkNoYXJzTGlzdCkpO1xuICAgIH1cblxuICAgIF9zZXRCb290c3RyYXBwZXJPcHRpb25zICgpIHtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLnByZXBhcmUoKTtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm5vdGlmeUFib3V0T3ZlcnJpZGRlbk9wdGlvbnMoKTtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm5vdGlmeUFib3V0RGVwcmVjYXRlZE9wdGlvbnModGhpcy53YXJuaW5nTG9nKTtcblxuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5zb3VyY2VzICAgICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc3JjKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5zb3VyY2VzO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5icm93c2VycyAgICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuYnJvd3NlcnMpIHx8IHRoaXMuYm9vdHN0cmFwcGVyLmJyb3dzZXJzO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5jb25jdXJyZW5jeSAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuY29uY3VycmVuY3kpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5hcHBDb21tYW5kICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuYXBwQ29tbWFuZCkgfHwgdGhpcy5ib290c3RyYXBwZXIuYXBwQ29tbWFuZDtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuYXBwSW5pdERlbGF5ICAgICAgICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmFwcEluaXREZWxheSk7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyLmZpbHRlciAgICAgICAgICAgICAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5maWx0ZXIpIHx8IHRoaXMuYm9vdHN0cmFwcGVyLmZpbHRlcjtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIucmVwb3J0ZXJzICAgICAgICAgICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnJlcG9ydGVyKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5yZXBvcnRlcnM7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyLnRzQ29uZmlnUGF0aCAgICAgICAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy50c0NvbmZpZ1BhdGgpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5jbGllbnRTY3JpcHRzICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuY2xpZW50U2NyaXB0cykgfHwgdGhpcy5ib290c3RyYXBwZXIuY2xpZW50U2NyaXB0cztcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuZGlzYWJsZU11bHRpcGxlV2luZG93cyA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmRpc2FibGVNdWx0aXBsZVdpbmRvd3MpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5jb21waWxlck9wdGlvbnMgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuY29tcGlsZXJPcHRpb25zKTtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuYnJvd3NlckluaXRUaW1lb3V0ICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmJyb3dzZXJJbml0VGltZW91dCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX3ByZXBhcmVDbGllbnRTY3JpcHRzICh0ZXN0cywgY2xpZW50U2NyaXB0cykge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwodGVzdHMubWFwKGFzeW5jIHRlc3QgPT4ge1xuICAgICAgICAgICAgaWYgKHRlc3QuaXNMZWdhY3kpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICBsZXQgbG9hZGVkVGVzdENsaWVudFNjcmlwdHMgPSBhd2FpdCBsb2FkQ2xpZW50U2NyaXB0cyh0ZXN0LmNsaWVudFNjcmlwdHMsIGRpcm5hbWUodGVzdC50ZXN0RmlsZS5maWxlbmFtZSkpO1xuXG4gICAgICAgICAgICBsb2FkZWRUZXN0Q2xpZW50U2NyaXB0cyA9IGNsaWVudFNjcmlwdHMuY29uY2F0KGxvYWRlZFRlc3RDbGllbnRTY3JpcHRzKTtcblxuICAgICAgICAgICAgdGVzdC5jbGllbnRTY3JpcHRzID0gc2V0VW5pcXVlVXJscyhsb2FkZWRUZXN0Q2xpZW50U2NyaXB0cyk7XG4gICAgICAgIH0pKTtcbiAgICB9XG5cbiAgICAvLyBBUElcbiAgICBlbWJlZGRpbmdPcHRpb25zIChvcHRzKSB7XG4gICAgICAgIGNvbnN0IHsgYXNzZXRzLCBUZXN0UnVuQ3RvciB9ID0gb3B0cztcblxuICAgICAgICB0aGlzLl9yZWdpc3RlckFzc2V0cyhhc3NldHMpO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgVGVzdFJ1bkN0b3IgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgc3JjICguLi5zb3VyY2VzKSB7XG4gICAgICAgIGlmICh0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5zcmMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLnNyYyk7XG5cbiAgICAgICAgc291cmNlcyA9IHRoaXMuX3ByZXBhcmVBcnJheVBhcmFtZXRlcihzb3VyY2VzKTtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IFtPUFRJT05fTkFNRVMuc3JjXTogc291cmNlcyB9KTtcblxuICAgICAgICB0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5zcmMgPSB0cnVlO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGJyb3dzZXJzICguLi5icm93c2Vycykge1xuICAgICAgICBpZiAodGhpcy5hcGlNZXRob2RXYXNDYWxsZWQuYnJvd3NlcnMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLmJyb3dzZXJzKTtcblxuICAgICAgICBicm93c2VycyA9IHRoaXMuX3ByZXBhcmVBcnJheVBhcmFtZXRlcihicm93c2Vycyk7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBicm93c2VycyB9KTtcblxuICAgICAgICB0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5icm93c2VycyA9IHRydWU7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgY29uY3VycmVuY3kgKGNvbmN1cnJlbmN5KSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBjb25jdXJyZW5jeSB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICByZXBvcnRlciAobmFtZSwgb3V0cHV0KSB7XG4gICAgICAgIGlmICh0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5yZXBvcnRlcilcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMubXVsdGlwbGVBUElNZXRob2RDYWxsRm9yYmlkZGVuLCBPUFRJT05fTkFNRVMucmVwb3J0ZXIpO1xuXG4gICAgICAgIGxldCByZXBvcnRlcnMgPSBwcmVwYXJlUmVwb3J0ZXJzKG5hbWUsIG91dHB1dCk7XG5cbiAgICAgICAgcmVwb3J0ZXJzID0gdGhpcy5fcHJlcGFyZUFycmF5UGFyYW1ldGVyKHJlcG9ydGVycyk7XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IFtPUFRJT05fTkFNRVMucmVwb3J0ZXJdOiByZXBvcnRlcnMgfSk7XG5cbiAgICAgICAgdGhpcy5hcGlNZXRob2RXYXNDYWxsZWQucmVwb3J0ZXIgPSB0cnVlO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZpbHRlciAoZmlsdGVyKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBmaWx0ZXIgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdXNlUHJveHkgKHByb3h5LCBwcm94eUJ5cGFzcykge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgcHJveHksIHByb3h5QnlwYXNzIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHNjcmVlbnNob3RzICguLi5vcHRpb25zKSB7XG4gICAgICAgIGxldCBmdWxsUGFnZTtcbiAgICAgICAgbGV0IFtwYXRoLCB0YWtlT25GYWlscywgcGF0aFBhdHRlcm5dID0gb3B0aW9ucztcblxuICAgICAgICBpZiAob3B0aW9ucy5sZW5ndGggPT09IDEgJiYgb3B0aW9uc1swXSAmJiB0eXBlb2Ygb3B0aW9uc1swXSA9PT0gJ29iamVjdCcpXG4gICAgICAgICAgICAoeyBwYXRoLCB0YWtlT25GYWlscywgcGF0aFBhdHRlcm4sIGZ1bGxQYWdlIH0gPSBvcHRpb25zWzBdKTtcblxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgc2NyZWVuc2hvdHM6IHsgcGF0aCwgdGFrZU9uRmFpbHMsIHBhdGhQYXR0ZXJuLCBmdWxsUGFnZSB9IH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHZpZGVvIChwYXRoLCBvcHRpb25zLCBlbmNvZGluZ09wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7XG4gICAgICAgICAgICBbT1BUSU9OX05BTUVTLnZpZGVvUGF0aF06ICAgICAgICAgICAgcGF0aCxcbiAgICAgICAgICAgIFtPUFRJT05fTkFNRVMudmlkZW9PcHRpb25zXTogICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgW09QVElPTl9OQU1FUy52aWRlb0VuY29kaW5nT3B0aW9uc106IGVuY29kaW5nT3B0aW9uc1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBzdGFydEFwcCAoY29tbWFuZCwgaW5pdERlbGF5KSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoe1xuICAgICAgICAgICAgW09QVElPTl9OQU1FUy5hcHBDb21tYW5kXTogICBjb21tYW5kLFxuICAgICAgICAgICAgW09QVElPTl9OQU1FUy5hcHBJbml0RGVsYXldOiBpbml0RGVsYXlcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdHNDb25maWdQYXRoIChwYXRoKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoe1xuICAgICAgICAgICAgW09QVElPTl9OQU1FUy50c0NvbmZpZ1BhdGhdOiBwYXRoXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGNsaWVudFNjcmlwdHMgKC4uLnNjcmlwdHMpIHtcbiAgICAgICAgaWYgKHRoaXMuYXBpTWV0aG9kV2FzQ2FsbGVkLmNsaWVudFNjcmlwdHMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLmNsaWVudFNjcmlwdHMpO1xuXG4gICAgICAgIHNjcmlwdHMgPSB0aGlzLl9wcmVwYXJlQXJyYXlQYXJhbWV0ZXIoc2NyaXB0cyk7XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IFtPUFRJT05fTkFNRVMuY2xpZW50U2NyaXB0c106IHNjcmlwdHMgfSk7XG5cbiAgICAgICAgdGhpcy5hcGlNZXRob2RXYXNDYWxsZWQuY2xpZW50U2NyaXB0cyA9IHRydWU7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgY29tcGlsZXJPcHRpb25zIChvcHRzKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoe1xuICAgICAgICAgICAgW09QVElPTl9OQU1FUy5jb21waWxlck9wdGlvbnNdOiBvcHRzXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHJ1biAob3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHRoaXMuYXBpTWV0aG9kV2FzQ2FsbGVkLnJlc2V0KCk7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMob3B0aW9ucyk7XG4gICAgICAgIHRoaXMuX3NldEJvb3RzdHJhcHBlck9wdGlvbnMoKTtcblxuICAgICAgICBjb25zdCBydW5UYXNrUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLl92YWxpZGF0ZVJ1bk9wdGlvbnMoKSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuX2NyZWF0ZVJ1bm5hYmxlQ29uZmlndXJhdGlvbigpKVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgKHsgcmVwb3J0ZXJQbHVnaW5zLCBicm93c2VyU2V0LCB0ZXN0cywgdGVzdGVkQXBwLCBjb21tb25DbGllbnRTY3JpcHRzIH0pID0+IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9wcmVwYXJlQ2xpZW50U2NyaXB0cyh0ZXN0cywgY29tbW9uQ2xpZW50U2NyaXB0cyk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHRPcHRpb25zID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbnMoKTtcblxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuYm9vdHN0cmFwcGVyLmNvbXBpbGVyU2VydmljZT8uc2V0T3B0aW9ucyh7IHZhbHVlOiByZXN1bHRPcHRpb25zIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3J1blRhc2soeyByZXBvcnRlclBsdWdpbnMsIGJyb3dzZXJTZXQsIHRlc3RzLCB0ZXN0ZWRBcHAsIG9wdGlvbnM6IHJlc3VsdE9wdGlvbnMgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fY3JlYXRlQ2FuY2VsYWJsZVByb21pc2UocnVuVGFza1Byb21pc2UpO1xuICAgIH1cblxuICAgIGFzeW5jIHN0b3AgKCkge1xuICAgICAgICAvLyBOT1RFOiBXaGVuIHRhc2tQcm9taXNlIGlzIGNhbmNlbGxlZCwgaXQgaXMgcmVtb3ZlZCBmcm9tXG4gICAgICAgIC8vIHRoZSBwZW5kaW5nVGFza1Byb21pc2VzIGFycmF5LCB3aGljaCBsZWFkcyB0byBzaGlmdGluZyBpbmRleGVzXG4gICAgICAgIC8vIHRvd2FyZHMgdGhlIGJlZ2lubmluZy4gU28sIHdlIG11c3QgY29weSB0aGUgYXJyYXkgaW4gb3JkZXIgdG8gaXRlcmF0ZSBpdCxcbiAgICAgICAgLy8gb3Igd2UgY2FuIHBlcmZvcm0gaXRlcmF0aW9uIGZyb20gdGhlIGVuZCB0byB0aGUgYmVnaW5uaW5nLlxuICAgICAgICBjb25zdCBjYW5jZWxsYXRpb25Qcm9taXNlcyA9IHRoaXMucGVuZGluZ1Rhc2tQcm9taXNlcy5yZWR1Y2VSaWdodCgocmVzdWx0LCB0YXNrUHJvbWlzZSkgPT4ge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2godGFza1Byb21pc2UuY2FuY2VsKCkpO1xuXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9LCBbXSk7XG5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoY2FuY2VsbGF0aW9uUHJvbWlzZXMpO1xuICAgIH1cbn1cbiJdfQ==
|