@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.
- package/README.md +552 -0
- package/build/es5/__tests__/ai-personalize.test.js +811 -0
- package/build/es5/__tests__/lua.js +134 -0
- package/build/es5/__tests__/original-roughly.js +197 -0
- package/build/es5/__tests__/original.js +174 -0
- package/build/es5/__tests__/unit.js +72 -0
- package/build/es5/__tests__/weighted-history.test.js +376 -0
- package/build/es5/ai-personalize.js +641 -0
- package/build/es5/index.js +30 -0
- package/build/es5/lua.js +366 -0
- package/build/es5/personalization.js +811 -0
- package/build/es5/prompts/personalization-prompts.js +260 -0
- package/build/es5/storage/weighted-history.js +384 -0
- package/build/es5/stores/browser-cookie.js +25 -0
- package/build/es5/stores/local.js +29 -0
- package/build/es5/stores/memory.js +22 -0
- package/build/es5/utils.js +54 -0
- package/build/es5/utm-personalize.js +817 -0
- package/build/es5/utm.js +304 -0
- package/build/lua.dev.js +1574 -0
- package/build/lua.es.js +1566 -0
- package/build/lua.js +1574 -0
- package/build/lua.min.js +8 -0
- package/package.json +68 -0
|
@@ -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=
|
package/build/es5/lua.js
ADDED
|
@@ -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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
|