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.
Files changed (332) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +21 -21
  3. package/bin/testcafe-with-v8-flag-filter.js +0 -0
  4. package/lib/api/exportable-lib/index.js +49 -49
  5. package/lib/api/request-hooks/assert-type.js +7 -7
  6. package/lib/api/request-hooks/hook-method-names.js +9 -9
  7. package/lib/api/request-hooks/hook.js +32 -32
  8. package/lib/api/request-hooks/interfaces.js +2 -2
  9. package/lib/api/request-hooks/request-logger.js +112 -112
  10. package/lib/api/request-hooks/request-mock/create-request-mock.js +10 -10
  11. package/lib/api/request-hooks/request-mock/index.js +44 -44
  12. package/lib/api/request-hooks/request-mock.js +46 -46
  13. package/lib/api/structure/base-unit.js +11 -11
  14. package/lib/api/structure/fixture.js +75 -75
  15. package/lib/api/structure/interfaces.js +2 -2
  16. package/lib/api/structure/test-file.js +31 -31
  17. package/lib/api/structure/test-timeout.js +9 -9
  18. package/lib/api/structure/test.js +85 -85
  19. package/lib/api/structure/testing-unit.js +89 -89
  20. package/lib/api/structure/unit-type.js +9 -9
  21. package/lib/api/test-controller/assertion.js +88 -88
  22. package/lib/api/test-controller/execution-context.js +82 -82
  23. package/lib/api/test-controller/index.js +358 -358
  24. package/lib/api/test-controller/proxy.js +28 -28
  25. package/lib/api/test-page-url.js +60 -60
  26. package/lib/api/test-run-tracker.js +68 -68
  27. package/lib/api/wrap-test-function.js +49 -49
  28. package/lib/assertions/executor.js +74 -74
  29. package/lib/assertions/get-fn.js +46 -46
  30. package/lib/assertions/type.js +20 -20
  31. package/lib/assets/content-types.js +9 -9
  32. package/lib/assets/injectables.js +18 -18
  33. package/lib/browser/connection/command.js +10 -10
  34. package/lib/browser/connection/error-hints.js +9 -9
  35. package/lib/browser/connection/gateway.js +159 -159
  36. package/lib/browser/connection/get-hints.js +33 -33
  37. package/lib/browser/connection/heartbeat-status.js +8 -8
  38. package/lib/browser/connection/index.js +328 -328
  39. package/lib/browser/connection/remotes-queue.js +46 -46
  40. package/lib/browser/connection/service-routes.js +12 -12
  41. package/lib/browser/connection/status.js +12 -12
  42. package/lib/browser/interfaces.js +2 -2
  43. package/lib/browser/provider/built-in/dedicated/base.js +80 -80
  44. package/lib/browser/provider/built-in/dedicated/chrome/browser-client.js +204 -204
  45. package/lib/browser/provider/built-in/dedicated/chrome/build-chrome-args.js +17 -17
  46. package/lib/browser/provider/built-in/dedicated/chrome/config.js +110 -110
  47. package/lib/browser/provider/built-in/dedicated/chrome/create-temp-profile.js +45 -45
  48. package/lib/browser/provider/built-in/dedicated/chrome/elapsed-upperbounds.js +15 -15
  49. package/lib/browser/provider/built-in/dedicated/chrome/index.js +102 -102
  50. package/lib/browser/provider/built-in/dedicated/chrome/interfaces.js +2 -2
  51. package/lib/browser/provider/built-in/dedicated/chrome/local-chrome.js +24 -24
  52. package/lib/browser/provider/built-in/dedicated/chrome/runtime-info.js +29 -29
  53. package/lib/browser/provider/built-in/dedicated/edge/index.js +10 -10
  54. package/lib/browser/provider/built-in/dedicated/edge/runtime-info.js +29 -29
  55. package/lib/browser/provider/built-in/dedicated/firefox/config.js +33 -33
  56. package/lib/browser/provider/built-in/dedicated/firefox/create-temp-profile.js +78 -78
  57. package/lib/browser/provider/built-in/dedicated/firefox/index.js +73 -73
  58. package/lib/browser/provider/built-in/dedicated/firefox/local-firefox.js +36 -36
  59. package/lib/browser/provider/built-in/dedicated/firefox/marionette-client/commands.js +13 -13
  60. package/lib/browser/provider/built-in/dedicated/firefox/marionette-client/index.js +200 -200
  61. package/lib/browser/provider/built-in/dedicated/firefox/runtime-info.js +17 -17
  62. package/lib/browser/provider/built-in/index.js +21 -21
  63. package/lib/browser/provider/built-in/locally-installed.js +30 -30
  64. package/lib/browser/provider/built-in/path.js +47 -47
  65. package/lib/browser/provider/built-in/remote.js +58 -58
  66. package/lib/browser/provider/index.js +303 -303
  67. package/lib/browser/provider/parse-provider-name.js +16 -16
  68. package/lib/browser/provider/plugin-host.js +121 -121
  69. package/lib/browser/provider/pool.js +115 -115
  70. package/lib/browser/provider/utils/argument-parsing.js +74 -74
  71. package/lib/browser/provider/utils/browser-starter.js +34 -34
  72. package/lib/browser/provider/utils/client-functions.js +24 -24
  73. package/lib/browser/provider/utils/get-maximized-headless-window-size.js +9 -9
  74. package/lib/cli/argument-parser.js +284 -284
  75. package/lib/cli/authentication-helper.js +35 -35
  76. package/lib/cli/cli.js +134 -134
  77. package/lib/cli/correct-browsers-and-sources.js +40 -40
  78. package/lib/cli/index.js +19 -19
  79. package/lib/cli/log.js +43 -43
  80. package/lib/cli/remotes-wizard.js +36 -36
  81. package/lib/cli/termination-handler.js +38 -38
  82. package/lib/client/automation/index.js +34 -16
  83. package/lib/client/automation/index.min.js +1 -1
  84. package/lib/client/browser/idle-page/index.html.mustache +35 -35
  85. package/lib/client/browser/idle-page/logo.svg +86 -86
  86. package/lib/client/core/index.js +14 -14
  87. package/lib/client/driver/index.js +46 -16
  88. package/lib/client/driver/index.min.js +1 -1
  89. package/lib/client/driver/internal-properties.js +9 -9
  90. package/lib/client/test-run/iframe.js.mustache +17 -17
  91. package/lib/client/test-run/index.js.mustache +51 -51
  92. package/lib/client/ui/index.js +14 -14
  93. package/lib/client/ui/sprite.svg +42 -42
  94. package/lib/client-functions/builder-symbol.js +4 -4
  95. package/lib/client-functions/client-function-builder.js +155 -155
  96. package/lib/client-functions/replicator.js +61 -61
  97. package/lib/client-functions/return-single-prop-mode.js +8 -8
  98. package/lib/client-functions/selector-api-execution-mode.js +20 -20
  99. package/lib/client-functions/selectors/add-api.js +645 -645
  100. package/lib/client-functions/selectors/create-snapshot-methods.js +13 -13
  101. package/lib/client-functions/selectors/prepare-api-args.js +20 -20
  102. package/lib/client-functions/selectors/selector-attribute-filter.js +22 -22
  103. package/lib/client-functions/selectors/selector-builder.js +153 -153
  104. package/lib/client-functions/selectors/selector-text-filter.js +43 -43
  105. package/lib/client-functions/selectors/snapshot-properties.js +48 -48
  106. package/lib/client-functions/types.js +18 -18
  107. package/lib/compiler/babel/format-babel-produced-code.js +10 -10
  108. package/lib/compiler/babel/get-base-babel-options.js +11 -11
  109. package/lib/compiler/babel/load-libs.js +63 -63
  110. package/lib/compiler/babel/preset-stage-2.js +19 -19
  111. package/lib/compiler/compile-client-function.js +73 -73
  112. package/lib/compiler/compilers.js +33 -33
  113. package/lib/compiler/index.js +92 -92
  114. package/lib/compiler/interfaces.js +2 -2
  115. package/lib/compiler/test-file/api-based.js +146 -146
  116. package/lib/compiler/test-file/base.js +36 -36
  117. package/lib/compiler/test-file/exportble-lib-path.js +5 -5
  118. package/lib/compiler/test-file/formats/coffeescript/compiler.js +38 -38
  119. package/lib/compiler/test-file/formats/coffeescript/get-test-list.js +29 -29
  120. package/lib/compiler/test-file/formats/es-next/compiler.js +42 -42
  121. package/lib/compiler/test-file/formats/es-next/get-test-list.js +166 -166
  122. package/lib/compiler/test-file/formats/es-next/is-flow-code.js +7 -7
  123. package/lib/compiler/test-file/formats/raw.js +85 -85
  124. package/lib/compiler/test-file/formats/typescript/compiler.js +135 -135
  125. package/lib/compiler/test-file/formats/typescript/get-test-list.js +185 -185
  126. package/lib/compiler/test-file/test-file-parser-base.js +214 -214
  127. package/lib/configuration/configuration-base.js +165 -165
  128. package/lib/configuration/constants.js +9 -9
  129. package/lib/configuration/customizable-compilers.js +7 -7
  130. package/lib/configuration/default-values.js +51 -51
  131. package/lib/configuration/interfaces.js +2 -2
  132. package/lib/configuration/option-names.js +53 -53
  133. package/lib/configuration/option-source.js +9 -9
  134. package/lib/configuration/option.js +14 -14
  135. package/lib/configuration/quarantine-option-names.js +8 -8
  136. package/lib/configuration/run-option-names.js +26 -26
  137. package/lib/configuration/screenshot-option-names.js +10 -10
  138. package/lib/configuration/testcafe-configuration.js +163 -163
  139. package/lib/configuration/types.js +2 -2
  140. package/lib/configuration/typescript-configuration.js +62 -62
  141. package/lib/custom-client-scripts/assert-type.js +7 -7
  142. package/lib/custom-client-scripts/client-script-init.js +2 -2
  143. package/lib/custom-client-scripts/client-script.js +106 -106
  144. package/lib/custom-client-scripts/get-code.js +11 -11
  145. package/lib/custom-client-scripts/get-url.js +6 -6
  146. package/lib/custom-client-scripts/load.js +15 -15
  147. package/lib/custom-client-scripts/problematic-scripts.js +2 -2
  148. package/lib/custom-client-scripts/routing.js +36 -36
  149. package/lib/custom-client-scripts/utils.js +60 -60
  150. package/lib/embedding-utils.js +83 -83
  151. package/lib/errors/create-stack-filter.js +18 -18
  152. package/lib/errors/error-list.js +26 -26
  153. package/lib/errors/get-callsite.js +31 -31
  154. package/lib/errors/internal-modules-prefix.js +8 -8
  155. package/lib/errors/is-internal-stack-frame.js +45 -45
  156. package/lib/errors/process-test-fn-error.js +37 -37
  157. package/lib/errors/runtime/index.js +123 -123
  158. package/lib/errors/runtime/templates.js +115 -115
  159. package/lib/errors/runtime/type-assertions.js +112 -112
  160. package/lib/errors/stack-cleaning-hook.js +64 -64
  161. package/lib/errors/test-run/formattable-adapter.js +59 -59
  162. package/lib/errors/test-run/index.js +301 -301
  163. package/lib/errors/test-run/render-error-template.js +31 -31
  164. package/lib/errors/test-run/templates.js +91 -91
  165. package/lib/errors/test-run/utils.js +89 -89
  166. package/lib/errors/types.js +156 -156
  167. package/lib/index.js +81 -81
  168. package/lib/live/bootstrapper.js +43 -43
  169. package/lib/live/controller.js +107 -107
  170. package/lib/live/file-watcher/index.js +67 -67
  171. package/lib/live/file-watcher/modules-graph.js +58 -58
  172. package/lib/live/keyboard-observer.js +76 -76
  173. package/lib/live/logger/index.js +64 -64
  174. package/lib/live/test-run-controller.js +96 -96
  175. package/lib/live/test-run-state.js +6 -6
  176. package/lib/live/test-run.js +56 -56
  177. package/lib/live/test-runner.js +167 -167
  178. package/lib/load-assets.js +29 -29
  179. package/lib/notifications/add-rendered-warning.js +16 -16
  180. package/lib/notifications/debug-logger.js +78 -78
  181. package/lib/notifications/deprecated.js +24 -24
  182. package/lib/notifications/information-message.js +9 -9
  183. package/lib/notifications/warning-log.js +31 -31
  184. package/lib/notifications/warning-message.js +47 -47
  185. package/lib/reporter/command/command-formatter.js +120 -109
  186. package/lib/reporter/command/format-command.js +8 -8
  187. package/lib/reporter/command/interfaces.js +2 -2
  188. package/lib/reporter/index.js +319 -314
  189. package/lib/reporter/interfaces.js +2 -2
  190. package/lib/reporter/plugin-host.js +135 -135
  191. package/lib/reporter/plugin-methods.js +12 -12
  192. package/lib/role/index.js +74 -74
  193. package/lib/role/marker-symbol.js +7 -7
  194. package/lib/role/phase.js +9 -9
  195. package/lib/runner/bootstrapper.js +271 -271
  196. package/lib/runner/browser-job-result.js +9 -9
  197. package/lib/runner/browser-job.js +152 -152
  198. package/lib/runner/browser-set.js +114 -114
  199. package/lib/runner/fixture-hook-controller.js +85 -85
  200. package/lib/runner/index.js +449 -449
  201. package/lib/runner/interfaces.js +2 -2
  202. package/lib/runner/reporter-stream-controller.js +27 -27
  203. package/lib/runner/task/index.js +151 -151
  204. package/lib/runner/task/phase.js +9 -9
  205. package/lib/runner/test-run-controller.js +165 -165
  206. package/lib/runner/tested-app.js +72 -72
  207. package/lib/screenshots/capturer.js +141 -141
  208. package/lib/screenshots/constants.js +11 -11
  209. package/lib/screenshots/crop.js +111 -111
  210. package/lib/screenshots/default-extension.js +4 -4
  211. package/lib/screenshots/index.js +67 -67
  212. package/lib/screenshots/utils.js +39 -39
  213. package/lib/services/compiler/host.js +190 -190
  214. package/lib/services/compiler/io.js +9 -9
  215. package/lib/services/compiler/protocol.js +17 -16
  216. package/lib/services/compiler/service.js +225 -212
  217. package/lib/services/compiler/test-run-proxy.js +111 -111
  218. package/lib/services/interfaces.js +2 -2
  219. package/lib/services/process-title.js +8 -8
  220. package/lib/services/serialization/prepare-options.js +17 -17
  221. package/lib/services/serialization/replicator/create-replicator.js +25 -25
  222. package/lib/services/serialization/replicator/custom-error-transform.js +26 -26
  223. package/lib/services/serialization/test-structure.js +92 -92
  224. package/lib/services/utils/ipc/interfaces.js +30 -30
  225. package/lib/services/utils/ipc/io.js +108 -108
  226. package/lib/services/utils/ipc/message.js +75 -75
  227. package/lib/services/utils/ipc/packet.js +55 -55
  228. package/lib/services/utils/ipc/proxy.js +109 -109
  229. package/lib/services/utils/ipc/transport.js +64 -64
  230. package/lib/shared/errors/index.js +382 -382
  231. package/lib/shared/node-modules-folder-name.js +4 -4
  232. package/lib/test-run/bookmark.js +90 -90
  233. package/lib/test-run/browser-console-messages.js +73 -73
  234. package/lib/test-run/browser-manipulation-queue.js +92 -92
  235. package/lib/test-run/client-messages.js +9 -9
  236. package/lib/test-run/commands/actions.js +486 -483
  237. package/lib/test-run/commands/assertion.js +45 -45
  238. package/lib/test-run/commands/base.js +14 -14
  239. package/lib/test-run/commands/browser-manipulation.js +95 -95
  240. package/lib/test-run/commands/from-object.js +82 -82
  241. package/lib/test-run/commands/observation.js +61 -61
  242. package/lib/test-run/commands/options.js +231 -215
  243. package/lib/test-run/commands/service.js +54 -48
  244. package/lib/test-run/commands/type.js +65 -64
  245. package/lib/test-run/commands/utils.js +87 -87
  246. package/lib/test-run/commands/validations/argument.js +90 -90
  247. package/lib/test-run/commands/validations/factories.js +47 -47
  248. package/lib/test-run/commands/validations/initializers.js +44 -44
  249. package/lib/test-run/debug-log.js +32 -32
  250. package/lib/test-run/execute-js-expression.js +74 -74
  251. package/lib/test-run/index.js +823 -799
  252. package/lib/test-run/marker-symbol.js +7 -7
  253. package/lib/test-run/observed-callsites-storage.js +17 -17
  254. package/lib/test-run/phase.js +16 -16
  255. package/lib/test-run/session-controller.js +104 -104
  256. package/lib/testcafe.js +118 -118
  257. package/lib/utils/assignable.js +39 -39
  258. package/lib/utils/async-event-emitter.js +28 -28
  259. package/lib/utils/async-queue.js +14 -14
  260. package/lib/utils/browser-connection-timeouts.js +19 -19
  261. package/lib/utils/callsite.js +17 -17
  262. package/lib/utils/check-file-path.js +31 -31
  263. package/lib/utils/check-url.js +51 -51
  264. package/lib/utils/convert-to-best-fit-type.js +16 -16
  265. package/lib/utils/correct-file-path.js +21 -21
  266. package/lib/utils/define-lazy-property.js +13 -13
  267. package/lib/utils/delay.js +6 -6
  268. package/lib/utils/delegated-api.js +44 -44
  269. package/lib/utils/detect-display.js +6 -6
  270. package/lib/utils/detect-ffmpeg.js +44 -44
  271. package/lib/utils/diff/colors.js +29 -29
  272. package/lib/utils/diff/index.js +52 -52
  273. package/lib/utils/diff/util.js +23 -23
  274. package/lib/utils/diff.js +29 -29
  275. package/lib/utils/escape-user-agent.js +10 -10
  276. package/lib/utils/flag-list.js +17 -17
  277. package/lib/utils/get-any-key.js +8 -8
  278. package/lib/utils/get-browser.js +8 -8
  279. package/lib/utils/get-common-path.js +34 -34
  280. package/lib/utils/get-filter-fn.js +40 -40
  281. package/lib/utils/get-options/base.js +36 -36
  282. package/lib/utils/get-options/compiler.js +33 -33
  283. package/lib/utils/get-options/grep.js +15 -15
  284. package/lib/utils/get-options/index.js +20 -20
  285. package/lib/utils/get-options/meta.js +22 -22
  286. package/lib/utils/get-options/quarantine.js +91 -91
  287. package/lib/utils/get-options/screenshot.js +17 -17
  288. package/lib/utils/get-options/ssl.js +45 -45
  289. package/lib/utils/get-options/video.js +10 -10
  290. package/lib/utils/get-viewport-width.js +17 -17
  291. package/lib/utils/guard-time-execution.js +10 -10
  292. package/lib/utils/handle-errors.js +74 -74
  293. package/lib/utils/handle-tag-args.js +8 -8
  294. package/lib/utils/http.js +30 -30
  295. package/lib/utils/is-localhost.js +11 -11
  296. package/lib/utils/is-password-input.js +11 -0
  297. package/lib/utils/is-repl.js +10 -10
  298. package/lib/utils/is-window-in-iframe.js +6 -6
  299. package/lib/utils/limit-number.js +10 -10
  300. package/lib/utils/make-reg-exp.js +7 -7
  301. package/lib/utils/moment-loader.js +20 -20
  302. package/lib/utils/parse-file-list.js +71 -71
  303. package/lib/utils/parse-user-agent.js +55 -55
  304. package/lib/utils/path-pattern.js +114 -114
  305. package/lib/utils/prepare-reporters.js +30 -30
  306. package/lib/utils/prerender-callsite.js +18 -18
  307. package/lib/utils/process.js +119 -119
  308. package/lib/utils/promisified-functions.js +46 -46
  309. package/lib/utils/re-executable-promise.js +39 -39
  310. package/lib/utils/render-callsite-sync.js +29 -29
  311. package/lib/utils/render-template.js +9 -9
  312. package/lib/utils/reporter.js +30 -30
  313. package/lib/utils/resolve-path-relatively-cwd.js +7 -7
  314. package/lib/utils/string.js +105 -105
  315. package/lib/utils/temp-directory/cleanup-process/commands.js +7 -7
  316. package/lib/utils/temp-directory/cleanup-process/index.js +143 -143
  317. package/lib/utils/temp-directory/cleanup-process/worker.js +58 -58
  318. package/lib/utils/temp-directory/index.js +87 -87
  319. package/lib/utils/temp-directory/lockfile.js +56 -56
  320. package/lib/utils/thennable.js +7 -7
  321. package/lib/utils/timer.js +15 -15
  322. package/lib/utils/to-posix-path.js +8 -8
  323. package/lib/utils/types.js +2 -2
  324. package/lib/video-recorder/interfaces.js +2 -2
  325. package/lib/video-recorder/process.js +126 -126
  326. package/lib/video-recorder/recorder.js +136 -136
  327. package/lib/video-recorder/test-run-video-recorder.js +69 -69
  328. package/lib/video-recorder/videos.js +37 -37
  329. package/package.json +2 -2
  330. package/ts-defs/index.d.ts +25 -14
  331. package/ts-defs/selectors.d.ts +16 -5
  332. package/ts-defs/testcafe-scripts.d.ts +17 -6
@@ -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==