test_track_rails_client 4.0.0.alpha33 → 4.0.0
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.
- checksums.yaml +5 -5
- data/README.md +14 -13
- data/Rakefile +3 -3
- data/app/assets/javascripts/testTrack.bundle.min.js +1 -1
- data/app/controllers/concerns/test_track/controller.rb +1 -3
- data/app/models/concerns/test_track/required_options.rb +1 -0
- data/app/models/test_track/ab_configuration.rb +3 -5
- data/app/models/test_track/analytics/mixpanel_client.rb +1 -0
- data/app/models/test_track/analytics/safe_wrapper.rb +1 -0
- data/app/models/test_track/application_identity.rb +1 -0
- data/app/models/test_track/assignment.rb +2 -1
- data/app/models/test_track/config_updater.rb +3 -3
- data/app/models/test_track/fake/split_registry.rb +4 -6
- data/app/models/test_track/job_session.rb +1 -3
- data/app/models/test_track/lazy_visitor_by_identity.rb +8 -4
- data/app/models/test_track/misconfiguration_notifier.rb +1 -0
- data/app/models/test_track/notify_assignment_job.rb +1 -0
- data/app/models/test_track/remote/assignment_event.rb +1 -1
- data/app/models/test_track/remote/fake_server.rb +1 -0
- data/app/models/test_track/remote/identifier.rb +2 -1
- data/app/models/test_track/remote/identifier_type.rb +1 -1
- data/app/models/test_track/remote/split_config.rb +1 -1
- data/app/models/test_track/remote/split_detail.rb +2 -2
- data/app/models/test_track/remote/split_registry.rb +2 -2
- data/app/models/test_track/remote/visitor.rb +2 -2
- data/app/models/test_track/remote/visitor_detail.rb +1 -1
- data/app/models/test_track/split_registry.rb +2 -2
- data/app/models/test_track/threaded_visitor_notifier.rb +6 -8
- data/app/models/test_track/unsynced_assignments_notifier.rb +4 -6
- data/app/models/test_track/variant_calculator.rb +1 -0
- data/app/models/test_track/vary_dsl.rb +4 -0
- data/app/models/test_track/visitor.rb +5 -4
- data/app/models/test_track/web_session.rb +2 -1
- data/app/models/test_track/web_session_visitor_repository.rb +1 -3
- data/config/initializers/set_build_timestamp.rb +1 -0
- data/lib/tasks/test_track_rails_client_tasks.rake +21 -0
- data/lib/test_track.rb +27 -0
- data/lib/test_track_rails_client/engine.rb +4 -2
- data/lib/test_track_rails_client/version.rb +1 -1
- data/vendor/bin/testtrack-cli/testtrack.darwin +0 -0
- data/vendor/bin/testtrack-cli/testtrack.linux +0 -0
- data/vendor/gems/her/her.gemspec +1 -1
- metadata +131 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 4c0f7e37c14f063fc4bd4eadc83508176280f0bb67368b844695a7b31e1bff41
|
|
4
|
+
data.tar.gz: 119dcf930588dcc2e21dcbe497ca5bbf133f626dbb6edf05e6b162a2f84d0c49
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c6250d9c4198aac51623251727abe60e36b137df1dd6261fdf6f1e26d8824e8fb734b262189274d6a880db8b776f8dab83b7983c6233dbd295e30a67db159b4
|
|
7
|
+
data.tar.gz: 7014e8acbbe52217c4555ff65d0584d473edd1df5174a29a02f4e673398aa6a54e3c2a4eda21604cefb641f7fc88919109c415770df67adb713e38d66b8cad5c
|
data/README.md
CHANGED
|
@@ -50,7 +50,7 @@ Set up ENV vars in every environment:
|
|
|
50
50
|
* `TEST_TRACK_API_URL` - Set this to the URL of your TestTrack instance with your app credentials, e.g. `http://[myapp]:[your new app password]@[your-app-domain]/`
|
|
51
51
|
|
|
52
52
|
[your-app-domain] can be
|
|
53
|
-
* `testtrack.
|
|
53
|
+
* `testtrack.test`
|
|
54
54
|
* `localhost:PORT`
|
|
55
55
|
* `example.org`
|
|
56
56
|
* etc
|
|
@@ -72,8 +72,8 @@ If your app doesn't support authentication, set
|
|
|
72
72
|
|
|
73
73
|
### Prepare your identity models (optional)
|
|
74
74
|
|
|
75
|
-
If your app supports authentication,
|
|
76
|
-
`User` model as a [TestTrack Identity](#varying-app-behavior-from-within-a-model)
|
|
75
|
+
If your app supports authentication, you'll need to configure your
|
|
76
|
+
`User` model as a [TestTrack Identity](#varying-app-behavior-from-within-a-model).
|
|
77
77
|
|
|
78
78
|
### Set up the Chrome extension (optional)
|
|
79
79
|
|
|
@@ -288,7 +288,7 @@ class BackgroundWorkJob
|
|
|
288
288
|
end
|
|
289
289
|
end
|
|
290
290
|
end
|
|
291
|
-
```
|
|
291
|
+
```
|
|
292
292
|
|
|
293
293
|
## Tracking visitor logins
|
|
294
294
|
|
|
@@ -391,28 +391,29 @@ def notify(message)
|
|
|
391
391
|
|
|
392
392
|
### From 3.0 to 4.0
|
|
393
393
|
|
|
394
|
-
The contract of custom analytics plugins has changed. Instead of
|
|
394
|
+
* The contract of custom analytics plugins has changed. Instead of
|
|
395
395
|
implementing `track_assignment` you now must implement `track`. It's
|
|
396
396
|
easier and more conventional, though, and takes care of differentiating
|
|
397
|
-
between
|
|
397
|
+
between experiment assignments and feature gate experiences, which are
|
|
398
398
|
no longer recorded server-side.
|
|
399
399
|
|
|
400
|
-
You
|
|
400
|
+
* You must add `self.test_track_identity = :current_user` (or
|
|
401
401
|
whatever your controller uses as a sign-in identity) to your
|
|
402
402
|
TestTrack-enabled controllers, or set it to `:none` if your app doesn't
|
|
403
|
-
support authentication.
|
|
403
|
+
support authentication. If your app supports authentication, you'll need to configure your
|
|
404
|
+
user model as a [TestTrack Identity](#varying-app-behavior-from-within-a-model).
|
|
404
405
|
|
|
405
|
-
If your
|
|
406
|
-
user model as a [TestTrack Identity](#varying-app-behavior-from-within-a-model)
|
|
406
|
+
* TestTrack server [introduced a new endpoint](https://github.com/Betterment/test_track/pull/133) for fetching the split registry that requires a timestamp of when the application was built. This prevents dropped splits from breaking a running application. If you use `rake assets:precompile` in your build pipeline, you're all set. If you don't, you'll need to call `rake test_track:generate_build_timestamp` and ensure that the file `testtrack/build_timestamp` is deployed along with your app.
|
|
407
407
|
|
|
408
408
|
### From 2.0 to 3.0
|
|
409
409
|
|
|
410
|
-
TestTrack Rails Client no longer manages your Mixpanel cookie. The analytics plugin now provides a callback on `sign_up!` that will allow you to implement this functionality within your application. Please see the [analytics documentation](#analytics) for more details.
|
|
411
|
-
|
|
410
|
+
* TestTrack Rails Client no longer manages your Mixpanel cookie. The analytics plugin now provides a callback on `sign_up!` that will allow you to implement this functionality within your application. Please see the [analytics documentation](#analytics) for more details.
|
|
411
|
+
|
|
412
|
+
* `TestTrack.analytics#track_assignment` no longer accepts a properties hash as an argument as `mixpanel_distinct_id` is no longer relevant.
|
|
412
413
|
|
|
413
414
|
### From 1.x to 1.3
|
|
414
415
|
|
|
415
|
-
`TestTrack::Session#log_in!` and `TestTrack:Session#sign_up!` now take a `TestTrack::Identity` instance argument instead of an identity type and identity value.
|
|
416
|
+
* `TestTrack::Session#log_in!` and `TestTrack:Session#sign_up!` now take a `TestTrack::Identity` instance argument instead of an identity type and identity value.
|
|
416
417
|
|
|
417
418
|
## How to Contribute
|
|
418
419
|
|
data/Rakefile
CHANGED
|
@@ -14,7 +14,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
|
14
14
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
APP_RAKEFILE = File.expand_path(
|
|
17
|
+
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
|
|
18
18
|
load 'rails/tasks/engine.rake'
|
|
19
19
|
|
|
20
20
|
Bundler::GemHelper.install_tasks
|
|
@@ -28,8 +28,8 @@ RuboCop::RakeTask.new
|
|
|
28
28
|
|
|
29
29
|
desc "Pull the latest versions of all dependencies into the gem for distribution"
|
|
30
30
|
task :vendor_deps do
|
|
31
|
-
TEST_TRACK_JS_CLIENT_VERSION = '2.0.0
|
|
32
|
-
TEST_TRACK_CLI_VERSION = 'v1.0
|
|
31
|
+
TEST_TRACK_JS_CLIENT_VERSION = '2.0.0'.freeze
|
|
32
|
+
TEST_TRACK_CLI_VERSION = 'v1.2.0'.freeze
|
|
33
33
|
|
|
34
34
|
# Bundle JS client
|
|
35
35
|
sh 'npm init -y'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).TestTrack=e()}(this,function(){"use strict";var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function e(t,e){return t(e={exports:{}},e.exports),e.exports}var r=e(function(t,e){var r;r=function(){function t(){for(var t=0,e={};t<arguments.length;t++){var r=arguments[t];for(var n in r)e[n]=r[n]}return e}return function e(r){function n(e,i,o){var s;if("undefined"!=typeof document){if(arguments.length>1){if("number"==typeof(o=t({path:"/"},n.defaults,o)).expires){var a=new Date;a.setMilliseconds(a.getMilliseconds()+864e5*o.expires),o.expires=a}o.expires=o.expires?o.expires.toUTCString():"";try{s=JSON.stringify(i),/^[\{\[]/.test(s)&&(i=s)}catch(t){}i=r.write?r.write(i,e):encodeURIComponent(String(i)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),e=(e=(e=encodeURIComponent(String(e))).replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent)).replace(/[\(\)]/g,escape);var u="";for(var c in o)o[c]&&(u+="; "+c,!0!==o[c]&&(u+="="+o[c]));return document.cookie=e+"="+i+u}e||(s={});for(var f=document.cookie?document.cookie.split("; "):[],p=/(%[0-9A-Z]{2})+/g,l=0;l<f.length;l++){var d=f[l].split("="),h=d.slice(1).join("=");this.json||'"'!==h.charAt(0)||(h=h.slice(1,-1));try{var g=d[0].replace(p,decodeURIComponent);if(h=r.read?r.read(h,g):r(h,g)||h.replace(p,decodeURIComponent),this.json)try{h=JSON.parse(h)}catch(t){}if(e===g){s=h;break}e||(s[g]=h)}catch(t){}}return s}}return n.set=n,n.get=function(t){return n.call(n,t)},n.getJSON=function(){return n.apply({json:!0},[].slice.call(arguments))},n.defaults={},n.remove=function(e,r){n(e,"",t(r,{expires:-1}))},n.withConverter=e,n}(function(){})},t.exports=r()}),n=function(t){if(!t.splitName)throw new Error("must provide splitName");if(!t.hasOwnProperty("variant"))throw new Error("must provide variant");if(!t.hasOwnProperty("isUnsynced"))throw new Error("must provide isUnsynced");this._splitName=t.splitName,this._variant=t.variant,this._context=t.context,this._isUnsynced=t.isUnsynced};n.fromJsonArray=function(t){for(var e=[],r=0;r<t.length;r++)e.push(new n({splitName:t[r].split_name,variant:t[r].variant,context:t[r].context,isUnsynced:t[r].unsynced}));return e},n.prototype.getSplitName=function(){return this._splitName},n.prototype.getVariant=function(){return this._variant},n.prototype.setVariant=function(t){this._variant=t},n.prototype.getContext=function(){return this._context},n.prototype.setContext=function(t){this._context=t},n.prototype.isUnsynced=function(){return this._isUnsynced},n.prototype.setUnsynced=function(t){this._isUnsynced=t};var i=Object.prototype.hasOwnProperty,o=Array.isArray,s=function(){for(var t=[],e=0;e<256;++e)t.push("%"+((e<16?"0":"")+e.toString(16)).toUpperCase());return t}(),a=function(t,e){for(var r=e&&e.plainObjects?Object.create(null):{},n=0;n<t.length;++n)void 0!==t[n]&&(r[n]=t[n]);return r},u={arrayToObject:a,assign:function(t,e){return Object.keys(e).reduce(function(t,r){return t[r]=e[r],t},t)},combine:function(t,e){return[].concat(t,e)},compact:function(t){for(var e=[{obj:{o:t},prop:"o"}],r=[],n=0;n<e.length;++n)for(var i=e[n],s=i.obj[i.prop],a=Object.keys(s),u=0;u<a.length;++u){var c=a[u],f=s[c];"object"==typeof f&&null!==f&&-1===r.indexOf(f)&&(e.push({obj:s,prop:c}),r.push(f))}return function(t){for(;t.length>1;){var e=t.pop(),r=e.obj[e.prop];if(o(r)){for(var n=[],i=0;i<r.length;++i)void 0!==r[i]&&n.push(r[i]);e.obj[e.prop]=n}}}(e),t},decode:function(t,e,r){var n=t.replace(/\+/g," ");if("iso-8859-1"===r)return n.replace(/%[0-9a-f]{2}/gi,unescape);try{return decodeURIComponent(n)}catch(t){return n}},encode:function(t,e,r){if(0===t.length)return t;var n=t;if("symbol"==typeof t?n=Symbol.prototype.toString.call(t):"string"!=typeof t&&(n=String(t)),"iso-8859-1"===r)return escape(n).replace(/%u[0-9a-f]{4}/gi,function(t){return"%26%23"+parseInt(t.slice(2),16)+"%3B"});for(var i="",o=0;o<n.length;++o){var a=n.charCodeAt(o);45===a||46===a||95===a||126===a||a>=48&&a<=57||a>=65&&a<=90||a>=97&&a<=122?i+=n.charAt(o):a<128?i+=s[a]:a<2048?i+=s[192|a>>6]+s[128|63&a]:a<55296||a>=57344?i+=s[224|a>>12]+s[128|a>>6&63]+s[128|63&a]:(o+=1,a=65536+((1023&a)<<10|1023&n.charCodeAt(o)),i+=s[240|a>>18]+s[128|a>>12&63]+s[128|a>>6&63]+s[128|63&a])}return i},isBuffer:function(t){return!(!t||"object"!=typeof t||!(t.constructor&&t.constructor.isBuffer&&t.constructor.isBuffer(t)))},isRegExp:function(t){return"[object RegExp]"===Object.prototype.toString.call(t)},merge:function t(e,r,n){if(!r)return e;if("object"!=typeof r){if(o(e))e.push(r);else{if(!e||"object"!=typeof e)return[e,r];(n&&(n.plainObjects||n.allowPrototypes)||!i.call(Object.prototype,r))&&(e[r]=!0)}return e}if(!e||"object"!=typeof e)return[e].concat(r);var s=e;return o(e)&&!o(r)&&(s=a(e,n)),o(e)&&o(r)?(r.forEach(function(r,o){if(i.call(e,o)){var s=e[o];s&&"object"==typeof s&&r&&"object"==typeof r?e[o]=t(s,r,n):e.push(r)}else e[o]=r}),e):Object.keys(r).reduce(function(e,o){var s=r[o];return i.call(e,o)?e[o]=t(e[o],s,n):e[o]=s,e},s)}},c=String.prototype.replace,f=/%20/g,p={RFC1738:"RFC1738",RFC3986:"RFC3986"},l=u.assign({default:p.RFC3986,formatters:{RFC1738:function(t){return c.call(t,f,"+")},RFC3986:function(t){return String(t)}}},p),d=Object.prototype.hasOwnProperty,h={brackets:function(t){return t+"[]"},comma:"comma",indices:function(t,e){return t+"["+e+"]"},repeat:function(t){return t}},g=Array.isArray,y=Array.prototype.push,m=function(t,e){y.apply(t,g(e)?e:[e])},v=Date.prototype.toISOString,w=l.default,_={addQueryPrefix:!1,allowDots:!1,charset:"utf-8",charsetSentinel:!1,delimiter:"&",encode:!0,encoder:u.encode,encodeValuesOnly:!1,format:w,formatter:l.formatters[w],indices:!1,serializeDate:function(t){return v.call(t)},skipNulls:!1,strictNullHandling:!1},b=function t(e,r,n,i,o,s,a,c,f,p,l,d,h){var y,v=e;if("function"==typeof a?v=a(r,v):v instanceof Date?v=p(v):"comma"===n&&g(v)&&(v=v.join(",")),null===v){if(i)return s&&!d?s(r,_.encoder,h,"key"):r;v=""}if("string"==typeof(y=v)||"number"==typeof y||"boolean"==typeof y||"symbol"==typeof y||"bigint"==typeof y||u.isBuffer(v))return s?[l(d?r:s(r,_.encoder,h,"key"))+"="+l(s(v,_.encoder,h,"value"))]:[l(r)+"="+l(String(v))];var w,b=[];if(void 0===v)return b;if(g(a))w=a;else{var A=Object.keys(v);w=c?A.sort(c):A}for(var S=0;S<w.length;++S){var x=w[S];o&&null===v[x]||(g(v)?m(b,t(v[x],"function"==typeof n?n(r,x):r,n,i,o,s,a,c,f,p,l,d,h)):m(b,t(v[x],r+(f?"."+x:"["+x+"]"),n,i,o,s,a,c,f,p,l,d,h)))}return b},A=(Object.prototype.hasOwnProperty,Array.isArray,function(t,e){var r,n=t,i=function(t){if(!t)return _;if(null!==t.encoder&&void 0!==t.encoder&&"function"!=typeof t.encoder)throw new TypeError("Encoder has to be a function.");var e=t.charset||_.charset;if(void 0!==t.charset&&"utf-8"!==t.charset&&"iso-8859-1"!==t.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");var r=l.default;if(void 0!==t.format){if(!d.call(l.formatters,t.format))throw new TypeError("Unknown format option provided.");r=t.format}var n=l.formatters[r],i=_.filter;return("function"==typeof t.filter||g(t.filter))&&(i=t.filter),{addQueryPrefix:"boolean"==typeof t.addQueryPrefix?t.addQueryPrefix:_.addQueryPrefix,allowDots:void 0===t.allowDots?_.allowDots:!!t.allowDots,charset:e,charsetSentinel:"boolean"==typeof t.charsetSentinel?t.charsetSentinel:_.charsetSentinel,delimiter:void 0===t.delimiter?_.delimiter:t.delimiter,encode:"boolean"==typeof t.encode?t.encode:_.encode,encoder:"function"==typeof t.encoder?t.encoder:_.encoder,encodeValuesOnly:"boolean"==typeof t.encodeValuesOnly?t.encodeValuesOnly:_.encodeValuesOnly,filter:i,formatter:n,serializeDate:"function"==typeof t.serializeDate?t.serializeDate:_.serializeDate,skipNulls:"boolean"==typeof t.skipNulls?t.skipNulls:_.skipNulls,sort:"function"==typeof t.sort?t.sort:null,strictNullHandling:"boolean"==typeof t.strictNullHandling?t.strictNullHandling:_.strictNullHandling}}(e);"function"==typeof i.filter?n=(0,i.filter)("",n):g(i.filter)&&(r=i.filter);var o,s=[];if("object"!=typeof n||null===n)return"";o=e&&e.arrayFormat in h?e.arrayFormat:e&&"indices"in e?e.indices?"indices":"repeat":"indices";var a=h[o];r||(r=Object.keys(n)),i.sort&&r.sort(i.sort);for(var u=0;u<r.length;++u){var c=r[u];i.skipNulls&&null===n[c]||m(s,b(n[c],c,a,i.strictNullHandling,i.skipNulls,i.encode?i.encoder:null,i.filter,i.sort,i.allowDots,i.serializeDate,i.formatter,i.encodeValuesOnly,i.charset))}var f=s.join(i.delimiter),p=!0===i.addQueryPrefix?"?":"";return i.charsetSentinel&&("iso-8859-1"===i.charset?p+="utf8=%26%2310003%3B&":p+="utf8=%E2%9C%93&"),f.length>0?p+f:""}),S=function(t,e){return function(){for(var r=new Array(arguments.length),n=0;n<r.length;n++)r[n]=arguments[n];return t.apply(e,r)}},x=Object.prototype.toString;function E(t){return"[object Array]"===x.call(t)}function C(t){return null!==t&&"object"==typeof t}function O(t){return"[object Function]"===x.call(t)}function N(t,e){if(null!=t)if("object"!=typeof t&&(t=[t]),E(t))for(var r=0,n=t.length;r<n;r++)e.call(null,t[r],r,t);else for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&e.call(null,t[i],i,t)}var j={isArray:E,isArrayBuffer:function(t){return"[object ArrayBuffer]"===x.call(t)},isBuffer:function(t){return null!=t&&null!=t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)},isFormData:function(t){return"undefined"!=typeof FormData&&t instanceof FormData},isArrayBufferView:function(t){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer&&t.buffer instanceof ArrayBuffer},isString:function(t){return"string"==typeof t},isNumber:function(t){return"number"==typeof t},isObject:C,isUndefined:function(t){return void 0===t},isDate:function(t){return"[object Date]"===x.call(t)},isFile:function(t){return"[object File]"===x.call(t)},isBlob:function(t){return"[object Blob]"===x.call(t)},isFunction:O,isStream:function(t){return C(t)&&O(t.pipe)},isURLSearchParams:function(t){return"undefined"!=typeof URLSearchParams&&t instanceof URLSearchParams},isStandardBrowserEnv:function(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&"undefined"!=typeof window&&"undefined"!=typeof document},forEach:N,merge:function t(){var e={};function r(r,n){"object"==typeof e[n]&&"object"==typeof r?e[n]=t(e[n],r):e[n]=r}for(var n=0,i=arguments.length;n<i;n++)N(arguments[n],r);return e},deepMerge:function t(){var e={};function r(r,n){"object"==typeof e[n]&&"object"==typeof r?e[n]=t(e[n],r):e[n]="object"==typeof r?t({},r):r}for(var n=0,i=arguments.length;n<i;n++)N(arguments[n],r);return e},extend:function(t,e,r){return N(e,function(e,n){t[n]=r&&"function"==typeof e?S(e,r):e}),t},trim:function(t){return t.replace(/^\s*/,"").replace(/\s*$/,"")}};function V(t){return encodeURIComponent(t).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var R=function(t,e,r){if(!e)return t;var n;if(r)n=r(e);else if(j.isURLSearchParams(e))n=e.toString();else{var i=[];j.forEach(e,function(t,e){null!=t&&(j.isArray(t)?e+="[]":t=[t],j.forEach(t,function(t){j.isDate(t)?t=t.toISOString():j.isObject(t)&&(t=JSON.stringify(t)),i.push(V(e)+"="+V(t))}))}),n=i.join("&")}if(n){var o=t.indexOf("#");-1!==o&&(t=t.slice(0,o)),t+=(-1===t.indexOf("?")?"?":"&")+n}return t};function k(){this.handlers=[]}k.prototype.use=function(t,e){return this.handlers.push({fulfilled:t,rejected:e}),this.handlers.length-1},k.prototype.eject=function(t){this.handlers[t]&&(this.handlers[t]=null)},k.prototype.forEach=function(t){j.forEach(this.handlers,function(e){null!==e&&t(e)})};var T=k,U=function(t,e,r){return j.forEach(r,function(r){t=r(t,e)}),t},P=function(t){return!(!t||!t.__CANCEL__)},L=function(t,e){j.forEach(t,function(r,n){n!==e&&n.toUpperCase()===e.toUpperCase()&&(t[e]=r,delete t[n])})},I=function(t,e,r,n,i){return function(t,e,r,n,i){return t.config=e,r&&(t.code=r),t.request=n,t.response=i,t.isAxiosError=!0,t.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},t}(new Error(t),e,r,n,i)},D=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"],B=j.isStandardBrowserEnv()?function(){var t,e=/(msie|trident)/i.test(navigator.userAgent),r=document.createElement("a");function n(t){var n=t;return e&&(r.setAttribute("href",n),n=r.href),r.setAttribute("href",n),{href:r.href,protocol:r.protocol?r.protocol.replace(/:$/,""):"",host:r.host,search:r.search?r.search.replace(/^\?/,""):"",hash:r.hash?r.hash.replace(/^#/,""):"",hostname:r.hostname,port:r.port,pathname:"/"===r.pathname.charAt(0)?r.pathname:"/"+r.pathname}}return t=n(window.location.href),function(e){var r=j.isString(e)?n(e):e;return r.protocol===t.protocol&&r.host===t.host}}():function(){return!0},F=j.isStandardBrowserEnv()?{write:function(t,e,r,n,i,o){var s=[];s.push(t+"="+encodeURIComponent(e)),j.isNumber(r)&&s.push("expires="+new Date(r).toGMTString()),j.isString(n)&&s.push("path="+n),j.isString(i)&&s.push("domain="+i),!0===o&&s.push("secure"),document.cookie=s.join("; ")},read:function(t){var e=document.cookie.match(new RegExp("(^|;\\s*)("+t+")=([^;]*)"));return e?decodeURIComponent(e[3]):null},remove:function(t){this.write(t,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}},H=function(t){return new Promise(function(e,r){var n=t.data,i=t.headers;j.isFormData(n)&&delete i["Content-Type"];var o=new XMLHttpRequest;if(t.auth){var s=t.auth.username||"",a=t.auth.password||"";i.Authorization="Basic "+btoa(s+":"+a)}if(o.open(t.method.toUpperCase(),R(t.url,t.params,t.paramsSerializer),!0),o.timeout=t.timeout,o.onreadystatechange=function(){if(o&&4===o.readyState&&(0!==o.status||o.responseURL&&0===o.responseURL.indexOf("file:"))){var n,i,s,a,u,c="getAllResponseHeaders"in o?(n=o.getAllResponseHeaders(),u={},n?(j.forEach(n.split("\n"),function(t){if(a=t.indexOf(":"),i=j.trim(t.substr(0,a)).toLowerCase(),s=j.trim(t.substr(a+1)),i){if(u[i]&&D.indexOf(i)>=0)return;u[i]="set-cookie"===i?(u[i]?u[i]:[]).concat([s]):u[i]?u[i]+", "+s:s}}),u):u):null,f={data:t.responseType&&"text"!==t.responseType?o.response:o.responseText,status:o.status,statusText:o.statusText,headers:c,config:t,request:o};!function(t,e,r){var n=r.config.validateStatus;!n||n(r.status)?t(r):e(I("Request failed with status code "+r.status,r.config,null,r.request,r))}(e,r,f),o=null}},o.onabort=function(){o&&(r(I("Request aborted",t,"ECONNABORTED",o)),o=null)},o.onerror=function(){r(I("Network Error",t,null,o)),o=null},o.ontimeout=function(){r(I("timeout of "+t.timeout+"ms exceeded",t,"ECONNABORTED",o)),o=null},j.isStandardBrowserEnv()){var u=F,c=(t.withCredentials||B(t.url))&&t.xsrfCookieName?u.read(t.xsrfCookieName):void 0;c&&(i[t.xsrfHeaderName]=c)}if("setRequestHeader"in o&&j.forEach(i,function(t,e){void 0===n&&"content-type"===e.toLowerCase()?delete i[e]:o.setRequestHeader(e,t)}),t.withCredentials&&(o.withCredentials=!0),t.responseType)try{o.responseType=t.responseType}catch(e){if("json"!==t.responseType)throw e}"function"==typeof t.onDownloadProgress&&o.addEventListener("progress",t.onDownloadProgress),"function"==typeof t.onUploadProgress&&o.upload&&o.upload.addEventListener("progress",t.onUploadProgress),t.cancelToken&&t.cancelToken.promise.then(function(t){o&&(o.abort(),r(t),o=null)}),void 0===n&&(n=null),o.send(n)})},q={"Content-Type":"application/x-www-form-urlencoded"};function z(t,e){!j.isUndefined(t)&&j.isUndefined(t["Content-Type"])&&(t["Content-Type"]=e)}var J,M={adapter:("undefined"!=typeof process&&"[object process]"===Object.prototype.toString.call(process)?J=H:"undefined"!=typeof XMLHttpRequest&&(J=H),J),transformRequest:[function(t,e){return L(e,"Accept"),L(e,"Content-Type"),j.isFormData(t)||j.isArrayBuffer(t)||j.isBuffer(t)||j.isStream(t)||j.isFile(t)||j.isBlob(t)?t:j.isArrayBufferView(t)?t.buffer:j.isURLSearchParams(t)?(z(e,"application/x-www-form-urlencoded;charset=utf-8"),t.toString()):j.isObject(t)?(z(e,"application/json;charset=utf-8"),JSON.stringify(t)):t}],transformResponse:[function(t){if("string"==typeof t)try{t=JSON.parse(t)}catch(t){}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,validateStatus:function(t){return t>=200&&t<300}};M.headers={common:{Accept:"application/json, text/plain, */*"}},j.forEach(["delete","get","head"],function(t){M.headers[t]={}}),j.forEach(["post","put","patch"],function(t){M.headers[t]=j.merge(q)});var Q=M;function W(t){t.cancelToken&&t.cancelToken.throwIfRequested()}var $=function(t){var e,r,n;return W(t),t.baseURL&&(n=t.url,!/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(n))&&(t.url=(e=t.baseURL,(r=t.url)?e.replace(/\/+$/,"")+"/"+r.replace(/^\/+/,""):e)),t.headers=t.headers||{},t.data=U(t.data,t.headers,t.transformRequest),t.headers=j.merge(t.headers.common||{},t.headers[t.method]||{},t.headers||{}),j.forEach(["delete","get","head","post","put","patch","common"],function(e){delete t.headers[e]}),(t.adapter||Q.adapter)(t).then(function(e){return W(t),e.data=U(e.data,e.headers,t.transformResponse),e},function(e){return P(e)||(W(t),e&&e.response&&(e.response.data=U(e.response.data,e.response.headers,t.transformResponse))),Promise.reject(e)})},X=function(t,e){e=e||{};var r={};return j.forEach(["url","method","params","data"],function(t){void 0!==e[t]&&(r[t]=e[t])}),j.forEach(["headers","auth","proxy"],function(n){j.isObject(e[n])?r[n]=j.deepMerge(t[n],e[n]):void 0!==e[n]?r[n]=e[n]:j.isObject(t[n])?r[n]=j.deepMerge(t[n]):void 0!==t[n]&&(r[n]=t[n])}),j.forEach(["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","maxContentLength","validateStatus","maxRedirects","httpAgent","httpsAgent","cancelToken","socketPath"],function(n){void 0!==e[n]?r[n]=e[n]:void 0!==t[n]&&(r[n]=t[n])}),r};function G(t){this.defaults=t,this.interceptors={request:new T,response:new T}}G.prototype.request=function(t){"string"==typeof t?(t=arguments[1]||{}).url=arguments[0]:t=t||{},(t=X(this.defaults,t)).method=t.method?t.method.toLowerCase():"get";var e=[$,void 0],r=Promise.resolve(t);for(this.interceptors.request.forEach(function(t){e.unshift(t.fulfilled,t.rejected)}),this.interceptors.response.forEach(function(t){e.push(t.fulfilled,t.rejected)});e.length;)r=r.then(e.shift(),e.shift());return r},G.prototype.getUri=function(t){return t=X(this.defaults,t),R(t.url,t.params,t.paramsSerializer).replace(/^\?/,"")},j.forEach(["delete","get","head","options"],function(t){G.prototype[t]=function(e,r){return this.request(j.merge(r||{},{method:t,url:e}))}}),j.forEach(["post","put","patch"],function(t){G.prototype[t]=function(e,r,n){return this.request(j.merge(n||{},{method:t,url:e,data:r}))}});var K=G;function Z(t){this.message=t}Z.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},Z.prototype.__CANCEL__=!0;var Y=Z;function tt(t){if("function"!=typeof t)throw new TypeError("executor must be a function.");var e;this.promise=new Promise(function(t){e=t});var r=this;t(function(t){r.reason||(r.reason=new Y(t),e(r.reason))})}tt.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},tt.source=function(){var t;return{token:new tt(function(e){t=e}),cancel:t}};var et=tt;function rt(t){var e=new K(t),r=S(K.prototype.request,e);return j.extend(r,K.prototype,e),j.extend(r,e),r}var nt=rt(Q);nt.Axios=K,nt.create=function(t){return rt(X(nt.defaults,t))},nt.Cancel=Y,nt.CancelToken=et,nt.isCancel=P,nt.all=function(t){return Promise.all(t)},nt.spread=function(t){return function(e){return t.apply(null,e)}};var it=nt,ot=nt;it.default=ot;var st=it,at=e(function(e,r){!function(n){var i=r,o=e&&e.exports==i&&e,s="object"==typeof t&&t;s.global!==s&&s.window!==s||(n=s);var a=function(t){this.message=t};(a.prototype=new Error).name="InvalidCharacterError";var u=function(t){throw new a(t)},c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=/[\t\n\f\r ]/g,p={encode:function(t){t=String(t),/[^\0-\xFF]/.test(t)&&u("The string to be encoded contains characters outside of the Latin1 range.");for(var e,r,n,i,o=t.length%3,s="",a=-1,f=t.length-o;++a<f;)e=t.charCodeAt(a)<<16,r=t.charCodeAt(++a)<<8,n=t.charCodeAt(++a),s+=c.charAt((i=e+r+n)>>18&63)+c.charAt(i>>12&63)+c.charAt(i>>6&63)+c.charAt(63&i);return 2==o?(e=t.charCodeAt(a)<<8,r=t.charCodeAt(++a),s+=c.charAt((i=e+r)>>10)+c.charAt(i>>4&63)+c.charAt(i<<2&63)+"="):1==o&&(i=t.charCodeAt(a),s+=c.charAt(i>>2)+c.charAt(i<<4&63)+"=="),s},decode:function(t){var e=(t=String(t).replace(f,"")).length;e%4==0&&(e=(t=t.replace(/==?$/,"")).length),(e%4==1||/[^+a-zA-Z0-9\/]/.test(t))&&u("Invalid character: the string to be decoded is not correctly encoded.");for(var r,n,i=0,o="",s=-1;++s<e;)n=c.indexOf(t.charAt(s)),r=i%4?64*r+n:n,i++%4&&(o+=String.fromCharCode(255&r>>(-2*i&6)));return o},version:"0.1.0"};if(i&&!i.nodeType)if(o)o.exports=p;else for(var l in p)p.hasOwnProperty(l)&&(i[l]=p[l]);else n.base64=p}(t)}),ut=function(){};ut.prototype.getConfig=function(){return"function"==typeof window.atob?JSON.parse(window.atob(window.TT)):JSON.parse(at.decode(window.TT))};var ct=function(t,e,r){this._name=t,this._isFeatureGate=e,this._weighting=r};ct.prototype.getName=function(){return this._name},ct.prototype.isFeatureGate=function(){return this._isFeatureGate},ct.prototype.getVariants=function(){return Object.keys(this._weighting)},ct.prototype.getWeighting=function(){return this._weighting},ct.prototype.hasVariant=function(t){return t in this._weighting};var ft=function(t){this._splitArray=t,this._loaded=null!==t};ft.prototype.getSplit=function(t){return this.getSplits()[t]},ft.prototype.isLoaded=function(){return this._loaded},ft.prototype.asV1Hash=function(){var t={};for(var e in this.getSplits()){var r=this._splits[e];t[e]=r.getWeighting()}return t},ft.prototype.getSplits=function(){return this._loaded?(this._splits||(this._splits={},this._splitArray.forEach(function(t){this._splits[t.getName()]=t}.bind(this))),this._splits):{}};var pt,lt,dt,ht=function(){if(!pt){var t=new ut;pt=t.getConfig()}return pt},gt=function(){return ht().url},yt=function(){return ht().cookieDomain},mt=function(){return ht().cookieName||"tt_visitor_id"},vt=function(){var t=ht().splits;if(!t)return new ft(null);if(!dt){var e=Object.keys(t).map(function(e){var r=t[e];return new ct(e,r.feature_gate,r.weights)});dt=new ft(e)}return dt},wt=function(){var t=ht().assignments;if(!t)return null;if(!lt)for(var e in lt=[],t)lt.push(new n({splitName:e,variant:t[e],isUnsynced:!1}));return lt},_t=st.create({baseURL:"".concat(gt(),"/api"),headers:{"Content-Type":"application/x-www-form-urlencoded"},crossDomain:!0}),bt=function(t){if(t=t||{},this._visitor=t.visitor,this._assignment=t.assignment,this._username=t.username,this._password=t.password,!this._visitor)throw new Error("must provide visitor");if(!this._assignment)throw new Error("must provide assignment");if(!this._username)throw new Error("must provide username");if(!this._password)throw new Error("must provide password")};function At(t){return(At="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function St(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}bt.prototype.persistAssignment=function(){var t=this;return _t.post("/v1/assignment_override",A({visitor_id:this._visitor.getId(),split_name:this._assignment.getSplitName(),variant:this._assignment.getVariant(),context:this._assignment.getContext(),mixpanel_result:"success"}),{auth:{username:this._username,password:this._password}}).catch(function(e){var r=e.response;t._visitor.logError("test_track persistAssignment error: ".concat(r.status,", ").concat(r.statusText,", ").concat(r.data))})};var xt=function(t){if(!t.splitName)throw new Error("must provide splitName");if(!t.hasOwnProperty("trueVariant"))throw new Error("must provide trueVariant");if(!t.visitor)throw new Error("must provide visitor");this._splitName=t.splitName,this._trueVariant=t.trueVariant,this._visitor=t.visitor,this._splitRegistry=vt()};xt.prototype.getVariants=function(){var t=this._getSplitVariants();return t&&t.length>2&&this._visitor.logError("A/B for "+this._splitName+" configures split with more than 2 variants"),{true:this._getTrueVariant(),false:this._getFalseVariant()}},xt.prototype._getTrueVariant=function(){return this._trueVariant||"true"},xt.prototype._getFalseVariant=function(){var t=this._getNonTrueVariants();return Array.isArray(t)&&0!==t.length?t.sort()[0]:"false"},xt.prototype._getNonTrueVariants=function(){var t=this._getSplitVariants();if(t){var e=this._getTrueVariant(),r=t.indexOf(e);return-1!==r&&t.splice(r,1),t}return null},xt.prototype._getSplit=function(){return this._splitRegistry.getSplit(this._splitName)},xt.prototype._getSplitVariants=function(){return this._getSplit()&&this._getSplit().getVariants()};var Et=function(t){if(t=t||{},this._visitor=t.visitor,this._assignment=t.assignment,!this._visitor)throw new Error("must provide visitor");if(!this._assignment)throw new Error("must provide assignment")};Et.prototype.send=function(){var t=this,e=this._persistAssignment(),r=new Promise(function(e){t._visitor.analytics.trackAssignment(t._visitor.getId(),t._assignment,function(r){return t._persistAssignment(r?"success":"failure").then(e)})});return Promise.all([e,r])},Et.prototype._persistAssignment=function(t){var e=this;return _t.post("/v1/assignment_event",A({visitor_id:this._visitor.getId(),split_name:this._assignment.getSplitName(),context:this._assignment.getContext(),mixpanel_result:t})).catch(function(t){var r=t.response;e._visitor.logError("test_track persistAssignment error: ".concat(r.status,", ").concat(r.statusText,", ").concat(r.data))})};var Ct=function(t){if(this.visitorId=t.visitorId,this.identifierType=t.identifierType,this.value=t.value,!this.visitorId)throw new Error("must provide visitorId");if(!this.identifierType)throw new Error("must provide identifierType");if(!this.value)throw new Error("must provide value")};Ct.prototype.save=function(){return _t.post("/v1/identifier",A({identifier_type:this.identifierType,value:this.value,visitor_id:this.visitorId})).then(function(t){var e=t.data;return new Lt({id:e.visitor.id,assignments:n.fromJsonArray(e.visitor.assignments)})})};var Ot=function(){};Ot.prototype.trackAssignment=function(t,e,r){var n={TTVisitorID:t,SplitName:e.getSplitName(),SplitVariant:e.getVariant(),SplitContext:e.getContext()};window.mixpanel&&window.mixpanel.track("SplitAssigned",n,r)},Ot.prototype.identify=function(t){window.mixpanel&&window.mixpanel.identify(t)},Ot.prototype.alias=function(t){window.mixpanel&&window.mixpanel.alias(t)};for(var Nt=e(function(t){var e="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(e){var r=new Uint8Array(16);t.exports=function(){return e(r),r}}else{var n=new Array(16);t.exports=function(){for(var t,e=0;e<16;e++)0==(3&e)&&(t=4294967296*Math.random()),n[e]=t>>>((3&e)<<3)&255;return n}}}),jt=[],Vt=0;Vt<256;++Vt)jt[Vt]=(Vt+256).toString(16).substr(1);var Rt=function(t,e){var r=e||0,n=jt;return[n[t[r++]],n[t[r++]],n[t[r++]],n[t[r++]],"-",n[t[r++]],n[t[r++]],"-",n[t[r++]],n[t[r++]],"-",n[t[r++]],n[t[r++]],"-",n[t[r++]],n[t[r++]],n[t[r++]],n[t[r++]],n[t[r++]],n[t[r++]]].join("")};var kt=function(t,e,r){var n=e&&r||0;"string"==typeof t&&(e="binary"===t?new Array(16):null,t=null);var i=(t=t||{}).random||(t.rng||Nt)();if(i[6]=15&i[6]|64,i[8]=63&i[8]|128,e)for(var o=0;o<16;++o)e[n+o]=i[o];return e||Rt(i)},Tt=e(function(e){!function(t){function r(t,e){var r=(65535&t)+(65535&e);return(t>>16)+(e>>16)+(r>>16)<<16|65535&r}function n(t,e,n,i,o,s){return r((a=r(r(e,t),r(i,s)))<<(u=o)|a>>>32-u,n);var a,u}function i(t,e,r,i,o,s,a){return n(e&r|~e&i,t,e,o,s,a)}function o(t,e,r,i,o,s,a){return n(e&i|r&~i,t,e,o,s,a)}function s(t,e,r,i,o,s,a){return n(e^r^i,t,e,o,s,a)}function a(t,e,r,i,o,s,a){return n(r^(e|~i),t,e,o,s,a)}function u(t,e){var n,u,c,f,p;t[e>>5]|=128<<e%32,t[14+(e+64>>>9<<4)]=e;var l=1732584193,d=-271733879,h=-1732584194,g=271733878;for(n=0;n<t.length;n+=16)u=l,c=d,f=h,p=g,l=i(l,d,h,g,t[n],7,-680876936),g=i(g,l,d,h,t[n+1],12,-389564586),h=i(h,g,l,d,t[n+2],17,606105819),d=i(d,h,g,l,t[n+3],22,-1044525330),l=i(l,d,h,g,t[n+4],7,-176418897),g=i(g,l,d,h,t[n+5],12,1200080426),h=i(h,g,l,d,t[n+6],17,-1473231341),d=i(d,h,g,l,t[n+7],22,-45705983),l=i(l,d,h,g,t[n+8],7,1770035416),g=i(g,l,d,h,t[n+9],12,-1958414417),h=i(h,g,l,d,t[n+10],17,-42063),d=i(d,h,g,l,t[n+11],22,-1990404162),l=i(l,d,h,g,t[n+12],7,1804603682),g=i(g,l,d,h,t[n+13],12,-40341101),h=i(h,g,l,d,t[n+14],17,-1502002290),l=o(l,d=i(d,h,g,l,t[n+15],22,1236535329),h,g,t[n+1],5,-165796510),g=o(g,l,d,h,t[n+6],9,-1069501632),h=o(h,g,l,d,t[n+11],14,643717713),d=o(d,h,g,l,t[n],20,-373897302),l=o(l,d,h,g,t[n+5],5,-701558691),g=o(g,l,d,h,t[n+10],9,38016083),h=o(h,g,l,d,t[n+15],14,-660478335),d=o(d,h,g,l,t[n+4],20,-405537848),l=o(l,d,h,g,t[n+9],5,568446438),g=o(g,l,d,h,t[n+14],9,-1019803690),h=o(h,g,l,d,t[n+3],14,-187363961),d=o(d,h,g,l,t[n+8],20,1163531501),l=o(l,d,h,g,t[n+13],5,-1444681467),g=o(g,l,d,h,t[n+2],9,-51403784),h=o(h,g,l,d,t[n+7],14,1735328473),l=s(l,d=o(d,h,g,l,t[n+12],20,-1926607734),h,g,t[n+5],4,-378558),g=s(g,l,d,h,t[n+8],11,-2022574463),h=s(h,g,l,d,t[n+11],16,1839030562),d=s(d,h,g,l,t[n+14],23,-35309556),l=s(l,d,h,g,t[n+1],4,-1530992060),g=s(g,l,d,h,t[n+4],11,1272893353),h=s(h,g,l,d,t[n+7],16,-155497632),d=s(d,h,g,l,t[n+10],23,-1094730640),l=s(l,d,h,g,t[n+13],4,681279174),g=s(g,l,d,h,t[n],11,-358537222),h=s(h,g,l,d,t[n+3],16,-722521979),d=s(d,h,g,l,t[n+6],23,76029189),l=s(l,d,h,g,t[n+9],4,-640364487),g=s(g,l,d,h,t[n+12],11,-421815835),h=s(h,g,l,d,t[n+15],16,530742520),l=a(l,d=s(d,h,g,l,t[n+2],23,-995338651),h,g,t[n],6,-198630844),g=a(g,l,d,h,t[n+7],10,1126891415),h=a(h,g,l,d,t[n+14],15,-1416354905),d=a(d,h,g,l,t[n+5],21,-57434055),l=a(l,d,h,g,t[n+12],6,1700485571),g=a(g,l,d,h,t[n+3],10,-1894986606),h=a(h,g,l,d,t[n+10],15,-1051523),d=a(d,h,g,l,t[n+1],21,-2054922799),l=a(l,d,h,g,t[n+8],6,1873313359),g=a(g,l,d,h,t[n+15],10,-30611744),h=a(h,g,l,d,t[n+6],15,-1560198380),d=a(d,h,g,l,t[n+13],21,1309151649),l=a(l,d,h,g,t[n+4],6,-145523070),g=a(g,l,d,h,t[n+11],10,-1120210379),h=a(h,g,l,d,t[n+2],15,718787259),d=a(d,h,g,l,t[n+9],21,-343485551),l=r(l,u),d=r(d,c),h=r(h,f),g=r(g,p);return[l,d,h,g]}function c(t){var e,r="",n=32*t.length;for(e=0;e<n;e+=8)r+=String.fromCharCode(t[e>>5]>>>e%32&255);return r}function f(t){var e,r=[];for(r[(t.length>>2)-1]=void 0,e=0;e<r.length;e+=1)r[e]=0;var n=8*t.length;for(e=0;e<n;e+=8)r[e>>5]|=(255&t.charCodeAt(e/8))<<e%32;return r}function p(t){var e,r,n="";for(r=0;r<t.length;r+=1)e=t.charCodeAt(r),n+="0123456789abcdef".charAt(e>>>4&15)+"0123456789abcdef".charAt(15&e);return n}function l(t){return unescape(encodeURIComponent(t))}function d(t){return function(t){return c(u(f(t),8*t.length))}(l(t))}function h(t,e){return function(t,e){var r,n,i=f(t),o=[],s=[];for(o[15]=s[15]=void 0,i.length>16&&(i=u(i,8*t.length)),r=0;r<16;r+=1)o[r]=909522486^i[r],s[r]=1549556828^i[r];return n=u(o.concat(f(e)),512+8*e.length),c(u(s.concat(n),640))}(l(t),l(e))}function g(t,e,r){return e?r?h(e,t):p(h(e,t)):r?d(t):p(d(t))}e.exports?e.exports=g:t.md5=g}(t)}),Ut=function(t){if(this.visitor=t.visitor,this.splitName=t.splitName,!this.visitor)throw new Error("must provide visitor");if(!this.splitName)throw new Error("must provide splitName")};Ut.prototype.getVariant=function(){if(!vt().isLoaded())return null;for(var t=0,e=this.getAssignmentBucket(),r=this.getWeighting(),n=this.getSortedVariants(),i=0;i<n.length;i++){var o=n[i];if((t+=r[o])>e)return o}throw new Error("Assignment bucket out of range. "+e+" unmatched in "+this.splitName+": "+JSON.stringify(r))},Ut.prototype.getSplitVisitorHash=function(){return Tt(this.splitName+this.visitor.getId())},Ut.prototype.getHashFixnum=function(){return parseInt(this.getSplitVisitorHash().substr(0,8),16)},Ut.prototype.getAssignmentBucket=function(){return this.getHashFixnum()%100},Ut.prototype.getSortedVariants=function(){return this.getVariants().sort()},Ut.prototype.getVariants=function(){return Object.getOwnPropertyNames(this.getWeighting())},Ut.prototype.getWeighting=function(){var t=vt().getSplit(this.splitName);if(!t){var e='Unknown split: "'+this.splitName+'"';throw this.visitor.logError(e),new Error(e)}return t.getWeighting()};var Pt=function(t){if(!t.assignment)throw new Error("must provide assignment");if(!t.visitor)throw new Error("must provide visitor");this._assignment=t.assignment,this._visitor=t.visitor,this._splitRegistry=vt(),this._variantHandlers={}};Pt.prototype.when=function(){var t=Array.prototype.slice.call(arguments,0),e=t.length-1,r="function"!=typeof t[0]&&t.length>0?t.slice(0,Math.max(1,e)):[],n=t[e];if(0===r.length)throw new Error("must provide at least one variant");for(var i=0;i<r.length;i++)this._assignHandlerToVariant(r[i],n)},Pt.prototype.default=function(t,e){if(this._defaultVariant)throw new Error("must provide exactly one `default`");this._defaultVariant=this._assignHandlerToVariant(t,e)},Pt.prototype.run=function(){var t;this._validate(),this._variantHandlers[this._assignment.getVariant()]?t=this._variantHandlers[this._assignment.getVariant()]:(t=this._variantHandlers[this.getDefaultVariant()],this._defaulted=!0),t()},Pt.prototype.isDefaulted=function(){return this._defaulted||!1},Pt.prototype.getDefaultVariant=function(){return this._defaultVariant},Pt.prototype._assignHandlerToVariant=function(t,e){if("function"!=typeof e)throw new Error("must provide handler for "+t);return t=t.toString(),this._getSplit()&&!this._getSplit().hasVariant(t)&&this._visitor.logError("configures unknown variant "+t),this._variantHandlers[t]=e,t},Pt.prototype._validate=function(){if(!this.getDefaultVariant())throw new Error("must provide exactly one `default`");if(this._getVariants().length<2)throw new Error("must provide at least one `when`");if(this._getSplit()){var t=this._getMissingVariants();if(t.length>0){var e=t.join(", ").replace(/, (.+)$/," and $1");this._visitor.logError("does not configure variants "+e)}}},Pt.prototype._getSplit=function(){return this._splitRegistry.getSplit(this._assignment.getSplitName())},Pt.prototype._getVariants=function(){return Object.getOwnPropertyNames(this._variantHandlers)},Pt.prototype._getMissingVariants=function(){for(var t=this._getVariants(),e=this._getSplit().getVariants(),r=[],n=0;n<e.length;n++){var i=e[n];-1===t.indexOf(i)&&r.push(i)}return r};var Lt=function(t){if(t=t||{},this._id=t.id,this._assignments=t.assignments,this._ttOffline=t.ttOffline,!this._id)throw new Error("must provide id");if(!this._assignments)throw new Error("must provide assignments");this._errorLogger=function(t){window.console.error(t)},this.analytics=new Ot};Lt.loadVisitor=function(t){return t?wt()?Promise.resolve(new Lt({id:t,assignments:wt(),ttOffline:!1})):_t.get("/v1/visitors/"+t,{timeout:5e3}).then(function(t){var e=t.data;return new Lt({id:e.id,assignments:n.fromJsonArray(e.assignments),ttOffline:!1})}).catch(function(){return new Lt({id:t,assignments:[],ttOffline:!0})}):Promise.resolve(new Lt({id:kt(),assignments:[],ttOffline:!1}))},Lt.prototype.getId=function(){return this._id},Lt.prototype.getAssignmentRegistry=function(){return this._assignmentRegistry||(this._assignmentRegistry=this._assignments.reduce(function(t,e){return function(t){for(var e=1;e<arguments.length;e++){var r=null!=arguments[e]?arguments[e]:{},n=Object.keys(r);"function"==typeof Object.getOwnPropertySymbols&&(n=n.concat(Object.getOwnPropertySymbols(r).filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable}))),n.forEach(function(e){St(t,e,r[e])})}return t}({},t,St({},e.getSplitName(),e))},{})),this._assignmentRegistry},Lt.prototype.vary=function(t,e){if("object"!==At(e.variants))throw new Error("must provide variants object to `vary` for "+t);if(!e.context)throw new Error("must provide context to `vary` for "+t);if(!e.defaultVariant&&!1!==e.defaultVariant)throw new Error("must provide defaultVariant to `vary` for "+t);var r=e.defaultVariant.toString(),n=e.variants,i=e.context;if(!n.hasOwnProperty(r))throw new Error("defaultVariant: "+r+" must be represented in variants object");var o=this._getAssignmentFor(t,i),s=new Pt({assignment:o,visitor:this});for(var a in n)n.hasOwnProperty(a)&&(a===r?s.default(a,n[a]):s.when(a,n[a]));s.run(),s.isDefaulted()&&(o.setVariant(s.getDefaultVariant()),o.setUnsynced(!0),o.setContext(i)),this.notifyUnsyncedAssignments()},Lt.prototype.ab=function(t,e){var r=new xt({splitName:t,trueVariant:e.trueVariant,visitor:this}).getVariants(),n={};n[r.true]=function(){e.callback(!0)},n[r.false]=function(){e.callback(!1)},this.vary(t,{context:e.context,variants:n,defaultVariant:r.false})},Lt.prototype.setErrorLogger=function(t){if("function"!=typeof t)throw new Error("must provide function for errorLogger");this._errorLogger=t},Lt.prototype.logError=function(t){this._errorLogger.call(null,t)},Lt.prototype.linkIdentifier=function(t,e){var r=this;return new Ct({identifierType:t,value:e,visitorId:this.getId()}).save().then(function(t){r._merge(t),r.notifyUnsyncedAssignments()})},Lt.prototype.setAnalytics=function(t){if("object"!==At(t))throw new Error("must provide object for setAnalytics");this.analytics=t},Lt.prototype.notifyUnsyncedAssignments=function(){this._getUnsyncedAssignments().forEach(this._notify.bind(this))},Lt.prototype._getUnsyncedAssignments=function(){var t=this.getAssignmentRegistry();return Object.keys(t).reduce(function(e,r){var n=t[r];return n.isUnsynced()&&e.push(n),e},[])},Lt.prototype._merge=function(t){var e=this.getAssignmentRegistry(),r=t.getAssignmentRegistry();this._id=t.getId(),Object.assign(e,r)},Lt.prototype._getAssignmentFor=function(t,e){return this.getAssignmentRegistry()[t]||this._generateAssignmentFor(t,e)},Lt.prototype._generateAssignmentFor=function(t,e){var r=new Ut({visitor:this,splitName:t}).getVariant();r||(this._ttOffline=!0);var i=new n({splitName:t,variant:r,context:e,isUnsynced:!0});return this._assignments.push(i),this._assignmentRegistry=null,i},Lt.prototype._notify=function(t){try{if(this._ttOffline)return;new Et({visitor:this,assignment:t}).send(),t.setUnsynced(!1)}catch(t){this.logError("test_track notify error: "+t)}};var It=null,Dt=function(){this._visitorLoaded=new Promise(function(t){It=t})};Dt.prototype.initialize=function(t){var e=r.get(mt());return Lt.loadVisitor(e).then(function(e){t&&t.analytics&&e.setAnalytics(t.analytics),t&&t.errorLogger&&e.setErrorLogger(t.errorLogger),t&&"function"==typeof t.onVisitorLoaded&&t.onVisitorLoaded.call(null,e),e.notifyUnsyncedAssignments(),It(e)}),this._setCookie(),this._visitorLoaded},Dt.prototype.vary=function(t,e){return this._visitorLoaded.then(function(r){r.vary(t,e)})},Dt.prototype.ab=function(t,e){return this._visitorLoaded.then(function(r){r.ab(t,e)})},Dt.prototype.logIn=function(t,e){var r=this;return this._visitorLoaded.then(function(n){return n.linkIdentifier(t,e).then(function(){r._setCookie(),n.analytics.identify(n.getId())})})},Dt.prototype.signUp=function(t,e){var r=this;return this._visitorLoaded.then(function(n){return n.linkIdentifier(t,e).then(function(){r._setCookie(),n.analytics.alias(n.getId())})})},Dt.prototype._setCookie=function(){return this._visitorLoaded.then(function(t){r.set(mt(),t.getId(),{expires:365,path:"/",domain:yt()})})},Dt.prototype.getPublicAPI=function(){var t=this;return{vary:this.vary.bind(this),ab:this.ab.bind(this),logIn:this.logIn.bind(this),signUp:this.signUp.bind(this),initialize:this.initialize.bind(this),_crx:{loadInfo:function(){return t._visitorLoaded.then(function(t){var e={};for(var r in t.getAssignmentRegistry())e[r]=t.getAssignmentRegistry()[r].getVariant();return{visitorId:t.getId(),splitRegistry:vt().asV1Hash(),assignmentRegistry:e}})},persistAssignment:function(e,r,i,o){return t._visitorLoaded.then(function(t){return new bt({visitor:t,username:i,password:o,assignment:new n({splitName:e,variant:r,context:"chrome_extension",isUnsynced:!0})}).persistAssignment()})}}}};var Bt=(new Dt).getPublicAPI(),Ft=function(){window.dispatchEvent(new CustomEvent("tt:lib:loaded",{detail:{TestTrack:Bt}}))},Ht=function(){document.body.classList.add("_tt");try{window.dispatchEvent(new CustomEvent("tt:class:added"))}catch(t){}};try{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",Ht):Ht(),Ft(),window.addEventListener("tt:listener:ready",Ft)}catch(t){}return Bt});
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).TestTrack=e()}(this,function(){"use strict";var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function e(t,e,r){return t(r={path:e,exports:{},require:function(t,e){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==e&&r.path)}},r.exports),r.exports}var r=e(function(t,e){var r;r=function(){function t(){for(var t=0,e={};t<arguments.length;t++){var r=arguments[t];for(var n in r)e[n]=r[n]}return e}return function e(r){function n(e,i,o){var s;if("undefined"!=typeof document){if(arguments.length>1){if("number"==typeof(o=t({path:"/"},n.defaults,o)).expires){var a=new Date;a.setMilliseconds(a.getMilliseconds()+864e5*o.expires),o.expires=a}o.expires=o.expires?o.expires.toUTCString():"";try{s=JSON.stringify(i),/^[\{\[]/.test(s)&&(i=s)}catch(t){}i=r.write?r.write(i,e):encodeURIComponent(String(i)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),e=(e=(e=encodeURIComponent(String(e))).replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent)).replace(/[\(\)]/g,escape);var u="";for(var c in o)o[c]&&(u+="; "+c,!0!==o[c]&&(u+="="+o[c]));return document.cookie=e+"="+i+u}e||(s={});for(var f=document.cookie?document.cookie.split("; "):[],p=/(%[0-9A-Z]{2})+/g,l=0;l<f.length;l++){var d=f[l].split("="),h=d.slice(1).join("=");this.json||'"'!==h.charAt(0)||(h=h.slice(1,-1));try{var g=d[0].replace(p,decodeURIComponent);if(h=r.read?r.read(h,g):r(h,g)||h.replace(p,decodeURIComponent),this.json)try{h=JSON.parse(h)}catch(t){}if(e===g){s=h;break}e||(s[g]=h)}catch(t){}}return s}}return n.set=n,n.get=function(t){return n.call(n,t)},n.getJSON=function(){return n.apply({json:!0},[].slice.call(arguments))},n.defaults={},n.remove=function(e,r){n(e,"",t(r,{expires:-1}))},n.withConverter=e,n}(function(){})},t.exports=r()}),n=function(){function t(t){if(!t.splitName)throw new Error("must provide splitName");if(!t.hasOwnProperty("variant"))throw new Error("must provide variant");if(!t.hasOwnProperty("isUnsynced"))throw new Error("must provide isUnsynced");this._splitName=t.splitName,this._variant=t.variant,this._context=t.context,this._isUnsynced=t.isUnsynced}return t.fromJsonArray=function(e){return e.map(function(e){var r=e.split_name,n=e.variant;return new t({context:e.context,variant:n,splitName:r,isUnsynced:e.unsynced})})},t.prototype.getSplitName=function(){return this._splitName},t.prototype.getVariant=function(){return this._variant},t.prototype.setVariant=function(t){this._variant=t},t.prototype.getContext=function(){return this._context},t.prototype.setContext=function(t){this._context=t},t.prototype.isUnsynced=function(){return this._isUnsynced},t.prototype.setUnsynced=function(t){this._isUnsynced=t},t}(),i=Object.prototype.hasOwnProperty,o=Array.isArray,s=function(){for(var t=[],e=0;e<256;++e)t.push("%"+((e<16?"0":"")+e.toString(16)).toUpperCase());return t}(),a=function(t,e){for(var r=e&&e.plainObjects?Object.create(null):{},n=0;n<t.length;++n)void 0!==t[n]&&(r[n]=t[n]);return r},u={arrayToObject:a,assign:function(t,e){return Object.keys(e).reduce(function(t,r){return t[r]=e[r],t},t)},combine:function(t,e){return[].concat(t,e)},compact:function(t){for(var e=[{obj:{o:t},prop:"o"}],r=[],n=0;n<e.length;++n)for(var i=e[n],s=i.obj[i.prop],a=Object.keys(s),u=0;u<a.length;++u){var c=a[u],f=s[c];"object"==typeof f&&null!==f&&-1===r.indexOf(f)&&(e.push({obj:s,prop:c}),r.push(f))}return function(t){for(;t.length>1;){var e=t.pop(),r=e.obj[e.prop];if(o(r)){for(var n=[],i=0;i<r.length;++i)void 0!==r[i]&&n.push(r[i]);e.obj[e.prop]=n}}}(e),t},decode:function(t,e,r){var n=t.replace(/\+/g," ");if("iso-8859-1"===r)return n.replace(/%[0-9a-f]{2}/gi,unescape);try{return decodeURIComponent(n)}catch(t){return n}},encode:function(t,e,r){if(0===t.length)return t;var n=t;if("symbol"==typeof t?n=Symbol.prototype.toString.call(t):"string"!=typeof t&&(n=String(t)),"iso-8859-1"===r)return escape(n).replace(/%u[0-9a-f]{4}/gi,function(t){return"%26%23"+parseInt(t.slice(2),16)+"%3B"});for(var i="",o=0;o<n.length;++o){var a=n.charCodeAt(o);45===a||46===a||95===a||126===a||a>=48&&a<=57||a>=65&&a<=90||a>=97&&a<=122?i+=n.charAt(o):a<128?i+=s[a]:a<2048?i+=s[192|a>>6]+s[128|63&a]:a<55296||a>=57344?i+=s[224|a>>12]+s[128|a>>6&63]+s[128|63&a]:(o+=1,a=65536+((1023&a)<<10|1023&n.charCodeAt(o)),i+=s[240|a>>18]+s[128|a>>12&63]+s[128|a>>6&63]+s[128|63&a])}return i},isBuffer:function(t){return!(!t||"object"!=typeof t||!(t.constructor&&t.constructor.isBuffer&&t.constructor.isBuffer(t)))},isRegExp:function(t){return"[object RegExp]"===Object.prototype.toString.call(t)},merge:function t(e,r,n){if(!r)return e;if("object"!=typeof r){if(o(e))e.push(r);else{if(!e||"object"!=typeof e)return[e,r];(n&&(n.plainObjects||n.allowPrototypes)||!i.call(Object.prototype,r))&&(e[r]=!0)}return e}if(!e||"object"!=typeof e)return[e].concat(r);var s=e;return o(e)&&!o(r)&&(s=a(e,n)),o(e)&&o(r)?(r.forEach(function(r,o){if(i.call(e,o)){var s=e[o];s&&"object"==typeof s&&r&&"object"==typeof r?e[o]=t(s,r,n):e.push(r)}else e[o]=r}),e):Object.keys(r).reduce(function(e,o){var s=r[o];return i.call(e,o)?e[o]=t(e[o],s,n):e[o]=s,e},s)}},c=String.prototype.replace,f=/%20/g,p={RFC1738:"RFC1738",RFC3986:"RFC3986"},l=u.assign({default:p.RFC3986,formatters:{RFC1738:function(t){return c.call(t,f,"+")},RFC3986:function(t){return String(t)}}},p),d=Object.prototype.hasOwnProperty,h={brackets:function(t){return t+"[]"},comma:"comma",indices:function(t,e){return t+"["+e+"]"},repeat:function(t){return t}},g=Array.isArray,m=Array.prototype.push,y=function(t,e){m.apply(t,g(e)?e:[e])},v=Date.prototype.toISOString,w=l.default,_={addQueryPrefix:!1,allowDots:!1,charset:"utf-8",charsetSentinel:!1,delimiter:"&",encode:!0,encoder:u.encode,encodeValuesOnly:!1,format:w,formatter:l.formatters[w],indices:!1,serializeDate:function(t){return v.call(t)},skipNulls:!1,strictNullHandling:!1},b=function t(e,r,n,i,o,s,a,c,f,p,l,d,h){var m,v=e;if("function"==typeof a?v=a(r,v):v instanceof Date?v=p(v):"comma"===n&&g(v)&&(v=v.join(",")),null===v){if(i)return s&&!d?s(r,_.encoder,h,"key"):r;v=""}if("string"==typeof(m=v)||"number"==typeof m||"boolean"==typeof m||"symbol"==typeof m||"bigint"==typeof m||u.isBuffer(v))return s?[l(d?r:s(r,_.encoder,h,"key"))+"="+l(s(v,_.encoder,h,"value"))]:[l(r)+"="+l(String(v))];var w,b=[];if(void 0===v)return b;if(g(a))w=a;else{var C=Object.keys(v);w=c?C.sort(c):C}for(var A=0;A<w.length;++A){var S=w[A];o&&null===v[S]||(g(v)?y(b,t(v[S],"function"==typeof n?n(r,S):r,n,i,o,s,a,c,f,p,l,d,h)):y(b,t(v[S],r+(f?"."+S:"["+S+"]"),n,i,o,s,a,c,f,p,l,d,h)))}return b},C=(Object.prototype.hasOwnProperty,Array.isArray,function(t,e){var r,n=t,i=function(t){if(!t)return _;if(null!==t.encoder&&void 0!==t.encoder&&"function"!=typeof t.encoder)throw new TypeError("Encoder has to be a function.");var e=t.charset||_.charset;if(void 0!==t.charset&&"utf-8"!==t.charset&&"iso-8859-1"!==t.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");var r=l.default;if(void 0!==t.format){if(!d.call(l.formatters,t.format))throw new TypeError("Unknown format option provided.");r=t.format}var n=l.formatters[r],i=_.filter;return("function"==typeof t.filter||g(t.filter))&&(i=t.filter),{addQueryPrefix:"boolean"==typeof t.addQueryPrefix?t.addQueryPrefix:_.addQueryPrefix,allowDots:void 0===t.allowDots?_.allowDots:!!t.allowDots,charset:e,charsetSentinel:"boolean"==typeof t.charsetSentinel?t.charsetSentinel:_.charsetSentinel,delimiter:void 0===t.delimiter?_.delimiter:t.delimiter,encode:"boolean"==typeof t.encode?t.encode:_.encode,encoder:"function"==typeof t.encoder?t.encoder:_.encoder,encodeValuesOnly:"boolean"==typeof t.encodeValuesOnly?t.encodeValuesOnly:_.encodeValuesOnly,filter:i,formatter:n,serializeDate:"function"==typeof t.serializeDate?t.serializeDate:_.serializeDate,skipNulls:"boolean"==typeof t.skipNulls?t.skipNulls:_.skipNulls,sort:"function"==typeof t.sort?t.sort:null,strictNullHandling:"boolean"==typeof t.strictNullHandling?t.strictNullHandling:_.strictNullHandling}}(e);"function"==typeof i.filter?n=(0,i.filter)("",n):g(i.filter)&&(r=i.filter);var o,s=[];if("object"!=typeof n||null===n)return"";o=e&&e.arrayFormat in h?e.arrayFormat:e&&"indices"in e?e.indices?"indices":"repeat":"indices";var a=h[o];r||(r=Object.keys(n)),i.sort&&r.sort(i.sort);for(var u=0;u<r.length;++u){var c=r[u];i.skipNulls&&null===n[c]||y(s,b(n[c],c,a,i.strictNullHandling,i.skipNulls,i.encode?i.encoder:null,i.filter,i.sort,i.allowDots,i.serializeDate,i.formatter,i.encodeValuesOnly,i.charset))}var f=s.join(i.delimiter),p=!0===i.addQueryPrefix?"?":"";return i.charsetSentinel&&("iso-8859-1"===i.charset?p+="utf8=%26%2310003%3B&":p+="utf8=%E2%9C%93&"),f.length>0?p+f:""}),A=function(t,e){return function(){for(var r=new Array(arguments.length),n=0;n<r.length;n++)r[n]=arguments[n];return t.apply(e,r)}},S=Object.prototype.toString;function E(t){return"[object Array]"===S.call(t)}function x(t){return void 0===t}function N(t){return null!==t&&"object"==typeof t}function O(t){if("[object Object]"!==S.call(t))return!1;var e=Object.getPrototypeOf(t);return null===e||e===Object.prototype}function j(t){return"[object Function]"===S.call(t)}function R(t,e){if(null!=t)if("object"!=typeof t&&(t=[t]),E(t))for(var r=0,n=t.length;r<n;r++)e.call(null,t[r],r,t);else for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&e.call(null,t[i],i,t)}var V={isArray:E,isArrayBuffer:function(t){return"[object ArrayBuffer]"===S.call(t)},isBuffer:function(t){return null!==t&&!x(t)&&null!==t.constructor&&!x(t.constructor)&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)},isFormData:function(t){return"undefined"!=typeof FormData&&t instanceof FormData},isArrayBufferView:function(t){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(t):t&&t.buffer&&t.buffer instanceof ArrayBuffer},isString:function(t){return"string"==typeof t},isNumber:function(t){return"number"==typeof t},isObject:N,isPlainObject:O,isUndefined:x,isDate:function(t){return"[object Date]"===S.call(t)},isFile:function(t){return"[object File]"===S.call(t)},isBlob:function(t){return"[object Blob]"===S.call(t)},isFunction:j,isStream:function(t){return N(t)&&j(t.pipe)},isURLSearchParams:function(t){return"undefined"!=typeof URLSearchParams&&t instanceof URLSearchParams},isStandardBrowserEnv:function(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&"undefined"!=typeof window&&"undefined"!=typeof document},forEach:R,merge:function t(){var e={};function r(r,n){O(e[n])&&O(r)?e[n]=t(e[n],r):O(r)?e[n]=t({},r):E(r)?e[n]=r.slice():e[n]=r}for(var n=0,i=arguments.length;n<i;n++)R(arguments[n],r);return e},extend:function(t,e,r){return R(e,function(e,n){t[n]=r&&"function"==typeof e?A(e,r):e}),t},trim:function(t){return t.replace(/^\s*/,"").replace(/\s*$/,"")},stripBOM:function(t){return 65279===t.charCodeAt(0)&&(t=t.slice(1)),t}};function k(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var U=function(t,e,r){if(!e)return t;var n;if(r)n=r(e);else if(V.isURLSearchParams(e))n=e.toString();else{var i=[];V.forEach(e,function(t,e){null!=t&&(V.isArray(t)?e+="[]":t=[t],V.forEach(t,function(t){V.isDate(t)?t=t.toISOString():V.isObject(t)&&(t=JSON.stringify(t)),i.push(k(e)+"="+k(t))}))}),n=i.join("&")}if(n){var o=t.indexOf("#");-1!==o&&(t=t.slice(0,o)),t+=(-1===t.indexOf("?")?"?":"&")+n}return t};function T(){this.handlers=[]}T.prototype.use=function(t,e){return this.handlers.push({fulfilled:t,rejected:e}),this.handlers.length-1},T.prototype.eject=function(t){this.handlers[t]&&(this.handlers[t]=null)},T.prototype.forEach=function(t){V.forEach(this.handlers,function(e){null!==e&&t(e)})};var P=T,L=function(t,e,r){return V.forEach(r,function(r){t=r(t,e)}),t},D=function(t){return!(!t||!t.__CANCEL__)},I=function(t,e){V.forEach(t,function(r,n){n!==e&&n.toUpperCase()===e.toUpperCase()&&(t[e]=r,delete t[n])})},B=function(t,e,r,n,i){return function(t,e,r,n,i){return t.config=e,r&&(t.code=r),t.request=n,t.response=i,t.isAxiosError=!0,t.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},t}(new Error(t),e,r,n,i)},F=V.isStandardBrowserEnv()?{write:function(t,e,r,n,i,o){var s=[];s.push(t+"="+encodeURIComponent(e)),V.isNumber(r)&&s.push("expires="+new Date(r).toGMTString()),V.isString(n)&&s.push("path="+n),V.isString(i)&&s.push("domain="+i),!0===o&&s.push("secure"),document.cookie=s.join("; ")},read:function(t){var e=document.cookie.match(new RegExp("(^|;\\s*)("+t+")=([^;]*)"));return e?decodeURIComponent(e[3]):null},remove:function(t){this.write(t,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}},H=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"],q=V.isStandardBrowserEnv()?function(){var t,e=/(msie|trident)/i.test(navigator.userAgent),r=document.createElement("a");function n(t){var n=t;return e&&(r.setAttribute("href",n),n=r.href),r.setAttribute("href",n),{href:r.href,protocol:r.protocol?r.protocol.replace(/:$/,""):"",host:r.host,search:r.search?r.search.replace(/^\?/,""):"",hash:r.hash?r.hash.replace(/^#/,""):"",hostname:r.hostname,port:r.port,pathname:"/"===r.pathname.charAt(0)?r.pathname:"/"+r.pathname}}return t=n(window.location.href),function(e){var r=V.isString(e)?n(e):e;return r.protocol===t.protocol&&r.host===t.host}}():function(){return!0},z=function(t){return new Promise(function(e,r){var n=t.data,i=t.headers;V.isFormData(n)&&delete i["Content-Type"];var o=new XMLHttpRequest;if(t.auth){var s=t.auth.username||"",a=t.auth.password?unescape(encodeURIComponent(t.auth.password)):"";i.Authorization="Basic "+btoa(s+":"+a)}var u,c,f=(u=t.baseURL,c=t.url,u&&!/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(c)?function(t,e){return e?t.replace(/\/+$/,"")+"/"+e.replace(/^\/+/,""):t}(u,c):c);if(o.open(t.method.toUpperCase(),U(f,t.params,t.paramsSerializer),!0),o.timeout=t.timeout,o.onreadystatechange=function(){if(o&&4===o.readyState&&(0!==o.status||o.responseURL&&0===o.responseURL.indexOf("file:"))){var n,i,s,a,u,c="getAllResponseHeaders"in o?(n=o.getAllResponseHeaders(),u={},n?(V.forEach(n.split("\n"),function(t){if(a=t.indexOf(":"),i=V.trim(t.substr(0,a)).toLowerCase(),s=V.trim(t.substr(a+1)),i){if(u[i]&&H.indexOf(i)>=0)return;u[i]="set-cookie"===i?(u[i]?u[i]:[]).concat([s]):u[i]?u[i]+", "+s:s}}),u):u):null,f={data:t.responseType&&"text"!==t.responseType?o.response:o.responseText,status:o.status,statusText:o.statusText,headers:c,config:t,request:o};!function(t,e,r){var n=r.config.validateStatus;r.status&&n&&!n(r.status)?e(B("Request failed with status code "+r.status,r.config,null,r.request,r)):t(r)}(e,r,f),o=null}},o.onabort=function(){o&&(r(B("Request aborted",t,"ECONNABORTED",o)),o=null)},o.onerror=function(){r(B("Network Error",t,null,o)),o=null},o.ontimeout=function(){var e="timeout of "+t.timeout+"ms exceeded";t.timeoutErrorMessage&&(e=t.timeoutErrorMessage),r(B(e,t,"ECONNABORTED",o)),o=null},V.isStandardBrowserEnv()){var p=(t.withCredentials||q(f))&&t.xsrfCookieName?F.read(t.xsrfCookieName):void 0;p&&(i[t.xsrfHeaderName]=p)}if("setRequestHeader"in o&&V.forEach(i,function(t,e){void 0===n&&"content-type"===e.toLowerCase()?delete i[e]:o.setRequestHeader(e,t)}),V.isUndefined(t.withCredentials)||(o.withCredentials=!!t.withCredentials),t.responseType)try{o.responseType=t.responseType}catch(e){if("json"!==t.responseType)throw e}"function"==typeof t.onDownloadProgress&&o.addEventListener("progress",t.onDownloadProgress),"function"==typeof t.onUploadProgress&&o.upload&&o.upload.addEventListener("progress",t.onUploadProgress),t.cancelToken&&t.cancelToken.promise.then(function(t){o&&(o.abort(),r(t),o=null)}),n||(n=null),o.send(n)})},M={"Content-Type":"application/x-www-form-urlencoded"};function J(t,e){!V.isUndefined(t)&&V.isUndefined(t["Content-Type"])&&(t["Content-Type"]=e)}var $,W={adapter:("undefined"!=typeof XMLHttpRequest?$=z:"undefined"!=typeof process&&"[object process]"===Object.prototype.toString.call(process)&&($=z),$),transformRequest:[function(t,e){return I(e,"Accept"),I(e,"Content-Type"),V.isFormData(t)||V.isArrayBuffer(t)||V.isBuffer(t)||V.isStream(t)||V.isFile(t)||V.isBlob(t)?t:V.isArrayBufferView(t)?t.buffer:V.isURLSearchParams(t)?(J(e,"application/x-www-form-urlencoded;charset=utf-8"),t.toString()):V.isObject(t)?(J(e,"application/json;charset=utf-8"),JSON.stringify(t)):t}],transformResponse:[function(t){if("string"==typeof t)try{t=JSON.parse(t)}catch(t){}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(t){return t>=200&&t<300}};W.headers={common:{Accept:"application/json, text/plain, */*"}},V.forEach(["delete","get","head"],function(t){W.headers[t]={}}),V.forEach(["post","put","patch"],function(t){W.headers[t]=V.merge(M)});var Q=W;function X(t){t.cancelToken&&t.cancelToken.throwIfRequested()}var G=function(t){return X(t),t.headers=t.headers||{},t.data=L(t.data,t.headers,t.transformRequest),t.headers=V.merge(t.headers.common||{},t.headers[t.method]||{},t.headers),V.forEach(["delete","get","head","post","put","patch","common"],function(e){delete t.headers[e]}),(t.adapter||Q.adapter)(t).then(function(e){return X(t),e.data=L(e.data,e.headers,t.transformResponse),e},function(e){return D(e)||(X(t),e&&e.response&&(e.response.data=L(e.response.data,e.response.headers,t.transformResponse))),Promise.reject(e)})},Z=function(t,e){e=e||{};var r={},n=["url","method","data"],i=["headers","auth","proxy","params"],o=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],s=["validateStatus"];function a(t,e){return V.isPlainObject(t)&&V.isPlainObject(e)?V.merge(t,e):V.isPlainObject(e)?V.merge({},e):V.isArray(e)?e.slice():e}function u(n){V.isUndefined(e[n])?V.isUndefined(t[n])||(r[n]=a(void 0,t[n])):r[n]=a(t[n],e[n])}V.forEach(n,function(t){V.isUndefined(e[t])||(r[t]=a(void 0,e[t]))}),V.forEach(i,u),V.forEach(o,function(n){V.isUndefined(e[n])?V.isUndefined(t[n])||(r[n]=a(void 0,t[n])):r[n]=a(void 0,e[n])}),V.forEach(s,function(n){n in e?r[n]=a(t[n],e[n]):n in t&&(r[n]=a(void 0,t[n]))});var c=n.concat(i).concat(o).concat(s),f=Object.keys(t).concat(Object.keys(e)).filter(function(t){return-1===c.indexOf(t)});return V.forEach(f,u),r};function K(t){this.defaults=t,this.interceptors={request:new P,response:new P}}K.prototype.request=function(t){"string"==typeof t?(t=arguments[1]||{}).url=arguments[0]:t=t||{},(t=Z(this.defaults,t)).method?t.method=t.method.toLowerCase():this.defaults.method?t.method=this.defaults.method.toLowerCase():t.method="get";var e=[G,void 0],r=Promise.resolve(t);for(this.interceptors.request.forEach(function(t){e.unshift(t.fulfilled,t.rejected)}),this.interceptors.response.forEach(function(t){e.push(t.fulfilled,t.rejected)});e.length;)r=r.then(e.shift(),e.shift());return r},K.prototype.getUri=function(t){return t=Z(this.defaults,t),U(t.url,t.params,t.paramsSerializer).replace(/^\?/,"")},V.forEach(["delete","get","head","options"],function(t){K.prototype[t]=function(e,r){return this.request(Z(r||{},{method:t,url:e,data:(r||{}).data}))}}),V.forEach(["post","put","patch"],function(t){K.prototype[t]=function(e,r,n){return this.request(Z(n||{},{method:t,url:e,data:r}))}});var Y=K;function tt(t){this.message=t}tt.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},tt.prototype.__CANCEL__=!0;var et=tt;function rt(t){if("function"!=typeof t)throw new TypeError("executor must be a function.");var e;this.promise=new Promise(function(t){e=t});var r=this;t(function(t){r.reason||(r.reason=new et(t),e(r.reason))})}rt.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},rt.source=function(){var t;return{token:new rt(function(e){t=e}),cancel:t}};var nt=rt;function it(t){var e=new Y(t),r=A(Y.prototype.request,e);return V.extend(r,Y.prototype,e),V.extend(r,e),r}var ot=it(Q);ot.Axios=Y,ot.create=function(t){return it(Z(ot.defaults,t))},ot.Cancel=et,ot.CancelToken=nt,ot.isCancel=D,ot.all=function(t){return Promise.all(t)},ot.spread=function(t){return function(e){return t.apply(null,e)}},ot.isAxiosError=function(t){return"object"==typeof t&&!0===t.isAxiosError};var st=ot,at=ot;st.default=at;var ut=st;for(var ct={atob:function(t){if((t=(t=`${t}`).replace(/[ \t\n\f\r]/g,"")).length%4==0&&(t=t.replace(/==?$/,"")),t.length%4==1||/[^+/0-9A-Za-z]/.test(t))return null;let e="",r=0,n=0;for(let o=0;o<t.length;o++)r<<=6,r|=(i=t[o],/[A-Z]/.test(i)?i.charCodeAt(0)-"A".charCodeAt(0):/[a-z]/.test(i)?i.charCodeAt(0)-"a".charCodeAt(0)+26:/[0-9]/.test(i)?i.charCodeAt(0)-"0".charCodeAt(0)+52:"+"===i?62:"/"===i?63:void 0),24===(n+=6)&&(e+=String.fromCharCode((16711680&r)>>16),e+=String.fromCharCode((65280&r)>>8),e+=String.fromCharCode(255&r),r=n=0);var i;return 12===n?(r>>=4,e+=String.fromCharCode(r)):18===n&&(r>>=2,e+=String.fromCharCode((65280&r)>>8),e+=String.fromCharCode(255&r)),e},btoa:function(t){let e;for(t=`${t}`,e=0;e<t.length;e++)if(t.charCodeAt(e)>255)return null;let r="";for(e=0;e<t.length;e+=3){const i=[void 0,void 0,void 0,void 0];i[0]=t.charCodeAt(e)>>2,i[1]=(3&t.charCodeAt(e))<<4,t.length>e+1&&(i[1]|=t.charCodeAt(e+1)>>4,i[2]=(15&t.charCodeAt(e+1))<<2),t.length>e+2&&(i[2]|=t.charCodeAt(e+2)>>6,i[3]=63&t.charCodeAt(e+2));for(let t=0;t<i.length;t++)void 0===i[t]?r+="=":r+=(n=i[t])<26?String.fromCharCode(n+"A".charCodeAt(0)):n<52?String.fromCharCode(n-26+"a".charCodeAt(0)):n<62?String.fromCharCode(n-52+"0".charCodeAt(0)):62===n?"+":63===n?"/":void 0}var n;return r}},ft=function(){function t(){}return t.prototype.getConfig=function(){var t=ct.atob(window.TT);if(t)return JSON.parse(t);throw new Error("Unable to parse configuration")},t}(),pt=function(){function t(t,e,r){this._name=t,this._isFeatureGate=e,this._weighting=r}return t.prototype.getName=function(){return this._name},t.prototype.isFeatureGate=function(){return this._isFeatureGate},t.prototype.getVariants=function(){return Object.keys(this._weighting)},t.prototype.getWeighting=function(){return this._weighting},t.prototype.hasVariant=function(t){return t in this._weighting},t}(),lt=function(){return(lt=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var i in e=arguments[r])Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t}).apply(this,arguments)},dt=function(){function t(t){this._splitArray=t||[],this._loaded=null!==t}return t.prototype.getSplit=function(t){return this.getSplits()[t]},t.prototype.isLoaded=function(){return this._loaded},t.prototype.asV1Hash=function(){var t={};for(var e in this.getSplits()){var r=this.getSplits()[e];t[e]=r.getWeighting()}return t},t.prototype.getSplits=function(){return this._loaded?(this._splits||(this._splits=this._splitArray.reduce(function(t,e){var r;return lt(lt({},t),((r={})[e.getName()]=e,r))},{})),this._splits):{}},t}(),ht=null,gt=null,mt=null,yt=function(){if(!ht){var t=new ft;ht=t.getConfig()}return ht},vt={_clear:function(){ht=null},getUrl:function(){return yt().url},getCookieDomain:function(){return yt().cookieDomain},getCookieName:function(){return yt().cookieName||"tt_visitor_id"},getExperienceSamplingWeight:function(){return yt().experienceSamplingWeight},getSplitRegistry:function(){var t=yt().splits;if(!t)return new dt(null);if(!mt){var e=Object.keys(t).map(function(e){var r=t[e];return new pt(e,r.feature_gate,r.weights)});mt=new dt(e)}return mt},getAssignments:function(){var t=yt().assignments;if(!t)return null;if(!gt)for(var e in gt=[],t)gt.push(new n({splitName:e,variant:t[e],isUnsynced:!1}));return gt}},wt=ut.create({baseURL:vt.getUrl()+"/api",headers:{"Content-Type":"application/x-www-form-urlencoded"},crossDomain:!0}),_t=function(){function t(t){if(this._visitor=t.visitor,this._assignment=t.assignment,this._username=t.username,this._password=t.password,!this._visitor)throw new Error("must provide visitor");if(!this._assignment)throw new Error("must provide assignment");if(!this._username)throw new Error("must provide username");if(!this._password)throw new Error("must provide password")}return t.prototype.persistAssignment=function(){var t=this;return wt.post("/v1/assignment_override",C({visitor_id:this._visitor.getId(),split_name:this._assignment.getSplitName(),variant:this._assignment.getVariant(),context:this._assignment.getContext(),mixpanel_result:"success"}),{auth:{username:this._username,password:this._password}}).catch(function(e){if(e.response){var r=e.response,n=r.status,i=r.statusText,o=r.data;t._visitor.logError("test_track persistAssignment response error: "+n+", "+i+", "+o)}else t._visitor.logError("test_track persistAssignment other error: "+e)})},t}(),bt=function(){function t(t){if(!t.splitName)throw new Error("must provide splitName");if(!t.hasOwnProperty("trueVariant"))throw new Error("must provide trueVariant");if(!t.visitor)throw new Error("must provide visitor");this._splitName=t.splitName,this._trueVariant=t.trueVariant,this._visitor=t.visitor,this._splitRegistry=vt.getSplitRegistry()}return t.prototype.getVariants=function(){var t=this._getSplitVariants();return t&&t.length>2&&this._visitor.logError("A/B for "+this._splitName+" configures split with more than 2 variants"),{true:this._getTrueVariant(),false:this._getFalseVariant()}},t.prototype._getTrueVariant=function(){return this._trueVariant||"true"},t.prototype._getFalseVariant=function(){var t=this._getNonTrueVariants();return Array.isArray(t)&&0!==t.length?t.sort()[0]:"false"},t.prototype._getNonTrueVariants=function(){var t=this._getSplitVariants();if(t){var e=this._getTrueVariant(),r=t.indexOf(e.toString());return-1!==r&&t.splice(r,1),t}return null},t.prototype._getSplit=function(){return this._splitRegistry.getSplit(this._splitName)},t.prototype._getSplitVariants=function(){return this._getSplit()&&this._getSplit().getVariants()},t}(),Ct=function(){function t(t){var e=t.visitor,r=t.assignment;if(this._visitor=e,this._assignment=r,!this._visitor)throw new Error("must provide visitor");if(!this._assignment)throw new Error("must provide assignment")}return t.prototype.send=function(){var t=this,e=this._persistAssignment(),r=new Promise(function(e){t._visitor.analytics.trackAssignment(t._visitor.getId(),t._assignment,function(r){return t._persistAssignment(r?"success":"failure").then(e)})});return Promise.all([e,r])},t.prototype._persistAssignment=function(t){var e=this;return wt.post("/v1/assignment_event",C({visitor_id:this._visitor.getId(),split_name:this._assignment.getSplitName(),context:this._assignment.getContext(),mixpanel_result:t})).catch(function(t){if(t.response){var r=t.response,n=r.status,i=r.statusText,o=r.data;e._visitor.logError("test_track persistAssignment response error: "+n+", "+i+", "+o)}else e._visitor.logError("test_track persistAssignment other error: "+t)})},t}(),At=function(){function t(t){if(this.visitorId=t.visitorId,this.identifierType=t.identifierType,this.value=t.value,!this.visitorId)throw new Error("must provide visitorId");if(!this.identifierType)throw new Error("must provide identifierType");if(!this.value)throw new Error("must provide value")}return t.prototype.save=function(){return wt.post("/v1/identifier",C({identifier_type:this.identifierType,value:this.value,visitor_id:this.visitorId})).then(function(t){var e=t.data;return new Ut({id:e.visitor.id,assignments:n.fromJsonArray(e.visitor.assignments)})})},t}(),St=function(){function t(){}return t.prototype.trackAssignment=function(t,e,r){var n={TTVisitorID:t,SplitName:e.getSplitName(),SplitVariant:e.getVariant(),SplitContext:e.getContext()};window.mixpanel&&window.mixpanel.track("SplitAssigned",n,r)},t.prototype.identify=function(t){window.mixpanel&&window.mixpanel.identify(t)},t.prototype.alias=function(t){window.mixpanel&&window.mixpanel.alias(t)},t}(),Et=e(function(t){var e="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(e){var r=new Uint8Array(16);t.exports=function(){return e(r),r}}else{var n=new Array(16);t.exports=function(){for(var t,e=0;e<16;e++)0==(3&e)&&(t=4294967296*Math.random()),n[e]=t>>>((3&e)<<3)&255;return n}}}),xt=[],Nt=0;Nt<256;++Nt)xt[Nt]=(Nt+256).toString(16).substr(1);var Ot=function(t,e){var r=e||0,n=xt;return[n[t[r++]],n[t[r++]],n[t[r++]],n[t[r++]],"-",n[t[r++]],n[t[r++]],"-",n[t[r++]],n[t[r++]],"-",n[t[r++]],n[t[r++]],"-",n[t[r++]],n[t[r++]],n[t[r++]],n[t[r++]],n[t[r++]],n[t[r++]]].join("")};var jt=function(t,e,r){var n=e&&r||0;"string"==typeof t&&(e="binary"===t?new Array(16):null,t=null);var i=(t=t||{}).random||(t.rng||Et)();if(i[6]=15&i[6]|64,i[8]=63&i[8]|128,e)for(var o=0;o<16;++o)e[n+o]=i[o];return e||Ot(i)},Rt=e(function(e){!function(t){function r(t,e){var r=(65535&t)+(65535&e);return(t>>16)+(e>>16)+(r>>16)<<16|65535&r}function n(t,e,n,i,o,s){return r((a=r(r(e,t),r(i,s)))<<(u=o)|a>>>32-u,n);var a,u}function i(t,e,r,i,o,s,a){return n(e&r|~e&i,t,e,o,s,a)}function o(t,e,r,i,o,s,a){return n(e&i|r&~i,t,e,o,s,a)}function s(t,e,r,i,o,s,a){return n(e^r^i,t,e,o,s,a)}function a(t,e,r,i,o,s,a){return n(r^(e|~i),t,e,o,s,a)}function u(t,e){var n,u,c,f,p;t[e>>5]|=128<<e%32,t[14+(e+64>>>9<<4)]=e;var l=1732584193,d=-271733879,h=-1732584194,g=271733878;for(n=0;n<t.length;n+=16)u=l,c=d,f=h,p=g,l=i(l,d,h,g,t[n],7,-680876936),g=i(g,l,d,h,t[n+1],12,-389564586),h=i(h,g,l,d,t[n+2],17,606105819),d=i(d,h,g,l,t[n+3],22,-1044525330),l=i(l,d,h,g,t[n+4],7,-176418897),g=i(g,l,d,h,t[n+5],12,1200080426),h=i(h,g,l,d,t[n+6],17,-1473231341),d=i(d,h,g,l,t[n+7],22,-45705983),l=i(l,d,h,g,t[n+8],7,1770035416),g=i(g,l,d,h,t[n+9],12,-1958414417),h=i(h,g,l,d,t[n+10],17,-42063),d=i(d,h,g,l,t[n+11],22,-1990404162),l=i(l,d,h,g,t[n+12],7,1804603682),g=i(g,l,d,h,t[n+13],12,-40341101),h=i(h,g,l,d,t[n+14],17,-1502002290),l=o(l,d=i(d,h,g,l,t[n+15],22,1236535329),h,g,t[n+1],5,-165796510),g=o(g,l,d,h,t[n+6],9,-1069501632),h=o(h,g,l,d,t[n+11],14,643717713),d=o(d,h,g,l,t[n],20,-373897302),l=o(l,d,h,g,t[n+5],5,-701558691),g=o(g,l,d,h,t[n+10],9,38016083),h=o(h,g,l,d,t[n+15],14,-660478335),d=o(d,h,g,l,t[n+4],20,-405537848),l=o(l,d,h,g,t[n+9],5,568446438),g=o(g,l,d,h,t[n+14],9,-1019803690),h=o(h,g,l,d,t[n+3],14,-187363961),d=o(d,h,g,l,t[n+8],20,1163531501),l=o(l,d,h,g,t[n+13],5,-1444681467),g=o(g,l,d,h,t[n+2],9,-51403784),h=o(h,g,l,d,t[n+7],14,1735328473),l=s(l,d=o(d,h,g,l,t[n+12],20,-1926607734),h,g,t[n+5],4,-378558),g=s(g,l,d,h,t[n+8],11,-2022574463),h=s(h,g,l,d,t[n+11],16,1839030562),d=s(d,h,g,l,t[n+14],23,-35309556),l=s(l,d,h,g,t[n+1],4,-1530992060),g=s(g,l,d,h,t[n+4],11,1272893353),h=s(h,g,l,d,t[n+7],16,-155497632),d=s(d,h,g,l,t[n+10],23,-1094730640),l=s(l,d,h,g,t[n+13],4,681279174),g=s(g,l,d,h,t[n],11,-358537222),h=s(h,g,l,d,t[n+3],16,-722521979),d=s(d,h,g,l,t[n+6],23,76029189),l=s(l,d,h,g,t[n+9],4,-640364487),g=s(g,l,d,h,t[n+12],11,-421815835),h=s(h,g,l,d,t[n+15],16,530742520),l=a(l,d=s(d,h,g,l,t[n+2],23,-995338651),h,g,t[n],6,-198630844),g=a(g,l,d,h,t[n+7],10,1126891415),h=a(h,g,l,d,t[n+14],15,-1416354905),d=a(d,h,g,l,t[n+5],21,-57434055),l=a(l,d,h,g,t[n+12],6,1700485571),g=a(g,l,d,h,t[n+3],10,-1894986606),h=a(h,g,l,d,t[n+10],15,-1051523),d=a(d,h,g,l,t[n+1],21,-2054922799),l=a(l,d,h,g,t[n+8],6,1873313359),g=a(g,l,d,h,t[n+15],10,-30611744),h=a(h,g,l,d,t[n+6],15,-1560198380),d=a(d,h,g,l,t[n+13],21,1309151649),l=a(l,d,h,g,t[n+4],6,-145523070),g=a(g,l,d,h,t[n+11],10,-1120210379),h=a(h,g,l,d,t[n+2],15,718787259),d=a(d,h,g,l,t[n+9],21,-343485551),l=r(l,u),d=r(d,c),h=r(h,f),g=r(g,p);return[l,d,h,g]}function c(t){var e,r="",n=32*t.length;for(e=0;e<n;e+=8)r+=String.fromCharCode(t[e>>5]>>>e%32&255);return r}function f(t){var e,r=[];for(r[(t.length>>2)-1]=void 0,e=0;e<r.length;e+=1)r[e]=0;var n=8*t.length;for(e=0;e<n;e+=8)r[e>>5]|=(255&t.charCodeAt(e/8))<<e%32;return r}function p(t){var e,r,n="";for(r=0;r<t.length;r+=1)e=t.charCodeAt(r),n+="0123456789abcdef".charAt(e>>>4&15)+"0123456789abcdef".charAt(15&e);return n}function l(t){return unescape(encodeURIComponent(t))}function d(t){return function(t){return c(u(f(t),8*t.length))}(l(t))}function h(t,e){return function(t,e){var r,n,i=f(t),o=[],s=[];for(o[15]=s[15]=void 0,i.length>16&&(i=u(i,8*t.length)),r=0;r<16;r+=1)o[r]=909522486^i[r],s[r]=1549556828^i[r];return n=u(o.concat(f(e)),512+8*e.length),c(u(s.concat(n),640))}(l(t),l(e))}function g(t,e,r){return e?r?h(e,t):p(h(e,t)):r?d(t):p(d(t))}e.exports?e.exports=g:t.md5=g}(t)}),Vt=function(){function t(t){if(this.visitor=t.visitor,this.splitName=t.splitName,!this.visitor)throw new Error("must provide visitor");if(!this.splitName)throw new Error("must provide splitName")}return t.prototype.getVariant=function(){if(!vt.getSplitRegistry().isLoaded())return null;for(var t=0,e=this.getAssignmentBucket(),r=this.getWeighting(),n=this.getSortedVariants(),i=0;i<n.length;i++){var o=n[i];if((t+=r[o])>e)return o}throw new Error("Assignment bucket out of range. "+e+" unmatched in "+this.splitName+": "+JSON.stringify(r))},t.prototype.getSplitVisitorHash=function(){return Rt(this.splitName+this.visitor.getId())},t.prototype.getHashFixnum=function(){return parseInt(this.getSplitVisitorHash().substr(0,8),16)},t.prototype.getAssignmentBucket=function(){return this.getHashFixnum()%100},t.prototype.getSortedVariants=function(){return this.getVariants().sort()},t.prototype.getVariants=function(){return Object.getOwnPropertyNames(this.getWeighting())},t.prototype.getWeighting=function(){var t=vt.getSplitRegistry().getSplit(this.splitName);if(!t){var e='Unknown split: "'+this.splitName+'"';throw this.visitor.logError(e),new Error(e)}return t.getWeighting()},t}(),kt=function(){function t(t){if(!t.assignment)throw new Error("must provide assignment");if(!t.visitor)throw new Error("must provide visitor");this._assignment=t.assignment,this._visitor=t.visitor,this._splitRegistry=vt.getSplitRegistry(),this._variantHandlers={}}return t.prototype.when=function(){for(var t=this,e=[],r=0;r<arguments.length;r++)e[r]=arguments[r];var n="function"==typeof e[e.length-1]?e.pop():null;if(0===e.length)throw new Error("must provide at least one variant");e.forEach(function(e){"string"==typeof e&&t._assignHandlerToVariant(e,n)})},t.prototype.default=function(t,e){if(this._defaultVariant)throw new Error("must provide exactly one `default`");this._defaultVariant=this._assignHandlerToVariant(t,e)},t.prototype.run=function(){this._validate();var t=this.getDefaultVariant();if(void 0===t)throw new Error("must provide exactly one `default`");var e=this._variantHandlers[t],r=this._assignment.getVariant();r&&this._variantHandlers[r]?e=this._variantHandlers[r]:this._defaulted=!0,e()},t.prototype.isDefaulted=function(){return this._defaulted||!1},t.prototype.getDefaultVariant=function(){return this._defaultVariant},t.prototype._assignHandlerToVariant=function(t,e){if("function"!=typeof e)throw new Error("must provide handler for "+t);return t=t.toString(),this._getSplit()&&!this._getSplit().hasVariant(t)&&this._visitor.logError("configures unknown variant "+t),this._variantHandlers[t]=e,t},t.prototype._validate=function(){if(!this.getDefaultVariant())throw new Error("must provide exactly one `default`");if(this._getVariants().length<2)throw new Error("must provide at least one `when`");if(this._getSplit()){var t=this._getMissingVariants();if(t.length>0){var e=t.join(", ").replace(/, (.+)$/," and $1");this._visitor.logError("does not configure variants "+e)}}},t.prototype._getSplit=function(){return this._splitRegistry.getSplit(this._assignment.getSplitName())},t.prototype._getVariants=function(){return Object.getOwnPropertyNames(this._variantHandlers)},t.prototype._getMissingVariants=function(){var t=this._getVariants();return this._getSplit().getVariants().filter(function(e){return!t.includes(e)})},t}(),Ut=function(){function t(t){var e=t.id,r=t.assignments,n=t.ttOffline;if(this._id=e,this._assignments=r,this._ttOffline=n,!this._id)throw new Error("must provide id");if(!this._assignments)throw new Error("must provide assignments");this._errorLogger=function(t){window.console.error(t)},this.analytics=new St}return t.loadVisitor=function(e){if(e){var r=vt.getAssignments();return r?Promise.resolve(new t({id:e,assignments:r,ttOffline:!1})):wt.get("/v1/visitors/"+e,{timeout:5e3}).then(function(e){var r=e.data;return new t({id:r.id,assignments:n.fromJsonArray(r.assignments),ttOffline:!1})}).catch(function(){return new t({id:e,assignments:[],ttOffline:!0})})}return Promise.resolve(new t({id:jt(),assignments:[],ttOffline:!1}))},t.prototype.getId=function(){return this._id},t.prototype.getAssignmentRegistry=function(){return this._assignmentRegistry||(this._assignmentRegistry=this._assignments.reduce(function(t,e){var r;return lt(lt({},t),((r={})[e.getSplitName()]=e,r))},{})),this._assignmentRegistry},t.prototype.vary=function(t,e){if("object"!=typeof e.variants)throw new Error("must provide variants object to `vary` for "+t);if(!e.context)throw new Error("must provide context to `vary` for "+t);if(!e.defaultVariant&&!1!==e.defaultVariant)throw new Error("must provide defaultVariant to `vary` for "+t);var r=e.defaultVariant.toString(),n=e.variants,i=e.context;if(!n.hasOwnProperty(r))throw new Error("defaultVariant: "+r+" must be represented in variants object");var o=this._getAssignmentFor(t,i),s=new kt({assignment:o,visitor:this});for(var a in n)n.hasOwnProperty(a)&&(a===r?s.default(a,n[a]):s.when(a,n[a]));s.run(),s.isDefaulted()&&(o.setVariant(s.getDefaultVariant()),o.setUnsynced(!0),o.setContext(i)),this.notifyUnsyncedAssignments()},t.prototype.ab=function(t,e){var r=new bt({splitName:t,trueVariant:e.trueVariant,visitor:this}).getVariants(),n={};n[r.true.toString()]=function(){e.callback(!0)},n[r.false.toString()]=function(){e.callback(!1)},this.vary(t,{context:e.context,variants:n,defaultVariant:r.false})},t.prototype.setErrorLogger=function(t){if("function"!=typeof t)throw new Error("must provide function for errorLogger");this._errorLogger=t},t.prototype.logError=function(t){this._errorLogger.call(null,t)},t.prototype.linkIdentifier=function(t,e){var r=this;return new At({identifierType:t,value:e,visitorId:this.getId()}).save().then(function(t){r._merge(t),r.notifyUnsyncedAssignments()})},t.prototype.setAnalytics=function(t){if("object"!=typeof t)throw new Error("must provide object for setAnalytics");this.analytics=t},t.prototype.notifyUnsyncedAssignments=function(){this._getUnsyncedAssignments().forEach(this._notify.bind(this))},t.prototype._getUnsyncedAssignments=function(){var t=this.getAssignmentRegistry();return Object.keys(t).reduce(function(e,r){var n=t[r];return n.isUnsynced()&&e.push(n),e},[])},t.prototype._merge=function(t){var e=this.getAssignmentRegistry(),r=t.getAssignmentRegistry();this._id=t.getId(),Object.assign(e,r)},t.prototype._getAssignmentFor=function(t,e){return this.getAssignmentRegistry()[t]||this._generateAssignmentFor(t,e)},t.prototype._generateAssignmentFor=function(t,e){var r=new Vt({visitor:this,splitName:t}).getVariant();r||(this._ttOffline=!0);var i=new n({splitName:t,variant:r,context:e,isUnsynced:!0});return this._assignments.push(i),this._assignmentRegistry=null,i},t.prototype._notify=function(t){try{if(this._ttOffline)return;new Ct({visitor:this,assignment:t}).send(),t.setUnsynced(!1)}catch(t){this.logError("test_track notify error: "+t)}},t}(),Tt=null,Pt=(new(function(){function t(){this._visitorLoaded=new Promise(function(t){return Tt=t})}return t.prototype.initialize=function(t){var e=r.get(vt.getCookieName());return Ut.loadVisitor(e).then(function(e){t&&t.analytics&&e.setAnalytics(t.analytics),t&&t.errorLogger&&e.setErrorLogger(t.errorLogger),t&&"function"==typeof t.onVisitorLoaded&&t.onVisitorLoaded.call(null,e),e.notifyUnsyncedAssignments(),Tt&&Tt(e)}),this._setCookie(),this._visitorLoaded},t.prototype.vary=function(t,e){return this._visitorLoaded.then(function(r){r.vary(t,e)})},t.prototype.ab=function(t,e){return this._visitorLoaded.then(function(r){r.ab(t,e)})},t.prototype.logIn=function(t,e){var r=this;return this._visitorLoaded.then(function(n){return n.linkIdentifier(t,e).then(function(){r._setCookie(),n.analytics.identify(n.getId())})})},t.prototype.signUp=function(t,e){var r=this;return this._visitorLoaded.then(function(n){return n.linkIdentifier(t,e).then(function(){r._setCookie(),n.analytics.alias(n.getId())})})},t.prototype._setCookie=function(){return this._visitorLoaded.then(function(t){r.set(vt.getCookieName(),t.getId(),{expires:365,path:"/",domain:vt.getCookieDomain()})})},t.prototype.getPublicAPI=function(){var t=this;return{vary:this.vary.bind(this),ab:this.ab.bind(this),logIn:this.logIn.bind(this),signUp:this.signUp.bind(this),initialize:this.initialize.bind(this),_crx:{loadInfo:function(){return t._visitorLoaded.then(function(t){var e={};for(var r in t.getAssignmentRegistry())e[r]=t.getAssignmentRegistry()[r].getVariant();return{visitorId:t.getId(),splitRegistry:vt.getSplitRegistry().asV1Hash(),assignmentRegistry:e}})},persistAssignment:function(e,r,i,o){return t._visitorLoaded.then(function(t){return new _t({visitor:t,username:i,password:o,assignment:new n({splitName:e,variant:r,context:"chrome_extension",isUnsynced:!0})}).persistAssignment()})}}}},t}())).getPublicAPI(),Lt=function(){window.dispatchEvent(new CustomEvent("tt:lib:loaded",{detail:{TestTrack:Pt}}))},Dt=function(){document.body.classList.add("_tt");try{window.dispatchEvent(new CustomEvent("tt:class:added"))}catch(t){}};try{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",Dt):Dt(),Lt(),window.addEventListener("tt:listener:ready",Lt)}catch(t){}return Pt});
|
|
@@ -12,9 +12,7 @@ module TestTrack::Controller
|
|
|
12
12
|
class_methods do
|
|
13
13
|
def require_feature_flag(feature_flag, *args)
|
|
14
14
|
before_action(*args) do
|
|
15
|
-
unless test_track_visitor.ab(feature_flag, context: self.class.name.underscore)
|
|
16
|
-
raise ActionController::RoutingError, 'Not Found'
|
|
17
|
-
end
|
|
15
|
+
raise ActionController::RoutingError, 'Not Found' unless test_track_visitor.ab(feature_flag, context: self.class.name.underscore)
|
|
18
16
|
end
|
|
19
17
|
end
|
|
20
18
|
end
|
|
@@ -6,6 +6,7 @@ module TestTrack::RequiredOptions
|
|
|
6
6
|
def require_option!(opts, opt_name, my_opts = {})
|
|
7
7
|
opt_provided = my_opts[:allow_nil] ? opts.key?(opt_name) : opts[opt_name]
|
|
8
8
|
raise(ArgumentError, "Must provide #{opt_name}") unless opt_provided
|
|
9
|
+
|
|
9
10
|
opts.delete(opt_name)
|
|
10
11
|
end
|
|
11
12
|
end
|
|
@@ -19,10 +19,8 @@ class TestTrack::ABConfiguration
|
|
|
19
19
|
private
|
|
20
20
|
|
|
21
21
|
def build_variant_hash
|
|
22
|
-
if split_variants && split_variants.size > 2
|
|
23
|
-
|
|
24
|
-
end
|
|
25
|
-
{ true: true_variant, false: false_variant }
|
|
22
|
+
notify_because_ab("configures split with more than 2 variants") if split_variants && split_variants.size > 2
|
|
23
|
+
{ true: true_variant, false: false_variant } # rubocop:disable Lint/BooleanSymbol
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
def true_variant
|
|
@@ -30,7 +28,7 @@ class TestTrack::ABConfiguration
|
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
def false_variant
|
|
33
|
-
@false_variant ||= non_true_variants.present? ? non_true_variants.
|
|
31
|
+
@false_variant ||= non_true_variants.present? ? non_true_variants.min : false
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
attr_reader :split_name, :split_registry
|
|
@@ -9,6 +9,7 @@ module TestTrack::Analytics
|
|
|
9
9
|
def error_handler=(handler)
|
|
10
10
|
raise ArgumentError, "error_handler must be a lambda" unless handler.lambda?
|
|
11
11
|
raise ArgumentError, "error_handler must accept 1 argument" unless handler.arity == 1
|
|
12
|
+
|
|
12
13
|
@error_handler = handler
|
|
13
14
|
end
|
|
14
15
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
class TestTrack::ConfigUpdater
|
|
2
|
-
def initialize(schema_file_path = Rails.root.join('db
|
|
2
|
+
def initialize(schema_file_path = Rails.root.join('db/test_track_schema.yml'))
|
|
3
3
|
@schema_file_path = schema_file_path
|
|
4
4
|
end
|
|
5
5
|
|
|
@@ -75,7 +75,7 @@ class TestTrack::ConfigUpdater
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def unpersisted_split_names
|
|
78
|
-
@
|
|
78
|
+
@unpersisted_split_names ||= splits.keys - remote_splits.keys
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def splits
|
|
@@ -90,7 +90,7 @@ class TestTrack::ConfigUpdater
|
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
def schema_file_hash
|
|
93
|
-
@
|
|
93
|
+
@schema_file_hash ||= YAML.safe_load(schema_file_contents) || {}
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
def schema_file_contents
|
|
@@ -50,26 +50,24 @@ class TestTrack::Fake::SplitRegistry
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def legacy_test_track_schema_yml
|
|
53
|
-
unless instance_variable_defined?(:@legacy_test_track_schema_yml)
|
|
54
|
-
@legacy_test_track_schema_yml = _legacy_test_track_schema_yml
|
|
55
|
-
end
|
|
53
|
+
@legacy_test_track_schema_yml = _legacy_test_track_schema_yml unless instance_variable_defined?(:@legacy_test_track_schema_yml)
|
|
56
54
|
@legacy_test_track_schema_yml
|
|
57
55
|
end
|
|
58
56
|
|
|
59
57
|
def _legacy_test_track_schema_yml
|
|
60
58
|
File.exist?(legacy_test_track_schema_yml_path) &&
|
|
61
59
|
YAML.load_file(legacy_test_track_schema_yml_path).with_indifferent_access
|
|
62
|
-
rescue
|
|
60
|
+
rescue StandardError
|
|
63
61
|
nil
|
|
64
62
|
end
|
|
65
63
|
|
|
66
64
|
def legacy_test_track_schema_yml_path
|
|
67
|
-
ENV["TEST_TRACK_SCHEMA_FILE_PATH"] || Rails.root.join('db
|
|
65
|
+
ENV["TEST_TRACK_SCHEMA_FILE_PATH"] || Rails.root.join('db/test_track_schema.yml').to_s
|
|
68
66
|
end
|
|
69
67
|
|
|
70
68
|
def split_registry_with_deterministic_weights
|
|
71
69
|
splits = split_hash.each_with_object({}) do |(split_name, weighting_registry), result|
|
|
72
|
-
default_variant = weighting_registry.keys.
|
|
70
|
+
default_variant = weighting_registry.keys.min
|
|
73
71
|
|
|
74
72
|
adjusted_weights = { default_variant => 100 }
|
|
75
73
|
weighting_registry.except(default_variant).each_key do |variant|
|
|
@@ -24,9 +24,7 @@ class TestTrack::JobSession
|
|
|
24
24
|
|
|
25
25
|
def notify_unsynced_assignments!
|
|
26
26
|
identity_visitor_map.each_value do |visitor|
|
|
27
|
-
if visitor.loaded? && visitor.unsynced_assignments.present?
|
|
28
|
-
TestTrack::ThreadedVisitorNotifier.new(visitor).notify
|
|
29
|
-
end
|
|
27
|
+
TestTrack::ThreadedVisitorNotifier.new(visitor).notify if visitor.loaded? && visitor.unsynced_assignments.present?
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
30
|
|
|
@@ -4,7 +4,7 @@ class TestTrack::LazyVisitorByIdentity
|
|
|
4
4
|
end
|
|
5
5
|
|
|
6
6
|
def loaded?
|
|
7
|
-
@
|
|
7
|
+
@__visitor__.present?
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def id_loaded?
|
|
@@ -13,8 +13,12 @@ class TestTrack::LazyVisitorByIdentity
|
|
|
13
13
|
|
|
14
14
|
private
|
|
15
15
|
|
|
16
|
-
def method_missing(method, *args, &block)
|
|
17
|
-
__visitor__.
|
|
16
|
+
def method_missing(method, *args, &block)
|
|
17
|
+
if __visitor__.respond_to?(method)
|
|
18
|
+
__visitor__.send(method, *args, &block)
|
|
19
|
+
else
|
|
20
|
+
super
|
|
21
|
+
end
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
def respond_to_missing?(method, include_private = false)
|
|
@@ -22,7 +26,7 @@ class TestTrack::LazyVisitorByIdentity
|
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def __visitor__
|
|
25
|
-
@
|
|
29
|
+
@__visitor__ ||= __load_visitor__
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
def __load_visitor__
|
|
@@ -22,6 +22,7 @@ module TestTrack::MisconfigurationNotifier
|
|
|
22
22
|
class Airbrake
|
|
23
23
|
def notify(msg)
|
|
24
24
|
raise "Aibrake was configured but not found" unless defined?(::Airbrake)
|
|
25
|
+
|
|
25
26
|
if ::Airbrake.respond_to?(:notify_or_ignore)
|
|
26
27
|
::Airbrake.notify_or_ignore(StandardError.new, error_message: msg)
|
|
27
28
|
else
|
|
@@ -28,6 +28,7 @@ class TestTrack::NotifyAssignmentJob
|
|
|
28
28
|
def maybe_track
|
|
29
29
|
return "failure" unless TestTrack.enabled?
|
|
30
30
|
return "success" if skip_analytics_event?
|
|
31
|
+
|
|
31
32
|
result = TestTrack.analytics.track(TestTrack::AnalyticsEvent.new(visitor_id, assignment))
|
|
32
33
|
result ? "success" : "failure"
|
|
33
34
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class TestTrack::Remote::Identifier
|
|
2
2
|
include TestTrack::RemoteModel
|
|
3
3
|
|
|
4
|
-
collection_path '
|
|
4
|
+
collection_path 'api/v1/identifier'
|
|
5
5
|
|
|
6
6
|
has_one :remote_visitor, data_key: :visitor, class_name: "TestTrack::Remote::Visitor"
|
|
7
7
|
|
|
@@ -21,6 +21,7 @@ class TestTrack::Remote::Identifier
|
|
|
21
21
|
|
|
22
22
|
def visitor_opts!
|
|
23
23
|
raise("Visitor data unavailable until you save this identifier.") unless attributes[:remote_visitor]
|
|
24
|
+
|
|
24
25
|
{ id: remote_visitor.id, assignments: remote_visitor.assignments }
|
|
25
26
|
end
|
|
26
27
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class TestTrack::Remote::SplitDetail
|
|
2
2
|
include TestTrack::RemoteModel
|
|
3
3
|
|
|
4
|
-
collection_path '
|
|
4
|
+
collection_path 'api/v1/split_details'
|
|
5
5
|
|
|
6
6
|
attributes :name, :hypothesis, :assignment_criteria, :description, :owner, :location, :platform, :variant_details
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ class TestTrack::Remote::SplitDetail
|
|
|
10
10
|
if faked?
|
|
11
11
|
new(fake_instance_attributes(name))
|
|
12
12
|
else
|
|
13
|
-
get("
|
|
13
|
+
get("api/v1/split_details/#{name}")
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -3,7 +3,7 @@ class TestTrack::Remote::SplitRegistry
|
|
|
3
3
|
|
|
4
4
|
CACHE_KEY = 'test_track_split_registry'.freeze
|
|
5
5
|
|
|
6
|
-
collection_path '
|
|
6
|
+
collection_path 'api/v3/builds/:build_timestamp/split_registry'
|
|
7
7
|
|
|
8
8
|
class << self
|
|
9
9
|
def fake_instance_attributes(_)
|
|
@@ -15,7 +15,7 @@ class TestTrack::Remote::SplitRegistry
|
|
|
15
15
|
if faked?
|
|
16
16
|
new(fake_instance_attributes(nil))
|
|
17
17
|
else
|
|
18
|
-
get(
|
|
18
|
+
get("api/v3/builds/#{TestTrack.build_timestamp}/split_registry")
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class TestTrack::Remote::Visitor
|
|
2
2
|
include TestTrack::RemoteModel
|
|
3
3
|
|
|
4
|
-
collection_path '
|
|
4
|
+
collection_path 'api/v1/visitors'
|
|
5
5
|
|
|
6
6
|
has_many :assignments
|
|
7
7
|
|
|
@@ -13,7 +13,7 @@ class TestTrack::Remote::Visitor
|
|
|
13
13
|
if faked?
|
|
14
14
|
new(fake_instance_attributes(nil))
|
|
15
15
|
else
|
|
16
|
-
get("
|
|
16
|
+
get("api/v1/identifier_types/#{identifier_type}/identifiers/#{identifier_value}/visitor")
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -8,7 +8,7 @@ class TestTrack::Remote::VisitorDetail
|
|
|
8
8
|
if faked?
|
|
9
9
|
new(fake_instance_attributes(nil))
|
|
10
10
|
else
|
|
11
|
-
get("
|
|
11
|
+
get("api/v1/identifier_types/#{identifier_type}/identifiers/#{identifier_value}/visitor_detail")
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -28,8 +28,8 @@ class TestTrack::SplitRegistry
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def to_hash
|
|
31
|
-
registry_hash && registry_hash['splits'].
|
|
32
|
-
|
|
31
|
+
registry_hash && registry_hash['splits'].transform_values do |v|
|
|
32
|
+
{ weights: v['weights'], feature_gate: v['feature_gate'] }
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -21,14 +21,12 @@ class TestTrack::ThreadedVisitorNotifier
|
|
|
21
21
|
|
|
22
22
|
def new_thread_with_request_store
|
|
23
23
|
Thread.new(RequestStore.store) do |original_store|
|
|
24
|
-
begin
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
RequestStore.clear!
|
|
31
|
-
end
|
|
24
|
+
RequestStore.begin!
|
|
25
|
+
RequestStore.store.merge!(original_store)
|
|
26
|
+
yield
|
|
27
|
+
ensure
|
|
28
|
+
RequestStore.end!
|
|
29
|
+
RequestStore.clear!
|
|
32
30
|
end
|
|
33
31
|
end
|
|
34
32
|
end
|
|
@@ -14,12 +14,10 @@ class TestTrack::UnsyncedAssignmentsNotifier
|
|
|
14
14
|
def notify
|
|
15
15
|
assignments.each do |assignment|
|
|
16
16
|
build_notify_assignment_job(assignment).tap do |job|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Delayed::Job.enqueue(build_notify_assignment_job(assignment))
|
|
22
|
-
end
|
|
17
|
+
job.perform
|
|
18
|
+
rescue *TestTrack::SERVER_ERRORS => e
|
|
19
|
+
Rails.logger.error "TestTrack failed to notify unsynced assignments, retrying. #{e}"
|
|
20
|
+
Delayed::Job.enqueue(build_notify_assignment_job(assignment))
|
|
23
21
|
end
|
|
24
22
|
end
|
|
25
23
|
end
|
|
@@ -18,6 +18,7 @@ class TestTrack::VaryDSL
|
|
|
18
18
|
|
|
19
19
|
def when(*variants, &block)
|
|
20
20
|
raise ArgumentError, "must provide at least one variant" if variants.blank?
|
|
21
|
+
|
|
21
22
|
variants.each do |variant|
|
|
22
23
|
assign_behavior_to_variant(variant, block)
|
|
23
24
|
end
|
|
@@ -25,6 +26,7 @@ class TestTrack::VaryDSL
|
|
|
25
26
|
|
|
26
27
|
def default(variant, &block)
|
|
27
28
|
raise ArgumentError, "cannot provide more than one `default`" unless default_variant.nil?
|
|
29
|
+
|
|
28
30
|
@default_variant = assign_behavior_to_variant(variant, block)
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -57,6 +59,7 @@ class TestTrack::VaryDSL
|
|
|
57
59
|
variant = variant.to_s
|
|
58
60
|
|
|
59
61
|
raise ArgumentError, "must provide block for #{variant}" unless behavior_proc
|
|
62
|
+
|
|
60
63
|
notify_because_vary(<<-MESSAGE) if variant_behaviors.include?(variant)
|
|
61
64
|
configures variant "#{variant}" more than once.
|
|
62
65
|
This will raise an error in the next version of test_track_rails_client.
|
|
@@ -93,6 +96,7 @@ class TestTrack::VaryDSL
|
|
|
93
96
|
raise ArgumentError, "must provide exactly one `default`" unless default_variant
|
|
94
97
|
raise ArgumentError, "must provide at least one `when`" unless variant_behaviors.size >= 2
|
|
95
98
|
return true unless split_variants
|
|
99
|
+
|
|
96
100
|
missing_variants = split_variants - variant_behaviors.keys
|
|
97
101
|
notify_because_vary("does not configure variants #{missing_variants.to_sentence}") && false unless missing_variants.empty?
|
|
98
102
|
end
|
|
@@ -23,6 +23,7 @@ class TestTrack::Visitor
|
|
|
23
23
|
raise "unknown opts: #{opts.keys.to_sentence}" if opts.present?
|
|
24
24
|
|
|
25
25
|
raise ArgumentError, "must provide block to `vary` for #{split_name}" unless block_given?
|
|
26
|
+
|
|
26
27
|
v = TestTrack::VaryDSL.new(assignment: assignment_for(split_name), context: context, split_registry: split_registry)
|
|
27
28
|
yield v
|
|
28
29
|
v.send :run
|
|
@@ -38,18 +39,18 @@ class TestTrack::Visitor
|
|
|
38
39
|
ab_configuration = TestTrack::ABConfiguration.new split_name: split_name, true_variant: true_variant, split_registry: split_registry
|
|
39
40
|
|
|
40
41
|
vary(split_name, context: context) do |v|
|
|
41
|
-
v.when ab_configuration.variants[:true] do
|
|
42
|
+
v.when ab_configuration.variants[:true] do # rubocop:disable Lint/BooleanSymbol
|
|
42
43
|
true
|
|
43
44
|
end
|
|
44
|
-
v.default ab_configuration.variants[:false] do
|
|
45
|
+
v.default ab_configuration.variants[:false] do # rubocop:disable Lint/BooleanSymbol
|
|
45
46
|
false
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
def assignment_registry
|
|
51
|
-
@assignment_registry ||= assignments.
|
|
52
|
-
|
|
52
|
+
@assignment_registry ||= assignments.index_by do |assignment|
|
|
53
|
+
assignment.split_name
|
|
53
54
|
end
|
|
54
55
|
end
|
|
55
56
|
|
|
@@ -59,6 +59,7 @@ class TestTrack::WebSession
|
|
|
59
59
|
|
|
60
60
|
If your app doesn't support authentication, set it to `:none`.
|
|
61
61
|
ERROR
|
|
62
|
+
|
|
62
63
|
identity = controller.class.test_track_identity
|
|
63
64
|
controller.send(identity) unless identity == :none
|
|
64
65
|
end
|
|
@@ -93,7 +94,7 @@ class TestTrack::WebSession
|
|
|
93
94
|
end
|
|
94
95
|
|
|
95
96
|
def _cookie_domain
|
|
96
|
-
if bare_ip_address? || fully_qualified_cookie_domain_enabled?
|
|
97
|
+
if bare_ip_address? || request.local? || fully_qualified_cookie_domain_enabled?
|
|
97
98
|
request.host
|
|
98
99
|
else
|
|
99
100
|
wildcard_domain
|
|
@@ -34,9 +34,7 @@ class TestTrack::WebSessionVisitorRepository
|
|
|
34
34
|
|
|
35
35
|
def notify_unsynced_assignments!
|
|
36
36
|
all.each do |visitor|
|
|
37
|
-
if visitor.loaded? && visitor.unsynced_assignments.present?
|
|
38
|
-
TestTrack::ThreadedVisitorNotifier.new(visitor).notify
|
|
39
|
-
end
|
|
37
|
+
TestTrack::ThreadedVisitorNotifier.new(visitor).notify if visitor.loaded? && visitor.unsynced_assignments.present?
|
|
40
38
|
end
|
|
41
39
|
end
|
|
42
40
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
TestTrack.set_build_timestamp! unless ENV['SKIP_TESTTRACK_SET_BUILD_TIMESTAMP'] == '1'
|
|
@@ -10,6 +10,24 @@ namespace :test_track do
|
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
desc 'Generates build timestamp for fetching point-in-time split registries'
|
|
14
|
+
task generate_build_timestamp: :environment do
|
|
15
|
+
cli = TesttrackCli.instance
|
|
16
|
+
|
|
17
|
+
result = cli.call('generate_build_timestamp')
|
|
18
|
+
exit(result.exitstatus) unless result.success?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
desc 'Sets an environment variable to block build timestamp generation on application initialization'
|
|
22
|
+
task :skip_set_build_timestamp do # rubocop:disable Rails/RakeEnvironment
|
|
23
|
+
ENV['SKIP_TESTTRACK_SET_BUILD_TIMESTAMP'] = '1'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
desc 'Removes the testtrack/build_timestamp file'
|
|
27
|
+
task remove_build_timestamp: :environment do
|
|
28
|
+
File.delete('testtrack/build_timestamp') if File.exist?('testtrack/build_timestamp')
|
|
29
|
+
end
|
|
30
|
+
|
|
13
31
|
namespace :schema do
|
|
14
32
|
desc 'Load schema.yml state into TestTrack server'
|
|
15
33
|
task load: :environment do
|
|
@@ -28,6 +46,9 @@ namespace :test_track do
|
|
|
28
46
|
end
|
|
29
47
|
end
|
|
30
48
|
|
|
49
|
+
task 'assets:clobber' => ['test_track:remove_build_timestamp']
|
|
50
|
+
task 'assets:environment' => ['test_track:skip_set_build_timestamp']
|
|
51
|
+
task 'assets:precompile' => ['test_track:generate_build_timestamp']
|
|
31
52
|
task 'db:schema:load' => ['test_track:schema:load']
|
|
32
53
|
task 'db:structure:load' => ['test_track:schema:load']
|
|
33
54
|
task 'db:migrate' => ['test_track:migrate']
|
data/lib/test_track.rb
CHANGED
|
@@ -16,6 +16,8 @@ module TestTrack
|
|
|
16
16
|
module_function
|
|
17
17
|
|
|
18
18
|
SERVER_ERRORS = [Faraday::ConnectionFailed, Faraday::TimeoutError, Her::Errors::RemoteServerError].freeze
|
|
19
|
+
BUILD_TIMESTAMP_FILE_PATH = 'testtrack/build_timestamp'.freeze
|
|
20
|
+
BUILD_TIMESTAMP_REGEX = /\A\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d(.\d+)?([+-][0-2]\d:[0-5]\d|Z)\z/.freeze
|
|
19
21
|
|
|
20
22
|
mattr_accessor :enabled_override, :app_name
|
|
21
23
|
|
|
@@ -52,6 +54,26 @@ module TestTrack
|
|
|
52
54
|
@misconfiguration_notifier_class_name = notifier_class_name
|
|
53
55
|
end
|
|
54
56
|
|
|
57
|
+
def build_timestamp # rubocop:disable Metrics/MethodLength
|
|
58
|
+
@build_timestamp ||= begin
|
|
59
|
+
timestamp = _build_timestamp
|
|
60
|
+
|
|
61
|
+
if Rails.env.test? || Rails.env.development?
|
|
62
|
+
Time.zone.now.iso8601
|
|
63
|
+
elsif timestamp.present?
|
|
64
|
+
unless BUILD_TIMESTAMP_REGEX.match?(timestamp)
|
|
65
|
+
raise "./testtrack/build_timestamp is not a valid ISO 8601 timestamp, got '#{timestamp}'"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
timestamp
|
|
69
|
+
else
|
|
70
|
+
raise 'TestTrack failed to load the required build timestamp. ' \
|
|
71
|
+
'Ensure `test_track:generate_build_timestamp` task is run in `assets:precompile` and the build timestamp file is present.'
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
alias set_build_timestamp! build_timestamp
|
|
76
|
+
|
|
55
77
|
private
|
|
56
78
|
|
|
57
79
|
def analytics_instance
|
|
@@ -95,6 +117,7 @@ module TestTrack
|
|
|
95
117
|
|
|
96
118
|
def url
|
|
97
119
|
return nil unless private_url
|
|
120
|
+
|
|
98
121
|
full_uri = URI.parse(private_url)
|
|
99
122
|
full_uri.user = nil
|
|
100
123
|
full_uri.password = nil
|
|
@@ -105,6 +128,10 @@ module TestTrack
|
|
|
105
128
|
ENV['TEST_TRACK_API_URL']
|
|
106
129
|
end
|
|
107
130
|
|
|
131
|
+
def _build_timestamp
|
|
132
|
+
File.read(BUILD_TIMESTAMP_FILE_PATH).chomp.presence if File.exist?(BUILD_TIMESTAMP_FILE_PATH)
|
|
133
|
+
end
|
|
134
|
+
|
|
108
135
|
def enabled?
|
|
109
136
|
enabled_override.nil? ? !Rails.env.test? : enabled_override
|
|
110
137
|
end
|
|
@@ -2,13 +2,15 @@ require 'delayed_job'
|
|
|
2
2
|
|
|
3
3
|
begin
|
|
4
4
|
require 'airbrake'
|
|
5
|
-
rescue LoadError
|
|
5
|
+
rescue LoadError
|
|
6
|
+
# no-op
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
unless defined?(Delayed::Plugins::Airbrake) && Delayed::Worker.plugins.include?(Delayed::Plugins::Airbrake)
|
|
9
10
|
begin
|
|
10
11
|
require 'delayed-plugins-airbrake'
|
|
11
|
-
rescue LoadError
|
|
12
|
+
rescue LoadError
|
|
13
|
+
# no-op
|
|
12
14
|
end
|
|
13
15
|
end
|
|
14
16
|
|
|
Binary file
|
|
Binary file
|
data/vendor/gems/her/her.gemspec
CHANGED
|
@@ -24,6 +24,6 @@ Gem::Specification.new do |s|
|
|
|
24
24
|
s.add_development_dependency "rspec", "~> 3.5"
|
|
25
25
|
|
|
26
26
|
s.add_runtime_dependency "activemodel", ">= 4.2.1"
|
|
27
|
-
s.add_runtime_dependency "faraday", ">= 0.8"
|
|
27
|
+
s.add_runtime_dependency "faraday", ">= 0.8"
|
|
28
28
|
s.add_runtime_dependency "multi_json", "~> 1.7"
|
|
29
29
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: test_track_rails_client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.0.0
|
|
4
|
+
version: 4.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan O'Neill
|
|
@@ -10,10 +10,10 @@ authors:
|
|
|
10
10
|
- John Mileham
|
|
11
11
|
- Alan Norton
|
|
12
12
|
- Sam Moore
|
|
13
|
-
autorequire:
|
|
13
|
+
autorequire:
|
|
14
14
|
bindir: bin
|
|
15
15
|
cert_chain: []
|
|
16
|
-
date:
|
|
16
|
+
date: 2021-01-29 00:00:00.000000000 Z
|
|
17
17
|
dependencies:
|
|
18
18
|
- !ruby/object:Gem::Dependency
|
|
19
19
|
name: delayed_job
|
|
@@ -50,9 +50,6 @@ dependencies:
|
|
|
50
50
|
- - ">="
|
|
51
51
|
- !ruby/object:Gem::Version
|
|
52
52
|
version: '0.8'
|
|
53
|
-
- - "<"
|
|
54
|
-
- !ruby/object:Gem::Version
|
|
55
|
-
version: '1.0'
|
|
56
53
|
type: :runtime
|
|
57
54
|
prerelease: false
|
|
58
55
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -60,9 +57,6 @@ dependencies:
|
|
|
60
57
|
- - ">="
|
|
61
58
|
- !ruby/object:Gem::Version
|
|
62
59
|
version: '0.8'
|
|
63
|
-
- - "<"
|
|
64
|
-
- !ruby/object:Gem::Version
|
|
65
|
-
version: '1.0'
|
|
66
60
|
- !ruby/object:Gem::Dependency
|
|
67
61
|
name: faraday_middleware
|
|
68
62
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -134,7 +128,7 @@ dependencies:
|
|
|
134
128
|
version: '4.1'
|
|
135
129
|
- - "<"
|
|
136
130
|
- !ruby/object:Gem::Version
|
|
137
|
-
version: '
|
|
131
|
+
version: '7.0'
|
|
138
132
|
type: :runtime
|
|
139
133
|
prerelease: false
|
|
140
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -144,7 +138,7 @@ dependencies:
|
|
|
144
138
|
version: '4.1'
|
|
145
139
|
- - "<"
|
|
146
140
|
- !ruby/object:Gem::Version
|
|
147
|
-
version: '
|
|
141
|
+
version: '7.0'
|
|
148
142
|
- !ruby/object:Gem::Dependency
|
|
149
143
|
name: request_store
|
|
150
144
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -161,20 +155,132 @@ dependencies:
|
|
|
161
155
|
version: '1.3'
|
|
162
156
|
- !ruby/object:Gem::Dependency
|
|
163
157
|
name: appraisal
|
|
158
|
+
requirement: !ruby/object:Gem::Requirement
|
|
159
|
+
requirements:
|
|
160
|
+
- - ">="
|
|
161
|
+
- !ruby/object:Gem::Version
|
|
162
|
+
version: '0'
|
|
163
|
+
type: :development
|
|
164
|
+
prerelease: false
|
|
165
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - ">="
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '0'
|
|
170
|
+
- !ruby/object:Gem::Dependency
|
|
171
|
+
name: pry-rails
|
|
172
|
+
requirement: !ruby/object:Gem::Requirement
|
|
173
|
+
requirements:
|
|
174
|
+
- - ">="
|
|
175
|
+
- !ruby/object:Gem::Version
|
|
176
|
+
version: '0'
|
|
177
|
+
type: :development
|
|
178
|
+
prerelease: false
|
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
180
|
+
requirements:
|
|
181
|
+
- - ">="
|
|
182
|
+
- !ruby/object:Gem::Version
|
|
183
|
+
version: '0'
|
|
184
|
+
- !ruby/object:Gem::Dependency
|
|
185
|
+
name: rails-controller-testing
|
|
186
|
+
requirement: !ruby/object:Gem::Requirement
|
|
187
|
+
requirements:
|
|
188
|
+
- - ">="
|
|
189
|
+
- !ruby/object:Gem::Version
|
|
190
|
+
version: '0'
|
|
191
|
+
type: :development
|
|
192
|
+
prerelease: false
|
|
193
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
194
|
+
requirements:
|
|
195
|
+
- - ">="
|
|
196
|
+
- !ruby/object:Gem::Version
|
|
197
|
+
version: '0'
|
|
198
|
+
- !ruby/object:Gem::Dependency
|
|
199
|
+
name: rspec-rails
|
|
200
|
+
requirement: !ruby/object:Gem::Requirement
|
|
201
|
+
requirements:
|
|
202
|
+
- - ">="
|
|
203
|
+
- !ruby/object:Gem::Version
|
|
204
|
+
version: '0'
|
|
205
|
+
type: :development
|
|
206
|
+
prerelease: false
|
|
207
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
208
|
+
requirements:
|
|
209
|
+
- - ">="
|
|
210
|
+
- !ruby/object:Gem::Version
|
|
211
|
+
version: '0'
|
|
212
|
+
- !ruby/object:Gem::Dependency
|
|
213
|
+
name: rubocop
|
|
164
214
|
requirement: !ruby/object:Gem::Requirement
|
|
165
215
|
requirements:
|
|
166
216
|
- - "~>"
|
|
167
217
|
- !ruby/object:Gem::Version
|
|
168
|
-
version:
|
|
218
|
+
version: 0.81.0
|
|
169
219
|
type: :development
|
|
170
220
|
prerelease: false
|
|
171
221
|
version_requirements: !ruby/object:Gem::Requirement
|
|
172
222
|
requirements:
|
|
173
223
|
- - "~>"
|
|
174
224
|
- !ruby/object:Gem::Version
|
|
175
|
-
version:
|
|
225
|
+
version: 0.81.0
|
|
176
226
|
- !ruby/object:Gem::Dependency
|
|
177
|
-
name:
|
|
227
|
+
name: rubocop-performance
|
|
228
|
+
requirement: !ruby/object:Gem::Requirement
|
|
229
|
+
requirements:
|
|
230
|
+
- - ">="
|
|
231
|
+
- !ruby/object:Gem::Version
|
|
232
|
+
version: '0'
|
|
233
|
+
type: :development
|
|
234
|
+
prerelease: false
|
|
235
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
236
|
+
requirements:
|
|
237
|
+
- - ">="
|
|
238
|
+
- !ruby/object:Gem::Version
|
|
239
|
+
version: '0'
|
|
240
|
+
- !ruby/object:Gem::Dependency
|
|
241
|
+
name: rubocop-rails
|
|
242
|
+
requirement: !ruby/object:Gem::Requirement
|
|
243
|
+
requirements:
|
|
244
|
+
- - ">="
|
|
245
|
+
- !ruby/object:Gem::Version
|
|
246
|
+
version: '0'
|
|
247
|
+
type: :development
|
|
248
|
+
prerelease: false
|
|
249
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
250
|
+
requirements:
|
|
251
|
+
- - ">="
|
|
252
|
+
- !ruby/object:Gem::Version
|
|
253
|
+
version: '0'
|
|
254
|
+
- !ruby/object:Gem::Dependency
|
|
255
|
+
name: shoulda-matchers
|
|
256
|
+
requirement: !ruby/object:Gem::Requirement
|
|
257
|
+
requirements:
|
|
258
|
+
- - ">="
|
|
259
|
+
- !ruby/object:Gem::Version
|
|
260
|
+
version: '2.8'
|
|
261
|
+
type: :development
|
|
262
|
+
prerelease: false
|
|
263
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
264
|
+
requirements:
|
|
265
|
+
- - ">="
|
|
266
|
+
- !ruby/object:Gem::Version
|
|
267
|
+
version: '2.8'
|
|
268
|
+
- !ruby/object:Gem::Dependency
|
|
269
|
+
name: simplecov
|
|
270
|
+
requirement: !ruby/object:Gem::Requirement
|
|
271
|
+
requirements:
|
|
272
|
+
- - ">="
|
|
273
|
+
- !ruby/object:Gem::Version
|
|
274
|
+
version: '0'
|
|
275
|
+
type: :development
|
|
276
|
+
prerelease: false
|
|
277
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
278
|
+
requirements:
|
|
279
|
+
- - ">="
|
|
280
|
+
- !ruby/object:Gem::Version
|
|
281
|
+
version: '0'
|
|
282
|
+
- !ruby/object:Gem::Dependency
|
|
283
|
+
name: sqlite3
|
|
178
284
|
requirement: !ruby/object:Gem::Requirement
|
|
179
285
|
requirements:
|
|
180
286
|
- - ">="
|
|
@@ -205,16 +311,16 @@ dependencies:
|
|
|
205
311
|
name: webmock
|
|
206
312
|
requirement: !ruby/object:Gem::Requirement
|
|
207
313
|
requirements:
|
|
208
|
-
- - "
|
|
314
|
+
- - ">="
|
|
209
315
|
- !ruby/object:Gem::Version
|
|
210
|
-
version:
|
|
316
|
+
version: '0'
|
|
211
317
|
type: :development
|
|
212
318
|
prerelease: false
|
|
213
319
|
version_requirements: !ruby/object:Gem::Requirement
|
|
214
320
|
requirements:
|
|
215
|
-
- - "
|
|
321
|
+
- - ">="
|
|
216
322
|
- !ruby/object:Gem::Version
|
|
217
|
-
version:
|
|
323
|
+
version: '0'
|
|
218
324
|
description: Easy split testing and feature flagging for Rails with TestTrack server
|
|
219
325
|
email:
|
|
220
326
|
- ryan.oneill@betterment.com
|
|
@@ -285,6 +391,7 @@ files:
|
|
|
285
391
|
- app/views/tt/api/v1/split_details/show.json.jbuilder
|
|
286
392
|
- app/views/tt/api/v1/visitors/_show.json.jbuilder
|
|
287
393
|
- app/views/tt/api/v1/visitors/show.json.jbuilder
|
|
394
|
+
- config/initializers/set_build_timestamp.rb
|
|
288
395
|
- config/initializers/test_track_api.rb
|
|
289
396
|
- config/routes.rb
|
|
290
397
|
- lib/generators/test_track/migration_generator.rb
|
|
@@ -341,7 +448,7 @@ homepage: https://github.com/Betterment
|
|
|
341
448
|
licenses:
|
|
342
449
|
- MIT
|
|
343
450
|
metadata: {}
|
|
344
|
-
post_install_message:
|
|
451
|
+
post_install_message:
|
|
345
452
|
rdoc_options: []
|
|
346
453
|
require_paths:
|
|
347
454
|
- lib
|
|
@@ -349,16 +456,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
349
456
|
requirements:
|
|
350
457
|
- - ">="
|
|
351
458
|
- !ruby/object:Gem::Version
|
|
352
|
-
version: 2.
|
|
459
|
+
version: 2.5.0
|
|
353
460
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
354
461
|
requirements:
|
|
355
|
-
- - "
|
|
462
|
+
- - ">="
|
|
356
463
|
- !ruby/object:Gem::Version
|
|
357
|
-
version:
|
|
464
|
+
version: '0'
|
|
358
465
|
requirements: []
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
signing_key:
|
|
466
|
+
rubygems_version: 3.1.4
|
|
467
|
+
signing_key:
|
|
362
468
|
specification_version: 4
|
|
363
469
|
summary: Rails client for TestTrack
|
|
364
470
|
test_files: []
|