appium 2.0.0-beta.21 → 2.0.0-beta.25
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/LICENSE +201 -0
- package/README.md +1 -2
- package/build/check-npm-pack-files.js +23 -0
- package/build/commands-yml/parse.js +319 -0
- package/build/commands-yml/validator.js +130 -0
- package/build/index.js +19 -0
- package/build/lib/appium.js +22 -7
- package/build/lib/cli/args.js +13 -15
- package/build/lib/cli/npm.js +27 -16
- package/build/lib/cli/parser.js +7 -3
- package/build/lib/config-file.js +4 -7
- package/build/lib/config.js +57 -48
- package/build/lib/extension-config.js +1 -1
- package/build/lib/main.js +28 -28
- package/build/lib/plugin-config.js +2 -2
- package/build/lib/plugins.js +4 -2
- package/build/lib/schema/appium-config-schema.js +3 -2
- package/build/lib/schema/arg-spec.js +5 -3
- package/build/lib/schema/cli-args.js +25 -16
- package/build/lib/schema/keywords.js +14 -4
- package/build/lib/schema/schema.js +86 -9
- package/build/lib/utils.js +16 -36
- package/build/postinstall.js +90 -0
- package/build/test/cli/cli-e2e-specs.js +221 -0
- package/build/test/cli/cli-helpers.js +86 -0
- package/build/test/cli/cli-specs.js +71 -0
- package/build/test/cli/fixtures/test-driver/package.json +27 -0
- package/build/test/cli/schema-args-specs.js +48 -0
- package/build/test/cli/schema-e2e-specs.js +47 -0
- package/build/test/config-e2e-specs.js +112 -0
- package/build/test/config-file-e2e-specs.js +191 -0
- package/build/test/config-file-specs.js +281 -0
- package/build/test/config-specs.js +258 -0
- package/build/test/driver-e2e-specs.js +435 -0
- package/build/test/driver-specs.js +386 -0
- package/build/test/ext-config-io-specs.js +181 -0
- package/build/test/extension-config-specs.js +365 -0
- package/build/test/fixtures/allow-feat.txt +5 -0
- package/build/test/fixtures/caps.json +3 -0
- package/build/test/fixtures/config/allow-insecure.txt +3 -0
- package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +5 -0
- package/build/test/fixtures/config/appium.config.bad.json +32 -0
- package/build/test/fixtures/config/appium.config.ext-good.json +9 -0
- package/build/test/fixtures/config/appium.config.ext-unknown-props.json +10 -0
- package/build/test/fixtures/config/appium.config.good.js +40 -0
- package/build/test/fixtures/config/appium.config.good.json +33 -0
- package/build/test/fixtures/config/appium.config.good.yaml +30 -0
- package/build/test/fixtures/config/appium.config.invalid.json +31 -0
- package/build/test/fixtures/config/appium.config.security-array.json +5 -0
- package/build/test/fixtures/config/appium.config.security-delimited.json +5 -0
- package/build/test/fixtures/config/appium.config.security-path.json +5 -0
- package/build/test/fixtures/config/driver-fake.config.json +8 -0
- package/build/test/fixtures/config/nodeconfig.json +3 -0
- package/build/test/fixtures/config/plugin-fake.config.json +0 -0
- package/build/test/fixtures/default-args.js +35 -0
- package/build/test/fixtures/deny-feat.txt +5 -0
- package/build/test/fixtures/driver.schema.js +20 -0
- package/build/test/fixtures/extensions.yaml +27 -0
- package/build/test/fixtures/flattened-schema.js +532 -0
- package/build/test/fixtures/plugin.schema.js +20 -0
- package/build/test/fixtures/schema-with-extensions.js +28 -0
- package/build/test/grid-register-specs.js +74 -0
- package/build/test/helpers.js +75 -0
- package/build/test/logger-specs.js +76 -0
- package/build/test/npm-specs.js +20 -0
- package/build/test/parser-specs.js +319 -0
- package/build/test/plugin-e2e-specs.js +316 -0
- package/build/test/schema/arg-spec-specs.js +70 -0
- package/build/test/schema/cli-args-specs.js +408 -0
- package/build/test/schema/schema-specs.js +407 -0
- package/build/test/utils-specs.js +288 -0
- package/index.js +11 -0
- package/lib/appium-config.schema.json +2 -1
- package/lib/appium.js +51 -8
- package/lib/cli/args.js +17 -14
- package/lib/cli/npm.js +68 -6
- package/lib/cli/parser.js +5 -2
- package/lib/config-file.js +9 -12
- package/lib/config.js +104 -56
- package/lib/extension-config.js +1 -1
- package/lib/main.js +94 -40
- package/lib/plugin-config.js +1 -1
- package/lib/plugins.js +2 -0
- package/lib/schema/appium-config-schema.js +1 -0
- package/lib/schema/arg-spec.js +13 -3
- package/lib/schema/cli-args.js +22 -34
- package/lib/schema/keywords.js +20 -4
- package/lib/schema/schema.js +150 -24
- package/lib/utils.js +28 -29
- package/package.json +9 -14
- package/types/types.d.ts +5 -0
- package/build/lib/cli/argparse-actions.js +0 -104
- package/lib/cli/argparse-actions.js +0 -77
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
require("source-map-support/register");
|
|
6
|
+
|
|
7
|
+
var _fs = require("fs");
|
|
8
|
+
|
|
9
|
+
var _path = _interopRequireDefault(require("path"));
|
|
10
|
+
|
|
11
|
+
var _sinon = _interopRequireDefault(require("sinon"));
|
|
12
|
+
|
|
13
|
+
var _yaml = _interopRequireDefault(require("yaml"));
|
|
14
|
+
|
|
15
|
+
var _helpers = require("./helpers");
|
|
16
|
+
|
|
17
|
+
const expect = chai.expect;
|
|
18
|
+
describe('ExtensionConfigIO', function () {
|
|
19
|
+
let sandbox;
|
|
20
|
+
let yamlFixture;
|
|
21
|
+
before(async function () {
|
|
22
|
+
yamlFixture = await _fs.promises.readFile(_path.default.join(__dirname, 'fixtures', 'extensions.yaml'), 'utf8');
|
|
23
|
+
});
|
|
24
|
+
let getExtConfigIOInstance;
|
|
25
|
+
let mocks;
|
|
26
|
+
beforeEach(function () {
|
|
27
|
+
sandbox = _sinon.default.createSandbox();
|
|
28
|
+
mocks = {
|
|
29
|
+
'@appium/support': {
|
|
30
|
+
fs: {
|
|
31
|
+
readFile: sandbox.stub().resolves(yamlFixture),
|
|
32
|
+
writeFile: sandbox.stub().resolves(true)
|
|
33
|
+
},
|
|
34
|
+
mkdirp: sandbox.stub().resolves()
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
getExtConfigIOInstance = _helpers.rewiremock.proxy('../lib/ext-config-io', mocks).getExtConfigIOInstance;
|
|
38
|
+
});
|
|
39
|
+
afterEach(function () {
|
|
40
|
+
sandbox.restore();
|
|
41
|
+
getExtConfigIOInstance.cache = new Map();
|
|
42
|
+
});
|
|
43
|
+
describe('instantiation', function () {
|
|
44
|
+
describe('when called twice with the same `appiumHome` value', function () {
|
|
45
|
+
it('should return the same object both times', function () {
|
|
46
|
+
const firstInstance = getExtConfigIOInstance('/some/path');
|
|
47
|
+
const secondInstance = getExtConfigIOInstance('/some/path');
|
|
48
|
+
expect(firstInstance).to.equal(secondInstance);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('when called twice with different `appiumHome` values', function () {
|
|
52
|
+
it('should return different objects', function () {
|
|
53
|
+
const firstInstance = getExtConfigIOInstance('/some/path');
|
|
54
|
+
const secondInstance = getExtConfigIOInstance('/some/other/path');
|
|
55
|
+
expect(firstInstance).to.not.equal(secondInstance);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe('property', function () {
|
|
60
|
+
describe('filepath', function () {
|
|
61
|
+
it('should not be writable', function () {
|
|
62
|
+
const instance = getExtConfigIOInstance('/some/path');
|
|
63
|
+
expect(() => {
|
|
64
|
+
instance.filepath = '/some/other/path';
|
|
65
|
+
}).to.throw(TypeError);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('read()', function () {
|
|
70
|
+
let io;
|
|
71
|
+
beforeEach(function () {
|
|
72
|
+
io = getExtConfigIOInstance('/some/path');
|
|
73
|
+
});
|
|
74
|
+
describe('when called with a valid extension type', function () {
|
|
75
|
+
describe('when the file does not yet exist', function () {
|
|
76
|
+
beforeEach(async function () {
|
|
77
|
+
const err = new Error();
|
|
78
|
+
err.code = 'ENOENT';
|
|
79
|
+
mocks['@appium/support'].fs.readFile.rejects(err);
|
|
80
|
+
await io.read('driver');
|
|
81
|
+
});
|
|
82
|
+
it('should create a new file', function () {
|
|
83
|
+
expect(mocks['@appium/support'].fs.writeFile).to.be.calledOnceWith(io.filepath, _yaml.default.stringify({
|
|
84
|
+
drivers: {},
|
|
85
|
+
plugins: {},
|
|
86
|
+
schemaRev: 2
|
|
87
|
+
}), 'utf8');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe('when the file already exists', function () {
|
|
91
|
+
beforeEach(async function () {
|
|
92
|
+
await io.read('driver');
|
|
93
|
+
});
|
|
94
|
+
it('should attempt to create the `appiumHome` directory', function () {
|
|
95
|
+
expect(mocks['@appium/support'].mkdirp).to.have.been.calledOnceWith('/some/path');
|
|
96
|
+
});
|
|
97
|
+
it('should attempt to read the file at `filepath`', function () {
|
|
98
|
+
expect(mocks['@appium/support'].fs.readFile).to.have.been.calledOnceWith(io.filepath, 'utf8');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('when called with an unknown extension type`', function () {
|
|
103
|
+
it('should reject', async function () {
|
|
104
|
+
const promise = io.read('unknown');
|
|
105
|
+
return await expect(promise).to.be.rejectedWith(TypeError, /invalid extension type/i);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe('when called twice with the same `extensionType`', function () {
|
|
109
|
+
it('should return the same object both times', async function () {
|
|
110
|
+
const firstInstance = await io.read('driver');
|
|
111
|
+
const secondInstance = await io.read('driver');
|
|
112
|
+
expect(firstInstance).to.equal(secondInstance);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('write()', function () {
|
|
117
|
+
let io;
|
|
118
|
+
let driverData;
|
|
119
|
+
beforeEach(function () {
|
|
120
|
+
io = getExtConfigIOInstance('/some/path');
|
|
121
|
+
});
|
|
122
|
+
describe('when called after `read()`', function () {
|
|
123
|
+
beforeEach(async function () {
|
|
124
|
+
driverData = await io.read('driver');
|
|
125
|
+
});
|
|
126
|
+
describe('when called without modifying the data', function () {
|
|
127
|
+
it('should not write the file', async function () {
|
|
128
|
+
expect(await io.write()).to.be.false;
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
describe('when called after adding a property', function () {
|
|
132
|
+
beforeEach(function () {
|
|
133
|
+
driverData.foo = {
|
|
134
|
+
name: 'foo',
|
|
135
|
+
version: '1.0.0',
|
|
136
|
+
path: '/foo/path'
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
it('should write the file', async function () {
|
|
140
|
+
expect(await io.write()).to.be.true;
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('when called after deleting a property', function () {
|
|
144
|
+
beforeEach(function () {
|
|
145
|
+
driverData.foo = {
|
|
146
|
+
name: 'foo',
|
|
147
|
+
version: '1.0.0',
|
|
148
|
+
path: '/foo/path'
|
|
149
|
+
};
|
|
150
|
+
io._dirty = false;
|
|
151
|
+
delete driverData.foo;
|
|
152
|
+
});
|
|
153
|
+
it('should write the file', async function () {
|
|
154
|
+
expect(await io.write()).to.be.true;
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
describe('when the config file could not be written', function () {
|
|
158
|
+
beforeEach(function () {
|
|
159
|
+
mocks['@appium/support'].fs.writeFile = sandbox.stub().rejects(new Error());
|
|
160
|
+
io._dirty = true;
|
|
161
|
+
});
|
|
162
|
+
it('should reject', async function () {
|
|
163
|
+
await expect(io.write()).to.be.rejectedWith(Error, /Appium could not parse or write/i);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
describe('when called before `read()`', function () {
|
|
168
|
+
it('should return `false`', async function () {
|
|
169
|
+
expect(await io.write()).to.be.false;
|
|
170
|
+
});
|
|
171
|
+
describe('when called with `force: true`', function () {
|
|
172
|
+
it('should reject', async function () {
|
|
173
|
+
await expect(io.write(true)).to.be.rejectedWith(ReferenceError, 'No data to write. Call `read()` first');
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
});require('source-map-support').install();
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvZXh0LWNvbmZpZy1pby1zcGVjcy5qcyJdLCJuYW1lcyI6WyJleHBlY3QiLCJjaGFpIiwiZGVzY3JpYmUiLCJzYW5kYm94IiwieWFtbEZpeHR1cmUiLCJiZWZvcmUiLCJmcyIsInJlYWRGaWxlIiwicGF0aCIsImpvaW4iLCJfX2Rpcm5hbWUiLCJnZXRFeHRDb25maWdJT0luc3RhbmNlIiwibW9ja3MiLCJiZWZvcmVFYWNoIiwic2lub24iLCJjcmVhdGVTYW5kYm94Iiwic3R1YiIsInJlc29sdmVzIiwid3JpdGVGaWxlIiwibWtkaXJwIiwicmV3aXJlbW9jayIsInByb3h5IiwiYWZ0ZXJFYWNoIiwicmVzdG9yZSIsImNhY2hlIiwiTWFwIiwiaXQiLCJmaXJzdEluc3RhbmNlIiwic2Vjb25kSW5zdGFuY2UiLCJ0byIsImVxdWFsIiwibm90IiwiaW5zdGFuY2UiLCJmaWxlcGF0aCIsInRocm93IiwiVHlwZUVycm9yIiwiaW8iLCJlcnIiLCJFcnJvciIsImNvZGUiLCJyZWplY3RzIiwicmVhZCIsImJlIiwiY2FsbGVkT25jZVdpdGgiLCJZQU1MIiwic3RyaW5naWZ5IiwiZHJpdmVycyIsInBsdWdpbnMiLCJzY2hlbWFSZXYiLCJoYXZlIiwiYmVlbiIsInByb21pc2UiLCJyZWplY3RlZFdpdGgiLCJkcml2ZXJEYXRhIiwid3JpdGUiLCJmYWxzZSIsImZvbyIsIm5hbWUiLCJ2ZXJzaW9uIiwidHJ1ZSIsIl9kaXJ0eSIsIlJlZmVyZW5jZUVycm9yIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFFQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQSxNQUFNQSxNQUFNLEdBQUdDLElBQUksQ0FBQ0QsTUFBcEI7QUFFQUUsUUFBUSxDQUFDLG1CQUFELEVBQXNCLFlBQVk7QUFJeEMsTUFBSUMsT0FBSjtBQUdBLE1BQUlDLFdBQUo7QUFFQUMsRUFBQUEsTUFBTSxDQUFDLGtCQUFrQjtBQUN2QkQsSUFBQUEsV0FBVyxHQUFHLE1BQU1FLGFBQUdDLFFBQUgsQ0FDbEJD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QUFzREFwQyxJQUFBQSxRQUFRLENBQUMsNkJBQUQsRUFBZ0MsWUFBWTtBQUNsRHdCLE1BQUFBLEVBQUUsQ0FBQyx1QkFBRCxFQUEwQixrQkFBa0I7QUFDNUMxQixRQUFBQSxNQUFNLENBQUMsTUFBTW9DLEVBQUUsQ0FBQ2tCLEtBQUgsRUFBUCxDQUFOLENBQXlCekIsRUFBekIsQ0FBNEJhLEVBQTVCLENBQStCYSxLQUEvQjtBQUNELE9BRkMsQ0FBRjtBQUlBckQsTUFBQUEsUUFBUSxDQUFDLGdDQUFELEVBQW1DLFlBQVk7QUFDckR3QixRQUFBQSxFQUFFLENBQUMsZUFBRCxFQUFrQixrQkFBa0I7QUFDcEMsZ0JBQU0xQixNQUFNLENBQUNvQyxFQUFFLENBQUNrQixLQUFILENBQVMsSUFBVCxDQUFELENBQU4sQ0FBdUJ6QixFQUF2QixDQUEwQmEsRUFBMUIsQ0FBNkJVLFlBQTdCLENBQTBDUyxjQUExQyxFQUEwRCx1Q0FBMUQsQ0FBTjtBQUNELFNBRkMsQ0FBRjtBQUdELE9BSk8sQ0FBUjtBQUtELEtBVk8sQ0FBUjtBQVdELEdBekVPLENBQVI7QUEwRUQsQ0F2Tk8sQ0FBUiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgeyBwcm9taXNlcyBhcyBmcyB9IGZyb20gJ2ZzJztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCBZQU1MIGZyb20gJ3lhbWwnO1xuaW1wb3J0IHsgcmV3aXJlbW9jayB9IGZyb20gJy4vaGVscGVycyc7XG5jb25zdCBleHBlY3QgPSBjaGFpLmV4cGVjdDtcblxuZGVzY3JpYmUoJ0V4dGVuc2lvbkNvbmZpZ0lPJywgZnVuY3Rpb24gKCkge1xuICAvKipcbiAgICogQHR5cGUge2ltcG9ydCgnc2lub24nKS5TaW5vblNhbmRib3h9XG4gICAqL1xuICBsZXQgc2FuZGJveDtcblxuICAvKiogQHR5cGUge3N0cmluZ30gKi9cbiAgbGV0IHlhbWxGaXh0dXJlO1xuXG4gIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgeWFtbEZpeHR1cmUgPSBhd2FpdCBmcy5yZWFkRmlsZShcbiAgICAgIHBhdGguam9pbihfX2Rpcm5hbWUsICdmaXh0dXJlcycsICdleHRlbnNpb25zLnlhbWwnKSxcbiAgICAgICd1dGY4JyxcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogQHR5cGUge3R5cGVvZiBpbXBvcnQoJy4uL2xpYi9leHQtY29uZmlnLWlvJykuZ2V0RXh0Q29uZmlnSU9JbnN0YW5jZX1cbiAgICovXG4gIGxldCBnZXRFeHRDb25maWdJT0luc3RhbmNlO1xuXG4gIGxldCBtb2NrcztcblxuICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgIG1vY2tzID0ge1xuICAgICAgJ0BhcHBpdW0vc3VwcG9ydCc6IHtcbiAgICAgICAgZnM6IHtcbiAgICAgICAgICByZWFkRmlsZTogc2FuZGJveC5zdHViKCkucmVzb2x2ZXMoeWFtbEZpeHR1cmUpLFxuICAgICAgICAgIHdyaXRlRmlsZTogc2FuZGJveC5zdHViKCkucmVzb2x2ZXModHJ1ZSksXG4gICAgICAgIH0sXG4gICAgICAgIG1rZGlycDogc2FuZGJveC5zdHViKCkucmVzb2x2ZXMoKSxcbiAgICAgIH0sXG4gICAgfTtcbiAgICBnZXRFeHRDb25maWdJT0luc3RhbmNlID0gcmV3aXJlbW9jay5wcm94eShcbiAgICAgICcuLi9saWIvZXh0LWNvbmZpZy1pbycsXG4gICAgICBtb2NrcyxcbiAgICApLmdldEV4dENvbmZpZ0lPSW5zdGFuY2U7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgZ2V0RXh0Q29uZmlnSU9JbnN0YW5jZS5jYWNoZSA9IG5ldyBNYXAoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2luc3RhbnRpYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgZGVzY3JpYmUoJ3doZW4gY2FsbGVkIHR3aWNlIHdpdGggdGhlIHNhbWUgYGFwcGl1bUhvbWVgIHZhbHVlJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCByZXR1cm4gdGhlIHNhbWUgb2JqZWN0IGJvdGggdGltZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGZpcnN0SW5zdGFuY2UgPSBnZXRFeHRDb25maWdJT0luc3RhbmNlKCcvc29tZS9wYXRoJyk7XG4gICAgICAgIGNvbnN0IHNlY29uZEluc3RhbmNlID0gZ2V0RXh0Q29uZmlnSU9JbnN0YW5jZSgnL3NvbWUvcGF0aCcpO1xuICAgICAgICBleHBlY3QoZmlyc3RJbnN0YW5jZSkudG8uZXF1YWwoc2Vjb25kSW5zdGFuY2UpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnd2hlbiBjYWxsZWQgdHdpY2Ugd2l0aCBkaWZmZXJlbnQgYGFwcGl1bUhvbWVgIHZhbHVlcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdzaG91bGQgcmV0dXJuIGRpZmZlcmVudCBvYmplY3RzJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBmaXJzdEluc3RhbmNlID0gZ2V0RXh0Q29uZmlnSU9JbnN0YW5jZSgnL3NvbWUvcGF0aCcpO1xuICAgICAgICBjb25zdCBzZWNvbmRJbnN0YW5jZSA9IGdldEV4dENvbmZpZ0lPSW5zdGFuY2UoJy9zb21lL290aGVyL3BhdGgnKTtcbiAgICAgICAgZXhwZWN0KGZpcnN0SW5zdGFuY2UpLnRvLm5vdC5lcXVhbChzZWNvbmRJbnN0YW5jZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Byb3BlcnR5JywgZnVuY3Rpb24gKCkge1xuICAgIGRlc2NyaWJlKCdmaWxlcGF0aCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdzaG91bGQgbm90IGJlIHdyaXRhYmxlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBpbnN0YW5jZSA9IGdldEV4dENvbmZpZ0lPSW5zdGFuY2UoJy9zb21lL3BhdGgnKTtcbiAgICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgaW5zdGFuY2UuZmlsZXBhdGggPSAnL3NvbWUvb3RoZXIvcGF0aCc7XG4gICAgICAgIH0pLnRvLnRocm93KFR5cGVFcnJvcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3JlYWQoKScsIGZ1bmN0aW9uICgpIHtcbiAgICAvKiogQHR5cGUge2ltcG9ydCgnLi4vbGliL2V4dC1jb25maWctaW8nKS5FeHRlbnNpb25Db25maWdJT30gKi9cbiAgICBsZXQgaW87XG5cbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIGlvID0gZ2V0RXh0Q29uZmlnSU9JbnN0YW5jZSgnL3NvbWUvcGF0aCcpO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3doZW4gY2FsbGVkIHdpdGggYSB2YWxpZCBleHRlbnNpb24gdHlwZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGRlc2NyaWJlKCd3aGVuIHRoZSBmaWxlIGRvZXMgbm90IHlldCBleGlzdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYmVmb3JlRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgLyoqIEB0eXBlIHtOb2RlSlMuRXJybm9FeGNlcHRpb259ICovXG4gICAgICAgICAgY29uc3QgZXJyID0gbmV3IEVycm9yKCk7XG4gICAgICAgICAgZXJyLmNvZGUgPSAnRU5PRU5UJztcbiAgICAgICAgICBtb2Nrc1snQGFwcGl1bS9zdXBwb3J0J10uZnMucmVhZEZpbGUucmVqZWN0cyhlcnIpO1xuICAgICAgICAgIGF3YWl0IGlvLnJlYWQoJ2RyaXZlcicpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIGNyZWF0ZSBhIG5ldyBmaWxlJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGV4cGVjdChtb2Nrc1snQGFwcGl1bS9zdXBwb3J0J10uZnMud3JpdGVGaWxlKS50by5iZS5jYWxsZWRPbmNlV2l0aChcbiAgICAgICAgICAgIGlvLmZpbGVwYXRoLFxuICAgICAgICAgICAgWUFNTC5zdHJpbmdpZnkoe2RyaXZlcnM6IHt9LCBwbHVnaW5zOiB7fSwgc2NoZW1hUmV2OiAyfSksXG4gICAgICAgICAgICAndXRmOCcsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgZGVzY3JpYmUoJ3doZW4gdGhlIGZpbGUgYWxyZWFkeSBleGlzdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGJlZm9yZUVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGF3YWl0IGlvLnJlYWQoJ2RyaXZlcicpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIGF0dGVtcHQgdG8gY3JlYXRlIHRoZSBgYXBwaXVtSG9tZWAgZGlyZWN0b3J5JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGV4cGVjdChtb2Nrc1snQGFwcGl1bS9zdXBwb3J0J10ubWtkaXJwKS50by5oYXZlLmJlZW4uY2FsbGVkT25jZVdpdGgoXG4gICAgICAgICAgICAnL3NvbWUvcGF0aCcsXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBhdHRlbXB0IHRvIHJlYWQgdGhlIGZpbGUgYXQgYGZpbGVwYXRoYCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBleHBlY3QoXG4gICAgICAgICAgICBtb2Nrc1snQGFwcGl1bS9zdXBwb3J0J10uZnMucmVhZEZpbGUsXG4gICAgICAgICAgKS50by5oYXZlLmJlZW4uY2FsbGVkT25jZVdpdGgoaW8uZmlsZXBhdGgsICd1dGY4Jyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnd2hlbiBjYWxsZWQgd2l0aCBhbiB1bmtub3duIGV4dGVuc2lvbiB0eXBlYCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdzaG91bGQgcmVqZWN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBpby5yZWFkKCd1bmtub3duJyk7XG4gICAgICAgIHJldHVybiBhd2FpdCBleHBlY3QocHJvbWlzZSkudG8uYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIFR5cGVFcnJvcixcbiAgICAgICAgICAvaW52YWxpZCBleHRlbnNpb24gdHlwZS9pLFxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnd2hlbiBjYWxsZWQgdHdpY2Ugd2l0aCB0aGUgc2FtZSBgZXh0ZW5zaW9uVHlwZWAnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpdCgnc2hvdWxkIHJldHVybiB0aGUgc2FtZSBvYmplY3QgYm90aCB0aW1lcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZmlyc3RJbnN0YW5jZSA9IGF3YWl0IGlvLnJlYWQoJ2RyaXZlcicpO1xuICAgICAgICBjb25zdCBzZWNvbmRJbnN0YW5jZSA9IGF3YWl0IGlvLnJlYWQoJ2RyaXZlcicpO1xuICAgICAgICBleHBlY3QoZmlyc3RJbnN0YW5jZSkudG8uZXF1YWwoc2Vjb25kSW5zdGFuY2UpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd3cml0ZSgpJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBpbztcbiAgICBsZXQgZHJpdmVyRGF0YTtcblxuICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgaW8gPSBnZXRFeHRDb25maWdJT0luc3RhbmNlKCcvc29tZS9wYXRoJyk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnd2hlbiBjYWxsZWQgYWZ0ZXIgYHJlYWQoKWAnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZHJpdmVyRGF0YSA9IGF3YWl0IGlvLnJlYWQoJ2RyaXZlcicpO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd3aGVuIGNhbGxlZCB3aXRob3V0IG1vZGlmeWluZyB0aGUgZGF0YScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaXQoJ3Nob3VsZCBub3Qgd3JpdGUgdGhlIGZpbGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgZXhwZWN0KGF3YWl0IGlvLndyaXRlKCkpLnRvLmJlLmZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnd2hlbiBjYWxsZWQgYWZ0ZXIgYWRkaW5nIGEgcHJvcGVydHknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGRyaXZlckRhdGEuZm9vID0ge1xuICAgICAgICAgICAgbmFtZTogJ2ZvbycsXG4gICAgICAgICAgICB2ZXJzaW9uOiAnMS4wLjAnLFxuICAgICAgICAgICAgcGF0aDogJy9mb28vcGF0aCcsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCB3cml0ZSB0aGUgZmlsZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBleHBlY3QoYXdhaXQgaW8ud3JpdGUoKSkudG8uYmUudHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgZGVzY3JpYmUoJ3doZW4gY2FsbGVkIGFmdGVyIGRlbGV0aW5nIGEgcHJvcGVydHknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGRyaXZlckRhdGEuZm9vID0ge1xuICAgICAgICAgICAgbmFtZTogJ2ZvbycsXG4gICAgICAgICAgICB2ZXJzaW9uOiAnMS4wLjAnLFxuICAgICAgICAgICAgcGF0aDogJy9mb28vcGF0aCcsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBpby5fZGlydHkgPSBmYWxzZTtcbiAgICAgICAgICBkZWxldGUgZHJpdmVyRGF0YS5mb287XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgd3JpdGUgdGhlIGZpbGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgZXhwZWN0KGF3YWl0IGlvLndyaXRlKCkpLnRvLmJlLnRydWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd3aGVuIHRoZSBjb25maWcgZmlsZSBjb3VsZCBub3QgYmUgd3JpdHRlbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgbW9ja3NbJ0BhcHBpdW0vc3VwcG9ydCddLmZzLndyaXRlRmlsZSA9IHNhbmRib3guc3R1YigpLnJlamVjdHMobmV3IEVycm9yKCkpO1xuICAgICAgICAgIGlvLl9kaXJ0eSA9IHRydWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgcmVqZWN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGF3YWl0IGV4cGVjdChpby53cml0ZSgpKS50by5iZS5yZWplY3RlZFdpdGgoRXJyb3IsIC9BcHBpdW0gY291bGQgbm90IHBhcnNlIG9yIHdyaXRlL2kpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnd2hlbiBjYWxsZWQgYmVmb3JlIGByZWFkKClgJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCByZXR1cm4gYGZhbHNlYCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZXhwZWN0KGF3YWl0IGlvLndyaXRlKCkpLnRvLmJlLmZhbHNlO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd3aGVuIGNhbGxlZCB3aXRoIGBmb3JjZTogdHJ1ZWAnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgcmVqZWN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGF3YWl0IGV4cGVjdChpby53cml0ZSh0cnVlKSkudG8uYmUucmVqZWN0ZWRXaXRoKFJlZmVyZW5jZUVycm9yLCAnTm8gZGF0YSB0byB3cml0ZS4gQ2FsbCBgcmVhZCgpYCBmaXJzdCcpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl0sImZpbGUiOiJ0ZXN0L2V4dC1jb25maWctaW8tc3BlY3MuanMiLCJzb3VyY2VSb290IjoiLi4vLi4ifQ==
|