@appium/base-driver 8.3.0 → 8.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/basedriver/capabilities.d.ts +80 -0
- package/build/lib/basedriver/capabilities.d.ts.map +1 -0
- package/build/lib/basedriver/capabilities.js +12 -13
- package/build/lib/basedriver/commands/event.d.ts +9 -0
- package/build/lib/basedriver/commands/event.d.ts.map +1 -0
- package/build/lib/basedriver/commands/event.js +21 -23
- package/build/lib/basedriver/commands/find.d.ts +11 -0
- package/build/lib/basedriver/commands/find.d.ts.map +1 -0
- package/build/lib/basedriver/commands/find.js +42 -37
- package/build/lib/basedriver/commands/index.d.ts +8 -0
- package/build/lib/basedriver/commands/index.d.ts.map +1 -0
- package/build/lib/basedriver/commands/index.js +17 -16
- package/build/lib/basedriver/commands/log.d.ts +12 -0
- package/build/lib/basedriver/commands/log.d.ts.map +1 -0
- package/build/lib/basedriver/commands/log.js +23 -27
- package/build/lib/basedriver/commands/session.d.ts +11 -0
- package/build/lib/basedriver/commands/session.d.ts.map +1 -0
- package/build/lib/basedriver/commands/session.js +21 -149
- package/build/lib/basedriver/commands/settings.d.ts +10 -0
- package/build/lib/basedriver/commands/settings.d.ts.map +1 -0
- package/build/lib/basedriver/commands/settings.js +19 -19
- package/build/lib/basedriver/commands/timeout.d.ts +8 -0
- package/build/lib/basedriver/commands/timeout.d.ts.map +1 -0
- package/build/lib/basedriver/commands/timeout.js +118 -139
- package/build/lib/basedriver/core.d.ts +235 -0
- package/build/lib/basedriver/core.d.ts.map +1 -0
- package/build/lib/basedriver/core.js +283 -0
- package/build/lib/basedriver/desired-caps.d.ts +5 -0
- package/build/lib/basedriver/desired-caps.d.ts.map +1 -0
- package/build/lib/basedriver/desired-caps.js +2 -4
- package/build/lib/basedriver/device-settings.d.ts +32 -0
- package/build/lib/basedriver/device-settings.d.ts.map +1 -0
- package/build/lib/basedriver/device-settings.js +20 -14
- package/build/lib/basedriver/driver.d.ts +83 -0
- package/build/lib/basedriver/driver.d.ts.map +1 -0
- package/build/lib/basedriver/driver.js +101 -256
- package/build/lib/basedriver/helpers.d.ts +132 -0
- package/build/lib/basedriver/helpers.d.ts.map +1 -0
- package/build/lib/basedriver/helpers.js +16 -2
- package/build/lib/basedriver/logger.d.ts +3 -0
- package/build/lib/basedriver/logger.d.ts.map +1 -0
- package/build/lib/basedriver/logger.js +2 -4
- package/build/lib/constants.d.ts +9 -0
- package/build/lib/constants.d.ts.map +1 -0
- package/build/lib/constants.js +2 -4
- package/build/lib/express/crash.d.ts +3 -0
- package/build/lib/express/crash.d.ts.map +1 -0
- package/build/lib/express/crash.js +2 -4
- package/build/lib/express/express-logging.d.ts +3 -0
- package/build/lib/express/express-logging.d.ts.map +1 -0
- package/build/lib/express/express-logging.js +2 -4
- package/build/lib/express/idempotency.d.ts +2 -0
- package/build/lib/express/idempotency.d.ts.map +1 -0
- package/build/lib/express/idempotency.js +2 -4
- package/build/lib/express/logger.d.ts +3 -0
- package/build/lib/express/logger.d.ts.map +1 -0
- package/build/lib/express/logger.js +2 -4
- package/build/lib/express/middleware.d.ts +9 -0
- package/build/lib/express/middleware.d.ts.map +1 -0
- package/build/lib/express/middleware.js +2 -4
- package/build/lib/express/server.d.ts +10 -0
- package/build/lib/express/server.d.ts.map +1 -0
- package/build/lib/express/server.js +2 -4
- package/build/lib/express/static.d.ts +6 -0
- package/build/lib/express/static.d.ts.map +1 -0
- package/build/lib/express/static.js +2 -4
- package/build/lib/express/websocket.d.ts +64 -0
- package/build/lib/express/websocket.d.ts.map +1 -0
- package/build/lib/express/websocket.js +40 -41
- package/build/lib/helpers/capabilities.d.ts +13 -0
- package/build/lib/helpers/capabilities.d.ts.map +1 -0
- package/build/lib/helpers/capabilities.js +40 -2
- package/build/lib/index.d.ts +183 -0
- package/build/lib/index.d.ts.map +1 -0
- package/build/lib/index.js +41 -23
- package/build/lib/jsonwp-proxy/protocol-converter.d.ts +48 -0
- package/build/lib/jsonwp-proxy/protocol-converter.d.ts.map +1 -0
- package/build/lib/jsonwp-proxy/protocol-converter.js +2 -4
- package/build/lib/jsonwp-proxy/proxy.d.ts +41 -0
- package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -0
- package/build/lib/jsonwp-proxy/proxy.js +25 -9
- package/build/lib/jsonwp-status/status.d.ts +159 -0
- package/build/lib/jsonwp-status/status.d.ts.map +1 -0
- package/build/lib/jsonwp-status/status.js +2 -4
- package/build/lib/protocol/errors.d.ts +310 -0
- package/build/lib/protocol/errors.d.ts.map +1 -0
- package/build/lib/protocol/errors.js +82 -5
- package/build/lib/protocol/helpers.d.ts +22 -0
- package/build/lib/protocol/helpers.d.ts.map +1 -0
- package/build/lib/protocol/helpers.js +2 -4
- package/build/lib/protocol/index.d.ts +16 -0
- package/build/lib/protocol/index.d.ts.map +1 -0
- package/build/lib/protocol/index.js +8 -10
- package/build/lib/protocol/protocol.d.ts +11 -0
- package/build/lib/protocol/protocol.d.ts.map +1 -0
- package/build/lib/protocol/protocol.js +3 -9
- package/build/lib/protocol/routes.d.ts +6 -0
- package/build/lib/protocol/routes.d.ts.map +1 -0
- package/build/lib/protocol/routes.js +18 -4
- package/build/lib/protocol/validators.d.ts +8 -0
- package/build/lib/protocol/validators.d.ts.map +1 -0
- package/build/lib/protocol/validators.js +2 -4
- package/build/test/basedriver/README.md +5 -0
- package/build/test/basedriver/driver-e2e-tests.js +2 -4
- package/build/test/basedriver/driver-tests.js +31 -6
- package/build/test/basedriver/index.js +2 -4
- package/build/test/e2e/basedriver/driver.e2e.spec.js +15 -0
- package/build/test/e2e/basedriver/helpers.e2e.spec.js +192 -0
- package/build/test/e2e/basedriver/websockets.e2e.spec.js +87 -0
- package/build/test/e2e/express/server.e2e.spec.js +159 -0
- package/build/test/e2e/jsonwp-proxy/proxy.e2e.spec.js +59 -0
- package/build/test/e2e/protocol/fake-driver.js +163 -0
- package/build/test/e2e/protocol/helpers.js +25 -0
- package/build/test/e2e/protocol/protocol.e2e.spec.js +1186 -0
- package/build/test/helpers.js +2 -4
- package/build/test/unit/basedriver/capabilities.spec.js +672 -0
- package/build/test/unit/basedriver/capability.spec.js +353 -0
- package/build/test/unit/basedriver/commands/event.spec.js +110 -0
- package/build/test/unit/basedriver/commands/log.spec.js +92 -0
- package/build/test/unit/basedriver/driver.spec.js +15 -0
- package/build/test/unit/basedriver/helpers.spec.js +151 -0
- package/build/test/unit/basedriver/timeout.spec.js +135 -0
- package/build/test/unit/express/server.spec.js +155 -0
- package/build/test/unit/express/static.spec.js +26 -0
- package/build/test/unit/jsonwp-proxy/mock-request.js +91 -0
- package/build/test/unit/jsonwp-proxy/protocol-converter.spec.js +171 -0
- package/build/test/unit/jsonwp-proxy/proxy.spec.js +292 -0
- package/build/test/unit/jsonwp-proxy/url.spec.js +165 -0
- package/build/test/unit/jsonwp-status/status.spec.js +34 -0
- package/build/test/unit/protocol/errors.spec.js +390 -0
- package/build/test/unit/protocol/routes.spec.js +80 -0
- package/build/test/unit/protocol/validator.spec.js +149 -0
- package/build/tsconfig.tsbuildinfo +1 -0
- package/lib/basedriver/capabilities.js +49 -10
- package/lib/basedriver/commands/event.js +49 -31
- package/lib/basedriver/commands/find.js +108 -43
- package/lib/basedriver/commands/index.js +25 -19
- package/lib/basedriver/commands/log.js +60 -33
- package/lib/basedriver/commands/session.js +39 -141
- package/lib/basedriver/commands/settings.js +33 -13
- package/lib/basedriver/commands/timeout.js +153 -153
- package/lib/basedriver/core.js +497 -0
- package/lib/basedriver/desired-caps.js +1 -1
- package/lib/basedriver/device-settings.js +47 -12
- package/lib/basedriver/driver.js +272 -383
- package/lib/basedriver/helpers.js +18 -2
- package/lib/express/websocket.js +35 -32
- package/lib/helpers/capabilities.js +60 -1
- package/lib/index.js +16 -12
- package/lib/jsonwp-proxy/proxy.js +26 -6
- package/lib/protocol/errors.js +42 -42
- package/lib/protocol/index.js +4 -4
- package/lib/protocol/protocol.js +1 -3
- package/lib/protocol/routes.js +9 -0
- package/package.json +22 -14
- package/test/basedriver/README.md +5 -0
- package/test/basedriver/driver-e2e-tests.js +1 -1
- package/test/basedriver/driver-tests.js +31 -2
- package/build/test/basedriver/capabilities-specs.js +0 -674
- package/build/test/basedriver/capability-specs.js +0 -355
- package/build/test/basedriver/commands/event-specs.js +0 -112
- package/build/test/basedriver/commands/log-specs.js +0 -87
- package/build/test/basedriver/driver-e2e-specs.js +0 -17
- package/build/test/basedriver/driver-specs.js +0 -17
- package/build/test/basedriver/helpers-e2e-specs.js +0 -194
- package/build/test/basedriver/helpers-specs.js +0 -153
- package/build/test/basedriver/timeout-specs.js +0 -137
- package/build/test/basedriver/websockets-e2e-specs.js +0 -84
- package/build/test/express/server-e2e-specs.js +0 -161
- package/build/test/express/server-specs.js +0 -157
- package/build/test/express/static-specs.js +0 -28
- package/build/test/jsonwp-proxy/mock-request.js +0 -93
- package/build/test/jsonwp-proxy/protocol-converter-specs.js +0 -173
- package/build/test/jsonwp-proxy/proxy-e2e-specs.js +0 -61
- package/build/test/jsonwp-proxy/proxy-specs.js +0 -294
- package/build/test/jsonwp-proxy/url-specs.js +0 -167
- package/build/test/jsonwp-status/status-specs.js +0 -36
- package/build/test/protocol/errors-specs.js +0 -388
- package/build/test/protocol/fake-driver.js +0 -165
- package/build/test/protocol/helpers.js +0 -27
- package/build/test/protocol/protocol-e2e-specs.js +0 -1188
- package/build/test/protocol/routes-specs.js +0 -82
- package/build/test/protocol/validator-specs.js +0 -151
- package/index.d.ts +0 -386
- package/test/basedriver/capabilities-specs.js +0 -537
- package/test/basedriver/capability-specs.js +0 -383
- package/test/basedriver/commands/event-specs.js +0 -74
- package/test/basedriver/commands/log-specs.js +0 -79
- package/test/basedriver/driver-e2e-specs.js +0 -8
- package/test/basedriver/driver-specs.js +0 -8
- package/test/basedriver/fixtures/BadZippedApp.zip +0 -1
- package/test/basedriver/fixtures/FakeAndroidApp.apk +0 -1
- package/test/basedriver/fixtures/FakeAndroidApp.asd +0 -0
- package/test/basedriver/fixtures/FakeIOSApp.app +0 -1
- package/test/basedriver/fixtures/FakeIOSApp.app.zip +0 -0
- package/test/basedriver/fixtures/FakeIOSApp.ipa +0 -0
- package/test/basedriver/fixtures/custom-element-finder-bad.js +0 -5
- package/test/basedriver/fixtures/custom-element-finder.js +0 -29
- package/test/basedriver/helpers-e2e-specs.js +0 -187
- package/test/basedriver/helpers-specs.js +0 -137
- package/test/basedriver/timeout-specs.js +0 -128
- package/test/basedriver/websockets-e2e-specs.js +0 -75
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
require("source-map-support/register");
|
|
6
|
+
|
|
7
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
|
+
|
|
9
|
+
var _constants = require("../../../lib/constants");
|
|
10
|
+
|
|
11
|
+
var _protocolConverter = _interopRequireWildcard(require("../../../lib/jsonwp-proxy/protocol-converter"));
|
|
12
|
+
|
|
13
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
14
|
+
|
|
15
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
MJSONWP,
|
|
19
|
+
W3C
|
|
20
|
+
} = _constants.PROTOCOLS;
|
|
21
|
+
describe('Protocol Converter', function () {
|
|
22
|
+
describe('getTimeoutRequestObjects', function () {
|
|
23
|
+
let converter;
|
|
24
|
+
before(function () {
|
|
25
|
+
converter = new _protocolConverter.default(_lodash.default.noop);
|
|
26
|
+
});
|
|
27
|
+
it('should take W3C inputs and produce MJSONWP compatible objects', function () {
|
|
28
|
+
converter.downstreamProtocol = MJSONWP;
|
|
29
|
+
let timeoutObjects = converter.getTimeoutRequestObjects({
|
|
30
|
+
script: 100
|
|
31
|
+
});
|
|
32
|
+
timeoutObjects.length.should.equal(1);
|
|
33
|
+
timeoutObjects[0].should.eql({
|
|
34
|
+
type: 'script',
|
|
35
|
+
ms: 100
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it('should ignore invalid entries while converting from W3C', function () {
|
|
39
|
+
converter.downstreamProtocol = MJSONWP;
|
|
40
|
+
let timeoutObjects = converter.getTimeoutRequestObjects({
|
|
41
|
+
script: 100,
|
|
42
|
+
sessionId: '5432a4f3-cd89-4781-8905-ea9d3150840c',
|
|
43
|
+
bar: -1,
|
|
44
|
+
baz: undefined
|
|
45
|
+
});
|
|
46
|
+
timeoutObjects.length.should.equal(1);
|
|
47
|
+
timeoutObjects[0].should.eql({
|
|
48
|
+
type: 'script',
|
|
49
|
+
ms: 100
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
it('should take multiple W3C timeouts and produce multiple MJSONWP compatible objects', function () {
|
|
53
|
+
converter.downstreamProtocol = MJSONWP;
|
|
54
|
+
let [scriptTimeout, pageLoadTimeout, implicitTimeout] = converter.getTimeoutRequestObjects({
|
|
55
|
+
script: 100,
|
|
56
|
+
pageLoad: 200,
|
|
57
|
+
implicit: 300
|
|
58
|
+
});
|
|
59
|
+
scriptTimeout.should.eql({
|
|
60
|
+
type: 'script',
|
|
61
|
+
ms: 100
|
|
62
|
+
});
|
|
63
|
+
pageLoadTimeout.should.eql({
|
|
64
|
+
type: 'page load',
|
|
65
|
+
ms: 200
|
|
66
|
+
});
|
|
67
|
+
implicitTimeout.should.eql({
|
|
68
|
+
type: 'implicit',
|
|
69
|
+
ms: 300
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
it('should take MJSONWP input and produce W3C compatible object', function () {
|
|
73
|
+
converter.downstreamProtocol = W3C;
|
|
74
|
+
let timeoutObjects = converter.getTimeoutRequestObjects({
|
|
75
|
+
type: 'implicit',
|
|
76
|
+
ms: 300
|
|
77
|
+
});
|
|
78
|
+
timeoutObjects.length.should.equal(1);
|
|
79
|
+
timeoutObjects[0].should.eql({
|
|
80
|
+
implicit: 300
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
it('should not change the input if protocol name is unknown', function () {
|
|
84
|
+
converter.downstreamProtocol = null;
|
|
85
|
+
let timeoutObjects = converter.getTimeoutRequestObjects({
|
|
86
|
+
type: 'implicit',
|
|
87
|
+
ms: 300
|
|
88
|
+
});
|
|
89
|
+
timeoutObjects.length.should.equal(1);
|
|
90
|
+
timeoutObjects[0].should.eql({
|
|
91
|
+
type: 'implicit',
|
|
92
|
+
ms: 300
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
it('should not change the input if protocol name is unchanged', function () {
|
|
96
|
+
converter.downstreamProtocol = MJSONWP;
|
|
97
|
+
let timeoutObjects = converter.getTimeoutRequestObjects({
|
|
98
|
+
type: 'implicit',
|
|
99
|
+
ms: 300
|
|
100
|
+
});
|
|
101
|
+
timeoutObjects.length.should.equal(1);
|
|
102
|
+
timeoutObjects[0].should.eql({
|
|
103
|
+
type: 'implicit',
|
|
104
|
+
ms: 300
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe('setValue', function () {
|
|
109
|
+
let converter;
|
|
110
|
+
let responseBody;
|
|
111
|
+
before(function () {
|
|
112
|
+
responseBody = null;
|
|
113
|
+
converter = new _protocolConverter.default((url, method, body) => {
|
|
114
|
+
responseBody = body;
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
beforeEach(function () {
|
|
118
|
+
responseBody = {};
|
|
119
|
+
});
|
|
120
|
+
it('should calculate value if not present', async function () {
|
|
121
|
+
await converter.proxySetValue('', '', {
|
|
122
|
+
text: 'bla'
|
|
123
|
+
});
|
|
124
|
+
responseBody.should.eql({
|
|
125
|
+
text: 'bla',
|
|
126
|
+
value: ['b', 'l', 'a']
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
it('should calculate text if not present', async function () {
|
|
130
|
+
await converter.proxySetValue('', '', {
|
|
131
|
+
value: ['b', 'l', 'a']
|
|
132
|
+
});
|
|
133
|
+
responseBody.should.eql({
|
|
134
|
+
text: 'bla',
|
|
135
|
+
value: ['b', 'l', 'a']
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
it('should keep the response body unchanged if both value and text are present', async function () {
|
|
139
|
+
await converter.proxySetValue('', '', {
|
|
140
|
+
text: 'bla',
|
|
141
|
+
value: ['b', 'l', 'a']
|
|
142
|
+
});
|
|
143
|
+
responseBody.should.eql({
|
|
144
|
+
text: 'bla',
|
|
145
|
+
value: ['b', 'l', 'a']
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
describe('getProperty', function () {
|
|
150
|
+
let jsonwpConverter, w3cConverter;
|
|
151
|
+
before(function () {
|
|
152
|
+
for (let command of _protocolConverter.COMMAND_URLS_CONFLICTS) {
|
|
153
|
+
if (command.commandNames.includes('getProperty')) {
|
|
154
|
+
jsonwpConverter = command.jsonwpConverter;
|
|
155
|
+
w3cConverter = command.w3cConverter;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
it('should convert "property/value" to "attribute/value"', function () {
|
|
160
|
+
jsonwpConverter('/session/123/element/456/property/value').should.equal('/session/123/element/456/attribute/value');
|
|
161
|
+
});
|
|
162
|
+
it('should convert "property/:somePropName" to "attribute/:somePropName"', function () {
|
|
163
|
+
jsonwpConverter('/session/123/element/456/property/somePropName').should.equal('/session/123/element/456/attribute/somePropName');
|
|
164
|
+
});
|
|
165
|
+
it('should not convert from JSONWP to W3C', function () {
|
|
166
|
+
w3cConverter('/session/123/element/456/attribute/someAttr').should.equal('/session/123/element/456/attribute/someAttr');
|
|
167
|
+
w3cConverter('/session/123/element/456/property/someProp').should.equal('/session/123/element/456/property/someProp');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Rlc3QvdW5pdC9qc29ud3AtcHJveHkvcHJvdG9jb2wtY29udmVydGVyLnNwZWMuanMiXSwibmFtZXMiOlsiTUpTT05XUCIsIlczQyIsIlBST1RPQ09MUyIsImRlc2NyaWJlIiwiY29udmVydGVyIiwiYmVmb3JlIiwiUHJvdG9jb2xDb252ZXJ0ZXIiLCJfIiwibm9vcCIsIml0IiwiZG93bnN0cmVhbVByb3RvY29sIiwidGltZW91dE9iamVjdHMiLCJnZXRUaW1lb3V0UmVxdWVzdE9iamVjdHMiLCJzY3JpcHQiLCJsZW5ndGgiLCJzaG91bGQiLCJlcXVhbCIsImVxbCIsInR5cGUiLCJtcyIsInNlc3Npb25JZCIsImJhciIsImJheiIsInVuZGVmaW5lZCIsInNjcmlwdFRpbWVvdXQiLCJwYWdlTG9hZFRpbWVvdXQiLCJpbXBsaWNpdFRpbWVvdXQiLCJwYWdlTG9hZCIsImltcGxpY2l0IiwicmVzcG9uc2VCb2R5IiwidXJsIiwibWV0aG9kIiwiYm9keSIsImJlZm9yZUVhY2giLCJwcm94eVNldFZhbHVlIiwidGV4dCIsInZhbHVlIiwianNvbndwQ29udmVydGVyIiwidzNjQ29udmVydGVyIiwiY29tbWFuZCIsIkNPTU1BTkRfVVJMU19DT05GTElDVFMiLCJjb21tYW5kTmFtZXMiLCJpbmNsdWRlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7Ozs7OztBQUVBLE1BQU07QUFBQ0EsRUFBQUEsT0FBRDtBQUFVQyxFQUFBQTtBQUFWLElBQWlCQyxvQkFBdkI7QUFHQUMsUUFBUSxDQUFDLG9CQUFELEVBQXVCLFlBQVk7QUFDekNBLEVBQUFBLFFBQVEsQ0FBQywwQkFBRCxFQUE2QixZQUFZO0FBQy9DLFFBQUlDLFNBQUo7QUFDQUMsSUFBQUEsTUFBTSxDQUFDLFlBQVk7QUFDakJELE1BQUFBLFNBQVMsR0FBRyxJQUFJRSwwQkFBSixDQUFzQkMsZ0JBQUVDLElBQXhCLENBQVo7QUFDRCxLQUZLLENBQU47QUFHQUMsSUFBQUEs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eUVDLEtBQXpFLENBQStFLGlEQUEvRTtBQUNELEtBRkMsQ0FBRjtBQUdBUCxJQUFBQSxFQUFFLENBQUMsdUNBQUQsRUFBMEMsWUFBWTtBQUN0RDZCLE1BQUFBLFlBQVksQ0FBQyw2Q0FBRCxDQUFaLENBQTREdkIsTUFBNUQsQ0FBbUVDLEtBQW5FLENBQXlFLDZDQUF6RTtBQUNBc0IsTUFBQUEsWUFBWSxDQUFDLDRDQUFELENBQVosQ0FBMkR2QixNQUEzRCxDQUFrRUMsS0FBbEUsQ0FBd0UsNENBQXhFO0FBQ0QsS0FIQyxDQUFGO0FBSUQsR0FwQk8sQ0FBUjtBQXFCRCxDQTFITyxDQUFSIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IFBST1RPQ09MUyB9IGZyb20gJy4uLy4uLy4uL2xpYi9jb25zdGFudHMnO1xuaW1wb3J0IFByb3RvY29sQ29udmVydGVyLCB7Q09NTUFORF9VUkxTX0NPTkZMSUNUU30gZnJvbSAnLi4vLi4vLi4vbGliL2pzb253cC1wcm94eS9wcm90b2NvbC1jb252ZXJ0ZXInO1xuXG5jb25zdCB7TUpTT05XUCwgVzNDfSA9IFBST1RPQ09MUztcblxuXG5kZXNjcmliZSgnUHJvdG9jb2wgQ29udmVydGVyJywgZnVuY3Rpb24gKCkge1xuICBkZXNjcmliZSgnZ2V0VGltZW91dFJlcXVlc3RPYmplY3RzJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBjb252ZXJ0ZXI7XG4gICAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnZlcnRlciA9IG5ldyBQcm90b2NvbENvbnZlcnRlcihfLm5vb3ApO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgdGFrZSBXM0MgaW5wdXRzIGFuZCBwcm9kdWNlIE1KU09OV1AgY29tcGF0aWJsZSBvYmplY3RzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29udmVydGVyLmRvd25zdHJlYW1Qcm90b2NvbCA9IE1KU09OV1A7XG4gICAgICBsZXQgdGltZW91dE9iamVjdHMgPSBjb252ZXJ0ZXIuZ2V0VGltZW91dFJlcXVlc3RPYmplY3RzKHtzY3JpcHQ6IDEwMH0pO1xuICAgICAgdGltZW91dE9iamVjdHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHRpbWVvdXRPYmplY3RzWzBdLnNob3VsZC5lcWwoe3R5cGU6ICdzY3JpcHQnLCBtczogMTAwfSk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCBpZ25vcmUgaW52YWxpZCBlbnRyaWVzIHdoaWxlIGNvbnZlcnRpbmcgZnJvbSBXM0MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb252ZXJ0ZXIuZG93bnN0cmVhbVByb3RvY29sID0gTUpTT05XUDtcbiAgICAgIGxldCB0aW1lb3V0T2JqZWN0cyA9IGNvbnZlcnRlci5nZXRUaW1lb3V0UmVxdWVzdE9iamVjdHMoe1xuICAgICAgICBzY3JpcHQ6IDEwMCxcbiAgICAgICAgc2Vzc2lvbklkOiAnNTQzMmE0ZjMtY2Q4OS00NzgxLTg5MDUtZWE5ZDMxNTA4NDBjJyxcbiAgICAgICAgYmFyOiAtMSxcbiAgICAgICAgYmF6OiB1bmRlZmluZWQsXG4gICAgICB9KTtcbiAgICAgIHRpbWVvdXRPYmplY3RzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB0aW1lb3V0T2JqZWN0c1swXS5zaG91bGQuZXFsKHt0eXBlOiAnc2NyaXB0JywgbXM6IDEwMH0pO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgdGFrZSBtdWx0aXBsZSBXM0MgdGltZW91dHMgYW5kIHByb2R1Y2UgbXVsdGlwbGUgTUpTT05XUCBjb21wYXRpYmxlIG9iamVjdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb252ZXJ0ZXIuZG93bnN0cmVhbVByb3RvY29sID0gTUpTT05XUDtcbiAgICAgIGxldCBbc2NyaXB0VGltZW91dCwgcGFnZUxvYWRUaW1lb3V0LCBpbXBsaWNpdFRpbWVvdXRdID0gY29udmVydGVyLmdldFRpbWVvdXRSZXF1ZXN0T2JqZWN0cyh7c2NyaXB0OiAxMDAsIHBhZ2VMb2FkOiAyMDAsIGltcGxpY2l0OiAzMDB9KTtcbiAgICAgIHNjcmlwdFRpbWVvdXQuc2hvdWxkLmVxbCh7XG4gICAgICAgIHR5cGU6ICdzY3JpcHQnLFxuICAgICAgICBtczogMTAwLFxuICAgICAgfSk7XG4gICAgICBwYWdlTG9hZFRpbWVvdXQuc2hvdWxkLmVxbCh7XG4gICAgICAgIHR5cGU6ICdwYWdlIGxvYWQnLFxuICAgICAgICBtczogMjAwLFxuICAgICAgfSk7XG4gICAgICBpbXBsaWNpdFRpbWVvdXQuc2hvdWxkLmVxbCh7XG4gICAgICAgIHR5cGU6ICdpbXBsaWNpdCcsXG4gICAgICAgIG1zOiAzMDAsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHRha2UgTUpTT05XUCBpbnB1dCBhbmQgcHJvZHVjZSBXM0MgY29tcGF0aWJsZSBvYmplY3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb252ZXJ0ZXIuZG93bnN0cmVhbVByb3RvY29sID0gVzNDO1xuICAgICAgbGV0IHRpbWVvdXRPYmplY3RzID0gY29udmVydGVyLmdldFRpbWVvdXRSZXF1ZXN0T2JqZWN0cyh7dHlwZTogJ2ltcGxpY2l0JywgbXM6IDMwMH0pO1xuICAgICAgdGltZW91dE9iamVjdHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHRpbWVvdXRPYmplY3RzWzBdLnNob3VsZC5lcWwoe2ltcGxpY2l0OiAzMDB9KTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIG5vdCBjaGFuZ2UgdGhlIGlucHV0IGlmIHByb3RvY29sIG5hbWUgaXMgdW5rbm93bicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnZlcnRlci5kb3duc3RyZWFtUHJvdG9jb2wgPSBudWxsO1xuICAgICAgbGV0IHRpbWVvdXRPYmplY3RzID0gY29udmVydGVyLmdldFRpbWVvdXRSZXF1ZXN0T2JqZWN0cyh7dHlwZTogJ2ltcGxpY2l0JywgbXM6IDMwMH0pO1xuICAgICAgdGltZW91dE9iamVjdHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHRpbWVvdXRPYmplY3RzWzBdLnNob3VsZC5lcWwoe3R5cGU6ICdpbXBsaWNpdCcsIG1zOiAzMDB9KTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIG5vdCBjaGFuZ2UgdGhlIGlucHV0IGlmIHByb3RvY29sIG5hbWUgaXMgdW5jaGFuZ2VkJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29udmVydGVyLmRvd25zdHJlYW1Qcm90b2NvbCA9IE1KU09OV1A7XG4gICAgICBsZXQgdGltZW91dE9iamVjdHMgPSBjb252ZXJ0ZXIuZ2V0VGltZW91dFJlcXVlc3RPYmplY3RzKHt0eXBlOiAnaW1wbGljaXQnLCBtczogMzAwfSk7XG4gICAgICB0aW1lb3V0T2JqZWN0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdGltZW91dE9iamVjdHNbMF0uc2hvdWxkLmVxbCh7dHlwZTogJ2ltcGxpY2l0JywgbXM6IDMwMH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2V0VmFsdWUnLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGNvbnZlcnRlcjtcbiAgICBsZXQgcmVzcG9uc2VCb2R5O1xuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICByZXNwb25zZUJvZHkgPSBudWxsO1xuICAgICAgY29udmVydGVyID0gbmV3IFByb3RvY29sQ29udmVydGVyKCh1cmwsIG1ldGhvZCwgYm9keSkgPT4ge1xuICAgICAgICByZXNwb25zZUJvZHkgPSBib2R5O1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICByZXNwb25zZUJvZHkgPSB7fTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsY3VsYXRlIHZhbHVlIGlmIG5vdCBwcmVzZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgY29udmVydGVyLnByb3h5U2V0VmFsdWUoJycsICcnLCB7XG4gICAgICAgIHRleHQ6ICdibGEnLFxuICAgICAgfSk7XG4gICAgICByZXNwb25zZUJvZHkuc2hvdWxkLmVxbCh7XG4gICAgICAgIHRleHQ6ICdibGEnLFxuICAgICAgICB2YWx1ZTogWydiJywgJ2wnLCAnYSddLFxuICAgICAgfSk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCBjYWxjdWxhdGUgdGV4dCBpZiBub3QgcHJlc2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGNvbnZlcnRlci5wcm94eVNldFZhbHVlKCcnLCAnJywge1xuICAgICAgICB2YWx1ZTogWydiJywgJ2wnLCAnYSddLFxuICAgICAgfSk7XG4gICAgICByZXNwb25zZUJvZHkuc2hvdWxkLmVxbCh7XG4gICAgICAgIHRleHQ6ICdibGEnLFxuICAgICAgICB2YWx1ZTogWydiJywgJ2wnLCAnYSddLFxuICAgICAgfSk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCBrZWVwIHRoZSByZXNwb25zZSBib2R5IHVuY2hhbmdlZCBpZiBib3RoIHZhbHVlIGFuZCB0ZXh0IGFyZSBwcmVzZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgY29udmVydGVyLnByb3h5U2V0VmFsdWUoJycsICcnLCB7XG4gICAgICAgIHRleHQ6ICdibGEnLFxuICAgICAgICB2YWx1ZTogWydiJywgJ2wnLCAnYSddLFxuICAgICAgfSk7XG4gICAgICByZXNwb25zZUJvZHkuc2hvdWxkLmVxbCh7XG4gICAgICAgIHRleHQ6ICdibGEnLFxuICAgICAgICB2YWx1ZTogWydiJywgJ2wnLCAnYSddLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuICBkZXNjcmliZSgnZ2V0UHJvcGVydHknLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGpzb253cENvbnZlcnRlciwgdzNjQ29udmVydGVyO1xuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBmb3IgKGxldCBjb21tYW5kIG9mIENPTU1BTkRfVVJMU19DT05GTElDVFMpIHtcbiAgICAgICAgaWYgKGNvbW1hbmQuY29tbWFuZE5hbWVzLmluY2x1ZGVzKCdnZXRQcm9wZXJ0eScpKSB7XG4gICAgICAgICAganNvbndwQ29udmVydGVyID0gY29tbWFuZC5qc29ud3BDb252ZXJ0ZXI7XG4gICAgICAgICAgdzNjQ29udmVydGVyID0gY29tbWFuZC53M2NDb252ZXJ0ZXI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIGNvbnZlcnQgXCJwcm9wZXJ0eS92YWx1ZVwiIHRvIFwiYXR0cmlidXRlL3ZhbHVlXCInLCBmdW5jdGlvbiAoKSB7XG4gICAgICBqc29ud3BDb252ZXJ0ZXIoJy9zZXNzaW9uLzEyMy9lbGVtZW50LzQ1Ni9wcm9wZXJ0eS92YWx1ZScpLnNob3VsZC5lcXVhbCgnL3Nlc3Npb24vMTIzL2VsZW1lbnQvNDU2L2F0dHJpYnV0ZS92YWx1ZScpO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgY29udmVydCBcInByb3BlcnR5Lzpzb21lUHJvcE5hbWVcIiB0byBcImF0dHJpYnV0ZS86c29tZVByb3BOYW1lXCInLCBmdW5jdGlvbiAoKSB7XG4gICAgICBqc29ud3BDb252ZXJ0ZXIoJy9zZXNzaW9uLzEyMy9lbGVtZW50LzQ1Ni9wcm9wZXJ0eS9zb21lUHJvcE5hbWUnKS5zaG91bGQuZXF1YWwoJy9zZXNzaW9uLzEyMy9lbGVtZW50LzQ1Ni9hdHRyaWJ1dGUvc29tZVByb3BOYW1lJyk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCBub3QgY29udmVydCBmcm9tIEpTT05XUCB0byBXM0MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB3M2NDb252ZXJ0ZXIoJy9zZXNzaW9uLzEyMy9lbGVtZW50LzQ1Ni9hdHRyaWJ1dGUvc29tZUF0dHInKS5zaG91bGQuZXF1YWwoJy9zZXNzaW9uLzEyMy9lbGVtZW50LzQ1Ni9hdHRyaWJ1dGUvc29tZUF0dHInKTtcbiAgICAgIHczY0NvbnZlcnRlcignL3Nlc3Npb24vMTIzL2VsZW1lbnQvNDU2L3Byb3BlcnR5L3NvbWVQcm9wJykuc2hvdWxkLmVxdWFsKCcvc2Vzc2lvbi8xMjMvZWxlbWVudC80NTYvcHJvcGVydHkvc29tZVByb3AnKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
require("source-map-support/register");
|
|
6
|
+
|
|
7
|
+
var _lib = require("../../../lib");
|
|
8
|
+
|
|
9
|
+
var _mockRequest = _interopRequireDefault(require("./mock-request"));
|
|
10
|
+
|
|
11
|
+
var _errors = require("../../../lib/protocol/errors");
|
|
12
|
+
|
|
13
|
+
var _helpers = require("../../helpers");
|
|
14
|
+
|
|
15
|
+
function buildReqRes(url, method, body) {
|
|
16
|
+
let req = {
|
|
17
|
+
originalUrl: url,
|
|
18
|
+
method,
|
|
19
|
+
body
|
|
20
|
+
};
|
|
21
|
+
let res = {};
|
|
22
|
+
res.headers = {};
|
|
23
|
+
|
|
24
|
+
res.set = (k, v) => {
|
|
25
|
+
res[k] = v;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
res.status = code => {
|
|
29
|
+
res.sentCode = code;
|
|
30
|
+
return res;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
res.send = body => {
|
|
34
|
+
try {
|
|
35
|
+
body = JSON.parse(body);
|
|
36
|
+
} catch (e) {}
|
|
37
|
+
|
|
38
|
+
res.sentBody = body;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return [req, res];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe('proxy', function () {
|
|
45
|
+
let port;
|
|
46
|
+
|
|
47
|
+
function mockProxy(opts = {}) {
|
|
48
|
+
opts = {
|
|
49
|
+
server: _helpers.TEST_HOST,
|
|
50
|
+
port,
|
|
51
|
+
...opts
|
|
52
|
+
};
|
|
53
|
+
let proxy = new _lib.JWProxy(opts);
|
|
54
|
+
|
|
55
|
+
proxy.request = async function (...args) {
|
|
56
|
+
return await (0, _mockRequest.default)(...args);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return proxy;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
before(async function () {
|
|
63
|
+
port = await (0, _helpers.getTestPort)();
|
|
64
|
+
});
|
|
65
|
+
it('should override default params', function () {
|
|
66
|
+
let j = mockProxy({
|
|
67
|
+
server: '127.0.0.2',
|
|
68
|
+
port
|
|
69
|
+
});
|
|
70
|
+
j.server.should.equal('127.0.0.2');
|
|
71
|
+
j.port.should.equal(port);
|
|
72
|
+
});
|
|
73
|
+
it('should save session id on session creation', async function () {
|
|
74
|
+
let j = mockProxy();
|
|
75
|
+
let [res, body] = await j.proxy('/session', 'POST', {
|
|
76
|
+
desiredCapabilities: {}
|
|
77
|
+
});
|
|
78
|
+
res.statusCode.should.equal(200);
|
|
79
|
+
body.should.eql({
|
|
80
|
+
status: 0,
|
|
81
|
+
sessionId: '123',
|
|
82
|
+
value: {
|
|
83
|
+
browserName: 'boo'
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
j.sessionId.should.equal('123');
|
|
87
|
+
});
|
|
88
|
+
describe('getUrlForProxy', function () {
|
|
89
|
+
it('should modify session id, host, and port', function () {
|
|
90
|
+
let j = mockProxy({
|
|
91
|
+
sessionId: '123'
|
|
92
|
+
});
|
|
93
|
+
j.getUrlForProxy('http://host.com:1234/session/456/element/200/value').should.eql(`http://${_helpers.TEST_HOST}:${port}/session/123/element/200/value`);
|
|
94
|
+
});
|
|
95
|
+
it('should prepend scheme, host and port if not provided', function () {
|
|
96
|
+
let j = mockProxy({
|
|
97
|
+
sessionId: '123'
|
|
98
|
+
});
|
|
99
|
+
j.getUrlForProxy('/session/456/element/200/value').should.eql(`http://${_helpers.TEST_HOST}:${port}/session/123/element/200/value`);
|
|
100
|
+
});
|
|
101
|
+
it('should respect nonstandard incoming request base path', function () {
|
|
102
|
+
let j = mockProxy({
|
|
103
|
+
sessionId: '123',
|
|
104
|
+
reqBasePath: ''
|
|
105
|
+
});
|
|
106
|
+
j.getUrlForProxy('/session/456/element/200/value').should.eql(`http://${_helpers.TEST_HOST}:${port}/session/123/element/200/value`);
|
|
107
|
+
j = mockProxy({
|
|
108
|
+
sessionId: '123',
|
|
109
|
+
reqBasePath: '/my/base/path'
|
|
110
|
+
});
|
|
111
|
+
j.getUrlForProxy('/my/base/path/session/456/element/200/value').should.eql(`http://${_helpers.TEST_HOST}:${port}/session/123/element/200/value`);
|
|
112
|
+
});
|
|
113
|
+
it('should work with urls which do not have session ids', function () {
|
|
114
|
+
let j = mockProxy({
|
|
115
|
+
sessionId: '123'
|
|
116
|
+
});
|
|
117
|
+
j.getUrlForProxy('http://host.com:1234/session').should.eql(`http://${_helpers.TEST_HOST}:${port}/session`);
|
|
118
|
+
let newUrl = j.getUrlForProxy('/session');
|
|
119
|
+
newUrl.should.eql(`http://${_helpers.TEST_HOST}:${port}/session`);
|
|
120
|
+
});
|
|
121
|
+
it('should throw an error if url requires a sessionId but its null', function () {
|
|
122
|
+
let j = mockProxy();
|
|
123
|
+
let e;
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
j.getUrlForProxy('/session/456/element/200/value');
|
|
127
|
+
} catch (err) {
|
|
128
|
+
e = err;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
should.exist(e);
|
|
132
|
+
e.message.should.contain('without session id');
|
|
133
|
+
});
|
|
134
|
+
it('should not throw an error if url does not require a session id and its null', function () {
|
|
135
|
+
let j = mockProxy();
|
|
136
|
+
let newUrl = j.getUrlForProxy('/status');
|
|
137
|
+
should.exist(newUrl);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe('straight proxy', function () {
|
|
141
|
+
it('should successfully proxy straight', async function () {
|
|
142
|
+
let j = mockProxy();
|
|
143
|
+
let [res, body] = await j.proxy('/status', 'GET');
|
|
144
|
+
res.statusCode.should.equal(200);
|
|
145
|
+
body.should.eql({
|
|
146
|
+
status: 0,
|
|
147
|
+
value: {
|
|
148
|
+
foo: 'bar'
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
it('should pass along request errors', function () {
|
|
153
|
+
let j = mockProxy({
|
|
154
|
+
sessionId: '123'
|
|
155
|
+
});
|
|
156
|
+
j.proxy('/badurl', 'GET').should.eventually.be.rejectedWith('Could not proxy');
|
|
157
|
+
});
|
|
158
|
+
it('should proxy error responses and codes', async function () {
|
|
159
|
+
let j = mockProxy({
|
|
160
|
+
sessionId: '123'
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
await j.proxy('/element/bad/text', 'GET');
|
|
165
|
+
} catch (e) {
|
|
166
|
+
(0, _errors.isErrorType)(e.getActualError(), _errors.errors.ElementNotVisibleError).should.be.true;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('command proxy', function () {
|
|
171
|
+
it('should successfully proxy command', async function () {
|
|
172
|
+
let j = mockProxy();
|
|
173
|
+
let res = await j.command('/status', 'GET');
|
|
174
|
+
res.should.eql({
|
|
175
|
+
foo: 'bar'
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
it('should pass along request errors', function () {
|
|
179
|
+
let j = mockProxy({
|
|
180
|
+
sessionId: '123'
|
|
181
|
+
});
|
|
182
|
+
j.command('/badurl', 'GET').should.eventually.be.rejectedWith('Could not proxy');
|
|
183
|
+
});
|
|
184
|
+
it('should throw when a command fails', async function () {
|
|
185
|
+
let j = mockProxy({
|
|
186
|
+
sessionId: '123'
|
|
187
|
+
});
|
|
188
|
+
let e = null;
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
await j.command('/element/bad/text', 'GET');
|
|
192
|
+
} catch (err) {
|
|
193
|
+
e = err;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
should.exist(e);
|
|
197
|
+
e.message.should.contain('Invisible element');
|
|
198
|
+
});
|
|
199
|
+
it('should throw when a command fails with a 200 because the status is not 0', async function () {
|
|
200
|
+
let j = mockProxy({
|
|
201
|
+
sessionId: '123'
|
|
202
|
+
});
|
|
203
|
+
let e = null;
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
await j.command('/element/200/text', 'GET');
|
|
207
|
+
} catch (err) {
|
|
208
|
+
e = err;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
should.exist(e);
|
|
212
|
+
e.error.should.eql('element not visible');
|
|
213
|
+
});
|
|
214
|
+
it('should throw when a command fails with a 100', async function () {
|
|
215
|
+
let j = mockProxy({
|
|
216
|
+
sessionId: '123'
|
|
217
|
+
});
|
|
218
|
+
let e = null;
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
await j.command('/session/badchrome/nochrome', 'GET');
|
|
222
|
+
} catch (err) {
|
|
223
|
+
e = err;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
should.exist(e);
|
|
227
|
+
e.message.should.contain('chrome not reachable');
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
describe('req/res proxy', function () {
|
|
231
|
+
it('should successfully proxy via req and send to res', async function () {
|
|
232
|
+
let j = mockProxy();
|
|
233
|
+
let [req, res] = buildReqRes('/status', 'GET');
|
|
234
|
+
await j.proxyReqRes(req, res);
|
|
235
|
+
res.headers['content-type'].should.equal('application/json; charset=utf-8');
|
|
236
|
+
res.sentCode.should.equal(200);
|
|
237
|
+
res.sentBody.should.eql({
|
|
238
|
+
value: {
|
|
239
|
+
foo: 'bar'
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
it('should rewrite the inner session id so it doesnt change', async function () {
|
|
244
|
+
let j = mockProxy({
|
|
245
|
+
sessionId: '123'
|
|
246
|
+
});
|
|
247
|
+
let [req, res] = buildReqRes('/element/200/value', 'GET');
|
|
248
|
+
await j.proxyReqRes(req, res);
|
|
249
|
+
res.sentBody.should.eql({
|
|
250
|
+
value: 'foobar',
|
|
251
|
+
sessionId: '123'
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
it('should rewrite the inner session id with sessionId in url', async function () {
|
|
255
|
+
let j = mockProxy({
|
|
256
|
+
sessionId: '123'
|
|
257
|
+
});
|
|
258
|
+
let [req, res] = buildReqRes('/session/456/element/200/value', 'POST');
|
|
259
|
+
await j.proxyReqRes(req, res);
|
|
260
|
+
res.sentBody.should.eql({
|
|
261
|
+
value: 'foobar',
|
|
262
|
+
sessionId: '456'
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
it('should pass through urls that do not require session IDs', async function () {
|
|
266
|
+
let j = mockProxy({
|
|
267
|
+
sessionId: '123'
|
|
268
|
+
});
|
|
269
|
+
let [req, res] = buildReqRes('/status', 'GET');
|
|
270
|
+
await j.proxyReqRes(req, res);
|
|
271
|
+
res.sentBody.should.eql({
|
|
272
|
+
value: {
|
|
273
|
+
'foo': 'bar'
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
it('should proxy strange responses', async function () {
|
|
278
|
+
let j = mockProxy({
|
|
279
|
+
sessionId: '123'
|
|
280
|
+
});
|
|
281
|
+
let [req, res] = buildReqRes('/nochrome', 'GET');
|
|
282
|
+
await j.proxyReqRes(req, res);
|
|
283
|
+
res.sentCode.should.equal(100);
|
|
284
|
+
res.sentBody.should.eql({
|
|
285
|
+
value: {
|
|
286
|
+
message: 'chrome not reachable'
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Rlc3QvdW5pdC9qc29ud3AtcHJveHkvcHJveHkuc3BlYy5qcyJdLCJuYW1lcyI6WyJidWlsZFJlcVJlcyIsInVybCIsIm1ldGhvZCIsImJvZHkiLCJyZXEiLCJvcmlnaW5hbFVybCIsInJlcyIsImhlYWRlcnMiLCJzZXQiLCJrIiwidiIsInN0YXR1cyIsImNvZGUiLCJzZW50Q29kZSIsInNlbmQiLCJKU09OIiwicGFyc2UiLCJlIiwic2VudEJvZHkiLCJkZXNjcmliZSIsInBvcnQiLCJtb2NrUHJveHkiLCJvcHRzIiwic2VydmVyIiwiVEVTVF9IT1NUIiwicHJveHkiLCJKV1Byb3h5IiwicmVxdWVzdCIsImFyZ3MiLCJiZWZvcmUiLCJpdCIsImoiLCJzaG91bGQiLCJlcXVhbCIsImRlc2lyZWRDYXBhYmlsaXRpZXMiLCJzdGF0dXNDb2RlIiwiZXFsIiwic2Vzc2lvbklkIiwidmFsdWUiLCJicm93c2VyTmFtZSIsImdldFVybEZvclByb3h5IiwicmVxQmFzZVBhdGgiLCJuZXdVcmwiLCJlcnIiLCJleGlzdCIsIm1lc3NhZ2UiLCJjb250YWluIiwiZm9vIiwiZXZlbnR1YWxseSIsImJlIiwicmVqZWN0ZWRXaXRoIiwiZ2V0QWN0dWFsRXJyb3IiLCJlcnJvcnMiLCJFbGVtZW50Tm90VmlzaWJsZUVycm9yIiwidHJ1ZSIsImNvbW1hbmQiLCJlcnJvciIsInByb3h5UmVxUmVzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFFQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQSxTQUFTQSxXQUFULENBQXNCQyxHQUF0QixFQUEyQkMsTUFBM0IsRUFBbUNDLElBQW5DLEVBQXlDO0FBQ3ZDLE1BQUlDLEdBQUcsR0FBRztBQUFDQyxJQUFBQSxXQUFXLEVBQUVKLEdBQWQ7QUFBbUJDLElBQUFBLE1BQW5CO0FBQTJCQyxJQUFBQTtBQUEzQixHQUFWO0FBQ0EsTUFBSUcsR0FBRyxHQUFHLEVBQVY7QUFDQUEsRUFBQUEsR0FBRyxDQUFDQyxPQUFKLEdBQWMsRUFB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K0IsQ0FBQyxDQUFDMEIsV0FBRixDQUFjckQsR0FBZCxFQUFtQkUsR0FBbkIsQ0FBTjtBQUNBQSxNQUFBQSxHQUFHLENBQUNPLFFBQUosQ0FBYW1CLE1BQWIsQ0FBb0JDLEtBQXBCLENBQTBCLEdBQTFCO0FBQ0EzQixNQUFBQSxHQUFHLENBQUNZLFFBQUosQ0FBYWMsTUFBYixDQUFvQkksR0FBcEIsQ0FBd0I7QUFBQ0UsUUFBQUEsS0FBSyxFQUFFO0FBQUNPLFVBQUFBLE9BQU8sRUFBRTtBQUFWO0FBQVIsT0FBeEI7QUFDRCxLQU5DLENBQUY7QUFPRCxHQWxDTyxDQUFSO0FBbUNELENBOUtPLENBQVIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0cmFuc3BpbGU6bW9jaGFcblxuaW1wb3J0IHsgSldQcm94eSB9IGZyb20gJy4uLy4uLy4uL2xpYic7XG5pbXBvcnQgcmVxdWVzdCBmcm9tICcuL21vY2stcmVxdWVzdCc7XG5pbXBvcnQgeyBpc0Vycm9yVHlwZSwgZXJyb3JzIH0gZnJvbSAnLi4vLi4vLi4vbGliL3Byb3RvY29sL2Vycm9ycyc7XG5pbXBvcnQgeyBnZXRUZXN0UG9ydCwgVEVTVF9IT1NUIH0gZnJvbSAnLi4vLi4vaGVscGVycyc7XG5cbmZ1bmN0aW9uIGJ1aWxkUmVxUmVzICh1cmwsIG1ldGhvZCwgYm9keSkge1xuICBsZXQgcmVxID0ge29yaWdpbmFsVXJsOiB1cmwsIG1ldGhvZCwgYm9keX07XG4gIGxldCByZXMgPSB7fTtcbiAgcmVzLmhlYWRlcnMgPSB7fTtcbiAgcmVzLnNldCA9IChrLCB2KSA9PiB7IHJlc1trXSA9IHY7IH07XG4gIHJlcy5zdGF0dXMgPSAoY29kZSkgPT4ge1xuICAgIHJlcy5zZW50Q29kZSA9IGNvZGU7XG4gICAgcmV0dXJuIHJlcztcbiAgfTtcbiAgcmVzLnNlbmQgPSAoYm9keSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBib2R5ID0gSlNPTi5wYXJzZShib2R5KTtcbiAgICB9IGNhdGNoIChlKSB7fVxuICAgIHJlcy5zZW50Qm9keSA9IGJvZHk7XG4gIH07XG4gIHJldHVybiBbcmVxLCByZXNdO1xufVxuXG5kZXNjcmliZSgncHJveHknLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBwb3J0O1xuXG4gIGZ1bmN0aW9uIG1vY2tQcm94eSAob3B0cyA9IHt9KSB7XG4gICAgLy8gc2V0cyBkZWZhdWx0IHNlcnZlci9wb3J0XG4gICAgb3B0cyA9IHtzZXJ2ZXI6IFRFU1RfSE9TVCwgcG9ydCwgLi4ub3B0c307XG4gICAgbGV0IHByb3h5ID0gbmV3IEpXUHJveHkob3B0cyk7XG4gICAgcHJveHkucmVxdWVzdCA9IGFzeW5jIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICByZXR1cm4gYXdhaXQgcmVxdWVzdCguLi5hcmdzKTtcbiAgICB9O1xuICAgIHJldHVybiBwcm94eTtcbiAgfVxuXG4gIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgcG9ydCA9IGF3YWl0IGdldFRlc3RQb3J0KCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgb3ZlcnJpZGUgZGVmYXVsdCBwYXJhbXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGogPSBtb2NrUHJveHkoe3NlcnZlcjogJzEyNy4wLjAuMicsIHBvcnR9KTtcbiAgICBqLnNlcnZlci5zaG91bGQuZXF1YWwoJzEyNy4wLjAuMicpO1xuICAgIGoucG9ydC5zaG91bGQuZXF1YWwocG9ydCk7XG4gIH0pO1xuICBpdCgnc2hvdWxkIHNhdmUgc2Vzc2lvbiBpZCBvbiBzZXNzaW9uIGNyZWF0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGxldCBqID0gbW9ja1Byb3h5KCk7XG4gICAgbGV0IFtyZXMsIGJvZHldID0gYXdhaXQgai5wcm94eSgnL3Nlc3Npb24nLCAnUE9TVCcsIHtkZXNpcmVkQ2FwYWJpbGl0aWVzOiB7fX0pO1xuICAgIHJlcy5zdGF0dXNDb2RlLnNob3VsZC5lcXVhbCgyMDApO1xuICAgIGJvZHkuc2hvdWxkLmVxbCh7c3RhdHVzOiAwLCBzZXNzaW9uSWQ6ICcxMjMnLCB2YWx1ZToge2Jyb3dzZXJOYW1lOiAnYm9vJ319KTtcbiAgICBqLnNlc3Npb25JZC5zaG91bGQuZXF1YWwoJzEyMycpO1xuICB9KTtcbiAgZGVzY3JpYmUoJ2dldFVybEZvclByb3h5JywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgbW9kaWZ5IHNlc3Npb24gaWQsIGhvc3QsIGFuZCBwb3J0JywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGogPSBtb2NrUHJveHkoe3Nlc3Npb25JZDogJzEyMyd9KTtcbiAgICAgIGouZ2V0VXJsRm9yUHJveHkoJ2h0dHA6Ly9ob3N0LmNvbToxMjM0L3Nlc3Npb24vNDU2L2VsZW1lbnQvMjAwL3ZhbHVlJylcbiAgICAgICAuc2hvdWxkLmVxbChgaHR0cDovLyR7VEVTVF9IT1NUfToke3BvcnR9L3Nlc3Npb24vMTIzL2VsZW1lbnQvMjAwL3ZhbHVlYCk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCBwcmVwZW5kIHNjaGVtZSwgaG9zdCBhbmQgcG9ydCBpZiBub3QgcHJvdmlkZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgaiA9IG1vY2tQcm94eSh7c2Vzc2lvbklkOiAnMTIzJ30pO1xuICAgICAgai5nZXRVcmxGb3JQcm94eSgnL3Nlc3Npb24vNDU2L2VsZW1lbnQvMjAwL3ZhbHVlJylcbiAgICAgICAuc2hvdWxkLmVxbChgaHR0cDovLyR7VEVTVF9IT1NUfToke3BvcnR9L3Nlc3Npb24vMTIzL2VsZW1lbnQvMjAwL3ZhbHVlYCk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCByZXNwZWN0IG5vbnN0YW5kYXJkIGluY29taW5nIHJlcXVlc3QgYmFzZSBwYXRoJywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGogPSBtb2NrUHJveHkoe3Nlc3Npb25JZDogJzEyMycsIHJlcUJhc2VQYXRoOiAnJ30pO1xuICAgICAgai5nZXRVcmxGb3JQcm94eSgnL3Nlc3Npb24vNDU2L2VsZW1lbnQvMjAwL3ZhbHVlJylcbiAgICAgICAuc2hvdWxkLmVxbChgaHR0cDovLyR7VEVTVF9IT1NUfToke3BvcnR9L3Nlc3Npb24vMTIzL2VsZW1lbnQvMjAwL3ZhbHVlYCk7XG5cbiAgICAgIGogPSBtb2NrUHJveHkoe3Nlc3Npb25JZDogJzEyMycsIHJlcUJhc2VQYXRoOiAnL215L2Jhc2UvcGF0aCd9KTtcbiAgICAgIGouZ2V0VXJsRm9yUHJveHkoJy9teS9iYXNlL3BhdGgvc2Vzc2lvbi80NTYvZWxlbWVudC8yMDAvdmFsdWUnKVxuICAgICAgIC5zaG91bGQuZXFsKGBodHRwOi8vJHtURVNUX0hPU1R9OiR7cG9ydH0vc2Vzc2lvbi8xMjMvZWxlbWVudC8yMDAvdmFsdWVgKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHdvcmsgd2l0aCB1cmxzIHdoaWNoIGRvIG5vdCBoYXZlIHNlc3Npb24gaWRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGogPSBtb2NrUHJveHkoe3Nlc3Npb25JZDogJzEyMyd9KTtcbiAgICAgIGouZ2V0VXJsRm9yUHJveHkoJ2h0dHA6Ly9ob3N0LmNvbToxMjM0L3Nlc3Npb24nKVxuICAgICAgIC5zaG91bGQuZXFsKGBodHRwOi8vJHtURVNUX0hPU1R9OiR7cG9ydH0vc2Vzc2lvbmApO1xuXG4gICAgICBsZXQgbmV3VXJsID0gai5nZXRVcmxGb3JQcm94eSgnL3Nlc3Npb24nKTtcbiAgICAgIG5ld1VybC5zaG91bGQuZXFsKGBodHRwOi8vJHtURVNUX0hPU1R9OiR7cG9ydH0vc2Vzc2lvbmApO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgdGhyb3cgYW4gZXJyb3IgaWYgdXJsIHJlcXVpcmVzIGEgc2Vzc2lvbklkIGJ1dCBpdHMgbnVsbCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBqID0gbW9ja1Byb3h5KCk7XG4gICAgICBsZXQgZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGouZ2V0VXJsRm9yUHJveHkoJy9zZXNzaW9uLzQ1Ni9lbGVtZW50LzIwMC92YWx1ZScpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGUgPSBlcnI7XG4gICAgICB9XG4gICAgICBzaG91bGQuZXhpc3QoZSk7XG4gICAgICBlLm1lc3NhZ2Uuc2hvdWxkLmNvbnRhaW4oJ3dpdGhvdXQgc2Vzc2lvbiBpZCcpO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgbm90IHRocm93IGFuIGVycm9yIGlmIHVybCBkb2VzIG5vdCByZXF1aXJlIGEgc2Vzc2lvbiBpZCBhbmQgaXRzIG51bGwnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgaiA9IG1vY2tQcm94eSgpO1xuICAgICAgbGV0IG5ld1VybCA9IGouZ2V0VXJsRm9yUHJveHkoJy9zdGF0dXMnKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KG5ld1VybCk7XG4gICAgfSk7XG4gIH0pO1xuICBkZXNjcmliZSgnc3RyYWlnaHQgcHJveHknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBzdWNjZXNzZnVsbHkgcHJveHkgc3RyYWlnaHQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgaiA9IG1vY2tQcm94eSgpO1xuICAgICAgbGV0IFtyZXMsIGJvZHldID0gYXdhaXQgai5wcm94eSgnL3N0YXR1cycsICdHRVQnKTtcbiAgICAgIHJlcy5zdGF0dXNDb2RlLnNob3VsZC5lcXVhbCgyMDApO1xuICAgICAgYm9keS5zaG91bGQuZXFsKHtzdGF0dXM6IDAsIHZhbHVlOiB7Zm9vOiAnYmFyJ319KTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHBhc3MgYWxvbmcgcmVxdWVzdCBlcnJvcnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgaiA9IG1vY2tQcm94eSh7c2Vzc2lvbklkOiAnMTIzJ30pO1xuICAgICAgai5wcm94eSgnL2JhZHVybCcsICdHRVQnKS5zaG91bGQuZXZlbnR1YWxseS5iZS5yZWplY3RlZFdpdGgoJ0NvdWxkIG5vdCBwcm94eScpO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgcHJveHkgZXJyb3IgcmVzcG9uc2VzIGFuZCBjb2RlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBqID0gbW9ja1Byb3h5KHtzZXNzaW9uSWQ6ICcxMjMnfSk7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBqLnByb3h5KCcvZWxlbWVudC9iYWQvdGV4dCcsICdHRVQnKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaXNFcnJvclR5cGUoZS5nZXRBY3R1YWxFcnJvcigpLCBlcnJvcnMuRWxlbWVudE5vdFZpc2libGVFcnJvcikuc2hvdWxkLmJlLnRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICBkZXNjcmliZSgnY29tbWFuZCBwcm94eScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHN1Y2Nlc3NmdWxseSBwcm94eSBjb21tYW5kJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGogPSBtb2NrUHJveHkoKTtcbiAgICAgIGxldCByZXMgPSBhd2FpdCBqLmNvbW1hbmQoJy9zdGF0dXMnLCAnR0VUJyk7XG4gICAgICByZXMuc2hvdWxkLmVxbCh7Zm9vOiAnYmFyJ30pO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgcGFzcyBhbG9uZyByZXF1ZXN0IGVycm9ycycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBqID0gbW9ja1Byb3h5KHtzZXNzaW9uSWQ6ICcxMjMnfSk7XG4gICAgICBqLmNvbW1hbmQoJy9iYWR1cmwnLCAnR0VUJykuc2hvdWxkLmV2ZW50dWFsbHkuYmUucmVqZWN0ZWRXaXRoKCdDb3VsZCBub3QgcHJveHknKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gYSBjb21tYW5kIGZhaWxzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGogPSBtb2NrUHJveHkoe3Nlc3Npb25JZDogJzEyMyd9KTtcbiAgICAgIGxldCBlID0gbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGouY29tbWFuZCgnL2VsZW1lbnQvYmFkL3RleHQnLCAnR0VUJyk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgZSA9IGVycjtcbiAgICAgIH1cbiAgICAgIHNob3VsZC5leGlzdChlKTtcbiAgICAgIGUubWVzc2FnZS5zaG91bGQuY29udGFpbignSW52aXNpYmxlIGVsZW1lbnQnKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gYSBjb21tYW5kIGZhaWxzIHdpdGggYSAyMDAgYmVjYXVzZSB0aGUgc3RhdHVzIGlzIG5vdCAwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGogPSBtb2NrUHJveHkoe3Nlc3Npb25JZDogJzEyMyd9KTtcbiAgICAgIGxldCBlID0gbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGouY29tbWFuZCgnL2VsZW1lbnQvMjAwL3RleHQnLCAnR0VUJyk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgZSA9IGVycjtcbiAgICAgIH1cbiAgICAgIHNob3VsZC5leGlzdChlKTtcbiAgICAgIGUuZXJyb3Iuc2hvdWxkLmVxbCgnZWxlbWVudCBub3QgdmlzaWJsZScpO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBhIGNvbW1hbmQgZmFpbHMgd2l0aCBhIDEwMCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBqID0gbW9ja1Byb3h5KHtzZXNzaW9uSWQ6ICcxMjMnfSk7XG4gICAgICBsZXQgZSA9IG51bGw7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBqLmNvbW1hbmQoJy9zZXNzaW9uL2JhZGNocm9tZS9ub2Nocm9tZScsICdHRVQnKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBlID0gZXJyO1xuICAgICAgfVxuICAgICAgc2hvdWxkLmV4aXN0KGUpO1xuICAgICAgZS5tZXNzYWdlLnNob3VsZC5jb250YWluKCdjaHJvbWUgbm90IHJlYWNoYWJsZScpO1xuICAgIH0pO1xuICB9KTtcbiAgZGVzY3JpYmUoJ3JlcS9yZXMgcHJveHknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBzdWNjZXNzZnVsbHkgcHJveHkgdmlhIHJlcSBhbmQgc2VuZCB0byByZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgaiA9IG1vY2tQcm94eSgpO1xuICAgICAgbGV0IFtyZXEsIHJlc10gPSBidWlsZFJlcVJlcygnL3N0YXR1cycsICdHRVQnKTtcbiAgICAgIGF3YWl0IGoucHJveHlSZXFSZXMocmVxLCByZXMpO1xuICAgICAgcmVzLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddLnNob3VsZC5lcXVhbCgnYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOCcpO1xuICAgICAgcmVzLnNlbnRDb2RlLnNob3VsZC5lcXVhbCgyMDApO1xuICAgICAgcmVzLnNlbnRCb2R5LnNob3VsZC5lcWwoe3ZhbHVlOiB7Zm9vOiAnYmFyJ319KTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHJld3JpdGUgdGhlIGlubmVyIHNlc3Npb24gaWQgc28gaXQgZG9lc250IGNoYW5nZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBqID0gbW9ja1Byb3h5KHtzZXNzaW9uSWQ6ICcxMjMnfSk7XG4gICAgICBsZXQgW3JlcSwgcmVzXSA9IGJ1aWxkUmVxUmVzKCcvZWxlbWVudC8yMDAvdmFsdWUnLCAnR0VUJyk7XG4gICAgICBhd2FpdCBqLnByb3h5UmVxUmVzKHJlcSwgcmVzKTtcbiAgICAgIHJlcy5zZW50Qm9keS5zaG91bGQuZXFsKHt2YWx1ZTogJ2Zvb2JhcicsIHNlc3Npb25JZDogJzEyMyd9KTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHJld3JpdGUgdGhlIGlubmVyIHNlc3Npb24gaWQgd2l0aCBzZXNzaW9uSWQgaW4gdXJsJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGogPSBtb2NrUHJveHkoe3Nlc3Npb25JZDogJzEyMyd9KTtcbiAgICAgIGxldCBbcmVxLCByZXNdID0gYnVpbGRSZXFSZXMoJy9zZXNzaW9uLzQ1Ni9lbGVtZW50LzIwMC92YWx1ZScsICdQT1NUJyk7XG4gICAgICBhd2FpdCBqLnByb3h5UmVxUmVzKHJlcSwgcmVzKTtcbiAgICAgIHJlcy5zZW50Qm9keS5zaG91bGQuZXFsKHt2YWx1ZTogJ2Zvb2JhcicsIHNlc3Npb25JZDogJzQ1Nid9KTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHBhc3MgdGhyb3VnaCB1cmxzIHRoYXQgZG8gbm90IHJlcXVpcmUgc2Vzc2lvbiBJRHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgaiA9IG1vY2tQcm94eSh7c2Vzc2lvbklkOiAnMTIzJ30pO1xuICAgICAgbGV0IFtyZXEsIHJlc10gPSBidWlsZFJlcVJlcygnL3N0YXR1cycsICdHRVQnKTtcbiAgICAgIGF3YWl0IGoucHJveHlSZXFSZXMocmVxLCByZXMpO1xuICAgICAgcmVzLnNlbnRCb2R5LnNob3VsZC5lcWwoe3ZhbHVlOiB7J2Zvbyc6ICdiYXInfX0pO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgcHJveHkgc3RyYW5nZSByZXNwb25zZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgaiA9IG1vY2tQcm94eSh7c2Vzc2lvbklkOiAnMTIzJ30pO1xuICAgICAgbGV0IFtyZXEsIHJlc10gPSBidWlsZFJlcVJlcygnL25vY2hyb21lJywgJ0dFVCcpO1xuICAgICAgYXdhaXQgai5wcm94eVJlcVJlcyhyZXEsIHJlcyk7XG4gICAgICByZXMuc2VudENvZGUuc2hvdWxkLmVxdWFsKDEwMCk7XG4gICAgICByZXMuc2VudEJvZHkuc2hvdWxkLmVxbCh7dmFsdWU6IHttZXNzYWdlOiAnY2hyb21lIG5vdCByZWFjaGFibGUnfX0pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|