@okeyamy/lua 5.0.4

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.
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _lua = _interopRequireDefault(require("./lua"));
9
+ var _browserCookie = _interopRequireDefault(require("./stores/browser-cookie"));
10
+ var _local = _interopRequireDefault(require("./stores/local"));
11
+ var _memory = _interopRequireDefault(require("./stores/memory"));
12
+ require("./utm");
13
+ require("./personalization");
14
+ // this is the build for webpack and UMD builds
15
+ // try not to use this!
16
+ // UTM and Personalization modules (IIFE pattern - self-register on window)
17
+ // These files populate window.LuaUTM and window.LuaPersonalize on execution
18
+ var _default = exports.default = _lua.default;
19
+ var stores = {
20
+ browserCookie: (0, _browserCookie.default)(),
21
+ local: (0, _local.default)(),
22
+ memory: (0, _memory.default)()
23
+ };
24
+ window.Lua = _lua.default;
25
+ _lua.default.stores = stores;
26
+
27
+ // Attach UTM and Personalization from window globals (populated by IIFEs)
28
+ _lua.default.utm = window.LuaUTM || {};
29
+ _lua.default.personalization = window.LuaPersonalize || {};
30
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbHVhIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfYnJvd3NlckNvb2tpZSIsIl9sb2NhbCIsIl9tZW1vcnkiLCJfZGVmYXVsdCIsImV4cG9ydHMiLCJkZWZhdWx0IiwiTHVhIiwic3RvcmVzIiwiYnJvd3NlckNvb2tpZSIsImxvY2FsIiwibWVtb3J5Iiwid2luZG93IiwidXRtIiwiTHVhVVRNIiwicGVyc29uYWxpemF0aW9uIiwiTHVhUGVyc29uYWxpemUiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiXG4vLyB0aGlzIGlzIHRoZSBidWlsZCBmb3Igd2VicGFjayBhbmQgVU1EIGJ1aWxkc1xuLy8gdHJ5IG5vdCB0byB1c2UgdGhpcyFcbmltcG9ydCBMdWEgZnJvbSAnLi9sdWEnXG5cbmltcG9ydCBicm93c2VyQ29va2llIGZyb20gJy4vc3RvcmVzL2Jyb3dzZXItY29va2llJ1xuaW1wb3J0IGxvY2FsIGZyb20gJy4vc3RvcmVzL2xvY2FsJ1xuaW1wb3J0IG1lbW9yeSBmcm9tICcuL3N0b3Jlcy9tZW1vcnknXG5cbi8vIFVUTSBhbmQgUGVyc29uYWxpemF0aW9uIG1vZHVsZXMgKElJRkUgcGF0dGVybiAtIHNlbGYtcmVnaXN0ZXIgb24gd2luZG93KVxuLy8gVGhlc2UgZmlsZXMgcG9wdWxhdGUgd2luZG93Lkx1YVVUTSBhbmQgd2luZG93Lkx1YVBlcnNvbmFsaXplIG9uIGV4ZWN1dGlvblxuaW1wb3J0ICcuL3V0bSdcbmltcG9ydCAnLi9wZXJzb25hbGl6YXRpb24nXG5cbmV4cG9ydCBkZWZhdWx0IEx1YVxuXG5jb25zdCBzdG9yZXMgPSB7XG4gIGJyb3dzZXJDb29raWU6IGJyb3dzZXJDb29raWUoKSxcbiAgbG9jYWw6IGxvY2FsKCksXG4gIG1lbW9yeTogbWVtb3J5KCksXG59XG5cbndpbmRvdy5MdWEgPSBMdWFcbkx1YS5zdG9yZXMgPSBzdG9yZXNcblxuLy8gQXR0YWNoIFVUTSBhbmQgUGVyc29uYWxpemF0aW9uIGZyb20gd2luZG93IGdsb2JhbHMgKHBvcHVsYXRlZCBieSBJSUZFcylcbkx1YS51dG0gPSB3aW5kb3cuTHVhVVRNIHx8IHt9XG5MdWEucGVyc29uYWxpemF0aW9uID0gd2luZG93Lkx1YVBlcnNvbmFsaXplIHx8IHt9Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBR0EsSUFBQUEsSUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUMsY0FBQSxHQUFBRixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUUsTUFBQSxHQUFBSCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUcsT0FBQSxHQUFBSixzQkFBQSxDQUFBQyxPQUFBO0FBSUFBLE9BQUE7QUFDQUEsT0FBQTtBQVhBO0FBQ0E7QUFPQTtBQUNBO0FBQUEsSUFBQUksUUFBQSxHQUFBQyxPQUFBLENBQUFDLE9BQUEsR0FJZUMsWUFBRztBQUVsQixJQUFNQyxNQUFNLEdBQUc7RUFDYkMsYUFBYSxFQUFFLElBQUFBLHNCQUFhLEVBQUMsQ0FBQztFQUM5QkMsS0FBSyxFQUFFLElBQUFBLGNBQUssRUFBQyxDQUFDO0VBQ2RDLE1BQU0sRUFBRSxJQUFBQSxlQUFNLEVBQUM7QUFDakIsQ0FBQztBQUVEQyxNQUFNLENBQUNMLEdBQUcsR0FBR0EsWUFBRztBQUNoQkEsWUFBRyxDQUFDQyxNQUFNLEdBQUdBLE1BQU07O0FBRW5CO0FBQ0FELFlBQUcsQ0FBQ00sR0FBRyxHQUFHRCxNQUFNLENBQUNFLE1BQU0sSUFBSSxDQUFDLENBQUM7QUFDN0JQLFlBQUcsQ0FBQ1EsZUFBZSxHQUFHSCxNQUFNLENBQUNJLGNBQWMsSUFBSSxDQUFDLENBQUMiLCJpZ25vcmVMaXN0IjpbXX0=
@@ -0,0 +1,366 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
+ var _utils = require("./utils");
11
+ // UTM functions are now on window.LuaUTM (IIFE pattern, no import needed)
12
+ // utm.js must be loaded before lua.js to populate window.LuaUTM
13
+ var Lua = exports.default = /*#__PURE__*/function () {
14
+ function Lua() {
15
+ var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16
+ (0, _classCallCheck2.default)(this, Lua);
17
+ Object.assign(this, {
18
+ storageKey: 'ab-tests',
19
+ root: typeof document !== 'undefined' ? document.body : null
20
+ }, options);
21
+ (0, _utils.validateStore)(this.store);
22
+ this.previousAssignments = {};
23
+ try {
24
+ // assert that the data is a JSON string
25
+ // that represents a JSON object
26
+ // saw a bug where it was, for some reason, stored as `null`
27
+ var data = this.store.get(this.storageKey);
28
+ if (typeof data === 'string' && data[0] === '{') {
29
+ this.previousAssignments = JSON.parse(data);
30
+ }
31
+ } catch (_) {
32
+ // ignore
33
+ }
34
+ this.userAssignments = {};
35
+ this.persistedUserAssignments = {};
36
+ this.providedTests = [];
37
+ }
38
+ return (0, _createClass2.default)(Lua, [{
39
+ key: "define",
40
+ value: function define(tests) {
41
+ var _this = this;
42
+ var normalizedData = tests;
43
+ if (!Array.isArray(tests)) normalizedData = [tests];
44
+ normalizedData.forEach(function (test) {
45
+ if (!test.name) throw new Error('Tests must have a name');
46
+ if (!test.buckets) throw new Error('Tests must have buckets');
47
+ if (!Object.keys(test.buckets)) throw new Error('Tests must have buckets');
48
+ _this.providedTests.push(test);
49
+ });
50
+ }
51
+ }, {
52
+ key: "definitions",
53
+ value: function definitions() {
54
+ return this.providedTests;
55
+ }
56
+ }, {
57
+ key: "removeClasses",
58
+ value: function removeClasses(testName, exceptClassName) {
59
+ try {
60
+ var root = this.root;
61
+ if (!root) return;
62
+
63
+ // classList does not support returning all classes
64
+ var currentClassNames = root.className.split(/\s+/g).map(function (x) {
65
+ return x.trim();
66
+ }).filter(Boolean);
67
+ currentClassNames.filter(function (x) {
68
+ return x.indexOf("".concat(testName, "--")) === 0;
69
+ }).filter(function (className) {
70
+ return className !== exceptClassName;
71
+ }).forEach(function (className) {
72
+ return root.classList.remove(className);
73
+ });
74
+ } catch (_) {
75
+ // Ignore
76
+ }
77
+ }
78
+ }, {
79
+ key: "applyClasses",
80
+ value: function applyClasses() {
81
+ var _this2 = this;
82
+ try {
83
+ var userAssignments = this.userAssignments,
84
+ root = this.root;
85
+ if (!root) return;
86
+ Object.keys(userAssignments).forEach(function (testName) {
87
+ var bucket = userAssignments[testName];
88
+ var className = bucket ? "".concat(testName, "--").concat(bucket) : null;
89
+ // remove all classes related to this bucket
90
+ _this2.removeClasses(testName, className);
91
+
92
+ // only assign a class is the test is assigned to a bucket
93
+ // this removes then adds a class, which is not ideal but is clean
94
+ if (className) root.classList.add(className);
95
+ });
96
+ } catch (_) {
97
+ // Ignore
98
+ }
99
+ }
100
+ }, {
101
+ key: "assignAll",
102
+ value: function assignAll() {
103
+ var previousAssignments = this.previousAssignments,
104
+ userAssignments = this.userAssignments,
105
+ persistedUserAssignments = this.persistedUserAssignments;
106
+ this.providedTests.forEach(function (test) {
107
+ // winners take precedence
108
+ {
109
+ var winner = Object.keys(test.buckets).filter(function (name) {
110
+ return test.buckets[name].winner;
111
+ })[0];
112
+ if (winner) {
113
+ userAssignments[test.name] = winner;
114
+ return;
115
+ }
116
+ }
117
+
118
+ // already assigned, probably because someone
119
+ // called `.assignAll()` twice.
120
+ if (userAssignments[test.name]) return;
121
+ {
122
+ // previously assigned, so we continue to persist it
123
+ var bucket = previousAssignments[test.name];
124
+ if (bucket && test.buckets[bucket]) {
125
+ var assignment = previousAssignments[test.name];
126
+ persistedUserAssignments[test.name] = assignment;
127
+ userAssignments[test.name] = assignment;
128
+ test.active = true;
129
+ return;
130
+ }
131
+ }
132
+
133
+ // inactive tests should be set to default
134
+ if (test.active === false) {
135
+ userAssignments[test.name] = (0, _utils.getDefaultBucket)(test.buckets);
136
+ return;
137
+ }
138
+
139
+ // randomly assign
140
+ {
141
+ var _assignment = (0, _utils.getRandomAssignment)(test);
142
+ persistedUserAssignments[test.name] = _assignment;
143
+ userAssignments[test.name] = _assignment;
144
+ }
145
+ });
146
+ this.persist();
147
+ this.applyClasses();
148
+ }
149
+ }, {
150
+ key: "assign",
151
+ value: function assign(testName, bucketName) {
152
+ if (!testName) return this.assignAll();
153
+ var test = this.providedTests.filter(function (x) {
154
+ return x.name === testName;
155
+ })[0];
156
+ if (bucketName === null || !test) {
157
+ delete this.userAssignments[testName];
158
+ delete this.persistedUserAssignments[testName];
159
+ this.persist();
160
+ this.removeClasses(testName);
161
+ return;
162
+ }
163
+ var assignment = bucketName || (0, _utils.getRandomAssignment)(test);
164
+ this.userAssignments[testName] = assignment;
165
+ this.persistedUserAssignments[testName] = assignment;
166
+ test.active = true;
167
+ this.persist();
168
+ this.applyClasses();
169
+ }
170
+ }, {
171
+ key: "extendAssignments",
172
+ value: function extendAssignments(assignments) {
173
+ return assignments;
174
+ }
175
+ }, {
176
+ key: "assignments",
177
+ value: function assignments() {
178
+ return this.extendAssignments(this.userAssignments);
179
+ }
180
+ }, {
181
+ key: "persist",
182
+ value: function persist() {
183
+ this.store.set(this.storageKey, JSON.stringify(this.persistedUserAssignments));
184
+ }
185
+
186
+ /**
187
+ * Get UTM context for the current page
188
+ * Uses window.LuaUTM global (populated by utm.js IIFE)
189
+ * @returns {Object} - Context object with UTM params, referrer, user agent, and intent
190
+ */
191
+ }, {
192
+ key: "getUTMContext",
193
+ value: function getUTMContext() {
194
+ try {
195
+ var _root = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {};
196
+ if (_root.LuaUTM && typeof _root.LuaUTM.getContext === 'function') {
197
+ return _root.LuaUTM.getContext();
198
+ }
199
+ return {
200
+ utm: {},
201
+ referrer: {},
202
+ userAgent: {},
203
+ primaryIntent: 'default',
204
+ hasUTM: false
205
+ };
206
+ } catch (_) {
207
+ return {
208
+ utm: {},
209
+ referrer: {},
210
+ userAgent: {},
211
+ primaryIntent: 'default',
212
+ hasUTM: false
213
+ };
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Get bucket based on UTM context
219
+ * Maps UTM intent to test buckets
220
+ * @param {Object} test - Test definition with buckets
221
+ * @param {Object} context - UTM context
222
+ * @returns {string|null} - Bucket name or null if no match
223
+ */
224
+ }, {
225
+ key: "getUTMBasedBucket",
226
+ value: function getUTMBasedBucket(test, context) {
227
+ if (!context || !context.hasUTM) return null;
228
+
229
+ // Check if test has UTM rules defined
230
+ var utmRules = test.utmRules || {};
231
+
232
+ // Priority 1: Match by utm_campaign
233
+ if (context.utm.utm_campaign) {
234
+ var campaignRule = utmRules[context.utm.utm_campaign];
235
+ if (campaignRule && test.buckets[campaignRule]) {
236
+ return campaignRule;
237
+ }
238
+ }
239
+
240
+ // Priority 2: Match by utm_source
241
+ if (context.utm.utm_source) {
242
+ var sourceRule = utmRules[context.utm.utm_source];
243
+ if (sourceRule && test.buckets[sourceRule]) {
244
+ return sourceRule;
245
+ }
246
+ }
247
+
248
+ // Priority 3: Match by inferred intent
249
+ var intent = context.primaryIntent;
250
+ if (intent && test.buckets[intent]) {
251
+ return intent;
252
+ }
253
+
254
+ // Priority 4: Check for intent-mapped buckets
255
+ var intentMapping = test.intentMapping || {};
256
+ if (intent && intentMapping[intent] && test.buckets[intentMapping[intent]]) {
257
+ return intentMapping[intent];
258
+ }
259
+ return null;
260
+ }
261
+
262
+ /**
263
+ * Assign with UTM-aware personalization
264
+ * Falls back to random A/B if no UTM match
265
+ * @param {string} [testName] - Optional specific test name
266
+ * @param {Object} [options] - Options including forceUTM, context
267
+ * @returns {Object} - { assignment, source: 'utm'|'random'|'persisted' }
268
+ */
269
+ }, {
270
+ key: "assignWithUTM",
271
+ value: function assignWithUTM(testName) {
272
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
273
+ var context = options.context || this.getUTMContext();
274
+
275
+ // If no test name, assign all with UTM awareness
276
+ if (!testName) {
277
+ return this.assignAllWithUTM(context);
278
+ }
279
+ var test = this.providedTests.filter(function (x) {
280
+ return x.name === testName;
281
+ })[0];
282
+ if (!test) {
283
+ return {
284
+ assignment: null,
285
+ source: 'none'
286
+ };
287
+ }
288
+
289
+ // Check for winner first (takes precedence)
290
+ var winner = Object.keys(test.buckets).filter(function (name) {
291
+ return test.buckets[name].winner;
292
+ })[0];
293
+ if (winner) {
294
+ this.userAssignments[testName] = winner;
295
+ this.persist();
296
+ this.applyClasses();
297
+ return {
298
+ assignment: winner,
299
+ source: 'winner'
300
+ };
301
+ }
302
+
303
+ // Check previous assignment
304
+ var previousBucket = this.previousAssignments[testName];
305
+ if (previousBucket && test.buckets[previousBucket]) {
306
+ this.userAssignments[testName] = previousBucket;
307
+ this.persistedUserAssignments[testName] = previousBucket;
308
+ test.active = true;
309
+ this.persist();
310
+ this.applyClasses();
311
+ return {
312
+ assignment: previousBucket,
313
+ source: 'persisted'
314
+ };
315
+ }
316
+
317
+ // Try UTM-based assignment
318
+ var utmBucket = this.getUTMBasedBucket(test, context);
319
+ if (utmBucket) {
320
+ this.userAssignments[testName] = utmBucket;
321
+ this.persistedUserAssignments[testName] = utmBucket;
322
+ test.active = true;
323
+ this.persist();
324
+ this.applyClasses();
325
+ return {
326
+ assignment: utmBucket,
327
+ source: 'utm',
328
+ intent: context.primaryIntent
329
+ };
330
+ }
331
+
332
+ // Fallback to random assignment
333
+ var assignment = (0, _utils.getRandomAssignment)(test);
334
+ this.userAssignments[testName] = assignment;
335
+ this.persistedUserAssignments[testName] = assignment;
336
+ test.active = true;
337
+ this.persist();
338
+ this.applyClasses();
339
+ return {
340
+ assignment: assignment,
341
+ source: 'random'
342
+ };
343
+ }
344
+
345
+ /**
346
+ * Assign all tests with UTM awareness
347
+ * @param {Object} context - UTM context
348
+ * @returns {Object} - Map of test names to assignment results
349
+ */
350
+ }, {
351
+ key: "assignAllWithUTM",
352
+ value: function assignAllWithUTM(context) {
353
+ var _this3 = this;
354
+ context = context || this.getUTMContext();
355
+ var results = {};
356
+ this.providedTests.forEach(function (test) {
357
+ var result = _this3.assignWithUTM(test.name, {
358
+ context: context
359
+ });
360
+ results[test.name] = result;
361
+ });
362
+ return results;
363
+ }
364
+ }]);
365
+ }();
366
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfdXRpbHMiLCJyZXF1aXJlIiwiTHVhIiwiZXhwb3J0cyIsImRlZmF1bHQiLCJvcHRpb25zIiwiYXJndW1lbnRzIiwibGVuZ3RoIiwidW5kZWZpbmVkIiwiX2NsYXNzQ2FsbENoZWNrMiIsIk9iamVjdCIsImFzc2lnbiIsInN0b3JhZ2VLZXkiLCJyb290IiwiZG9jdW1lbnQiLCJib2R5IiwidmFsaWRhdGVTdG9yZSIsInN0b3JlIiwicHJldmlvdXNBc3NpZ25tZW50cyIsImRhdGEiLCJnZXQiLCJKU09OIiwicGFyc2UiLCJfIiwidXNlckFzc2lnbm1lbnRzIiwicGVyc2lzdGVkVXNlckFzc2lnbm1lbnRzIiwicHJvdmlkZWRUZXN0cyIsIl9jcmVhdGVDbGFzczIiLCJrZXkiLCJ2YWx1ZSIsImRlZmluZSIsInRlc3RzIiwiX3RoaXMiLCJub3JtYWxpemVkRGF0YSIsIkFycmF5IiwiaXNBcnJheSIsImZvckVhY2giLCJ0ZXN0IiwibmFtZSIsIkVycm9yIiwiYnVja2V0cyIsImtleXMiLCJwdXNoIiwiZGVmaW5pdGlvbnMiLCJyZW1vdmVDbGFzc2VzIiwidGVzdE5hbWUiLCJleGNlcHRDbGFzc05hbWUiLCJjdXJyZW50Q2xhc3NOYW1lcyIsImNsYXNzTmFtZSIsInNwbGl0IiwibWFwIiwieCIsInRyaW0iLCJmaWx0ZXIiLCJCb29sZWFuIiwiaW5kZXhPZiIsImNvbmNhdCIsImNsYXNzTGlzdCIsInJlbW92ZSIsImFwcGx5Q2xhc3NlcyIsIl90aGlzMiIsImJ1Y2tldCIsImFkZCIsImFzc2lnbkFsbCIsIndpbm5lciIsImFzc2lnbm1lbnQiLCJhY3RpdmUiLCJnZXREZWZhdWx0QnVja2V0IiwiZ2V0UmFuZG9tQXNzaWdubWVudCIsInBlcnNpc3QiLCJidWNrZXROYW1lIiwiZXh0ZW5kQXNzaWdubWVudHMiLCJhc3NpZ25tZW50cyIsInNldCIsInN0cmluZ2lmeSIsImdldFVUTUNvbnRleHQiLCJfcm9vdCIsIndpbmRvdyIsImdsb2JhbCIsIkx1YVVUTSIsImdldENvbnRleHQiLCJ1dG0iLCJyZWZlcnJlciIsInVzZXJBZ2VudCIsInByaW1hcnlJbnRlbnQiLCJoYXNVVE0iLCJnZXRVVE1CYXNlZEJ1Y2tldCIsImNvbnRleHQiLCJ1dG1SdWxlcyIsInV0bV9jYW1wYWlnbiIsImNhbXBhaWduUnVsZSIsInV0bV9zb3VyY2UiLCJzb3VyY2VSdWxlIiwiaW50ZW50IiwiaW50ZW50TWFwcGluZyIsImFzc2lnbldpdGhVVE0iLCJhc3NpZ25BbGxXaXRoVVRNIiwic291cmNlIiwicHJldmlvdXNCdWNrZXQiLCJ1dG1CdWNrZXQiLCJfdGhpczMiLCJyZXN1bHRzIiwicmVzdWx0Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2x1YS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCB7XG4gIGdldFJhbmRvbUFzc2lnbm1lbnQsXG4gIGdldERlZmF1bHRCdWNrZXQsXG4gIHZhbGlkYXRlU3RvcmUsXG59IGZyb20gJy4vdXRpbHMnXG5cbi8vIFVUTSBmdW5jdGlvbnMgYXJlIG5vdyBvbiB3aW5kb3cuTHVhVVRNIChJSUZFIHBhdHRlcm4sIG5vIGltcG9ydCBuZWVkZWQpXG4vLyB1dG0uanMgbXVzdCBiZSBsb2FkZWQgYmVmb3JlIGx1YS5qcyB0byBwb3B1bGF0ZSB3aW5kb3cuTHVhVVRNXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEx1YSB7XG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMgPSB7fSkge1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywge1xuICAgICAgc3RvcmFnZUtleTogJ2FiLXRlc3RzJyxcbiAgICAgIHJvb3Q6IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyBkb2N1bWVudC5ib2R5IDogbnVsbCxcbiAgICB9LCBvcHRpb25zKVxuXG4gICAgdmFsaWRhdGVTdG9yZSh0aGlzLnN0b3JlKVxuXG4gICAgdGhpcy5wcmV2aW91c0Fzc2lnbm1lbnRzID0ge31cbiAgICB0cnkge1xuICAgICAgLy8gYXNzZXJ0IHRoYXQgdGhlIGRhdGEgaXMgYSBKU09OIHN0cmluZ1xuICAgICAgLy8gdGhhdCByZXByZXNlbnRzIGEgSlNPTiBvYmplY3RcbiAgICAgIC8vIHNhdyBhIGJ1ZyB3aGVyZSBpdCB3YXMsIGZvciBzb21lIHJlYXNvbiwgc3RvcmVkIGFzIGBudWxsYFxuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuc3RvcmUuZ2V0KHRoaXMuc3RvcmFnZUtleSlcbiAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycgJiYgZGF0YVswXSA9PT0gJ3snKSB7XG4gICAgICAgIHRoaXMucHJldmlvdXNBc3NpZ25tZW50cyA9IEpTT04ucGFyc2UoZGF0YSlcbiAgICAgIH1cbiAgICB9IGNhdGNoIChfKSB7XG4gICAgICAvLyBpZ25vcmVcbiAgICB9XG5cbiAgICB0aGlzLnVzZXJBc3NpZ25tZW50cyA9IHt9XG4gICAgdGhpcy5wZXJzaXN0ZWRVc2VyQXNzaWdubWVudHMgPSB7fVxuICAgIHRoaXMucHJvdmlkZWRUZXN0cyA9IFtdXG4gIH1cblxuICBkZWZpbmUodGVzdHMpIHtcbiAgICBsZXQgbm9ybWFsaXplZERhdGEgPSB0ZXN0c1xuICAgIGlmICghQXJyYXkuaXNBcnJheSh0ZXN0cykpIG5vcm1hbGl6ZWREYXRhID0gW3Rlc3RzXVxuXG4gICAgbm9ybWFsaXplZERhdGEuZm9yRWFjaCgodGVzdCkgPT4ge1xuICAgICAgaWYgKCF0ZXN0Lm5hbWUpIHRocm93IG5ldyBFcnJvcignVGVzdHMgbXVzdCBoYXZlIGEgbmFtZScpXG4gICAgICBpZiAoIXRlc3QuYnVja2V0cykgdGhyb3cgbmV3IEVycm9yKCdUZXN0cyBtdXN0IGhhdmUgYnVja2V0cycpXG4gICAgICBpZiAoIU9iamVjdC5rZXlzKHRlc3QuYnVja2V0cykpIHRocm93IG5ldyBFcnJvcignVGVzdHMgbXVzdCBoYXZlIGJ1Y2tldHMnKVxuICAgICAgdGhpcy5wcm92aWRlZFRlc3RzLnB1c2godGVzdClcbiAgICB9KVxuICB9XG5cbiAgZGVmaW5pdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMucHJvdmlkZWRUZXN0c1xuICB9XG5cbiAgcmVtb3ZlQ2xhc3Nlcyh0ZXN0TmFtZSwgZXhjZXB0Q2xhc3NOYW1lKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgcm9vdCB9ID0gdGhpc1xuICAgICAgaWYgKCFyb290KSByZXR1cm5cblxuICAgICAgLy8gY2xhc3NMaXN0IGRvZXMgbm90IHN1cHBvcnQgcmV0dXJuaW5nIGFsbCBjbGFzc2VzXG4gICAgICBjb25zdCBjdXJyZW50Q2xhc3NOYW1lcyA9IHJvb3QuY2xhc3NOYW1lLnNwbGl0KC9cXHMrL2cpXG4gICAgICAgIC5tYXAoeCA9PiB4LnRyaW0oKSlcbiAgICAgICAgLmZpbHRlcihCb29sZWFuKVxuXG4gICAgICBjdXJyZW50Q2xhc3NOYW1lc1xuICAgICAgICAuZmlsdGVyKHggPT4geC5pbmRleE9mKGAke3Rlc3ROYW1lfS0tYCkgPT09IDApXG4gICAgICAgIC5maWx0ZXIoY2xhc3NOYW1lID0+IGNsYXNzTmFtZSAhPT0gZXhjZXB0Q2xhc3NOYW1lKVxuICAgICAgICAuZm9yRWFjaChjbGFzc05hbWUgPT4gcm9vdC5jbGFzc0xpc3QucmVtb3ZlKGNsYXNzTmFtZSkpXG4gICAgfSBjYXRjaCAoXykge1xuICAgICAgLy8gSWdub3JlXG4gICAgfVxuICB9XG5cbiAgYXBwbHlDbGFzc2VzKCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IHVzZXJBc3NpZ25tZW50cywgcm9vdCB9ID0gdGhpc1xuICAgICAgaWYgKCFyb290KSByZXR1cm5cblxuICAgICAgT2JqZWN0LmtleXModXNlckFzc2lnbm1lbnRzKS5mb3JFYWNoKCh0ZXN0TmFtZSkgPT4ge1xuICAgICAgICBjb25zdCBidWNrZXQgPSB1c2VyQXNzaWdubWVudHNbdGVzdE5hbWVdXG5cbiAgICAgICAgY29uc3QgY2xhc3NOYW1lID0gYnVja2V0ID8gYCR7dGVzdE5hbWV9LS0ke2J1Y2tldH1gIDogbnVsbFxuICAgICAgICAvLyByZW1vdmUgYWxsIGNsYXNzZXMgcmVsYXRlZCB0byB0aGlzIGJ1Y2tldFxuICAgICAgICB0aGlzLnJlbW92ZUNsYXNzZXModGVzdE5hbWUsIGNsYXNzTmFtZSlcblxuICAgICAgICAvLyBvbmx5IGFzc2lnbiBhIGNsYXNzIGlzIHRoZSB0ZXN0IGlzIGFzc2lnbmVkIHRvIGEgYnVja2V0XG4gICAgICAgIC8vIHRoaXMgcmVtb3ZlcyB0aGVuIGFkZHMgYSBjbGFzcywgd2hpY2ggaXMgbm90IGlkZWFsIGJ1dCBpcyBjbGVhblxuICAgICAgICBpZiAoY2xhc3NOYW1lKSByb290LmNsYXNzTGlzdC5hZGQoY2xhc3NOYW1lKVxuICAgICAgfSlcbiAgICB9IGNhdGNoIChfKSB7XG4gICAgICAvLyBJZ25vcmVcbiAgICB9XG4gIH1cblxuICBhc3NpZ25BbGwoKSB7XG4gICAgY29uc3Qge1xuICAgICAgcHJldmlvdXNBc3NpZ25tZW50cyxcbiAgICAgIHVzZXJBc3NpZ25tZW50cyxcbiAgICAgIHBlcnNpc3RlZFVzZXJBc3NpZ25tZW50cyxcbiAgICB9ID0gdGhpc1xuXG4gICAgdGhpcy5wcm92aWRlZFRlc3RzLmZvckVhY2goKHRlc3QpID0+IHtcbiAgICAgIC8vIHdpbm5lcnMgdGFrZSBwcmVjZWRlbmNlXG4gICAgICB7XG4gICAgICAgIGNvbnN0IHdpbm5lciA9IE9iamVjdC5rZXlzKHRlc3QuYnVja2V0cylcbiAgICAgICAgICAuZmlsdGVyKG5hbWUgPT4gdGVzdC5idWNrZXRzW25hbWVdLndpbm5lcilbMF1cbiAgICAgICAgaWYgKHdpbm5lcikge1xuICAgICAgICAgIHVzZXJBc3NpZ25tZW50c1t0ZXN0Lm5hbWVdID0gd2lubmVyXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gYWxyZWFkeSBhc3NpZ25lZCwgcHJvYmFibHkgYmVjYXVzZSBzb21lb25lXG4gICAgICAvLyBjYWxsZWQgYC5hc3NpZ25BbGwoKWAgdHdpY2UuXG4gICAgICBpZiAodXNlckFzc2lnbm1lbnRzW3Rlc3QubmFtZV0pIHJldHVyblxuXG4gICAgICB7XG4gICAgICAgIC8vIHByZXZpb3VzbHkgYXNzaWduZWQsIHNvIHdlIGNvbnRpbnVlIHRvIHBlcnNpc3QgaXRcbiAgICAgICAgY29uc3QgYnVja2V0ID0gcHJldmlvdXNBc3NpZ25tZW50c1t0ZXN0Lm5hbWVdXG4gICAgICAgIGlmIChidWNrZXQgJiYgdGVzdC5idWNrZXRzW2J1Y2tldF0pIHtcbiAgICAgICAgICBjb25zdCBhc3NpZ25tZW50ID0gcHJldmlvdXNBc3NpZ25tZW50c1t0ZXN0Lm5hbWVdXG4gICAgICAgICAgcGVyc2lzdGVkVXNlckFzc2lnbm1lbnRzW3Rlc3QubmFtZV0gPSBhc3NpZ25tZW50XG4gICAgICAgICAgdXNlckFzc2lnbm1lbnRzW3Rlc3QubmFtZV0gPSBhc3NpZ25tZW50XG4gICAgICAgICAgdGVzdC5hY3RpdmUgPSB0cnVlXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gaW5hY3RpdmUgdGVzdHMgc2hvdWxkIGJlIHNldCB0byBkZWZhdWx0XG4gICAgICBpZiAodGVzdC5hY3RpdmUgPT09IGZhbHNlKSB7XG4gICAgICAgIHVzZXJBc3NpZ25tZW50c1t0ZXN0Lm5hbWVdID0gZ2V0RGVmYXVsdEJ1Y2tldCh0ZXN0LmJ1Y2tldHMpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICAvLyByYW5kb21seSBhc3NpZ25cbiAgICAgIHtcbiAgICAgICAgY29uc3QgYXNzaWdubWVudCA9IGdldFJhbmRvbUFzc2lnbm1lbnQodGVzdClcbiAgICAgICAgcGVyc2lzdGVkVXNlckFzc2lnbm1lbnRzW3Rlc3QubmFtZV0gPSBhc3NpZ25tZW50XG4gICAgICAgIHVzZXJBc3NpZ25tZW50c1t0ZXN0Lm5hbWVdID0gYXNzaWdubWVudFxuICAgICAgfVxuICAgIH0pXG5cbiAgICB0aGlzLnBlcnNpc3QoKVxuICAgIHRoaXMuYXBwbHlDbGFzc2VzKClcbiAgfVxuXG4gIGFzc2lnbih0ZXN0TmFtZSwgYnVja2V0TmFtZSkge1xuICAgIGlmICghdGVzdE5hbWUpIHJldHVybiB0aGlzLmFzc2lnbkFsbCgpXG5cbiAgICBjb25zdCB0ZXN0ID0gdGhpcy5wcm92aWRlZFRlc3RzLmZpbHRlcih4ID0+IHgubmFtZSA9PT0gdGVzdE5hbWUpWzBdXG4gICAgaWYgKGJ1Y2tldE5hbWUgPT09IG51bGwgfHwgIXRlc3QpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnVzZXJBc3NpZ25tZW50c1t0ZXN0TmFtZV1cbiAgICAgIGRlbGV0ZSB0aGlzLnBlcnNpc3RlZFVzZXJBc3NpZ25tZW50c1t0ZXN0TmFtZV1cbiAgICAgIHRoaXMucGVyc2lzdCgpXG4gICAgICB0aGlzLnJlbW92ZUNsYXNzZXModGVzdE5hbWUpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBhc3NpZ25tZW50ID0gYnVja2V0TmFtZSB8fCBnZXRSYW5kb21Bc3NpZ25tZW50KHRlc3QpXG4gICAgdGhpcy51c2VyQXNzaWdubWVudHNbdGVzdE5hbWVdID0gYXNzaWdubWVudFxuICAgIHRoaXMucGVyc2lzdGVkVXNlckFzc2lnbm1lbnRzW3Rlc3ROYW1lXSA9IGFzc2lnbm1lbnRcbiAgICB0ZXN0LmFjdGl2ZSA9IHRydWVcblxuICAgIHRoaXMucGVyc2lzdCgpXG4gICAgdGhpcy5hcHBseUNsYXNzZXMoKVxuICB9XG5cbiAgZXh0ZW5kQXNzaWdubWVudHMoYXNzaWdubWVudHMpIHtcbiAgICByZXR1cm4gYXNzaWdubWVudHNcbiAgfVxuXG4gIGFzc2lnbm1lbnRzKCkge1xuICAgIHJldHVybiB0aGlzLmV4dGVuZEFzc2lnbm1lbnRzKHRoaXMudXNlckFzc2lnbm1lbnRzKVxuICB9XG5cbiAgcGVyc2lzdCgpIHtcbiAgICB0aGlzLnN0b3JlLnNldCh0aGlzLnN0b3JhZ2VLZXksIEpTT04uc3RyaW5naWZ5KHRoaXMucGVyc2lzdGVkVXNlckFzc2lnbm1lbnRzKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgVVRNIGNvbnRleHQgZm9yIHRoZSBjdXJyZW50IHBhZ2VcbiAgICogVXNlcyB3aW5kb3cuTHVhVVRNIGdsb2JhbCAocG9wdWxhdGVkIGJ5IHV0bS5qcyBJSUZFKVxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSAtIENvbnRleHQgb2JqZWN0IHdpdGggVVRNIHBhcmFtcywgcmVmZXJyZXIsIHVzZXIgYWdlbnQsIGFuZCBpbnRlbnRcbiAgICovXG4gIGdldFVUTUNvbnRleHQoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhciBfcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB7fVxuICAgICAgaWYgKF9yb290Lkx1YVVUTSAmJiB0eXBlb2YgX3Jvb3QuTHVhVVRNLmdldENvbnRleHQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIF9yb290Lkx1YVVUTS5nZXRDb250ZXh0KClcbiAgICAgIH1cbiAgICAgIHJldHVybiB7IHV0bToge30sIHJlZmVycmVyOiB7fSwgdXNlckFnZW50OiB7fSwgcHJpbWFyeUludGVudDogJ2RlZmF1bHQnLCBoYXNVVE06IGZhbHNlIH1cbiAgICB9IGNhdGNoIChfKSB7XG4gICAgICByZXR1cm4geyB1dG06IHt9LCByZWZlcnJlcjoge30sIHVzZXJBZ2VudDoge30sIHByaW1hcnlJbnRlbnQ6ICdkZWZhdWx0JywgaGFzVVRNOiBmYWxzZSB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBidWNrZXQgYmFzZWQgb24gVVRNIGNvbnRleHRcbiAgICogTWFwcyBVVE0gaW50ZW50IHRvIHRlc3QgYnVja2V0c1xuICAgKiBAcGFyYW0ge09iamVjdH0gdGVzdCAtIFRlc3QgZGVmaW5pdGlvbiB3aXRoIGJ1Y2tldHNcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbnRleHQgLSBVVE0gY29udGV4dFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IC0gQnVja2V0IG5hbWUgb3IgbnVsbCBpZiBubyBtYXRjaFxuICAgKi9cbiAgZ2V0VVRNQmFzZWRCdWNrZXQodGVzdCwgY29udGV4dCkge1xuICAgIGlmICghY29udGV4dCB8fCAhY29udGV4dC5oYXNVVE0pIHJldHVybiBudWxsXG5cbiAgICAvLyBDaGVjayBpZiB0ZXN0IGhhcyBVVE0gcnVsZXMgZGVmaW5lZFxuICAgIGNvbnN0IHV0bVJ1bGVzID0gdGVzdC51dG1SdWxlcyB8fCB7fVxuXG4gICAgLy8gUHJpb3JpdHkgMTogTWF0Y2ggYnkgdXRtX2NhbXBhaWduXG4gICAgaWYgKGNvbnRleHQudXRtLnV0bV9jYW1wYWlnbikge1xuICAgICAgY29uc3QgY2FtcGFpZ25SdWxlID0gdXRtUnVsZXNbY29udGV4dC51dG0udXRtX2NhbXBhaWduXVxuICAgICAgaWYgKGNhbXBhaWduUnVsZSAmJiB0ZXN0LmJ1Y2tldHNbY2FtcGFpZ25SdWxlXSkge1xuICAgICAgICByZXR1cm4gY2FtcGFpZ25SdWxlXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUHJpb3JpdHkgMjogTWF0Y2ggYnkgdXRtX3NvdXJjZVxuICAgIGlmIChjb250ZXh0LnV0bS51dG1fc291cmNlKSB7XG4gICAgICBjb25zdCBzb3VyY2VSdWxlID0gdXRtUnVsZXNbY29udGV4dC51dG0udXRtX3NvdXJjZV1cbiAgICAgIGlmIChzb3VyY2VSdWxlICYmIHRlc3QuYnVja2V0c1tzb3VyY2VSdWxlXSkge1xuICAgICAgICByZXR1cm4gc291cmNlUnVsZVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFByaW9yaXR5IDM6IE1hdGNoIGJ5IGluZmVycmVkIGludGVudFxuICAgIGNvbnN0IGludGVudCA9IGNvbnRleHQucHJpbWFyeUludGVudFxuICAgIGlmIChpbnRlbnQgJiYgdGVzdC5idWNrZXRzW2ludGVudF0pIHtcbiAgICAgIHJldHVybiBpbnRlbnRcbiAgICB9XG5cbiAgICAvLyBQcmlvcml0eSA0OiBDaGVjayBmb3IgaW50ZW50LW1hcHBlZCBidWNrZXRzXG4gICAgY29uc3QgaW50ZW50TWFwcGluZyA9IHRlc3QuaW50ZW50TWFwcGluZyB8fCB7fVxuICAgIGlmIChpbnRlbnQgJiYgaW50ZW50TWFwcGluZ1tpbnRlbnRdICYmIHRlc3QuYnVja2V0c1tpbnRlbnRNYXBwaW5nW2ludGVudF1dKSB7XG4gICAgICByZXR1cm4gaW50ZW50TWFwcGluZ1tpbnRlbnRdXG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NpZ24gd2l0aCBVVE0tYXdhcmUgcGVyc29uYWxpemF0aW9uXG4gICAqIEZhbGxzIGJhY2sgdG8gcmFuZG9tIEEvQiBpZiBubyBVVE0gbWF0Y2hcbiAgICogQHBhcmFtIHtzdHJpbmd9IFt0ZXN0TmFtZV0gLSBPcHRpb25hbCBzcGVjaWZpYyB0ZXN0IG5hbWVcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSAtIE9wdGlvbnMgaW5jbHVkaW5nIGZvcmNlVVRNLCBjb250ZXh0XG4gICAqIEByZXR1cm5zIHtPYmplY3R9IC0geyBhc3NpZ25tZW50LCBzb3VyY2U6ICd1dG0nfCdyYW5kb20nfCdwZXJzaXN0ZWQnIH1cbiAgICovXG4gIGFzc2lnbldpdGhVVE0odGVzdE5hbWUsIG9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IGNvbnRleHQgPSBvcHRpb25zLmNvbnRleHQgfHwgdGhpcy5nZXRVVE1Db250ZXh0KClcblxuICAgIC8vIElmIG5vIHRlc3QgbmFtZSwgYXNzaWduIGFsbCB3aXRoIFVUTSBhd2FyZW5lc3NcbiAgICBpZiAoIXRlc3ROYW1lKSB7XG4gICAgICByZXR1cm4gdGhpcy5hc3NpZ25BbGxXaXRoVVRNKGNvbnRleHQpXG4gICAgfVxuXG4gICAgY29uc3QgdGVzdCA9IHRoaXMucHJvdmlkZWRUZXN0cy5maWx0ZXIoeCA9PiB4Lm5hbWUgPT09IHRlc3ROYW1lKVswXVxuICAgIGlmICghdGVzdCkge1xuICAgICAgcmV0dXJuIHsgYXNzaWdubWVudDogbnVsbCwgc291cmNlOiAnbm9uZScgfVxuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciB3aW5uZXIgZmlyc3QgKHRha2VzIHByZWNlZGVuY2UpXG4gICAgY29uc3Qgd2lubmVyID0gT2JqZWN0LmtleXModGVzdC5idWNrZXRzKS5maWx0ZXIobmFtZSA9PiB0ZXN0LmJ1Y2tldHNbbmFtZV0ud2lubmVyKVswXVxuICAgIGlmICh3aW5uZXIpIHtcbiAgICAgIHRoaXMudXNlckFzc2lnbm1lbnRzW3Rlc3ROYW1lXSA9IHdpbm5lclxuICAgICAgdGhpcy5wZXJzaXN0KClcbiAgICAgIHRoaXMuYXBwbHlDbGFzc2VzKClcbiAgICAgIHJldHVybiB7IGFzc2lnbm1lbnQ6IHdpbm5lciwgc291cmNlOiAnd2lubmVyJyB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgcHJldmlvdXMgYXNzaWdubWVudFxuICAgIGNvbnN0IHByZXZpb3VzQnVja2V0ID0gdGhpcy5wcmV2aW91c0Fzc2lnbm1lbnRzW3Rlc3ROYW1lXVxuICAgIGlmIChwcmV2aW91c0J1Y2tldCAmJiB0ZXN0LmJ1Y2tldHNbcHJldmlvdXNCdWNrZXRdKSB7XG4gICAgICB0aGlzLnVzZXJBc3NpZ25tZW50c1t0ZXN0TmFtZV0gPSBwcmV2aW91c0J1Y2tldFxuICAgICAgdGhpcy5wZXJzaXN0ZWRVc2VyQXNzaWdubWVudHNbdGVzdE5hbWVdID0gcHJldmlvdXNCdWNrZXRcbiAgICAgIHRlc3QuYWN0aXZlID0gdHJ1ZVxuICAgICAgdGhpcy5wZXJzaXN0KClcbiAgICAgIHRoaXMuYXBwbHlDbGFzc2VzKClcbiAgICAgIHJldHVybiB7IGFzc2lnbm1lbnQ6IHByZXZpb3VzQnVja2V0LCBzb3VyY2U6ICdwZXJzaXN0ZWQnIH1cbiAgICB9XG5cbiAgICAvLyBUcnkgVVRNLWJhc2VkIGFzc2lnbm1lbnRcbiAgICBjb25zdCB1dG1CdWNrZXQgPSB0aGlzLmdldFVUTUJhc2VkQnVja2V0KHRlc3QsIGNvbnRleHQpXG4gICAgaWYgKHV0bUJ1Y2tldCkge1xuICAgICAgdGhpcy51c2VyQXNzaWdubWVudHNbdGVzdE5hbWVdID0gdXRtQnVja2V0XG4gICAgICB0aGlzLnBlcnNpc3RlZFVzZXJBc3NpZ25tZW50c1t0ZXN0TmFtZV0gPSB1dG1CdWNrZXRcbiAgICAgIHRlc3QuYWN0aXZlID0gdHJ1ZVxuICAgICAgdGhpcy5wZXJzaXN0KClcbiAgICAgIHRoaXMuYXBwbHlDbGFzc2VzKClcbiAgICAgIHJldHVybiB7IGFzc2lnbm1lbnQ6IHV0bUJ1Y2tldCwgc291cmNlOiAndXRtJywgaW50ZW50OiBjb250ZXh0LnByaW1hcnlJbnRlbnQgfVxuICAgIH1cblxuICAgIC8vIEZhbGxiYWNrIHRvIHJhbmRvbSBhc3NpZ25tZW50XG4gICAgY29uc3QgYXNzaWdubWVudCA9IGdldFJhbmRvbUFzc2lnbm1lbnQodGVzdClcbiAgICB0aGlzLnVzZXJBc3NpZ25tZW50c1t0ZXN0TmFtZV0gPSBhc3NpZ25tZW50XG4gICAgdGhpcy5wZXJzaXN0ZWRVc2VyQXNzaWdubWVudHNbdGVzdE5hbWVdID0gYXNzaWdubWVudFxuICAgIHRlc3QuYWN0aXZlID0gdHJ1ZVxuICAgIHRoaXMucGVyc2lzdCgpXG4gICAgdGhpcy5hcHBseUNsYXNzZXMoKVxuICAgIHJldHVybiB7IGFzc2lnbm1lbnQsIHNvdXJjZTogJ3JhbmRvbScgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFzc2lnbiBhbGwgdGVzdHMgd2l0aCBVVE0gYXdhcmVuZXNzXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0IC0gVVRNIGNvbnRleHRcbiAgICogQHJldHVybnMge09iamVjdH0gLSBNYXAgb2YgdGVzdCBuYW1lcyB0byBhc3NpZ25tZW50IHJlc3VsdHNcbiAgICovXG4gIGFzc2lnbkFsbFdpdGhVVE0oY29udGV4dCkge1xuICAgIGNvbnRleHQgPSBjb250ZXh0IHx8IHRoaXMuZ2V0VVRNQ29udGV4dCgpXG4gICAgY29uc3QgcmVzdWx0cyA9IHt9XG5cbiAgICB0aGlzLnByb3ZpZGVkVGVzdHMuZm9yRWFjaCgodGVzdCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5hc3NpZ25XaXRoVVRNKHRlc3QubmFtZSwgeyBjb250ZXh0IH0pXG4gICAgICByZXN1bHRzW3Rlc3QubmFtZV0gPSByZXN1bHRcbiAgICB9KVxuXG4gICAgcmV0dXJuIHJlc3VsdHNcbiAgfVxufVxuXG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUNBLElBQUFBLE1BQUEsR0FBQUMsT0FBQTtBQU1BO0FBQ0E7QUFBQSxJQUVxQkMsR0FBRyxHQUFBQyxPQUFBLENBQUFDLE9BQUE7RUFDdEIsU0FBQUYsSUFBQSxFQUEwQjtJQUFBLElBQWRHLE9BQU8sR0FBQUMsU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQUUsU0FBQSxHQUFBRixTQUFBLE1BQUcsQ0FBQyxDQUFDO0lBQUEsSUFBQUcsZ0JBQUEsQ0FBQUwsT0FBQSxRQUFBRixHQUFBO0lBQ3RCUSxNQUFNLENBQUNDLE1BQU0sQ0FBQyxJQUFJLEVBQUU7TUFDbEJDLFVBQVUsRUFBRSxVQUFVO01BQ3RCQyxJQUFJLEVBQUUsT0FBT0MsUUFBUSxLQUFLLFdBQVcsR0FBR0EsUUFBUSxDQUFDQyxJQUFJLEdBQUc7SUFDMUQsQ0FBQyxFQUFFVixPQUFPLENBQUM7SUFFWCxJQUFBVyxvQkFBYSxFQUFDLElBQUksQ0FBQ0MsS0FBSyxDQUFDO0lBRXpCLElBQUksQ0FBQ0MsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLElBQUk7TUFDRjtNQUNBO01BQ0E7TUFDQSxJQUFNQyxJQUFJLEdBQUcsSUFBSSxDQUFDRixLQUFLLENBQUNHLEdBQUcsQ0FBQyxJQUFJLENBQUNSLFVBQVUsQ0FBQztNQUM1QyxJQUFJLE9BQU9PLElBQUksS0FBSyxRQUFRLElBQUlBLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7UUFDL0MsSUFBSSxDQUFDRCxtQkFBbUIsR0FBR0csSUFBSSxDQUFDQyxLQUFLLENBQUNILElBQUksQ0FBQztNQUM3QztJQUNGLENBQUMsQ0FBQyxPQUFPSSxDQUFDLEVBQUU7TUFDVjtJQUFBO0lBR0YsSUFBSSxDQUFDQyxlQUFlLEdBQUcsQ0FBQyxDQUFDO0lBQ3pCLElBQUksQ0FBQ0Msd0JBQXdCLEdBQUcsQ0FBQyxDQUFD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