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
|
@@ -1,360 +1,360 @@
|
|
|
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
|
-
// TODO: Fix https://github.com/DevExpress/testcafe/issues/4139 to get rid of Pinkie
|
|
7
|
-
const pinkie_1 = __importDefault(require("pinkie"));
|
|
8
|
-
const lodash_1 = require("lodash");
|
|
9
|
-
const get_callsite_1 = require("../../errors/get-callsite");
|
|
10
|
-
const client_function_builder_1 = __importDefault(require("../../client-functions/client-function-builder"));
|
|
11
|
-
const assertion_1 = __importDefault(require("./assertion"));
|
|
12
|
-
const delegated_api_1 = require("../../utils/delegated-api");
|
|
13
|
-
const warning_message_1 = __importDefault(require("../../notifications/warning-message"));
|
|
14
|
-
const get_browser_1 = __importDefault(require("../../utils/get-browser"));
|
|
15
|
-
const add_rendered_warning_1 = __importDefault(require("../../notifications/add-rendered-warning"));
|
|
16
|
-
const callsite_1 = require("../../utils/callsite");
|
|
17
|
-
const deprecated_1 = require("../../notifications/deprecated");
|
|
18
|
-
const actions_1 = require("../../test-run/commands/actions");
|
|
19
|
-
const browser_manipulation_1 = require("../../test-run/commands/browser-manipulation");
|
|
20
|
-
const observation_1 = require("../../test-run/commands/observation");
|
|
21
|
-
const assert_type_1 = __importDefault(require("../request-hooks/assert-type"));
|
|
22
|
-
const execution_context_1 = require("./execution-context");
|
|
23
|
-
const types_1 = require("../../client-functions/types");
|
|
24
|
-
const test_run_1 = require("../../errors/test-run");
|
|
25
|
-
const originalThen = pinkie_1.default.resolve().then;
|
|
26
|
-
class TestController {
|
|
27
|
-
constructor(testRun) {
|
|
28
|
-
this._executionContext = null;
|
|
29
|
-
this.testRun = testRun;
|
|
30
|
-
this.executionChain = pinkie_1.default.resolve();
|
|
31
|
-
this.warningLog = testRun.warningLog;
|
|
32
|
-
}
|
|
33
|
-
// NOTE: we track missing `awaits` by exposing a special custom Promise to user code.
|
|
34
|
-
// Action or assertion is awaited if:
|
|
35
|
-
// a)someone used `await` so Promise's `then` function executed
|
|
36
|
-
// b)Promise chained by using one of the mixed-in controller methods
|
|
37
|
-
//
|
|
38
|
-
// In both scenarios, we check that callsite that produced Promise is equal to the one
|
|
39
|
-
// that is currently missing await. This is required to workaround scenarios like this:
|
|
40
|
-
//
|
|
41
|
-
// var t2 = t.click('#btn1'); // <-- stores new callsiteWithoutAwait
|
|
42
|
-
// await t2; // <-- callsiteWithoutAwait = null
|
|
43
|
-
// t.click('#btn2'); // <-- stores new callsiteWithoutAwait
|
|
44
|
-
// await t2.click('#btn3'); // <-- without check it will set callsiteWithoutAwait = null, so we will lost tracking
|
|
45
|
-
_createExtendedPromise(promise, callsite) {
|
|
46
|
-
const extendedPromise = promise.then(lodash_1.identity);
|
|
47
|
-
const observedCallsites = this.testRun.observedCallsites;
|
|
48
|
-
const markCallsiteAwaited = () => observedCallsites.callsitesWithoutAwait.delete(callsite);
|
|
49
|
-
extendedPromise.then = function () {
|
|
50
|
-
markCallsiteAwaited();
|
|
51
|
-
return originalThen.apply(this, arguments);
|
|
52
|
-
};
|
|
53
|
-
delegated_api_1.delegateAPI(extendedPromise, TestController.API_LIST, {
|
|
54
|
-
handler: this,
|
|
55
|
-
proxyMethod: markCallsiteAwaited
|
|
56
|
-
});
|
|
57
|
-
return extendedPromise;
|
|
58
|
-
}
|
|
59
|
-
_enqueueTask(apiMethodName, createTaskExecutor) {
|
|
60
|
-
const callsite = get_callsite_1.getCallsiteForMethod(apiMethodName);
|
|
61
|
-
const executor = createTaskExecutor(callsite);
|
|
62
|
-
this.executionChain.then = originalThen;
|
|
63
|
-
this.executionChain = this.executionChain.then(executor);
|
|
64
|
-
this.testRun.observedCallsites.callsitesWithoutAwait.add(callsite);
|
|
65
|
-
this.executionChain = this._createExtendedPromise(this.executionChain, callsite);
|
|
66
|
-
return this.executionChain;
|
|
67
|
-
}
|
|
68
|
-
_enqueueCommand(apiMethodName, CmdCtor, cmdArgs) {
|
|
69
|
-
return this._enqueueTask(apiMethodName, callsite => {
|
|
70
|
-
let command = null;
|
|
71
|
-
try {
|
|
72
|
-
command = new CmdCtor(cmdArgs, this.testRun);
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
err.callsite = callsite;
|
|
76
|
-
throw err;
|
|
77
|
-
}
|
|
78
|
-
return () => {
|
|
79
|
-
return this.testRun.executeAction(apiMethodName, command, callsite)
|
|
80
|
-
.catch(err => {
|
|
81
|
-
this.executionChain = pinkie_1.default.resolve();
|
|
82
|
-
throw err;
|
|
83
|
-
});
|
|
84
|
-
};
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
_validateMultipleWindowCommand(apiMethodName) {
|
|
88
|
-
const { disableMultipleWindows, browserConnection } = this.testRun;
|
|
89
|
-
if (disableMultipleWindows)
|
|
90
|
-
throw new test_run_1.MultipleWindowsModeIsDisabledError(apiMethodName);
|
|
91
|
-
if (!browserConnection.activeWindowId)
|
|
92
|
-
throw new test_run_1.MultipleWindowsModeIsNotAvailableInRemoteBrowserError(apiMethodName);
|
|
93
|
-
}
|
|
94
|
-
getExecutionContext() {
|
|
95
|
-
if (!this._executionContext)
|
|
96
|
-
this._executionContext = execution_context_1.createExecutionContext(this.testRun);
|
|
97
|
-
return this._executionContext;
|
|
98
|
-
}
|
|
99
|
-
// API implementation
|
|
100
|
-
// We need implementation methods to obtain correct callsites. If we use plain API
|
|
101
|
-
// methods in chained wrappers then we will have callsite for the wrapped method
|
|
102
|
-
// in this file instead of chained method callsite in user code.
|
|
103
|
-
_ctx$getter() {
|
|
104
|
-
return this.testRun.ctx;
|
|
105
|
-
}
|
|
106
|
-
_ctx$setter(val) {
|
|
107
|
-
this.testRun.ctx = val;
|
|
108
|
-
return this.testRun.ctx;
|
|
109
|
-
}
|
|
110
|
-
_fixtureCtx$getter() {
|
|
111
|
-
return this.testRun.fixtureCtx;
|
|
112
|
-
}
|
|
113
|
-
_browser$getter() {
|
|
114
|
-
return get_browser_1.default(this.testRun.browserConnection);
|
|
115
|
-
}
|
|
116
|
-
_dispatchEvent$(selector, eventName, options = {}) {
|
|
117
|
-
return this._enqueueCommand('dispatchEvent', actions_1.DispatchEventCommand, { selector, eventName, options, relatedTarget: options.relatedTarget });
|
|
118
|
-
}
|
|
119
|
-
_click$(selector, options) {
|
|
120
|
-
return this._enqueueCommand('click', actions_1.ClickCommand, { selector, options });
|
|
121
|
-
}
|
|
122
|
-
_rightClick$(selector, options) {
|
|
123
|
-
return this._enqueueCommand('rightClick', actions_1.RightClickCommand, { selector, options });
|
|
124
|
-
}
|
|
125
|
-
_doubleClick$(selector, options) {
|
|
126
|
-
return this._enqueueCommand('doubleClick', actions_1.DoubleClickCommand, { selector, options });
|
|
127
|
-
}
|
|
128
|
-
_hover$(selector, options) {
|
|
129
|
-
return this._enqueueCommand('hover', actions_1.HoverCommand, { selector, options });
|
|
130
|
-
}
|
|
131
|
-
_drag$(selector, dragOffsetX, dragOffsetY, options) {
|
|
132
|
-
return this._enqueueCommand('drag', actions_1.DragCommand, { selector, dragOffsetX, dragOffsetY, options });
|
|
133
|
-
}
|
|
134
|
-
_dragToElement$(selector, destinationSelector, options) {
|
|
135
|
-
return this._enqueueCommand('dragToElement', actions_1.DragToElementCommand, { selector, destinationSelector, options });
|
|
136
|
-
}
|
|
137
|
-
_getSelectorForScroll(args) {
|
|
138
|
-
const selector = typeof args[0] === 'string' || types_1.isSelector(args[0]) ? args[0] : null;
|
|
139
|
-
if (selector)
|
|
140
|
-
args.shift();
|
|
141
|
-
else
|
|
142
|
-
// NOTE: here we use document.scrollingElement for old Safari versions
|
|
143
|
-
// document.documentElement does not work as expected on Mojave Safari 12.1/ High Sierra Safari 11.1
|
|
144
|
-
// eslint-disable-next-line no-undef
|
|
145
|
-
return () => document.scrollingElement || document.documentElement;
|
|
146
|
-
return selector;
|
|
147
|
-
}
|
|
148
|
-
_getPosition(args) {
|
|
149
|
-
const position = args.length === 1 && typeof args[0] === 'string' ? args[0] : null;
|
|
150
|
-
if (position)
|
|
151
|
-
args.shift();
|
|
152
|
-
return position;
|
|
153
|
-
}
|
|
154
|
-
_scroll$(...args) {
|
|
155
|
-
let position = this._getPosition(args);
|
|
156
|
-
const selector = this._getSelectorForScroll(args);
|
|
157
|
-
let x = void 0;
|
|
158
|
-
let y = void 0;
|
|
159
|
-
let options = void 0;
|
|
160
|
-
if (typeof args[0] === 'string')
|
|
161
|
-
[position, options] = args;
|
|
162
|
-
if (typeof args[0] === 'number')
|
|
163
|
-
[x, y, options] = args;
|
|
164
|
-
return this._enqueueCommand('scroll', actions_1.ScrollCommand, { selector, x, y, position, options });
|
|
165
|
-
}
|
|
166
|
-
_scrollBy$(...args) {
|
|
167
|
-
const selector = this._getSelectorForScroll(args);
|
|
168
|
-
const [byX, byY, options] = args;
|
|
169
|
-
return this._enqueueCommand('scrollBy', actions_1.ScrollByCommand, { selector, byX, byY, options });
|
|
170
|
-
}
|
|
171
|
-
_scrollIntoView$(selector, options) {
|
|
172
|
-
return this._enqueueCommand('scrollIntoView', actions_1.ScrollIntoViewCommand, { selector, options });
|
|
173
|
-
}
|
|
174
|
-
_typeText$(selector, text, options) {
|
|
175
|
-
return this._enqueueCommand('typeText', actions_1.TypeTextCommand, { selector, text, options });
|
|
176
|
-
}
|
|
177
|
-
_selectText$(selector, startPos, endPos, options) {
|
|
178
|
-
return this._enqueueCommand('selectText', actions_1.SelectTextCommand, { selector, startPos, endPos, options });
|
|
179
|
-
}
|
|
180
|
-
_selectTextAreaContent$(selector, startLine, startPos, endLine, endPos, options) {
|
|
181
|
-
return this._enqueueCommand('selectTextAreaContent', actions_1.SelectTextAreaContentCommand, {
|
|
182
|
-
selector,
|
|
183
|
-
startLine,
|
|
184
|
-
startPos,
|
|
185
|
-
endLine,
|
|
186
|
-
endPos,
|
|
187
|
-
options
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
_selectEditableContent$(startSelector, endSelector, options) {
|
|
191
|
-
return this._enqueueCommand('selectEditableContent', actions_1.SelectEditableContentCommand, {
|
|
192
|
-
startSelector,
|
|
193
|
-
endSelector,
|
|
194
|
-
options
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
_pressKey$(keys, options) {
|
|
198
|
-
return this._enqueueCommand('pressKey', actions_1.PressKeyCommand, { keys, options });
|
|
199
|
-
}
|
|
200
|
-
_wait$(timeout) {
|
|
201
|
-
return this._enqueueCommand('wait', observation_1.WaitCommand, { timeout });
|
|
202
|
-
}
|
|
203
|
-
_navigateTo$(url) {
|
|
204
|
-
return this._enqueueCommand('navigateTo', actions_1.NavigateToCommand, { url });
|
|
205
|
-
}
|
|
206
|
-
_setFilesToUpload$(selector, filePath) {
|
|
207
|
-
return this._enqueueCommand('setFilesToUpload', actions_1.SetFilesToUploadCommand, { selector, filePath });
|
|
208
|
-
}
|
|
209
|
-
_clearUpload$(selector) {
|
|
210
|
-
return this._enqueueCommand('clearUpload', actions_1.ClearUploadCommand, { selector });
|
|
211
|
-
}
|
|
212
|
-
_takeScreenshot$(options) {
|
|
213
|
-
if (options && typeof options !== 'object')
|
|
214
|
-
options = { path: options };
|
|
215
|
-
return this._enqueueCommand('takeScreenshot', browser_manipulation_1.TakeScreenshotCommand, options);
|
|
216
|
-
}
|
|
217
|
-
_takeElementScreenshot$(selector, ...args) {
|
|
218
|
-
const commandArgs = { selector };
|
|
219
|
-
if (args[1]) {
|
|
220
|
-
commandArgs.path = args[0];
|
|
221
|
-
commandArgs.options = args[1];
|
|
222
|
-
}
|
|
223
|
-
else if (typeof args[0] === 'object')
|
|
224
|
-
commandArgs.options = args[0];
|
|
225
|
-
else
|
|
226
|
-
commandArgs.path = args[0];
|
|
227
|
-
return this._enqueueCommand('takeElementScreenshot', browser_manipulation_1.TakeElementScreenshotCommand, commandArgs);
|
|
228
|
-
}
|
|
229
|
-
_resizeWindow$(width, height) {
|
|
230
|
-
return this._enqueueCommand('resizeWindow', browser_manipulation_1.ResizeWindowCommand, { width, height });
|
|
231
|
-
}
|
|
232
|
-
_resizeWindowToFitDevice$(device, options) {
|
|
233
|
-
return this._enqueueCommand('resizeWindowToFitDevice', browser_manipulation_1.ResizeWindowToFitDeviceCommand, { device, options });
|
|
234
|
-
}
|
|
235
|
-
_maximizeWindow$() {
|
|
236
|
-
return this._enqueueCommand('maximizeWindow', browser_manipulation_1.MaximizeWindowCommand);
|
|
237
|
-
}
|
|
238
|
-
_switchToIframe$(selector) {
|
|
239
|
-
return this._enqueueCommand('switchToIframe', actions_1.SwitchToIframeCommand, { selector });
|
|
240
|
-
}
|
|
241
|
-
_switchToMainWindow$() {
|
|
242
|
-
return this._enqueueCommand('switchToMainWindow', actions_1.SwitchToMainWindowCommand);
|
|
243
|
-
}
|
|
244
|
-
_openWindow$(url) {
|
|
245
|
-
const apiMethodName = 'openWindow';
|
|
246
|
-
this._validateMultipleWindowCommand(apiMethodName);
|
|
247
|
-
return this._enqueueCommand(apiMethodName, actions_1.OpenWindowCommand, { url });
|
|
248
|
-
}
|
|
249
|
-
_closeWindow$(window) {
|
|
250
|
-
const apiMethodName = 'closeWindow';
|
|
251
|
-
const windowId = (window === null || window === void 0 ? void 0 : window.id) || null;
|
|
252
|
-
this._validateMultipleWindowCommand(apiMethodName);
|
|
253
|
-
return this._enqueueCommand(apiMethodName, actions_1.CloseWindowCommand, { windowId });
|
|
254
|
-
}
|
|
255
|
-
_getCurrentWindow$() {
|
|
256
|
-
const apiMethodName = 'getCurrentWindow';
|
|
257
|
-
this._validateMultipleWindowCommand(apiMethodName);
|
|
258
|
-
return this._enqueueCommand(apiMethodName, actions_1.GetCurrentWindowCommand);
|
|
259
|
-
}
|
|
260
|
-
_switchToWindow$(windowSelector) {
|
|
261
|
-
const apiMethodName = 'switchToWindow';
|
|
262
|
-
this._validateMultipleWindowCommand(apiMethodName);
|
|
263
|
-
let command;
|
|
264
|
-
let args;
|
|
265
|
-
if (typeof windowSelector === 'function') {
|
|
266
|
-
command = actions_1.SwitchToWindowByPredicateCommand;
|
|
267
|
-
args = { findWindow: windowSelector };
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
command = actions_1.SwitchToWindowCommand;
|
|
271
|
-
args = { windowId: windowSelector === null || windowSelector === void 0 ? void 0 : windowSelector.id };
|
|
272
|
-
}
|
|
273
|
-
return this._enqueueCommand(apiMethodName, command, args);
|
|
274
|
-
}
|
|
275
|
-
_switchToParentWindow$() {
|
|
276
|
-
const apiMethodName = 'switchToParentWindow';
|
|
277
|
-
this._validateMultipleWindowCommand(apiMethodName);
|
|
278
|
-
return this._enqueueCommand(apiMethodName, actions_1.SwitchToParentWindowCommand);
|
|
279
|
-
}
|
|
280
|
-
_switchToPreviousWindow$() {
|
|
281
|
-
const apiMethodName = 'switchToPreviousWindow';
|
|
282
|
-
this._validateMultipleWindowCommand(apiMethodName);
|
|
283
|
-
return this._enqueueCommand(apiMethodName, actions_1.SwitchToPreviousWindowCommand);
|
|
284
|
-
}
|
|
285
|
-
_eval$(fn, options) {
|
|
286
|
-
if (!lodash_1.isNil(options))
|
|
287
|
-
options = lodash_1.assign({}, options, { boundTestRun: this });
|
|
288
|
-
const builder = new client_function_builder_1.default(fn, options, { instantiation: 'eval', execution: 'eval' });
|
|
289
|
-
const clientFn = builder.getFunction();
|
|
290
|
-
return clientFn();
|
|
291
|
-
}
|
|
292
|
-
_setNativeDialogHandler$(fn, options) {
|
|
293
|
-
return this._enqueueCommand('setNativeDialogHandler', actions_1.SetNativeDialogHandlerCommand, {
|
|
294
|
-
dialogHandler: { fn, options }
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
_getNativeDialogHistory$() {
|
|
298
|
-
const name = 'getNativeDialogHistory';
|
|
299
|
-
const callsite = get_callsite_1.getCallsiteForMethod(name);
|
|
300
|
-
return this.testRun.executeAction(name, new actions_1.GetNativeDialogHistoryCommand(), callsite);
|
|
301
|
-
}
|
|
302
|
-
_getBrowserConsoleMessages$() {
|
|
303
|
-
const name = 'getBrowserConsoleMessages';
|
|
304
|
-
const callsite = get_callsite_1.getCallsiteForMethod(name);
|
|
305
|
-
return this.testRun.executeAction(name, new actions_1.GetBrowserConsoleMessagesCommand(), callsite);
|
|
306
|
-
}
|
|
307
|
-
_checkForExcessiveAwaits(snapshotPropertyCallsites, checkedCallsite) {
|
|
308
|
-
const callsiteId = callsite_1.getCallsiteId(checkedCallsite);
|
|
309
|
-
// NOTE: If there are unasserted callsites, we should add all of them to awaitedSnapshotWarnings.
|
|
310
|
-
// The warnings themselves are raised after the test run in wrap-test-function
|
|
311
|
-
if (snapshotPropertyCallsites[callsiteId] && !snapshotPropertyCallsites[callsiteId].checked) {
|
|
312
|
-
for (const propertyCallsite of snapshotPropertyCallsites[callsiteId].callsites)
|
|
313
|
-
this.testRun.observedCallsites.awaitedSnapshotWarnings.set(callsite_1.getCallsiteStackFrameString(propertyCallsite), propertyCallsite);
|
|
314
|
-
delete snapshotPropertyCallsites[callsiteId];
|
|
315
|
-
}
|
|
316
|
-
else
|
|
317
|
-
snapshotPropertyCallsites[callsiteId] = { callsites: [], checked: true };
|
|
318
|
-
}
|
|
319
|
-
_expect$(actual) {
|
|
320
|
-
const callsite = get_callsite_1.getCallsiteForMethod('expect');
|
|
321
|
-
this._checkForExcessiveAwaits(this.testRun.observedCallsites.snapshotPropertyCallsites, callsite);
|
|
322
|
-
if (types_1.isClientFunction(actual))
|
|
323
|
-
add_rendered_warning_1.default(this.warningLog, warning_message_1.default.assertedClientFunctionInstance, callsite);
|
|
324
|
-
else if (types_1.isSelector(actual))
|
|
325
|
-
add_rendered_warning_1.default(this.warningLog, warning_message_1.default.assertedSelectorInstance, callsite);
|
|
326
|
-
return new assertion_1.default(actual, this, callsite);
|
|
327
|
-
}
|
|
328
|
-
_debug$() {
|
|
329
|
-
return this._enqueueCommand('debug', observation_1.DebugCommand);
|
|
330
|
-
}
|
|
331
|
-
_setTestSpeed$(speed) {
|
|
332
|
-
return this._enqueueCommand('setTestSpeed', actions_1.SetTestSpeedCommand, { speed });
|
|
333
|
-
}
|
|
334
|
-
_setPageLoadTimeout$(duration) {
|
|
335
|
-
add_rendered_warning_1.default(this.warningLog, deprecated_1.getDeprecationMessage(deprecated_1.DEPRECATED.setPageLoadTimeout));
|
|
336
|
-
return this._enqueueCommand('setPageLoadTimeout', actions_1.SetPageLoadTimeoutCommand, { duration });
|
|
337
|
-
}
|
|
338
|
-
_useRole$(role) {
|
|
339
|
-
return this._enqueueCommand('useRole', actions_1.UseRoleCommand, { role });
|
|
340
|
-
}
|
|
341
|
-
_addRequestHooks$(...hooks) {
|
|
342
|
-
return this._enqueueTask('addRequestHooks', () => {
|
|
343
|
-
hooks = lodash_1.flattenDeep(hooks);
|
|
344
|
-
assert_type_1.default(hooks);
|
|
345
|
-
hooks.forEach(hook => this.testRun.addRequestHook(hook));
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
_removeRequestHooks$(...hooks) {
|
|
349
|
-
return this._enqueueTask('removeRequestHooks', () => {
|
|
350
|
-
hooks = lodash_1.flattenDeep(hooks);
|
|
351
|
-
assert_type_1.default(hooks);
|
|
352
|
-
hooks.forEach(hook => this.testRun.removeRequestHook(hook));
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
exports.default = TestController;
|
|
357
|
-
TestController.API_LIST = delegated_api_1.getDelegatedAPIList(TestController.prototype);
|
|
358
|
-
delegated_api_1.delegateAPI(TestController.prototype, TestController.API_LIST, { useCurrentCtxAsHandler: true });
|
|
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
|
+
// TODO: Fix https://github.com/DevExpress/testcafe/issues/4139 to get rid of Pinkie
|
|
7
|
+
const pinkie_1 = __importDefault(require("pinkie"));
|
|
8
|
+
const lodash_1 = require("lodash");
|
|
9
|
+
const get_callsite_1 = require("../../errors/get-callsite");
|
|
10
|
+
const client_function_builder_1 = __importDefault(require("../../client-functions/client-function-builder"));
|
|
11
|
+
const assertion_1 = __importDefault(require("./assertion"));
|
|
12
|
+
const delegated_api_1 = require("../../utils/delegated-api");
|
|
13
|
+
const warning_message_1 = __importDefault(require("../../notifications/warning-message"));
|
|
14
|
+
const get_browser_1 = __importDefault(require("../../utils/get-browser"));
|
|
15
|
+
const add_rendered_warning_1 = __importDefault(require("../../notifications/add-rendered-warning"));
|
|
16
|
+
const callsite_1 = require("../../utils/callsite");
|
|
17
|
+
const deprecated_1 = require("../../notifications/deprecated");
|
|
18
|
+
const actions_1 = require("../../test-run/commands/actions");
|
|
19
|
+
const browser_manipulation_1 = require("../../test-run/commands/browser-manipulation");
|
|
20
|
+
const observation_1 = require("../../test-run/commands/observation");
|
|
21
|
+
const assert_type_1 = __importDefault(require("../request-hooks/assert-type"));
|
|
22
|
+
const execution_context_1 = require("./execution-context");
|
|
23
|
+
const types_1 = require("../../client-functions/types");
|
|
24
|
+
const test_run_1 = require("../../errors/test-run");
|
|
25
|
+
const originalThen = pinkie_1.default.resolve().then;
|
|
26
|
+
class TestController {
|
|
27
|
+
constructor(testRun) {
|
|
28
|
+
this._executionContext = null;
|
|
29
|
+
this.testRun = testRun;
|
|
30
|
+
this.executionChain = pinkie_1.default.resolve();
|
|
31
|
+
this.warningLog = testRun.warningLog;
|
|
32
|
+
}
|
|
33
|
+
// NOTE: we track missing `awaits` by exposing a special custom Promise to user code.
|
|
34
|
+
// Action or assertion is awaited if:
|
|
35
|
+
// a)someone used `await` so Promise's `then` function executed
|
|
36
|
+
// b)Promise chained by using one of the mixed-in controller methods
|
|
37
|
+
//
|
|
38
|
+
// In both scenarios, we check that callsite that produced Promise is equal to the one
|
|
39
|
+
// that is currently missing await. This is required to workaround scenarios like this:
|
|
40
|
+
//
|
|
41
|
+
// var t2 = t.click('#btn1'); // <-- stores new callsiteWithoutAwait
|
|
42
|
+
// await t2; // <-- callsiteWithoutAwait = null
|
|
43
|
+
// t.click('#btn2'); // <-- stores new callsiteWithoutAwait
|
|
44
|
+
// await t2.click('#btn3'); // <-- without check it will set callsiteWithoutAwait = null, so we will lost tracking
|
|
45
|
+
_createExtendedPromise(promise, callsite) {
|
|
46
|
+
const extendedPromise = promise.then(lodash_1.identity);
|
|
47
|
+
const observedCallsites = this.testRun.observedCallsites;
|
|
48
|
+
const markCallsiteAwaited = () => observedCallsites.callsitesWithoutAwait.delete(callsite);
|
|
49
|
+
extendedPromise.then = function () {
|
|
50
|
+
markCallsiteAwaited();
|
|
51
|
+
return originalThen.apply(this, arguments);
|
|
52
|
+
};
|
|
53
|
+
delegated_api_1.delegateAPI(extendedPromise, TestController.API_LIST, {
|
|
54
|
+
handler: this,
|
|
55
|
+
proxyMethod: markCallsiteAwaited
|
|
56
|
+
});
|
|
57
|
+
return extendedPromise;
|
|
58
|
+
}
|
|
59
|
+
_enqueueTask(apiMethodName, createTaskExecutor) {
|
|
60
|
+
const callsite = get_callsite_1.getCallsiteForMethod(apiMethodName);
|
|
61
|
+
const executor = createTaskExecutor(callsite);
|
|
62
|
+
this.executionChain.then = originalThen;
|
|
63
|
+
this.executionChain = this.executionChain.then(executor);
|
|
64
|
+
this.testRun.observedCallsites.callsitesWithoutAwait.add(callsite);
|
|
65
|
+
this.executionChain = this._createExtendedPromise(this.executionChain, callsite);
|
|
66
|
+
return this.executionChain;
|
|
67
|
+
}
|
|
68
|
+
_enqueueCommand(apiMethodName, CmdCtor, cmdArgs) {
|
|
69
|
+
return this._enqueueTask(apiMethodName, callsite => {
|
|
70
|
+
let command = null;
|
|
71
|
+
try {
|
|
72
|
+
command = new CmdCtor(cmdArgs, this.testRun);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
err.callsite = callsite;
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
78
|
+
return () => {
|
|
79
|
+
return this.testRun.executeAction(apiMethodName, command, callsite)
|
|
80
|
+
.catch(err => {
|
|
81
|
+
this.executionChain = pinkie_1.default.resolve();
|
|
82
|
+
throw err;
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
_validateMultipleWindowCommand(apiMethodName) {
|
|
88
|
+
const { disableMultipleWindows, browserConnection } = this.testRun;
|
|
89
|
+
if (disableMultipleWindows)
|
|
90
|
+
throw new test_run_1.MultipleWindowsModeIsDisabledError(apiMethodName);
|
|
91
|
+
if (!browserConnection.activeWindowId)
|
|
92
|
+
throw new test_run_1.MultipleWindowsModeIsNotAvailableInRemoteBrowserError(apiMethodName);
|
|
93
|
+
}
|
|
94
|
+
getExecutionContext() {
|
|
95
|
+
if (!this._executionContext)
|
|
96
|
+
this._executionContext = execution_context_1.createExecutionContext(this.testRun);
|
|
97
|
+
return this._executionContext;
|
|
98
|
+
}
|
|
99
|
+
// API implementation
|
|
100
|
+
// We need implementation methods to obtain correct callsites. If we use plain API
|
|
101
|
+
// methods in chained wrappers then we will have callsite for the wrapped method
|
|
102
|
+
// in this file instead of chained method callsite in user code.
|
|
103
|
+
_ctx$getter() {
|
|
104
|
+
return this.testRun.ctx;
|
|
105
|
+
}
|
|
106
|
+
_ctx$setter(val) {
|
|
107
|
+
this.testRun.ctx = val;
|
|
108
|
+
return this.testRun.ctx;
|
|
109
|
+
}
|
|
110
|
+
_fixtureCtx$getter() {
|
|
111
|
+
return this.testRun.fixtureCtx;
|
|
112
|
+
}
|
|
113
|
+
_browser$getter() {
|
|
114
|
+
return get_browser_1.default(this.testRun.browserConnection);
|
|
115
|
+
}
|
|
116
|
+
_dispatchEvent$(selector, eventName, options = {}) {
|
|
117
|
+
return this._enqueueCommand('dispatchEvent', actions_1.DispatchEventCommand, { selector, eventName, options, relatedTarget: options.relatedTarget });
|
|
118
|
+
}
|
|
119
|
+
_click$(selector, options) {
|
|
120
|
+
return this._enqueueCommand('click', actions_1.ClickCommand, { selector, options });
|
|
121
|
+
}
|
|
122
|
+
_rightClick$(selector, options) {
|
|
123
|
+
return this._enqueueCommand('rightClick', actions_1.RightClickCommand, { selector, options });
|
|
124
|
+
}
|
|
125
|
+
_doubleClick$(selector, options) {
|
|
126
|
+
return this._enqueueCommand('doubleClick', actions_1.DoubleClickCommand, { selector, options });
|
|
127
|
+
}
|
|
128
|
+
_hover$(selector, options) {
|
|
129
|
+
return this._enqueueCommand('hover', actions_1.HoverCommand, { selector, options });
|
|
130
|
+
}
|
|
131
|
+
_drag$(selector, dragOffsetX, dragOffsetY, options) {
|
|
132
|
+
return this._enqueueCommand('drag', actions_1.DragCommand, { selector, dragOffsetX, dragOffsetY, options });
|
|
133
|
+
}
|
|
134
|
+
_dragToElement$(selector, destinationSelector, options) {
|
|
135
|
+
return this._enqueueCommand('dragToElement', actions_1.DragToElementCommand, { selector, destinationSelector, options });
|
|
136
|
+
}
|
|
137
|
+
_getSelectorForScroll(args) {
|
|
138
|
+
const selector = typeof args[0] === 'string' || types_1.isSelector(args[0]) ? args[0] : null;
|
|
139
|
+
if (selector)
|
|
140
|
+
args.shift();
|
|
141
|
+
else
|
|
142
|
+
// NOTE: here we use document.scrollingElement for old Safari versions
|
|
143
|
+
// document.documentElement does not work as expected on Mojave Safari 12.1/ High Sierra Safari 11.1
|
|
144
|
+
// eslint-disable-next-line no-undef
|
|
145
|
+
return () => document.scrollingElement || document.documentElement;
|
|
146
|
+
return selector;
|
|
147
|
+
}
|
|
148
|
+
_getPosition(args) {
|
|
149
|
+
const position = args.length === 1 && typeof args[0] === 'string' ? args[0] : null;
|
|
150
|
+
if (position)
|
|
151
|
+
args.shift();
|
|
152
|
+
return position;
|
|
153
|
+
}
|
|
154
|
+
_scroll$(...args) {
|
|
155
|
+
let position = this._getPosition(args);
|
|
156
|
+
const selector = this._getSelectorForScroll(args);
|
|
157
|
+
let x = void 0;
|
|
158
|
+
let y = void 0;
|
|
159
|
+
let options = void 0;
|
|
160
|
+
if (typeof args[0] === 'string')
|
|
161
|
+
[position, options] = args;
|
|
162
|
+
if (typeof args[0] === 'number')
|
|
163
|
+
[x, y, options] = args;
|
|
164
|
+
return this._enqueueCommand('scroll', actions_1.ScrollCommand, { selector, x, y, position, options });
|
|
165
|
+
}
|
|
166
|
+
_scrollBy$(...args) {
|
|
167
|
+
const selector = this._getSelectorForScroll(args);
|
|
168
|
+
const [byX, byY, options] = args;
|
|
169
|
+
return this._enqueueCommand('scrollBy', actions_1.ScrollByCommand, { selector, byX, byY, options });
|
|
170
|
+
}
|
|
171
|
+
_scrollIntoView$(selector, options) {
|
|
172
|
+
return this._enqueueCommand('scrollIntoView', actions_1.ScrollIntoViewCommand, { selector, options });
|
|
173
|
+
}
|
|
174
|
+
_typeText$(selector, text, options) {
|
|
175
|
+
return this._enqueueCommand('typeText', actions_1.TypeTextCommand, { selector, text, options });
|
|
176
|
+
}
|
|
177
|
+
_selectText$(selector, startPos, endPos, options) {
|
|
178
|
+
return this._enqueueCommand('selectText', actions_1.SelectTextCommand, { selector, startPos, endPos, options });
|
|
179
|
+
}
|
|
180
|
+
_selectTextAreaContent$(selector, startLine, startPos, endLine, endPos, options) {
|
|
181
|
+
return this._enqueueCommand('selectTextAreaContent', actions_1.SelectTextAreaContentCommand, {
|
|
182
|
+
selector,
|
|
183
|
+
startLine,
|
|
184
|
+
startPos,
|
|
185
|
+
endLine,
|
|
186
|
+
endPos,
|
|
187
|
+
options
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
_selectEditableContent$(startSelector, endSelector, options) {
|
|
191
|
+
return this._enqueueCommand('selectEditableContent', actions_1.SelectEditableContentCommand, {
|
|
192
|
+
startSelector,
|
|
193
|
+
endSelector,
|
|
194
|
+
options
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
_pressKey$(keys, options) {
|
|
198
|
+
return this._enqueueCommand('pressKey', actions_1.PressKeyCommand, { keys, options });
|
|
199
|
+
}
|
|
200
|
+
_wait$(timeout) {
|
|
201
|
+
return this._enqueueCommand('wait', observation_1.WaitCommand, { timeout });
|
|
202
|
+
}
|
|
203
|
+
_navigateTo$(url) {
|
|
204
|
+
return this._enqueueCommand('navigateTo', actions_1.NavigateToCommand, { url });
|
|
205
|
+
}
|
|
206
|
+
_setFilesToUpload$(selector, filePath) {
|
|
207
|
+
return this._enqueueCommand('setFilesToUpload', actions_1.SetFilesToUploadCommand, { selector, filePath });
|
|
208
|
+
}
|
|
209
|
+
_clearUpload$(selector) {
|
|
210
|
+
return this._enqueueCommand('clearUpload', actions_1.ClearUploadCommand, { selector });
|
|
211
|
+
}
|
|
212
|
+
_takeScreenshot$(options) {
|
|
213
|
+
if (options && typeof options !== 'object')
|
|
214
|
+
options = { path: options };
|
|
215
|
+
return this._enqueueCommand('takeScreenshot', browser_manipulation_1.TakeScreenshotCommand, options);
|
|
216
|
+
}
|
|
217
|
+
_takeElementScreenshot$(selector, ...args) {
|
|
218
|
+
const commandArgs = { selector };
|
|
219
|
+
if (args[1]) {
|
|
220
|
+
commandArgs.path = args[0];
|
|
221
|
+
commandArgs.options = args[1];
|
|
222
|
+
}
|
|
223
|
+
else if (typeof args[0] === 'object')
|
|
224
|
+
commandArgs.options = args[0];
|
|
225
|
+
else
|
|
226
|
+
commandArgs.path = args[0];
|
|
227
|
+
return this._enqueueCommand('takeElementScreenshot', browser_manipulation_1.TakeElementScreenshotCommand, commandArgs);
|
|
228
|
+
}
|
|
229
|
+
_resizeWindow$(width, height) {
|
|
230
|
+
return this._enqueueCommand('resizeWindow', browser_manipulation_1.ResizeWindowCommand, { width, height });
|
|
231
|
+
}
|
|
232
|
+
_resizeWindowToFitDevice$(device, options) {
|
|
233
|
+
return this._enqueueCommand('resizeWindowToFitDevice', browser_manipulation_1.ResizeWindowToFitDeviceCommand, { device, options });
|
|
234
|
+
}
|
|
235
|
+
_maximizeWindow$() {
|
|
236
|
+
return this._enqueueCommand('maximizeWindow', browser_manipulation_1.MaximizeWindowCommand);
|
|
237
|
+
}
|
|
238
|
+
_switchToIframe$(selector) {
|
|
239
|
+
return this._enqueueCommand('switchToIframe', actions_1.SwitchToIframeCommand, { selector });
|
|
240
|
+
}
|
|
241
|
+
_switchToMainWindow$() {
|
|
242
|
+
return this._enqueueCommand('switchToMainWindow', actions_1.SwitchToMainWindowCommand);
|
|
243
|
+
}
|
|
244
|
+
_openWindow$(url) {
|
|
245
|
+
const apiMethodName = 'openWindow';
|
|
246
|
+
this._validateMultipleWindowCommand(apiMethodName);
|
|
247
|
+
return this._enqueueCommand(apiMethodName, actions_1.OpenWindowCommand, { url });
|
|
248
|
+
}
|
|
249
|
+
_closeWindow$(window) {
|
|
250
|
+
const apiMethodName = 'closeWindow';
|
|
251
|
+
const windowId = (window === null || window === void 0 ? void 0 : window.id) || null;
|
|
252
|
+
this._validateMultipleWindowCommand(apiMethodName);
|
|
253
|
+
return this._enqueueCommand(apiMethodName, actions_1.CloseWindowCommand, { windowId });
|
|
254
|
+
}
|
|
255
|
+
_getCurrentWindow$() {
|
|
256
|
+
const apiMethodName = 'getCurrentWindow';
|
|
257
|
+
this._validateMultipleWindowCommand(apiMethodName);
|
|
258
|
+
return this._enqueueCommand(apiMethodName, actions_1.GetCurrentWindowCommand);
|
|
259
|
+
}
|
|
260
|
+
_switchToWindow$(windowSelector) {
|
|
261
|
+
const apiMethodName = 'switchToWindow';
|
|
262
|
+
this._validateMultipleWindowCommand(apiMethodName);
|
|
263
|
+
let command;
|
|
264
|
+
let args;
|
|
265
|
+
if (typeof windowSelector === 'function') {
|
|
266
|
+
command = actions_1.SwitchToWindowByPredicateCommand;
|
|
267
|
+
args = { findWindow: windowSelector };
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
command = actions_1.SwitchToWindowCommand;
|
|
271
|
+
args = { windowId: windowSelector === null || windowSelector === void 0 ? void 0 : windowSelector.id };
|
|
272
|
+
}
|
|
273
|
+
return this._enqueueCommand(apiMethodName, command, args);
|
|
274
|
+
}
|
|
275
|
+
_switchToParentWindow$() {
|
|
276
|
+
const apiMethodName = 'switchToParentWindow';
|
|
277
|
+
this._validateMultipleWindowCommand(apiMethodName);
|
|
278
|
+
return this._enqueueCommand(apiMethodName, actions_1.SwitchToParentWindowCommand);
|
|
279
|
+
}
|
|
280
|
+
_switchToPreviousWindow$() {
|
|
281
|
+
const apiMethodName = 'switchToPreviousWindow';
|
|
282
|
+
this._validateMultipleWindowCommand(apiMethodName);
|
|
283
|
+
return this._enqueueCommand(apiMethodName, actions_1.SwitchToPreviousWindowCommand);
|
|
284
|
+
}
|
|
285
|
+
_eval$(fn, options) {
|
|
286
|
+
if (!lodash_1.isNil(options))
|
|
287
|
+
options = lodash_1.assign({}, options, { boundTestRun: this });
|
|
288
|
+
const builder = new client_function_builder_1.default(fn, options, { instantiation: 'eval', execution: 'eval' });
|
|
289
|
+
const clientFn = builder.getFunction();
|
|
290
|
+
return clientFn();
|
|
291
|
+
}
|
|
292
|
+
_setNativeDialogHandler$(fn, options) {
|
|
293
|
+
return this._enqueueCommand('setNativeDialogHandler', actions_1.SetNativeDialogHandlerCommand, {
|
|
294
|
+
dialogHandler: { fn, options }
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
_getNativeDialogHistory$() {
|
|
298
|
+
const name = 'getNativeDialogHistory';
|
|
299
|
+
const callsite = get_callsite_1.getCallsiteForMethod(name);
|
|
300
|
+
return this.testRun.executeAction(name, new actions_1.GetNativeDialogHistoryCommand(), callsite);
|
|
301
|
+
}
|
|
302
|
+
_getBrowserConsoleMessages$() {
|
|
303
|
+
const name = 'getBrowserConsoleMessages';
|
|
304
|
+
const callsite = get_callsite_1.getCallsiteForMethod(name);
|
|
305
|
+
return this.testRun.executeAction(name, new actions_1.GetBrowserConsoleMessagesCommand(), callsite);
|
|
306
|
+
}
|
|
307
|
+
_checkForExcessiveAwaits(snapshotPropertyCallsites, checkedCallsite) {
|
|
308
|
+
const callsiteId = callsite_1.getCallsiteId(checkedCallsite);
|
|
309
|
+
// NOTE: If there are unasserted callsites, we should add all of them to awaitedSnapshotWarnings.
|
|
310
|
+
// The warnings themselves are raised after the test run in wrap-test-function
|
|
311
|
+
if (snapshotPropertyCallsites[callsiteId] && !snapshotPropertyCallsites[callsiteId].checked) {
|
|
312
|
+
for (const propertyCallsite of snapshotPropertyCallsites[callsiteId].callsites)
|
|
313
|
+
this.testRun.observedCallsites.awaitedSnapshotWarnings.set(callsite_1.getCallsiteStackFrameString(propertyCallsite), propertyCallsite);
|
|
314
|
+
delete snapshotPropertyCallsites[callsiteId];
|
|
315
|
+
}
|
|
316
|
+
else
|
|
317
|
+
snapshotPropertyCallsites[callsiteId] = { callsites: [], checked: true };
|
|
318
|
+
}
|
|
319
|
+
_expect$(actual) {
|
|
320
|
+
const callsite = get_callsite_1.getCallsiteForMethod('expect');
|
|
321
|
+
this._checkForExcessiveAwaits(this.testRun.observedCallsites.snapshotPropertyCallsites, callsite);
|
|
322
|
+
if (types_1.isClientFunction(actual))
|
|
323
|
+
add_rendered_warning_1.default(this.warningLog, warning_message_1.default.assertedClientFunctionInstance, callsite);
|
|
324
|
+
else if (types_1.isSelector(actual))
|
|
325
|
+
add_rendered_warning_1.default(this.warningLog, warning_message_1.default.assertedSelectorInstance, callsite);
|
|
326
|
+
return new assertion_1.default(actual, this, callsite);
|
|
327
|
+
}
|
|
328
|
+
_debug$() {
|
|
329
|
+
return this._enqueueCommand('debug', observation_1.DebugCommand);
|
|
330
|
+
}
|
|
331
|
+
_setTestSpeed$(speed) {
|
|
332
|
+
return this._enqueueCommand('setTestSpeed', actions_1.SetTestSpeedCommand, { speed });
|
|
333
|
+
}
|
|
334
|
+
_setPageLoadTimeout$(duration) {
|
|
335
|
+
add_rendered_warning_1.default(this.warningLog, deprecated_1.getDeprecationMessage(deprecated_1.DEPRECATED.setPageLoadTimeout));
|
|
336
|
+
return this._enqueueCommand('setPageLoadTimeout', actions_1.SetPageLoadTimeoutCommand, { duration });
|
|
337
|
+
}
|
|
338
|
+
_useRole$(role) {
|
|
339
|
+
return this._enqueueCommand('useRole', actions_1.UseRoleCommand, { role });
|
|
340
|
+
}
|
|
341
|
+
_addRequestHooks$(...hooks) {
|
|
342
|
+
return this._enqueueTask('addRequestHooks', () => {
|
|
343
|
+
hooks = lodash_1.flattenDeep(hooks);
|
|
344
|
+
assert_type_1.default(hooks);
|
|
345
|
+
hooks.forEach(hook => this.testRun.addRequestHook(hook));
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
_removeRequestHooks$(...hooks) {
|
|
349
|
+
return this._enqueueTask('removeRequestHooks', () => {
|
|
350
|
+
hooks = lodash_1.flattenDeep(hooks);
|
|
351
|
+
assert_type_1.default(hooks);
|
|
352
|
+
hooks.forEach(hook => this.testRun.removeRequestHook(hook));
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
exports.default = TestController;
|
|
357
|
+
TestController.API_LIST = delegated_api_1.getDelegatedAPIList(TestController.prototype);
|
|
358
|
+
delegated_api_1.delegateAPI(TestController.prototype, TestController.API_LIST, { useCurrentCtxAsHandler: true });
|
|
359
359
|
module.exports = exports.default;
|
|
360
360
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBpL3Rlc3QtY29udHJvbGxlci9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9GQUFvRjtBQUNwRixvREFBNkI7QUFDN0IsbUNBS2dCO0FBRWhCLDREQUFpRTtBQUNqRSw2R0FBbUY7QUFDbkYsNERBQW9DO0FBQ3BDLDZEQUE2RTtBQUM3RSwwRkFBa0U7QUFDbEUsMEVBQWlEO0FBQ2pELG9HQUFrRTtBQUNsRSxtREFBa0Y7QUFDbEYsK0RBQW1GO0FBRW5GLDZEQWtDeUM7QUFFekMsdUZBTXNEO0FBRXRELHFFQUFnRjtBQUNoRiwrRUFBaUU7QUFDakUsMkRBQThFO0FBQzlFLHdEQUE0RTtBQUU1RSxvREFHK0I7QUFFL0IsTUFBTSxZQUFZLEdBQUcsZ0JBQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUM7QUFFNUMsTUFBcUIsY0FBYztJQUMvQixZQUFhLE9BQU87UUFDaEIsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztRQUU5QixJQUFJLENBQUMsT0FBTyxHQUFpQixPQUFPLENBQUM7UUFDckMsSUFBSSxDQUFDLGNBQWMsR0FBVSxnQkFBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQy9DLElBQUksQ0FBQyxVQUFVLEdBQWMsT0FBTyxDQUFDLFVBQVUsQ0FBQztJQUNwRCxDQUFDO0lBRUQscUZBQXFGO0lBQ3JGLHFDQUFxQztJQUNyQywrREFBK0Q7SUFDL0Qsb0VBQW9FO0lBQ3BFLEVBQUU7SUFDRixzRkFBc0Y7SUFDdEYsdUZBQXVGO0lBQ3ZGLEVBQUU7SUFDRixvRUFBb0U7SUFDcEUsZ0VBQWdFO0lBQ2hFLG9FQUFvRTtJQUNwRSxvSEFBb0g7SUFDcEgsc0JBQXNCLENBQUUsT0FBTyxFQUFFLFFBQVE7UUFDckMsTUFBTSxlQUFlLEdBQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxpQkFBUSxDQUFDLENBQUM7UUFDbkQsTUFB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RUFBRSx3QkFBYyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRUQsaUJBQWlCLENBQUUsR0FBRyxLQUFLO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLEVBQUU7WUFDN0MsS0FBSyxHQUFHLG9CQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFdkIscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFN0IsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDN0QsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsb0JBQW9CLENBQUUsR0FBRyxLQUFLO1FBQzFCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUU7WUFDaEQsS0FBSyxHQUFHLG9CQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFdkIscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFN0IsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNoRSxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7Q0FDSjtBQTViRCxpQ0E0YkM7QUFFRCxjQUFjLENBQUMsUUFBUSxHQUFHLG1DQUFtQixDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUV4RSwyQkFBVyxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsY0FBYyxDQUFDLFFBQVEsRUFBRSxFQUFFLHNCQUFzQixFQUFFLElBQUksRUFBRSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUT0RPOiBGaXggaHR0cHM6Ly9naXRodWIuY29tL0RldkV4cHJlc3MvdGVzdGNhZmUvaXNzdWVzLzQxMzkgdG8gZ2V0IHJpZCBvZiBQaW5raWVcbmltcG9ydCBQcm9taXNlIGZyb20gJ3BpbmtpZSc7XG5pbXBvcnQge1xuICAgIGlkZW50aXR5LFxuICAgIGFzc2lnbixcbiAgICBpc05pbCBhcyBpc051bGxPclVuZGVmaW5lZCxcbiAgICBmbGF0dGVuRGVlcCBhcyBmbGF0dGVuXG59IGZyb20gJ2xvZGFzaCc7XG5cbmltcG9ydCB7IGdldENhbGxzaXRlRm9yTWV0aG9kIH0gZnJvbSAnLi4vLi4vZXJyb3JzL2dldC1jYWxsc2l0ZSc7XG5pbXBvcnQgQ2xpZW50RnVuY3Rpb25CdWlsZGVyIGZyb20gJy4uLy4uL2NsaWVudC1mdW5jdGlvbnMvY2xpZW50LWZ1bmN0aW9uLWJ1aWxkZXInO1xuaW1wb3J0IEFzc2VydGlvbiBmcm9tICcuL2Fzc2VydGlvbic7XG5pbXBvcnQgeyBnZXREZWxlZ2F0ZWRBUElMaXN0LCBkZWxlZ2F0ZUFQSSB9IGZyb20gJy4uLy4uL3V0aWxzL2RlbGVnYXRlZC1hcGknO1xuaW1wb3J0IFdBUk5JTkdfTUVTU0FHRSBmcm9tICcuLi8uLi9ub3RpZmljYXRpb25zL3dhcm5pbmctbWVzc2FnZSc7XG5pbXBvcnQgZ2V0QnJvd3NlciBmcm9tICcuLi8uLi91dGlscy9nZXQtYnJvd3Nlcic7XG5pbXBvcnQgYWRkV2FybmluZyBmcm9tICcuLi8uLi9ub3RpZmljYXRpb25zL2FkZC1yZW5kZXJlZC13YXJuaW5nJztcbmltcG9ydCB7IGdldENhbGxzaXRlSWQsIGdldENhbGxzaXRlU3RhY2tGcmFtZVN0cmluZyB9IGZyb20gJy4uLy4uL3V0aWxzL2NhbGxzaXRlJztcbmltcG9ydCB7IGdldERlcHJlY2F0aW9uTWVzc2FnZSwgREVQUkVDQVRFRCB9IGZyb20gJy4uLy4uL25vdGlmaWNhdGlvbnMvZGVwcmVjYXRlZCc7XG5cbmltcG9ydCB7XG4gICAgQ2xpY2tDb21tYW5kLFxuICAgIFJpZ2h0Q2xpY2tDb21tYW5kLFxuICAgIERvdWJsZUNsaWNrQ29tbWFuZCxcbiAgICBIb3ZlckNvbW1hbmQsXG4gICAgRHJhZ0NvbW1hbmQsXG4gICAgRHJhZ1RvRWxlbWVudENvbW1hbmQsXG4gICAgVHlwZVRleHRDb21tYW5kLFxuICAgIFNlbGVjdFRleHRDb21tYW5kLFxuICAgIFNlbGVjdFRleHRBcmVhQ29udGVudENvbW1hbmQsXG4gICAgU2VsZWN0RWRpdGFibGVDb250ZW50Q29tbWFuZCxcbiAgICBQcmVzc0tleUNvbW1hbmQsXG4gICAgTmF2aWdhdGVUb0NvbW1hbmQsXG4gICAgU2V0RmlsZXNUb1VwbG9hZENvbW1hbmQsXG4gICAgQ2xlYXJVcGxvYWRDb21tYW5kLFxuICAgIFN3aXRjaFRvSWZyYW1lQ29tbWFuZCxcbiAgICBTd2l0Y2hUb01haW5XaW5kb3dDb21tYW5kLFxuICAgIE9wZW5XaW5kb3dDb21tYW5kLFxuICAgIENsb3NlV2luZG93Q29tbWFuZCxcbiAgICBHZXRDdXJyZW50V2luZG93Q29tbWFuZCxcbiAgICBTd2l0Y2hUb1dpbmRvd0NvbW1hbmQsXG4gICAgU3dpdGNoVG9XaW5kb3dCeVByZWRpY2F0ZUNvbW1hbmQsXG4gICAgU3dpdGNoVG9QYXJlbnRXaW5kb3dDb21tYW5kLFxuICAgIFN3aXRjaFRvUHJldmlvdXNXaW5kb3dDb21tYW5kLFxuICAgIFNldE5hdGl2ZURpYWxvZ0hhbmRsZXJDb21tYW5kLFxuICAgIEdldE5hdGl2ZURpYWxvZ0hpc3RvcnlDb21tYW5kLFxuICAgIEdldEJyb3dzZXJDb25zb2xlTWVzc2FnZXNDb21tYW5kLFxuICAgIFNldFRlc3RTcGVlZENvbW1hbmQsXG4gICAgU2V0UGFnZUxvYWRUaW1lb3V0Q29tbWFuZCxcbiAgICBTY3JvbGxDb21tYW5kLFxuICAgIFNjcm9sbEJ5Q29tbWFuZCxcbiAgICBTY3JvbGxJbnRvVmlld0NvbW1hbmQsXG4gICAgVXNlUm9sZUNvbW1hbmQsXG4gICAgRGlzcGF0Y2hFdmVudENvbW1hbmRcbn0gZnJvbSAnLi4vLi4vdGVzdC1ydW4vY29tbWFuZHMvYWN0aW9ucyc7XG5cbmltcG9ydCB7XG4gICAgVGFrZVNjcmVlbnNob3RDb21tYW5kLFxuICAgIFRha2VFbGVtZW50U2NyZWVuc2hvdENvbW1hbmQsXG4gICAgUmVzaXplV2luZG93Q29tbWFuZCxcbiAgICBSZXNpemVXaW5kb3dUb0ZpdERldmljZUNvbW1hbmQsXG4gICAgTWF4aW1pemVXaW5kb3dDb21tYW5kXG59IGZyb20gJy4uLy4uL3Rlc3QtcnVuL2NvbW1hbmRzL2Jyb3dzZXItbWFuaXB1bGF0aW9uJztcblxuaW1wb3J0IHsgV2FpdENvbW1hbmQsIERlYnVnQ29tbWFuZCB9IGZyb20gJy4uLy4uL3Rlc3QtcnVuL2NvbW1hbmRzL29ic2VydmF0aW9uJztcbmltcG9ydCBhc3NlcnRSZXF1ZXN0SG9va1R5cGUgZnJvbSAnLi4vcmVxdWVzdC1ob29rcy9hc3NlcnQtdHlwZSc7XG5pbXBvcnQgeyBjcmVhdGVFeGVjdXRpb25Db250ZXh0IGFzIGNyZWF0ZUNvbnRleHQgfSBmcm9tICcuL2V4ZWN1dGlvbi1jb250ZXh0JztcbmltcG9ydCB7IGlzQ2xpZW50RnVuY3Rpb24sIGlzU2VsZWN0b3IgfSBmcm9tICcuLi8uLi9jbGllbnQtZnVuY3Rpb25zL3R5cGVzJztcblxuaW1wb3J0IHtcbiAgICBNdWx0aXBsZVdpbmRvd3NNb2RlSXNEaXNhYmxlZEVycm9yLFxuICAgIE11bHRpcGxlV2luZG93c01vZGVJc05vdEF2YWlsYWJsZUluUmVtb3RlQnJvd3NlckVycm9yXG59IGZyb20gJy4uLy4uL2Vycm9ycy90ZXN0LXJ1bic7XG5cbmNvbnN0IG9yaWdpbmFsVGhlbiA9IFByb21pc2UucmVzb2x2ZSgpLnRoZW47XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRlc3RDb250cm9sbGVyIHtcbiAgICBjb25zdHJ1Y3RvciAodGVzdFJ1bikge1xuICAgICAgICB0aGlzLl9leGVjdXRpb25Db250ZXh0ID0gbnVsbDtcblxuICAgICAgICB0aGlzLnRlc3RSdW4gICAgICAgICAgICAgICA9IHRlc3RSdW47XG4gICAgICAgIHRoaXMuZXhlY3V0aW9uQ2hhaW4gICAgICAgID0gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIHRoaXMud2FybmluZ0xvZyAgICAgICAgICAgID0gdGVzdFJ1bi53YXJuaW5nTG9nO1xuICAgIH1cblxuICAgIC8vIE5PVEU6IHdlIHRyYWNrIG1pc3NpbmcgYGF3YWl0c2AgYnkgZXhwb3NpbmcgYSBzcGVjaWFsIGN1c3RvbSBQcm9taXNlIHRvIHVzZXIgY29kZS5cbiAgICAvLyBBY3Rpb24gb3IgYXNzZXJ0aW9uIGlzIGF3YWl0ZWQgaWY6XG4gICAgLy8gYSlzb21lb25lIHVzZWQgYGF3YWl0YCBzbyBQcm9taXNlJ3MgYHRoZW5gIGZ1bmN0aW9uIGV4ZWN1dGVkXG4gICAgLy8gYilQcm9taXNlIGNoYWluZWQgYnkgdXNpbmcgb25lIG9mIHRoZSBtaXhlZC1pbiBjb250cm9sbGVyIG1ldGhvZHNcbiAgICAvL1xuICAgIC8vIEluIGJvdGggc2NlbmFyaW9zLCB3ZSBjaGVjayB0aGF0IGNhbGxzaXRlIHRoYXQgcHJvZHVjZWQgUHJvbWlzZSBpcyBlcXVhbCB0byB0aGUgb25lXG4gICAgLy8gdGhhdCBpcyBjdXJyZW50bHkgbWlzc2luZyBhd2FpdC4gVGhpcyBpcyByZXF1aXJlZCB0byB3b3JrYXJvdW5kIHNjZW5hcmlvcyBsaWtlIHRoaXM6XG4gICAgLy9cbiAgICAvLyB2YXIgdDIgPSB0LmNsaWNrKCcjYnRuMScpOyAvLyA8LS0gc3RvcmVzIG5ldyBjYWxsc2l0ZVdpdGhvdXRBd2FpdFxuICAgIC8vIGF3YWl0IHQyOyAgICAgICAgICAgICAgICAgIC8vIDwtLSBjYWxsc2l0ZVdpdGhvdXRBd2FpdCA9IG51bGxcbiAgICAvLyB0LmNsaWNrKCcjYnRuMicpOyAgICAgICAgICAvLyA8LS0gc3RvcmVzIG5ldyBjYWxsc2l0ZVdpdGhvdXRBd2FpdFxuICAgIC8vIGF3YWl0IHQyLmNsaWNrKCcjYnRuMycpOyAgIC8vIDwtLSB3aXRob3V0IGNoZWNrIGl0IHdpbGwgc2V0IGNhbGxzaXRlV2l0aG91dEF3YWl0ID0gbnVsbCwgc28gd2Ugd2lsbCBsb3N0IHRyYWNraW5nXG4gICAgX2NyZWF0ZUV4dGVuZGVkUHJvbWlzZSAocHJvbWlzZSwgY2FsbHNpdGUpIHtcbiAgICAgICAgY29uc3QgZXh0ZW5kZWRQcm9taXNlICAgICA9IHByb21pc2UudGhlbihpZGVudGl0eSk7XG4gICAgICAgIGNvbnN0IG9ic2VydmVkQ2FsbHNpdGVzICAgPSB0aGlzLnRlc3RSdW4ub2JzZXJ2ZWRDYWxsc2l0ZXM7XG4gICAgICAgIGNvbnN0IG1hcmtDYWxsc2l0ZUF3YWl0ZWQgPSAoKSA9PiBvYnNlcnZlZENhbGxzaXRlcy5jYWxsc2l0ZXNXaXRob3V0QXdhaXQuZGVsZXRlKGNhbGxzaXRlKTtcblxuICAgICAgICBleHRlbmRlZFByb21pc2UudGhlbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIG1hcmtDYWxsc2l0ZUF3YWl0ZWQoKTtcblxuICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsVGhlbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGRlbGVnYXRlQVBJKGV4dGVuZGVkUHJvbWlzZSwgVGVzdENvbnRyb2xsZXIuQVBJX0xJU1QsIHtcbiAgICAgICAgICAgIGhhbmRsZXI6ICAgICB0aGlzLFxuICAgICAgICAgICAgcHJveHlNZXRob2Q6IG1hcmtDYWxsc2l0ZUF3YWl0ZWRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGV4dGVuZGVkUHJvbWlzZTtcbiAgICB9XG5cbiAgICBfZW5xdWV1ZVRhc2sgKGFwaU1ldGhvZE5hbWUsIGNyZWF0ZVRhc2tFeGVjdXRvcikge1xuICAgICAgICBjb25zdCBjYWxsc2l0ZSA9IGdldENhbGxzaXRlRm9yTWV0aG9kKGFwaU1ldGhvZE5hbWUpO1xuICAgICAgICBjb25zdCBleGVjdXRvciA9IGNyZWF0ZVRhc2tFeGVjdXRvcihjYWxsc2l0ZSk7XG5cbiAgICAgICAgdGhpcy5leGVjdXRpb25DaGFpbi50aGVuID0gb3JpZ2luYWxUaGVuO1xuICAgICAgICB0aGlzLmV4ZWN1dGlvbkNoYWluICAgICAgPSB0aGlzLmV4ZWN1dGlvbkNoYWluLnRoZW4oZXhlY3V0b3IpO1xuXG4gICAgICAgIHRoaXMudGVzdFJ1bi5vYnNlcnZlZENhbGxzaXRlcy5jYWxsc2l0ZXNXaXRob3V0QXdhaXQuYWRkKGNhbGxzaXRlKTtcblxuICAgICAgICB0aGlzLmV4ZWN1dGlvbkNoYWluID0gdGhpcy5fY3JlYXRlRXh0ZW5kZWRQcm9taXNlKHRoaXMuZXhlY3V0aW9uQ2hhaW4sIGNhbGxzaXRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5leGVjdXRpb25DaGFpbjtcbiAgICB9XG5cbiAgICBfZW5xdWV1ZUNvbW1hbmQgKGFwaU1ldGhvZE5hbWUsIENtZEN0b3IsIGNtZEFyZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVUYXNrKGFwaU1ldGhvZE5hbWUsIGNhbGxzaXRlID0+IHtcbiAgICAgICAgICAgIGxldCBjb21tYW5kID0gbnVsbDtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb21tYW5kID0gbmV3IENtZEN0b3IoY21kQXJncywgdGhpcy50ZXN0UnVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBlcnIuY2FsbHNpdGUgPSBjYWxsc2l0ZTtcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudGVzdFJ1bi5leGVjdXRlQWN0aW9uKGFwaU1ldGhvZE5hbWUsIGNvbW1hbmQsIGNhbGxzaXRlKVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXhlY3V0aW9uQ2hhaW4gPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZU11bHRpcGxlV2luZG93Q29tbWFuZCAoYXBpTWV0aG9kTmFtZSkge1xuICAgICAgICBjb25zdCB7IGRpc2FibGVNdWx0aXBsZVdpbmRvd3MsIGJyb3dzZXJDb25uZWN0aW9uIH0gPSB0aGlzLnRlc3RSdW47XG5cbiAgICAgICAgaWYgKGRpc2FibGVNdWx0aXBsZVdpbmRvd3MpXG4gICAgICAgICAgICB0aHJvdyBuZXcgTXVsdGlwbGVXaW5kb3dzTW9kZUlzRGlzYWJsZWRFcnJvcihhcGlNZXRob2ROYW1lKTtcblxuICAgICAgICBpZiAoIWJyb3dzZXJDb25uZWN0aW9uLmFjdGl2ZVdpbmRvd0lkKVxuICAgICAgICAgICAgdGhyb3cgbmV3IE11bHRpcGxlV2luZG93c01vZGVJc05vdEF2YWlsYWJsZUluUmVtb3RlQnJvd3NlckVycm9yKGFwaU1ldGhvZE5hbWUpO1xuICAgIH1cblxuICAgIGdldEV4ZWN1dGlvbkNvbnRleHQgKCkge1xuICAgICAgICBpZiAoIXRoaXMuX2V4ZWN1dGlvbkNvbnRleHQpXG4gICAgICAgICAgICB0aGlzLl9leGVjdXRpb25Db250ZXh0ID0gY3JlYXRlQ29udGV4dCh0aGlzLnRlc3RSdW4pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl9leGVjdXRpb25Db250ZXh0O1xuICAgIH1cblxuICAgIC8vIEFQSSBpbXBsZW1lbnRhdGlvblxuICAgIC8vIFdlIG5lZWQgaW1wbGVtZW50YXRpb24gbWV0aG9kcyB0byBvYnRhaW4gY29ycmVjdCBjYWxsc2l0ZXMuIElmIHdlIHVzZSBwbGFpbiBBUElcbiAgICAvLyBtZXRob2RzIGluIGNoYWluZWQgd3JhcHBlcnMgdGhlbiB3ZSB3aWxsIGhhdmUgY2FsbHNpdGUgZm9yIHRoZSB3cmFwcGVkIG1ldGhvZFxuICAgIC8vIGluIHRoaXMgZmlsZSBpbnN0ZWFkIG9mIGNoYWluZWQgbWV0aG9kIGNhbGxzaXRlIGluIHVzZXIgY29kZS5cbiAgICBfY3R4JGdldHRlciAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRlc3RSdW4uY3R4O1xuICAgIH1cblxuICAgIF9jdHgkc2V0dGVyICh2YWwpIHtcbiAgICAgICAgdGhpcy50ZXN0UnVuLmN0eCA9IHZhbDtcblxuICAgICAgICByZXR1cm4gdGhpcy50ZXN0UnVuLmN0eDtcbiAgICB9XG5cbiAgICBfZml4dHVyZUN0eCRnZXR0ZXIgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50ZXN0UnVuLmZpeHR1cmVDdHg7XG4gICAgfVxuXG4gICAgX2Jyb3dzZXIkZ2V0dGVyICgpIHtcbiAgICAgICAgcmV0dXJuIGdldEJyb3dzZXIodGhpcy50ZXN0UnVuLmJyb3dzZXJDb25uZWN0aW9uKTtcbiAgICB9XG5cbiAgICBfZGlzcGF0Y2hFdmVudCQgKHNlbGVjdG9yLCBldmVudE5hbWUsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ2Rpc3BhdGNoRXZlbnQnLCBEaXNwYXRjaEV2ZW50Q29tbWFuZCwgeyBzZWxlY3RvciwgZXZlbnROYW1lLCBvcHRpb25zLCByZWxhdGVkVGFyZ2V0OiBvcHRpb25zLnJlbGF0ZWRUYXJnZXQgfSk7XG4gICAgfVxuXG4gICAgX2NsaWNrJCAoc2VsZWN0b3IsIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdjbGljaycsIENsaWNrQ29tbWFuZCwgeyBzZWxlY3Rvciwgb3B0aW9ucyB9KTtcbiAgICB9XG5cbiAgICBfcmlnaHRDbGljayQgKHNlbGVjdG9yLCBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgncmlnaHRDbGljaycsIFJpZ2h0Q2xpY2tDb21tYW5kLCB7IHNlbGVjdG9yLCBvcHRpb25zIH0pO1xuICAgIH1cblxuICAgIF9kb3VibGVDbGljayQgKHNlbGVjdG9yLCBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgnZG91YmxlQ2xpY2snLCBEb3VibGVDbGlja0NvbW1hbmQsIHsgc2VsZWN0b3IsIG9wdGlvbnMgfSk7XG4gICAgfVxuXG4gICAgX2hvdmVyJCAoc2VsZWN0b3IsIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdob3ZlcicsIEhvdmVyQ29tbWFuZCwgeyBzZWxlY3Rvciwgb3B0aW9ucyB9KTtcbiAgICB9XG5cbiAgICBfZHJhZyQgKHNlbGVjdG9yLCBkcmFnT2Zmc2V0WCwgZHJhZ09mZnNldFksIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdkcmFnJywgRHJhZ0NvbW1hbmQsIHsgc2VsZWN0b3IsIGRyYWdPZmZzZXRYLCBkcmFnT2Zmc2V0WSwgb3B0aW9ucyB9KTtcbiAgICB9XG5cbiAgICBfZHJhZ1RvRWxlbWVudCQgKHNlbGVjdG9yLCBkZXN0aW5hdGlvblNlbGVjdG9yLCBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgnZHJhZ1RvRWxlbWVudCcsIERyYWdUb0VsZW1lbnRDb21tYW5kLCB7IHNlbGVjdG9yLCBkZXN0aW5hdGlvblNlbGVjdG9yLCBvcHRpb25zIH0pO1xuICAgIH1cblxuICAgIF9nZXRTZWxlY3RvckZvclNjcm9sbCAoYXJncykge1xuICAgICAgICBjb25zdCBzZWxlY3RvciA9IHR5cGVvZiBhcmdzWzBdID09PSAnc3RyaW5nJyB8fCBpc1NlbGVjdG9yKGFyZ3NbMF0pID8gYXJnc1swXSA6IG51bGw7XG5cbiAgICAgICAgaWYgKHNlbGVjdG9yKVxuICAgICAgICAgICAgYXJncy5zaGlmdCgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICAvLyBOT1RFOiBoZXJlIHdlIHVzZSBkb2N1bWVudC5zY3JvbGxpbmdFbGVtZW50IGZvciBvbGQgU2FmYXJpIHZlcnNpb25zXG4gICAgICAgICAgICAvLyBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgZG9lcyBub3Qgd29yayBhcyBleHBlY3RlZCBvbiBNb2phdmUgU2FmYXJpIDEyLjEvIEhpZ2ggU2llcnJhIFNhZmFyaSAxMS4xXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWZcbiAgICAgICAgICAgIHJldHVybiAoKSA9PiBkb2N1bWVudC5zY3JvbGxpbmdFbGVtZW50IHx8IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxuICAgICAgICByZXR1cm4gc2VsZWN0b3I7XG4gICAgfVxuXG4gICAgX2dldFBvc2l0aW9uIChhcmdzKSB7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uID0gYXJncy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGFyZ3NbMF0gPT09ICdzdHJpbmcnID8gYXJnc1swXSA6IG51bGw7XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uKVxuICAgICAgICAgICAgYXJncy5zaGlmdCgpO1xuXG4gICAgICAgIHJldHVybiBwb3NpdGlvbjtcbiAgICB9XG5cbiAgICBfc2Nyb2xsJCAoLi4uYXJncykge1xuICAgICAgICBsZXQgcG9zaXRpb24gPSB0aGlzLl9nZXRQb3NpdGlvbihhcmdzKTtcblxuICAgICAgICBjb25zdCBzZWxlY3RvciA9IHRoaXMuX2dldFNlbGVjdG9yRm9yU2Nyb2xsKGFyZ3MpO1xuXG4gICAgICAgIGxldCB4ICAgICAgID0gdm9pZCAwO1xuICAgICAgICBsZXQgeSAgICAgICA9IHZvaWQgMDtcbiAgICAgICAgbGV0IG9wdGlvbnMgPSB2b2lkIDA7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBhcmdzWzBdID09PSAnc3RyaW5nJylcbiAgICAgICAgICAgIFsgcG9zaXRpb24sIG9wdGlvbnMgXSA9IGFyZ3M7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBhcmdzWzBdID09PSAnbnVtYmVyJylcbiAgICAgICAgICAgIFsgeCwgeSwgb3B0aW9ucyBdID0gYXJncztcblxuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3Njcm9sbCcsIFNjcm9sbENvbW1hbmQsIHsgc2VsZWN0b3IsIHgsIHksIHBvc2l0aW9uLCBvcHRpb25zIH0pO1xuICAgIH1cblxuICAgIF9zY3JvbGxCeSQgKC4uLmFyZ3MpIHtcbiAgICAgICAgY29uc3Qgc2VsZWN0b3IgPSB0aGlzLl9nZXRTZWxlY3RvckZvclNjcm9sbChhcmdzKTtcblxuICAgICAgICBjb25zdCBbYnlYLCBieVksIG9wdGlvbnNdID0gYXJncztcblxuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3Njcm9sbEJ5JywgU2Nyb2xsQnlDb21tYW5kLCB7IHNlbGVjdG9yLCBieVgsIGJ5WSwgb3B0aW9ucyB9KTtcbiAgICB9XG5cbiAgICBfc2Nyb2xsSW50b1ZpZXckIChzZWxlY3Rvciwgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3Njcm9sbEludG9WaWV3JywgU2Nyb2xsSW50b1ZpZXdDb21tYW5kLCB7IHNlbGVjdG9yLCBvcHRpb25zIH0pO1xuICAgIH1cblxuICAgIF90eXBlVGV4dCQgKHNlbGVjdG9yLCB0ZXh0LCBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgndHlwZVRleHQnLCBUeXBlVGV4dENvbW1hbmQsIHsgc2VsZWN0b3IsIHRleHQsIG9wdGlvbnMgfSk7XG4gICAgfVxuXG4gICAgX3NlbGVjdFRleHQkIChzZWxlY3Rvciwgc3RhcnRQb3MsIGVuZFBvcywgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3NlbGVjdFRleHQnLCBTZWxlY3RUZXh0Q29tbWFuZCwgeyBzZWxlY3Rvciwgc3RhcnRQb3MsIGVuZFBvcywgb3B0aW9ucyB9KTtcbiAgICB9XG5cbiAgICBfc2VsZWN0VGV4dEFyZWFDb250ZW50JCAoc2VsZWN0b3IsIHN0YXJ0TGluZSwgc3RhcnRQb3MsIGVuZExpbmUsIGVuZFBvcywgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3NlbGVjdFRleHRBcmVhQ29udGVudCcsIFNlbGVjdFRleHRBcmVhQ29udGVudENvbW1hbmQsIHtcbiAgICAgICAgICAgIHNlbGVjdG9yLFxuICAgICAgICAgICAgc3RhcnRMaW5lLFxuICAgICAgICAgICAgc3RhcnRQb3MsXG4gICAgICAgICAgICBlbmRMaW5lLFxuICAgICAgICAgICAgZW5kUG9zLFxuICAgICAgICAgICAgb3B0aW9uc1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBfc2VsZWN0RWRpdGFibGVDb250ZW50JCAoc3RhcnRTZWxlY3RvciwgZW5kU2VsZWN0b3IsIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdzZWxlY3RFZGl0YWJsZUNvbnRlbnQnLCBTZWxlY3RFZGl0YWJsZUNvbnRlbnRDb21tYW5kLCB7XG4gICAgICAgICAgICBzdGFydFNlbGVjdG9yLFxuICAgICAgICAgICAgZW5kU2VsZWN0b3IsXG4gICAgICAgICAgICBvcHRpb25zXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIF9wcmVzc0tleSQgKGtleXMsIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdwcmVzc0tleScsIFByZXNzS2V5Q29tbWFuZCwgeyBrZXlzLCBvcHRpb25zIH0pO1xuICAgIH1cblxuICAgIF93YWl0JCAodGltZW91dCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3dhaXQnLCBXYWl0Q29tbWFuZCwgeyB0aW1lb3V0IH0pO1xuICAgIH1cblxuICAgIF9uYXZpZ2F0ZVRvJCAodXJsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgnbmF2aWdhdGVUbycsIE5hdmlnYXRlVG9Db21tYW5kLCB7IHVybCB9KTtcbiAgICB9XG5cbiAgICBfc2V0RmlsZXNUb1VwbG9hZCQgKHNlbGVjdG9yLCBmaWxlUGF0aCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3NldEZpbGVzVG9VcGxvYWQnLCBTZXRGaWxlc1RvVXBsb2FkQ29tbWFuZCwgeyBzZWxlY3RvciwgZmlsZVBhdGggfSk7XG4gICAgfVxuXG4gICAgX2NsZWFyVXBsb2FkJCAoc2VsZWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdjbGVhclVwbG9hZCcsIENsZWFyVXBsb2FkQ29tbWFuZCwgeyBzZWxlY3RvciB9KTtcbiAgICB9XG5cbiAgICBfdGFrZVNjcmVlbnNob3QkIChvcHRpb25zKSB7XG4gICAgICAgIGlmIChvcHRpb25zICYmIHR5cGVvZiBvcHRpb25zICE9PSAnb2JqZWN0JylcbiAgICAgICAgICAgIG9wdGlvbnMgPSB7IHBhdGg6IG9wdGlvbnMgfTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3Rha2VTY3JlZW5zaG90JywgVGFrZVNjcmVlbnNob3RDb21tYW5kLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBfdGFrZUVsZW1lbnRTY3JlZW5zaG90JCAoc2VsZWN0b3IsIC4uLmFyZ3MpIHtcbiAgICAgICAgY29uc3QgY29tbWFuZEFyZ3MgPSB7IHNlbGVjdG9yIH07XG5cbiAgICAgICAgaWYgKGFyZ3NbMV0pIHtcbiAgICAgICAgICAgIGNvbW1hbmRBcmdzLnBhdGggICAgPSBhcmdzWzBdO1xuICAgICAgICAgICAgY29tbWFuZEFyZ3Mub3B0aW9ucyA9IGFyZ3NbMV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZ3NbMF0gPT09ICdvYmplY3QnKVxuICAgICAgICAgICAgY29tbWFuZEFyZ3Mub3B0aW9ucyA9IGFyZ3NbMF07XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGNvbW1hbmRBcmdzLnBhdGggPSBhcmdzWzBdO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgndGFrZUVsZW1lbnRTY3JlZW5zaG90JywgVGFrZUVsZW1lbnRTY3JlZW5zaG90Q29tbWFuZCwgY29tbWFuZEFyZ3MpO1xuICAgIH1cblxuICAgIF9yZXNpemVXaW5kb3ckICh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgncmVzaXplV2luZG93JywgUmVzaXplV2luZG93Q29tbWFuZCwgeyB3aWR0aCwgaGVpZ2h0IH0pO1xuICAgIH1cblxuICAgIF9yZXNpemVXaW5kb3dUb0ZpdERldmljZSQgKGRldmljZSwgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3Jlc2l6ZVdpbmRvd1RvRml0RGV2aWNlJywgUmVzaXplV2luZG93VG9GaXREZXZpY2VDb21tYW5kLCB7IGRldmljZSwgb3B0aW9ucyB9KTtcbiAgICB9XG5cbiAgICBfbWF4aW1pemVXaW5kb3ckICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdtYXhpbWl6ZVdpbmRvdycsIE1heGltaXplV2luZG93Q29tbWFuZCk7XG4gICAgfVxuXG4gICAgX3N3aXRjaFRvSWZyYW1lJCAoc2VsZWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdzd2l0Y2hUb0lmcmFtZScsIFN3aXRjaFRvSWZyYW1lQ29tbWFuZCwgeyBzZWxlY3RvciB9KTtcbiAgICB9XG5cbiAgICBfc3dpdGNoVG9NYWluV2luZG93JCAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgnc3dpdGNoVG9NYWluV2luZG93JywgU3dpdGNoVG9NYWluV2luZG93Q29tbWFuZCk7XG4gICAgfVxuXG4gICAgX29wZW5XaW5kb3ckICh1cmwpIHtcbiAgICAgICAgY29uc3QgYXBpTWV0aG9kTmFtZSA9ICdvcGVuV2luZG93JztcblxuICAgICAgICB0aGlzLl92YWxpZGF0ZU11bHRpcGxlV2luZG93Q29tbWFuZChhcGlNZXRob2ROYW1lKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoYXBpTWV0aG9kTmFtZSwgT3BlbldpbmRvd0NvbW1hbmQsIHsgdXJsIH0pO1xuICAgIH1cblxuICAgIF9jbG9zZVdpbmRvdyQgKHdpbmRvdykge1xuICAgICAgICBjb25zdCBhcGlNZXRob2ROYW1lID0gJ2Nsb3NlV2luZG93JztcbiAgICAgICAgY29uc3Qgd2luZG93SWQgICAgICA9IHdpbmRvdz8uaWQgfHwgbnVsbDtcblxuICAgICAgICB0aGlzLl92YWxpZGF0ZU11bHRpcGxlV2luZG93Q29tbWFuZChhcGlNZXRob2ROYW1lKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoYXBpTWV0aG9kTmFtZSwgQ2xvc2VXaW5kb3dDb21tYW5kLCB7IHdpbmRvd0lkIH0pO1xuICAgIH1cblxuICAgIF9nZXRDdXJyZW50V2luZG93JCAoKSB7XG4gICAgICAgIGNvbnN0IGFwaU1ldGhvZE5hbWUgPSAnZ2V0Q3VycmVudFdpbmRvdyc7XG5cbiAgICAgICAgdGhpcy5fdmFsaWRhdGVNdWx0aXBsZVdpbmRvd0NvbW1hbmQoYXBpTWV0aG9kTmFtZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKGFwaU1ldGhvZE5hbWUsIEdldEN1cnJlbnRXaW5kb3dDb21tYW5kKTtcbiAgICB9XG5cbiAgICBfc3dpdGNoVG9XaW5kb3ckICh3aW5kb3dTZWxlY3Rvcikge1xuICAgICAgICBjb25zdCBhcGlNZXRob2ROYW1lID0gJ3N3aXRjaFRvV2luZG93JztcblxuICAgICAgICB0aGlzLl92YWxpZGF0ZU11bHRpcGxlV2luZG93Q29tbWFuZChhcGlNZXRob2ROYW1lKTtcblxuICAgICAgICBsZXQgY29tbWFuZDtcbiAgICAgICAgbGV0IGFyZ3M7XG5cbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3dTZWxlY3RvciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY29tbWFuZCA9IFN3aXRjaFRvV2luZG93QnlQcmVkaWNhdGVDb21tYW5kO1xuXG4gICAgICAgICAgICBhcmdzID0geyBmaW5kV2luZG93OiB3aW5kb3dTZWxlY3RvciB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29tbWFuZCA9IFN3aXRjaFRvV2luZG93Q29tbWFuZDtcblxuICAgICAgICAgICAgYXJncyA9IHsgd2luZG93SWQ6IHdpbmRvd1NlbGVjdG9yPy5pZCB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKGFwaU1ldGhvZE5hbWUsIGNvbW1hbmQsIGFyZ3MpO1xuICAgIH1cblxuICAgIF9zd2l0Y2hUb1BhcmVudFdpbmRvdyQgKCkge1xuICAgICAgICBjb25zdCBhcGlNZXRob2ROYW1lID0gJ3N3aXRjaFRvUGFyZW50V2luZG93JztcblxuICAgICAgICB0aGlzLl92YWxpZGF0ZU11bHRpcGxlV2luZG93Q29tbWFuZChhcGlNZXRob2ROYW1lKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoYXBpTWV0aG9kTmFtZSwgU3dpdGNoVG9QYXJlbnRXaW5kb3dDb21tYW5kKTtcbiAgICB9XG5cbiAgICBfc3dpdGNoVG9QcmV2aW91c1dpbmRvdyQgKCkge1xuICAgICAgICBjb25zdCBhcGlNZXRob2ROYW1lID0gJ3N3aXRjaFRvUHJldmlvdXNXaW5kb3cnO1xuXG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlTXVsdGlwbGVXaW5kb3dDb21tYW5kKGFwaU1ldGhvZE5hbWUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZChhcGlNZXRob2ROYW1lLCBTd2l0Y2hUb1ByZXZpb3VzV2luZG93Q29tbWFuZCk7XG4gICAgfVxuXG4gICAgX2V2YWwkIChmbiwgb3B0aW9ucykge1xuICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKG9wdGlvbnMpKVxuICAgICAgICAgICAgb3B0aW9ucyA9IGFzc2lnbih7fSwgb3B0aW9ucywgeyBib3VuZFRlc3RSdW46IHRoaXMgfSk7XG5cbiAgICAgICAgY29uc3QgYnVpbGRlciAgPSBuZXcgQ2xpZW50RnVuY3Rpb25CdWlsZGVyKGZuLCBvcHRpb25zLCB7IGluc3RhbnRpYXRpb246ICdldmFsJywgZXhlY3V0aW9uOiAnZXZhbCcgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudEZuID0gYnVpbGRlci5nZXRGdW5jdGlvbigpO1xuXG4gICAgICAgIHJldHVybiBjbGllbnRGbigpO1xuICAgIH1cblxuICAgIF9zZXROYXRpdmVEaWFsb2dIYW5kbGVyJCAoZm4sIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VucXVldWVDb21tYW5kKCdzZXROYXRpdmVEaWFsb2dIYW5kbGVyJywgU2V0TmF0aXZlRGlhbG9nSGFuZGxlckNvbW1hbmQsIHtcbiAgICAgICAgICAgIGRpYWxvZ0hhbmRsZXI6IHsgZm4sIG9wdGlvbnMgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBfZ2V0TmF0aXZlRGlhbG9nSGlzdG9yeSQgKCkge1xuICAgICAgICBjb25zdCBuYW1lICAgICA9ICdnZXROYXRpdmVEaWFsb2dIaXN0b3J5JztcbiAgICAgICAgY29uc3QgY2FsbHNpdGUgPSBnZXRDYWxsc2l0ZUZvck1ldGhvZChuYW1lKTtcblxuICAgICAgICByZXR1cm4gdGhpcy50ZXN0UnVuLmV4ZWN1dGVBY3Rpb24obmFtZSwgbmV3IEdldE5hdGl2ZURpYWxvZ0hpc3RvcnlDb21tYW5kKCksIGNhbGxzaXRlKTtcbiAgICB9XG5cbiAgICBfZ2V0QnJvd3NlckNvbnNvbGVNZXNzYWdlcyQgKCkge1xuICAgICAgICBjb25zdCBuYW1lICAgICA9ICdnZXRCcm93c2VyQ29uc29sZU1lc3NhZ2VzJztcbiAgICAgICAgY29uc3QgY2FsbHNpdGUgPSBnZXRDYWxsc2l0ZUZvck1ldGhvZChuYW1lKTtcblxuICAgICAgICByZXR1cm4gdGhpcy50ZXN0UnVuLmV4ZWN1dGVBY3Rpb24obmFtZSwgbmV3IEdldEJyb3dzZXJDb25zb2xlTWVzc2FnZXNDb21tYW5kKCksIGNhbGxzaXRlKTtcbiAgICB9XG5cbiAgICBfY2hlY2tGb3JFeGNlc3NpdmVBd2FpdHMgKHNuYXBzaG90UHJvcGVydHlDYWxsc2l0ZXMsIGNoZWNrZWRDYWxsc2l0ZSkge1xuICAgICAgICBjb25zdCBjYWxsc2l0ZUlkID0gZ2V0Q2FsbHNpdGVJZChjaGVja2VkQ2FsbHNpdGUpO1xuXG4gICAgICAgIC8vIE5PVEU6IElmIHRoZXJlIGFyZSB1bmFzc2VydGVkIGNhbGxzaXRlcywgd2Ugc2hvdWxkIGFkZCBhbGwgb2YgdGhlbSB0byBhd2FpdGVkU25hcHNob3RXYXJuaW5ncy5cbiAgICAgICAgLy8gVGhlIHdhcm5pbmdzIHRoZW1zZWx2ZXMgYXJlIHJhaXNlZCBhZnRlciB0aGUgdGVzdCBydW4gaW4gd3JhcC10ZXN0LWZ1bmN0aW9uXG4gICAgICAgIGlmIChzbmFwc2hvdFByb3BlcnR5Q2FsbHNpdGVzW2NhbGxzaXRlSWRdICYmICFzbmFwc2hvdFByb3BlcnR5Q2FsbHNpdGVzW2NhbGxzaXRlSWRdLmNoZWNrZWQpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcHJvcGVydHlDYWxsc2l0ZSBvZiBzbmFwc2hvdFByb3BlcnR5Q2FsbHNpdGVzW2NhbGxzaXRlSWRdLmNhbGxzaXRlcylcbiAgICAgICAgICAgICAgICB0aGlzLnRlc3RSdW4ub2JzZXJ2ZWRDYWxsc2l0ZXMuYXdhaXRlZFNuYXBzaG90V2FybmluZ3Muc2V0KGdldENhbGxzaXRlU3RhY2tGcmFtZVN0cmluZyhwcm9wZXJ0eUNhbGxzaXRlKSwgcHJvcGVydHlDYWxsc2l0ZSk7XG5cbiAgICAgICAgICAgIGRlbGV0ZSBzbmFwc2hvdFByb3BlcnR5Q2FsbHNpdGVzW2NhbGxzaXRlSWRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHNuYXBzaG90UHJvcGVydHlDYWxsc2l0ZXNbY2FsbHNpdGVJZF0gPSB7IGNhbGxzaXRlczogW10sIGNoZWNrZWQ6IHRydWUgfTtcbiAgICB9XG5cbiAgICBfZXhwZWN0JCAoYWN0dWFsKSB7XG4gICAgICAgIGNvbnN0IGNhbGxzaXRlID0gZ2V0Q2FsbHNpdGVGb3JNZXRob2QoJ2V4cGVjdCcpO1xuXG4gICAgICAgIHRoaXMuX2NoZWNrRm9yRXhjZXNzaXZlQXdhaXRzKHRoaXMudGVzdFJ1bi5vYnNlcnZlZENhbGxzaXRlcy5zbmFwc2hvdFByb3BlcnR5Q2FsbHNpdGVzLCBjYWxsc2l0ZSk7XG5cbiAgICAgICAgaWYgKGlzQ2xpZW50RnVuY3Rpb24oYWN0dWFsKSlcbiAgICAgICAgICAgIGFkZFdhcm5pbmcodGhpcy53YXJuaW5nTG9nLCBXQVJOSU5HX01FU1NBR0UuYXNzZXJ0ZWRDbGllbnRGdW5jdGlvbkluc3RhbmNlLCBjYWxsc2l0ZSk7XG4gICAgICAgIGVsc2UgaWYgKGlzU2VsZWN0b3IoYWN0dWFsKSlcbiAgICAgICAgICAgIGFkZFdhcm5pbmcodGhpcy53YXJuaW5nTG9nLCBXQVJOSU5HX01FU1NBR0UuYXNzZXJ0ZWRTZWxlY3Rvckluc3RhbmNlLCBjYWxsc2l0ZSk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBBc3NlcnRpb24oYWN0dWFsLCB0aGlzLCBjYWxsc2l0ZSk7XG4gICAgfVxuXG4gICAgX2RlYnVnJCAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgnZGVidWcnLCBEZWJ1Z0NvbW1hbmQpO1xuICAgIH1cblxuICAgIF9zZXRUZXN0U3BlZWQkIChzcGVlZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3NldFRlc3RTcGVlZCcsIFNldFRlc3RTcGVlZENvbW1hbmQsIHsgc3BlZWQgfSk7XG4gICAgfVxuXG4gICAgX3NldFBhZ2VMb2FkVGltZW91dCQgKGR1cmF0aW9uKSB7XG4gICAgICAgIGFkZFdhcm5pbmcodGhpcy53YXJuaW5nTG9nLCBnZXREZXByZWNhdGlvbk1lc3NhZ2UoREVQUkVDQVRFRC5zZXRQYWdlTG9hZFRpbWVvdXQpKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZUNvbW1hbmQoJ3NldFBhZ2VMb2FkVGltZW91dCcsIFNldFBhZ2VMb2FkVGltZW91dENvbW1hbmQsIHsgZHVyYXRpb24gfSk7XG4gICAgfVxuXG4gICAgX3VzZVJvbGUkIChyb2xlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlQ29tbWFuZCgndXNlUm9sZScsIFVzZVJvbGVDb21tYW5kLCB7IHJvbGUgfSk7XG4gICAgfVxuXG4gICAgX2FkZFJlcXVlc3RIb29rcyQgKC4uLmhvb2tzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbnF1ZXVlVGFzaygnYWRkUmVxdWVzdEhvb2tzJywgKCkgPT4ge1xuICAgICAgICAgICAgaG9va3MgPSBmbGF0dGVuKGhvb2tzKTtcblxuICAgICAgICAgICAgYXNzZXJ0UmVxdWVzdEhvb2tUeXBlKGhvb2tzKTtcblxuICAgICAgICAgICAgaG9va3MuZm9yRWFjaChob29rID0+IHRoaXMudGVzdFJ1bi5hZGRSZXF1ZXN0SG9vayhob29rKSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIF9yZW1vdmVSZXF1ZXN0SG9va3MkICguLi5ob29rcykge1xuICAgICAgICByZXR1cm4gdGhpcy5fZW5xdWV1ZVRhc2soJ3JlbW92ZVJlcXVlc3RIb29rcycsICgpID0+IHtcbiAgICAgICAgICAgIGhvb2tzID0gZmxhdHRlbihob29rcyk7XG5cbiAgICAgICAgICAgIGFzc2VydFJlcXVlc3RIb29rVHlwZShob29rcyk7XG5cbiAgICAgICAgICAgIGhvb2tzLmZvckVhY2goaG9vayA9PiB0aGlzLnRlc3RSdW4ucmVtb3ZlUmVxdWVzdEhvb2soaG9vaykpO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cblRlc3RDb250cm9sbGVyLkFQSV9MSVNUID0gZ2V0RGVsZWdhdGVkQVBJTGlzdChUZXN0Q29udHJvbGxlci5wcm90b3R5cGUpO1xuXG5kZWxlZ2F0ZUFQSShUZXN0Q29udHJvbGxlci5wcm90b3R5cGUsIFRlc3RDb250cm9sbGVyLkFQSV9MSVNULCB7IHVzZUN1cnJlbnRDdHhBc0hhbmRsZXI6IHRydWUgfSk7XG4iXX0=
|