From 0b843a4e5189a9551d9a38b74864ff9b77072d04 Mon Sep 17 00:00:00 2001 From: Ignat Ignatov Date: Thu, 12 Mar 2020 16:10:38 +0200 Subject: [PATCH 1/7] chore: refactor `PushManager` class --- dist/leanplum.d.ts | 2 +- dist/leanplum.js | 4 +- dist/leanplum.min.js | 2 +- src/Leanplum.ts | 22 ++-- src/PushManager.ts | 244 +++++++++++++++++++------------------------ 5 files changed, 124 insertions(+), 150 deletions(-) diff --git a/dist/leanplum.d.ts b/dist/leanplum.d.ts index 04c96a1a..85153520 100644 --- a/dist/leanplum.d.ts +++ b/dist/leanplum.d.ts @@ -93,7 +93,7 @@ export default class Leanplum { * Unregisters the browser form web push. * @return {Promise} Resolves on success, otherwise rejects. */ - static unregisterFromWebPush(): Promise; + static unregisterFromWebPush(): Promise; /** * Clears cached values for messages, variables and test assignments. * Use sparingly as if the app is updated, you'll have to deal with potentially diff --git a/dist/leanplum.js b/dist/leanplum.js index 57807539..c6451d7c 100644 --- a/dist/leanplum.js +++ b/dist/leanplum.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Leanplum=t():e.Leanplum=t()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=27)}([function(e,t,n){var r=n(18),o="object"==typeof self&&self&&self.Object===Object&&self,a=r||o||Function("return this")();e.exports=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={METHODS:{START:"start",STOP:"stop",ADVANCE:"advance",TRACK:"track",PAUSE_SESSION:"pauseSession",RESUME_SESSION:"resumeSession",PAUSE_STATE:"pauseState",RESUME_STATE:"resumeState",DOWNLOAD_FILE:"downloadFile",MULTI:"multi",SET_VARS:"setVars",GET_VARS:"getVars",SET_USER_ATTRIBUTES:"setUserAttributes",SET_DEVICE_ATTRIBUTES:"setDeviceAttributes",UPLOAD_FILE:"uploadFile",REGISTER_DEVICE:"registerDevice"},SDK_VERSION:"1.4.0",CLIENT:"js",PARAMS:{ACTION:"action",APP_ID:"appId",CLIENT:"client",CLIENT_KEY:"clientKey",DEVICE_ID:"deviceId",SDK_VERSION:"sdkVersion",USER_ID:"userId",NEW_USER_ID:"newUserId",DEV_MODE:"devMode",VERSION_NAME:"versionName",SYSTEM_NAME:"systemName",SYSTEM_VERSION:"systemVersion",BROWSER_NAME:"browserName",BROWSER_VERSION:"browserVersion",DEVICE_NAME:"deviceName",DEVICE_MODEL:"deviceModel",USER_ATTRIBUTES:"userAttributes",LOCALE:"locale",COUNTRY:"country",REGION:"region",CITY:"city",LOCATION:"location",STATE:"state",INFO:"info",EVENT:"event",VALUE:"value",FILENAME:"filename",TIME:"time",DATA:"data",VARS:"vars",FILE:"file",SIZE:"size",VARIATION:"variation",HASH:"hash",EMAIL:"email",VARIABLES:"vars",PARAMS:"params",INCLUDE_DEFAULTS:"includeDefaults",INCLUDE_VARIANT_DEBUG_INFO:"includeVariantDebugInfo",WEB_PUSH_SUBSCRIPTION:"webPushSubscription"},KEYS:{IS_REGISTERED:"isRegistered",LATEST_VERSION:"latestVersion",VARS:"vars",VARIANTS:"variants",VARIANT_DEBUG_INFO:"variantDebugInfo",ACTION_METADATA:"actionMetadata",TOKEN:"token"},DEFAULT_KEYS:{COUNT:"__leanplum_unsynced",ITEM:"__leanplum_unsynced_",VARIABLES:"__leanplum_variables",VARIANTS:"__leanplum_variants",VARIANT_DEBUG_INFO:"__leanplum_variant_debug_info",ACTION_METADATA:"__leanplum_action_metadata",TOKEN:"__leanplum_token",DEVICE_ID:"__leanplum_device_id",USER_ID:"__leanplum_user_id",PUSH_SUBSCRIPTION:"__leanplum_push_subscription"},VALUES:{DETECT:"(detect)"}}},function(e,t,n){var r=n(46),o=n(52);e.exports=function(e,t){var n=o(e,t);return r(n)?n:void 0}},function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(1)),a=function(){function e(){this.argString="",this.argValues={}}return e.prototype.add=function(e,t){return void 0===t?this:(this.argString&&(this.argString+="&"),this.argString+=e+"="+encodeURIComponent(t),this.argValues[e]=t,this)},e.prototype.body=function(e){return e?(this._body=e,this):this._body},e.prototype.attachApiKeys=function(e,t){return this.add(o.default.PARAMS.APP_ID,e).add(o.default.PARAMS.CLIENT,o.default.CLIENT).add(o.default.PARAMS.CLIENT_KEY,t)},e.prototype.build=function(){return this.argString},e.prototype.buildDict=function(){return this.argValues},e}();t.default=a},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0});var o={},a=function(){function e(){}return e.getFromLocalStorage=function(e){return!1===r?o[e]:localStorage[e]},e.saveToLocalStorage=function(e,t){if(!1!==r)try{localStorage[e]=t}catch(n){r=!1,o[e]=t}else o[e]=t},e.removeFromLocalStorage=function(e){if(!1!==r)try{localStorage.removeItem(e)}catch(t){r=!1,delete o[e]}else delete o[e]},e}();t.default=a},function(e,t,n){var r=n(36),o=n(37),a=n(38),i=n(39),s=n(40);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t=200&&f.status<300?setTimeout((function(){i&&i(t,f)}),0):setTimeout((function(){s&&s(t,f)}),0)),u&&(e.runningRequest=!1,e.dequeueRequest())}},f.open(t,n,!0),f.setRequestHeader("Content-Type","text/plain"),f.send(o),setTimeout((function(){l||f.abort()}),1e3*a)},e.ajaxIE8=function(t,n,r,o,i,s,u){var c=new XDomainRequest;c.onload=function(){var t,n=!1;if(u)t=c.responseText;else try{t=JSON.parse(c.responseText)}catch(e){setTimeout((function(){i&&i(null,c)}),0),n=!0}n||setTimeout((function(){o&&o(t,c)}),0),s&&(e.runningRequest=!1,e.dequeueRequest())},c.onerror=c.ontimeout=function(){setTimeout((function(){i&&i(null,c)}),0),s&&(e.runningRequest=!1,e.dequeueRequest())},c.onprogress=function(){},c.open(t,n),c.timeout=1e3*a,c.send(r)},e.enqueueRequest=function(e){o.push(e)},e.dequeueRequest=function(){var t=o.shift();t&&r.call(e.ajax,null,t)},e.runningRequest=!1,e}();t.default=i},function(e,t,n){var r=n(33);e.exports=function(e,t){return r(e,t)}},function(e,t){e.exports=function(e,t){return e===t||e!=e&&t!=t}},function(e,t,n){var r=n(7),o=n(19);e.exports=function(e){if(!o(e))return!1;var t=r(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},function(e,t,n){(function(t){var n="object"==typeof t&&t&&t.Object===Object&&t;e.exports=n}).call(this,n(47))},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t){var n=Function.prototype.toString;e.exports=function(e){if(null!=e){try{return n.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},function(e,t,n){var r=n(53),o=n(60),a=n(62),i=n(63),s=n(64);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++tl))return!1;var d=u.get(e);if(d&&u.get(t))return d==t;var p=-1,v=!0,h=2&n?new r:void 0;for(u.set(e,t),u.set(t,e);++p-1&&e%1==0&&e<=9007199254740991}},function(e,t,n){var r=n(28);e.exports=r.default},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=0&&this.startHandlers.splice(t,1)},e.prototype.triggerStartHandlers=function(){for(var e=0;e0){var t=JSON.stringify({data:e}),i=(new o.default).attachApiKeys(r.appId,r.clientKey).add(a.default.PARAMS.SDK_VERSION,a.default.SDK_VERSION).add(a.default.PARAMS.ACTION,a.default.METHODS.MULTI).add(a.default.PARAMS.TIME,((new Date).getTime()/1e3).toString().toString()).build();s.default.ajax("POST",r.apiPath+"?"+i,t,f,d,n.queued)}};if(!v&&this.batchCooldown){var S=(new Date).getTime()/1e3;!this.lastRequestTime||S-this.lastRequestTime>=this.batchCooldown?(v=!0,this.lastRequestTime=S):this.cooldownTimeout||(this.cooldownTimeout=setTimeout((function(){r.cooldownTimeout=null,r.lastRequestTime=(new Date).getTime()/1e3,h()}),1e3*(this.batchCooldown-(S-this.lastRequestTime))))}this.saveRequestForLater(l.buildDict()),v&&h()}},e.prototype.setNetworkTimeout=function(e){s.default.setNetworkTimeout(e)},e.prototype.getLastResponse=function(e){var t,n,r,o,a,i=null!=(r=null===(n=null===(t=e)||void 0===t?void 0:t.response)||void 0===n?void 0:n.length)?r:0;return i>0?null===(a=null===(o=e)||void 0===o?void 0:o.response)||void 0===a?void 0:a[i-1]:null},e.prototype.isResponseSuccess=function(e){var t;return Boolean(null===(t=e)||void 0===t?void 0:t.success)},e.prototype.saveRequestForLater=function(e){var t=this.loadLocal(a.default.DEFAULT_KEYS.COUNT)||0,n=a.default.DEFAULT_KEYS.ITEM+t;this.saveLocal(n,JSON.stringify(e)),t++,this.saveLocal(a.default.DEFAULT_KEYS.COUNT,t)},e.prototype.popUnsentRequests=function(){var e=[],t=this.loadLocal(a.default.DEFAULT_KEYS.COUNT)||0;this.removeLocal(a.default.DEFAULT_KEYS.COUNT);for(var n=0;n-1}},function(e,t,n){var r=n(6);e.exports=function(e,t){var n=this.__data__,o=r(n,e);return o<0?(++this.size,n.push([e,t])):n[o][1]=t,this}},function(e,t,n){var r=n(5);e.exports=function(){this.__data__=new r,this.size=0}},function(e,t){e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},function(e,t){e.exports=function(e){return this.__data__.get(e)}},function(e,t){e.exports=function(e){return this.__data__.has(e)}},function(e,t,n){var r=n(5),o=n(11),a=n(21);e.exports=function(e,t){var n=this.__data__;if(n instanceof r){var i=n.__data__;if(!o||i.length<199)return i.push([e,t]),this.size=++n.size,this;n=this.__data__=new a(i)}return n.set(e,t),this.size=n.size,this}},function(e,t,n){var r=n(17),o=n(50),a=n(19),i=n(20),s=/^\[object .+?Constructor\]$/,u=Function.prototype,c=Object.prototype,l=u.toString,f=c.hasOwnProperty,d=RegExp("^"+l.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=function(e){return!(!a(e)||o(e))&&(r(e)?d:s).test(i(e))}},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r=n(12),o=Object.prototype,a=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=a.call(e,s),n=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=n:delete e[s]),o}},function(e,t){var n=Object.prototype.toString;e.exports=function(e){return n.call(e)}},function(e,t,n){var r,o=n(51),a=(r=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";e.exports=function(e){return!!a&&a in e}},function(e,t,n){var r=n(0)["__core-js_shared__"];e.exports=r},function(e,t){e.exports=function(e,t){return null==e?void 0:e[t]}},function(e,t,n){var r=n(54),o=n(5),a=n(11);e.exports=function(){this.size=0,this.__data__={hash:new r,map:new(a||o),string:new r}}},function(e,t,n){var r=n(55),o=n(56),a=n(57),i=n(58),s=n(59);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e=u.length;)u.push(null);u[r]=e(u[r],o)})),u}var c={};return o((function(e){null!==n[e]&&void 0!==n[e]||(c[e]=t[e])})),a((function(r){c[r]=e(null===t?null:t[r]||{},n[r])})),c}(this.variables,e),this.saveDiffs(),this.onUpdate&&this.onUpdate()},e.prototype.loadDiffs=function(){try{this.applyDiffs(JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIABLES)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIANTS)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.ACTION_METADATA)||null)),this.token=this.loadLocal(a.default.DEFAULT_KEYS.TOKEN),this.variantDebugInfo=this.loadLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO)}catch(e){console.log("Leanplum: Invalid diffs: "+e)}},e.prototype.saveDiffs=function(){this.saveLocal(a.default.DEFAULT_KEYS.VARIABLES,JSON.stringify(this.diffs||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANTS,JSON.stringify(this.variants||[])),this.saveLocal(a.default.DEFAULT_KEYS.ACTION_METADATA,JSON.stringify(this.actionMetadata||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO,JSON.stringify(this.variantDebugInfo||{})),this.saveLocal(a.default.DEFAULT_KEYS.TOKEN,this.token)},e.prototype.getVariables=function(){return void 0!==this.merged?this.merged:this.variables},e.prototype.setVariables=function(e){this.variables=e},e.prototype.addVariablesChangedHandler=function(e){this.variablesChangedHandlers.push(e),this.hasReceivedDiffs&&e()},e.prototype.removeVariablesChangedHandler=function(e){var t=this.variablesChangedHandlers.indexOf(e);t>=0&&this.variablesChangedHandlers.splice(t,1)},e.prototype.triggerVariablesChangedHandlers=function(){for(var e=0;e=200&&f.status<300?setTimeout((function(){i&&i(t,f)}),0):setTimeout((function(){s&&s(t,f)}),0)),u&&(e.runningRequest=!1,e.dequeueRequest())}},f.open(t,n,!0),f.setRequestHeader("Content-Type","text/plain"),f.send(o),setTimeout((function(){l||f.abort()}),1e3*a)},e.ajaxIE8=function(t,n,r,o,i,s,u){var c=new XDomainRequest;c.onload=function(){var t,n=!1;if(u)t=c.responseText;else try{t=JSON.parse(c.responseText)}catch(e){setTimeout((function(){i&&i(null,c)}),0),n=!0}n||setTimeout((function(){o&&o(t,c)}),0),s&&(e.runningRequest=!1,e.dequeueRequest())},c.onerror=c.ontimeout=function(){setTimeout((function(){i&&i(null,c)}),0),s&&(e.runningRequest=!1,e.dequeueRequest())},c.onprogress=function(){},c.open(t,n),c.timeout=1e3*a,c.send(r)},e.enqueueRequest=function(e){o.push(e)},e.dequeueRequest=function(){var t=o.shift();t&&r.call(e.ajax,null,t)},e.runningRequest=!1,e}();t.default=i},function(e,t,n){var r=n(33);e.exports=function(e,t){return r(e,t)}},function(e,t){e.exports=function(e,t){return e===t||e!=e&&t!=t}},function(e,t,n){var r=n(7),o=n(19);e.exports=function(e){if(!o(e))return!1;var t=r(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},function(e,t,n){(function(t){var n="object"==typeof t&&t&&t.Object===Object&&t;e.exports=n}).call(this,n(47))},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t){var n=Function.prototype.toString;e.exports=function(e){if(null!=e){try{return n.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},function(e,t,n){var r=n(53),o=n(60),a=n(62),i=n(63),s=n(64);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++tl))return!1;var d=u.get(e);if(d&&u.get(t))return d==t;var p=-1,h=!0,v=2&n?new r:void 0;for(u.set(e,t),u.set(t,e);++p-1&&e%1==0&&e<=9007199254740991}},function(e,t,n){var r=n(28);e.exports=r.default},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=0&&this.startHandlers.splice(t,1)},e.prototype.triggerStartHandlers=function(){for(var e=0;e0){var t=JSON.stringify({data:e}),i=(new o.default).attachApiKeys(r.appId,r.clientKey).add(a.default.PARAMS.SDK_VERSION,a.default.SDK_VERSION).add(a.default.PARAMS.ACTION,a.default.METHODS.MULTI).add(a.default.PARAMS.TIME,((new Date).getTime()/1e3).toString().toString()).build();s.default.ajax("POST",r.apiPath+"?"+i,t,f,d,n.queued)}};if(!h&&this.batchCooldown){var S=(new Date).getTime()/1e3;!this.lastRequestTime||S-this.lastRequestTime>=this.batchCooldown?(h=!0,this.lastRequestTime=S):this.cooldownTimeout||(this.cooldownTimeout=setTimeout((function(){r.cooldownTimeout=null,r.lastRequestTime=(new Date).getTime()/1e3,v()}),1e3*(this.batchCooldown-(S-this.lastRequestTime))))}this.saveRequestForLater(l.buildDict()),h&&v()}},e.prototype.setNetworkTimeout=function(e){s.default.setNetworkTimeout(e)},e.prototype.getLastResponse=function(e){var t,n,r,o,a,i=null!=(r=null===(n=null===(t=e)||void 0===t?void 0:t.response)||void 0===n?void 0:n.length)?r:0;return i>0?null===(a=null===(o=e)||void 0===o?void 0:o.response)||void 0===a?void 0:a[i-1]:null},e.prototype.isResponseSuccess=function(e){var t;return Boolean(null===(t=e)||void 0===t?void 0:t.success)},e.prototype.saveRequestForLater=function(e){var t=this.loadLocal(a.default.DEFAULT_KEYS.COUNT)||0,n=a.default.DEFAULT_KEYS.ITEM+t;this.saveLocal(n,JSON.stringify(e)),t++,this.saveLocal(a.default.DEFAULT_KEYS.COUNT,t)},e.prototype.popUnsentRequests=function(){var e=[],t=this.loadLocal(a.default.DEFAULT_KEYS.COUNT)||0;this.removeLocal(a.default.DEFAULT_KEYS.COUNT);for(var n=0;n-1}},function(e,t,n){var r=n(6);e.exports=function(e,t){var n=this.__data__,o=r(n,e);return o<0?(++this.size,n.push([e,t])):n[o][1]=t,this}},function(e,t,n){var r=n(5);e.exports=function(){this.__data__=new r,this.size=0}},function(e,t){e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},function(e,t){e.exports=function(e){return this.__data__.get(e)}},function(e,t){e.exports=function(e){return this.__data__.has(e)}},function(e,t,n){var r=n(5),o=n(11),a=n(21);e.exports=function(e,t){var n=this.__data__;if(n instanceof r){var i=n.__data__;if(!o||i.length<199)return i.push([e,t]),this.size=++n.size,this;n=this.__data__=new a(i)}return n.set(e,t),this.size=n.size,this}},function(e,t,n){var r=n(17),o=n(50),a=n(19),i=n(20),s=/^\[object .+?Constructor\]$/,u=Function.prototype,c=Object.prototype,l=u.toString,f=c.hasOwnProperty,d=RegExp("^"+l.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=function(e){return!(!a(e)||o(e))&&(r(e)?d:s).test(i(e))}},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r=n(12),o=Object.prototype,a=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=a.call(e,s),n=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=n:delete e[s]),o}},function(e,t){var n=Object.prototype.toString;e.exports=function(e){return n.call(e)}},function(e,t,n){var r,o=n(51),a=(r=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";e.exports=function(e){return!!a&&a in e}},function(e,t,n){var r=n(0)["__core-js_shared__"];e.exports=r},function(e,t){e.exports=function(e,t){return null==e?void 0:e[t]}},function(e,t,n){var r=n(54),o=n(5),a=n(11);e.exports=function(){this.size=0,this.__data__={hash:new r,map:new(a||o),string:new r}}},function(e,t,n){var r=n(55),o=n(56),a=n(57),i=n(58),s=n(59);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]=u.length;)u.push(null);u[r]=e(u[r],o)})),u}var c={};return o((function(e){null!==n[e]&&void 0!==n[e]||(c[e]=t[e])})),a((function(r){c[r]=e(null===t?null:t[r]||{},n[r])})),c}(this.variables,e),this.saveDiffs(),this.onUpdate&&this.onUpdate()},e.prototype.loadDiffs=function(){try{this.applyDiffs(JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIABLES)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIANTS)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.ACTION_METADATA)||null)),this.token=this.loadLocal(a.default.DEFAULT_KEYS.TOKEN),this.variantDebugInfo=this.loadLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO)}catch(e){console.log("Leanplum: Invalid diffs: "+e)}},e.prototype.saveDiffs=function(){this.saveLocal(a.default.DEFAULT_KEYS.VARIABLES,JSON.stringify(this.diffs||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANTS,JSON.stringify(this.variants||[])),this.saveLocal(a.default.DEFAULT_KEYS.ACTION_METADATA,JSON.stringify(this.actionMetadata||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO,JSON.stringify(this.variantDebugInfo||{})),this.saveLocal(a.default.DEFAULT_KEYS.TOKEN,this.token)},e.prototype.getVariables=function(){return void 0!==this.merged?this.merged:this.variables},e.prototype.setVariables=function(e){this.variables=e},e.prototype.addVariablesChangedHandler=function(e){this.variablesChangedHandlers.push(e),this.hasReceivedDiffs&&e()},e.prototype.removeVariablesChangedHandler=function(e){var t=this.variablesChangedHandlers.indexOf(e);t>=0&&this.variablesChangedHandlers.splice(t,1)},e.prototype.triggerVariablesChangedHandlers=function(){for(var e=0;e=this.batchCooldown?(f=!0,this.lastRequestTime=p):this.cooldownTimeout||(this.cooldownTimeout=setTimeout(function(){o.cooldownTimeout=null,o.lastRequestTime=(new Date).getTime()/1e3,d()},1e3*(this.batchCooldown-(p-this.lastRequestTime))))}this.saveRequestForLater(s.buildDict()),f&&d()}},i.prototype.setNetworkTimeout=function(e){S.default.setNetworkTimeout(e)},i.prototype.getLastResponse=function(e){var t,n,r,o=null!=(n=null===(t=null==e?void 0:e.response)||void 0===t?void 0:t.length)?n:0;return 0=u.length;)u.push(null);u[t]=r(u[t],n)}),u}var c={};return n(function(e){null!==o[e]&&void 0!==o[e]||(c[e]=t[e])}),a(function(e){c[e]=r(null===t?null:t[e]||{},o[e])}),c}(this.variables,e),this.saveDiffs(),this.onUpdate&&this.onUpdate()},u.prototype.loadDiffs=function(){try{this.applyDiffs(JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIABLES)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIANTS)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.ACTION_METADATA)||null)),this.token=this.loadLocal(a.default.DEFAULT_KEYS.TOKEN),this.variantDebugInfo=this.loadLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO)}catch(e){console.log("Leanplum: Invalid diffs: "+e)}},u.prototype.saveDiffs=function(){this.saveLocal(a.default.DEFAULT_KEYS.VARIABLES,JSON.stringify(this.diffs||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANTS,JSON.stringify(this.variants||[])),this.saveLocal(a.default.DEFAULT_KEYS.ACTION_METADATA,JSON.stringify(this.actionMetadata||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO,JSON.stringify(this.variantDebugInfo||{})),this.saveLocal(a.default.DEFAULT_KEYS.TOKEN,this.token)},u.prototype.getVariables=function(){return void 0!==this.merged?this.merged:this.variables},u.prototype.setVariables=function(e){this.variables=e},u.prototype.addVariablesChangedHandler=function(e){this.variablesChangedHandlers.push(e),this.hasReceivedDiffs&&e()},u.prototype.removeVariablesChangedHandler=function(e){var t=this.variablesChangedHandlers.indexOf(e);0<=t&&this.variablesChangedHandlers.splice(t,1)},u.prototype.triggerVariablesChangedHandlers=function(){for(var e=0;e=this.batchCooldown?(f=!0,this.lastRequestTime=p):this.cooldownTimeout||(this.cooldownTimeout=setTimeout(function(){o.cooldownTimeout=null,o.lastRequestTime=(new Date).getTime()/1e3,d()},1e3*(this.batchCooldown-(p-this.lastRequestTime))))}this.saveRequestForLater(s.buildDict()),f&&d()}},i.prototype.setNetworkTimeout=function(e){S.default.setNetworkTimeout(e)},i.prototype.getLastResponse=function(e){var t,n,r,o=null!=(n=null===(t=null==e?void 0:e.response)||void 0===t?void 0:t.length)?n:0;return 0i[0]&&t[1]=u.length;)u.push(null);u[t]=r(u[t],n)}),u}var c={};return n(function(e){null!==o[e]&&void 0!==o[e]||(c[e]=t[e])}),a(function(e){c[e]=r(null===t?null:t[e]||{},o[e])}),c}(this.variables,e),this.saveDiffs(),this.onUpdate&&this.onUpdate()},u.prototype.loadDiffs=function(){try{this.applyDiffs(JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIABLES)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIANTS)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.ACTION_METADATA)||null)),this.token=this.loadLocal(a.default.DEFAULT_KEYS.TOKEN),this.variantDebugInfo=this.loadLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO)}catch(e){console.log("Leanplum: Invalid diffs: "+e)}},u.prototype.saveDiffs=function(){this.saveLocal(a.default.DEFAULT_KEYS.VARIABLES,JSON.stringify(this.diffs||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANTS,JSON.stringify(this.variants||[])),this.saveLocal(a.default.DEFAULT_KEYS.ACTION_METADATA,JSON.stringify(this.actionMetadata||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO,JSON.stringify(this.variantDebugInfo||{})),this.saveLocal(a.default.DEFAULT_KEYS.TOKEN,this.token)},u.prototype.getVariables=function(){return void 0!==this.merged?this.merged:this.variables},u.prototype.setVariables=function(e){this.variables=e},u.prototype.addVariablesChangedHandler=function(e){this.variablesChangedHandlers.push(e),this.hasReceivedDiffs&&e()},u.prototype.removeVariablesChangedHandler=function(e){var t=this.variablesChangedHandlers.indexOf(e);0<=t&&this.variablesChangedHandlers.splice(t,1)},u.prototype.triggerVariablesChangedHandlers=function(){for(var e=0;e { - return new Promise((resolve, reject) => { if (Leanplum._pushManager.isWebPushSupported()) { - return Leanplum._pushManager.register(serviceWorkerUrl, (isSubscribed) => { - if (isSubscribed) { - return resolve(true) - } - return Leanplum._pushManager.subscribeUser() - }) - } else { - return reject('Leanplum: WebPush is not supported.') - } - }) + return Leanplum._pushManager.register(serviceWorkerUrl, (isSubscribed) => { + if (isSubscribed) { + return Promise.resolve(true) + } + return Leanplum._pushManager.subscribeUser() + }) + } else { + return Promise.reject('Leanplum: WebPush is not supported.') + } } /** * Unregisters the browser form web push. * @return {Promise} Resolves on success, otherwise rejects. */ - static unregisterFromWebPush(): Promise { + static unregisterFromWebPush(): Promise { return Leanplum._pushManager.unsubscribeUser() } diff --git a/src/PushManager.ts b/src/PushManager.ts index 188593bd..5a6df4b0 100644 --- a/src/PushManager.ts +++ b/src/PushManager.ts @@ -1,10 +1,9 @@ /* - * * Copyright 2020 Leanplum Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * You may obtain a copy of the License at: * * https://www.apache.org/licenses/LICENSE-2.0 * @@ -12,7 +11,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. * */ @@ -22,16 +21,18 @@ import Constants from './Constants' import LocalStorageManager from './LocalStorageManager' const APPLICATION_SERVER_PUBLIC_KEY = - 'BInWPpWntfR39rgXSP04pqdmEdDGa50z6zqbMvxyxJCwzXIuSpSh8C888-CfJ82WELl7Xe8cjA' + - 'nfCt-3vK0Ci68' - -let isSubscribed = false -let serviceWorkerRegistration = null + 'BInWPpWntfR39rgXSP04pqdmEdDGa50z6zqbMvxyxJCwzXIuSpSh8C888-CfJ82WELl7Xe8cjAnfCt-3vK0Ci68' /** * Push Manager handles the registration and subscription for web push. */ export default class PushManager { + private serviceWorkerRegistration: ServiceWorkerRegistration | null = null + + private get serviceWorker(): ServiceWorkerContainer { + return window.navigator.serviceWorker; + } + public constructor( private createRequest: (action: string, args: ArgsBuilder, options: any) => void ) { } @@ -41,169 +42,139 @@ export default class PushManager { * @return {Boolean} True if supported, else false. */ public isWebPushSupported(): boolean { - return navigator && navigator.serviceWorker && 'serviceWorker' in navigator && - 'PushManager' in window + return Boolean( + window?.navigator !== undefined && + 'serviceWorker' in window.navigator && + 'PushManager' in window + ) } /** * Whether or not the browser is subscribed to web push notifications. * @return {Promise} True if subscribed, else false. */ - public isWebPushSubscribed(): Promise { - if (!this.isWebPushSupported()) { - return new Promise((resolve) => { - resolve(false) - }) + public async isWebPushSubscribed(): Promise { + if (this.isWebPushSupported()) { + const registration = await this.getServiceWorkerRegistration() + + if (registration) { + const subscription = await registration.pushManager.getSubscription() + const isSubscribed = subscription !== null + + if (isSubscribed) { + this.updateNewSubscriptionOnServer(subscription) + } + + return isSubscribed + } } - return this.getServiceWorkerRegistration() - .then((registration) => { - return new Promise((resolve) => { - if (!registration) { - resolve(false) - } else { - /** @namespace registration.pushManager The push manager object of the browser. **/ - /** @namespace registration.pushManager.getSubscription **/ - registration.pushManager.getSubscription() - .then((subscription) => { - isSubscribed = subscription !== null - if (isSubscribed) { - this.updateNewSubscriptionOnServer(subscription) - } - resolve(isSubscribed) - }) - } - }) - }) + + return false } /** * Register for WebPush. - * @param {String} serviceWorkerUrl The url that serves the service worker - * on your domain. + * @param {String} serviceWorkerUrl The url that serves the service worker on your domain. * @param {Function} callback The callback to be called with result. * @return {object} nothing */ - public register(serviceWorkerUrl, callback): void { + public async register( + serviceWorkerUrl: string, + callback: (isSubscribed: boolean) => Promise + ): Promise { if (!this.isWebPushSupported()) { console.log('Leanplum: Push messaging is not supported.') return callback(false) } - navigator.serviceWorker.register( - serviceWorkerUrl ? serviceWorkerUrl : '/sw.min.js', null) - .then((registration) => { - serviceWorkerRegistration = registration - - // Set the initial subscription value - serviceWorkerRegistration.pushManager.getSubscription() - .then((subscription) => { - isSubscribed = !(subscription === null) - if (isSubscribed) { - this.updateNewSubscriptionOnServer(subscription) - } - if (callback) { - return callback(isSubscribed) - } - }) - }) - .catch((error) => { - console.log('Leanplum: Service Worker Error: ', error) - }) + + try { + this.serviceWorkerRegistration = await this.serviceWorker.register( + serviceWorkerUrl || '/sw.min.js', + null + ) + + const subscription = this.serviceWorkerRegistration.pushManager.getSubscription() + const isSubscribed = subscription !== null + + if (isSubscribed) { + this.updateNewSubscriptionOnServer(subscription) + } + + return callback(isSubscribed) + } catch (error) { + console.log('Leanplum: Service Worker Error: ', error) + return callback(false) + } } /** * Subscribe the user(browser) to push. * @return {Promise} Resolves if subscription successful, otherwise rejects. */ - public subscribeUser(): Promise { + public async subscribeUser(): Promise { const applicationServerKey = this.urlB64ToUint8Array(APPLICATION_SERVER_PUBLIC_KEY) - return new Promise((resolve, reject) => { - /** @namespace serviceWorkerRegistration.pushManager.subscribe Subscribe to push. **/ - return serviceWorkerRegistration.pushManager.subscribe({ + + try { + const subscription = await this.serviceWorkerRegistration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey }) - .then((subscription) => { - if (subscription) { - this.updateNewSubscriptionOnServer(subscription) - isSubscribed = true - return resolve(isSubscribed) - } - isSubscribed = false - return reject() - }) - .catch((err) => { - return reject(`Leanplum: Failed to subscribe the user: ${err}`) - }) - }) + + if (!subscription) { + throw new Error() + } + + this.updateNewSubscriptionOnServer(subscription) + } catch (error) { + throw new Error(`Leanplum: Failed to subscribe the user: ${error}`) + } + + return true } /** * Unsubscribe the user(browser) from push. * @return {Promise} Resolves if unsubscribed, otherwise rejects. */ - public unsubscribeUser(): Promise { - return new Promise((resolve, reject) => { - this.isWebPushSubscribed().then((subscribed) => { - if (!subscribed) { - return resolve() + public async unsubscribeUser(): Promise { + let subscribed = await this.isWebPushSubscribed() + + if (subscribed) { + try { + const subscription = await this.serviceWorkerRegistration.pushManager.getSubscription() + + if (!subscription) { + throw new Error() } - serviceWorkerRegistration.pushManager.getSubscription() - .then((subscription) => { - if (subscription) { - /** @namespace serviceWorkerRegistration.pushManager.unsubscribe Unsubscribe to - * push. **/ - return subscription.unsubscribe() - } - return reject() - }) - .catch((error) => { - reject(`Leanplum: Error unsubscribing: ${error}`) - }) - .then((success) => { - if (success) { - isSubscribed = false - return resolve() - } - return reject() - }) - }, () => { - return reject() - }) - }) + await subscription.unsubscribe() + } catch (error) { + throw new Error(`Leanplum: Error unsubscribing: ${error}`) + } + } } /** * Retrieves the service worker registration object from browser. * @return {object} Returns the registration or null. */ - private getServiceWorkerRegistration(): Promise { - return new Promise((resolve) => { - if (serviceWorkerRegistration) { - resolve(serviceWorkerRegistration) - } else { - /** @namespace navigator.serviceWorker.getRegistration Retrieves the push registration - * from the browser. **/ - navigator.serviceWorker.getRegistration().then((registration) => { - serviceWorkerRegistration = registration - resolve(registration) - }) - } - }) + private async getServiceWorkerRegistration(): Promise { + if (!this.serviceWorkerRegistration) { + this.serviceWorkerRegistration = await this.serviceWorker.getRegistration() + } + + return this.serviceWorkerRegistration } /** * Encodes a base64 url string to an uint8 arrary. - * @param {string} base64String [description] - * @return {Uint8Array} [description] + * @param {string} base64String + * @return {Uint8Array} */ private urlB64ToUint8Array(base64String) { const padding = '='.repeat((4 - base64String.length % 4) % 4) - const base64 = (base64String + padding) - .replace(/-/g, '+') - .replace(/_/g, '/') - - const rawData = window.atob(base64) + const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/') + const rawData = this.decodeData(base64) const outputArray = new Uint8Array(rawData.length) for (let i = 0; i < rawData.length; ++i) { @@ -224,10 +195,8 @@ export default class PushManager { let apply = Function.prototype.apply let key = subscription.getKey ? subscription.getKey('p256dh') : '' let auth = subscription.getKey ? subscription.getKey('auth') : '' - // noinspection ES6ModulesDependencies - let keyAscii = btoa(apply.call(String.fromCharCode, null, new Uint8Array(key))) - // noinspection ES6ModulesDependencies - let authAscii = btoa(apply.call(String.fromCharCode, null, new Uint8Array(auth))) + let keyAscii = this.encodeData(apply.call(String.fromCharCode, null, new Uint8Array(key))) + let authAscii = this.encodeData(apply.call(String.fromCharCode, null, new Uint8Array(auth))) return { endpoint: subscription.endpoint, @@ -245,7 +214,8 @@ export default class PushManager { let preparedSubscription = this.prepareSubscription(subscription) let preparedSubscriptionString = JSON.stringify(preparedSubscription) let existingSubscriptionString = LocalStorageManager.getFromLocalStorage( - Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) + Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION + ) if (!isEqual(existingSubscriptionString, preparedSubscriptionString)) { LocalStorageManager.saveToLocalStorage( @@ -262,15 +232,21 @@ export default class PushManager { * @param {String/Object} subscription The subscription string. */ private setSubscription(subscription) { - if (!subscription) { - return + if (subscription) { + const args = new ArgsBuilder().add(Constants.PARAMS.WEB_PUSH_SUBSCRIPTION, subscription) + + this.createRequest(Constants.METHODS.SET_DEVICE_ATTRIBUTES, args, { + queued: false, + sendNow: true + }) } + } - const args = new ArgsBuilder().add(Constants.PARAMS.WEB_PUSH_SUBSCRIPTION, subscription) + private encodeData(data: string): string { + return window.btoa(data) + } - this.createRequest(Constants.METHODS.SET_DEVICE_ATTRIBUTES, args, { - queued: false, - sendNow: true - }) + private decodeData(data: string): string { + return window.atob(data) } } From cae5efb2eafc2ed9554af071aab3daa58341ba15 Mon Sep 17 00:00:00 2001 From: Ignat Ignatov Date: Thu, 12 Mar 2020 16:38:32 +0200 Subject: [PATCH 2/7] chore: extract common `CreateRequestFunction` --- src/LeanplumSocket.ts | 4 ++-- src/PushManager.ts | 3 ++- src/VarCache.ts | 3 ++- src/types.ts | 3 +++ 4 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 src/types.ts diff --git a/src/LeanplumSocket.ts b/src/LeanplumSocket.ts index 6f151b22..1ff917d6 100644 --- a/src/LeanplumSocket.ts +++ b/src/LeanplumSocket.ts @@ -19,8 +19,8 @@ import isEqual from 'lodash/isEqual' import ArgsBuilder from './ArgsBuilder' import Constants from './Constants' -import LeanplumRequest from './LeanplumRequest' import SocketIoClient from './SocketIoClient' +import { CreateRequestFunction } from './types' import VarCache from './VarCache' export default class LeanplumSocket { @@ -29,7 +29,7 @@ export default class LeanplumSocket { public connect( cache: VarCache, auth: { appId: string, deviceId: string }, - createRequest: (action: string, args: ArgsBuilder, options: any) => void, + createRequest: CreateRequestFunction, getLastResponse: (response: any) => any ): void { if (!WebSocket) { diff --git a/src/PushManager.ts b/src/PushManager.ts index 5a6df4b0..37a3e3f7 100644 --- a/src/PushManager.ts +++ b/src/PushManager.ts @@ -19,6 +19,7 @@ import isEqual from 'lodash/isEqual' import ArgsBuilder from './ArgsBuilder' import Constants from './Constants' import LocalStorageManager from './LocalStorageManager' +import { CreateRequestFunction } from './types' const APPLICATION_SERVER_PUBLIC_KEY = 'BInWPpWntfR39rgXSP04pqdmEdDGa50z6zqbMvxyxJCwzXIuSpSh8C888-CfJ82WELl7Xe8cjAnfCt-3vK0Ci68' @@ -34,7 +35,7 @@ export default class PushManager { } public constructor( - private createRequest: (action: string, args: ArgsBuilder, options: any) => void + private createRequest: CreateRequestFunction ) { } /** diff --git a/src/VarCache.ts b/src/VarCache.ts index bbd05a91..9976689f 100644 --- a/src/VarCache.ts +++ b/src/VarCache.ts @@ -18,6 +18,7 @@ import ArgsBuilder from './ArgsBuilder' import Constants from './Constants' import LocalStorageManager from './LocalStorageManager' +import { CreateRequestFunction } from './types' export default class VarCache { private actionMetadata: Object = {} @@ -33,7 +34,7 @@ export default class VarCache { public variants = [] public constructor( - private createRequest: (action: string, args: ArgsBuilder, options: any) => void + private createRequest: CreateRequestFunction ) {} public applyDiffs(diffs, variants, actionMetadata) { diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..90d1b967 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,3 @@ +import ArgsBuilder from "./ArgsBuilder"; + +export type CreateRequestFunction = (action: string, args: ArgsBuilder, options: any) => void From a483b062da8b264de09afc0ad587cc4bc9e9f9ab Mon Sep 17 00:00:00 2001 From: Ignat Ignatov Date: Mon, 30 Mar 2020 18:47:38 +0300 Subject: [PATCH 3/7] tests: add `PushManager` tests --- test/specs/Leanplum.test.ts | 4 +- test/specs/PushManager.test.ts | 566 +++++++++++++++++++++++++++++++++ 2 files changed, 568 insertions(+), 2 deletions(-) create mode 100644 test/specs/PushManager.test.ts diff --git a/test/specs/Leanplum.test.ts b/test/specs/Leanplum.test.ts index bb98764c..cd85a7e1 100644 --- a/test/specs/Leanplum.test.ts +++ b/test/specs/Leanplum.test.ts @@ -68,7 +68,7 @@ const testModes = { DEV: 1 } -let Leanplum; +let Leanplum const start = (done) => { interceptRequest((request) => { @@ -334,7 +334,7 @@ Object.keys(testModes).forEach((mode) => { }) }) - describe('Web push.', () => { + describe('Web push', () => { it('test isWebPushSupported', (done) => { expect(!Leanplum.isWebPushSupported()).toBeTruthy() done() diff --git a/test/specs/PushManager.test.ts b/test/specs/PushManager.test.ts new file mode 100644 index 00000000..c8123067 --- /dev/null +++ b/test/specs/PushManager.test.ts @@ -0,0 +1,566 @@ +import Constants from '../../src/Constants' +import LocalStorageManager from '../../src/LocalStorageManager' +import PushManager from '../../src/PushManager' + +describe(PushManager, () => { + let pushManager: PushManager + const createRequestSpy: jest.Mock<() => void> = jest.fn() + + beforeEach(() => { + pushManager = new PushManager(createRequestSpy) + }) + + afterEach(() => { + createRequestSpy.mockClear() + }) + + describe('isWebPushSupported', () => { + let windowMock: jest.SpyInstance + + beforeAll(() => { + windowMock = jest.spyOn(globalThis, 'window', 'get') + }) + + afterAll(() => { + windowMock.mockReset() + }) + + it('returns `false` when navigator is undefined', () => { + windowMock.mockReturnValue({ PushManager: {} } as any) + + expect(pushManager.isWebPushSupported()).toBeFalsy() + }) + + it('returns `false` when serviceWorker is undefined', () => { + windowMock.mockReturnValue({ navigator: {}, PushManager: {} } as any) + + expect(pushManager.isWebPushSupported()).toBeFalsy() + }) + + it('returns `false` when PushManager is undefined', () => { + windowMock.mockReturnValue({ navigator: { serviceWorker: {} } } as any) + + expect(pushManager.isWebPushSupported()).toBeFalsy() + }) + + it('returns `true` when supported', () => { + windowMock.mockReturnValue({ + navigator: { + serviceWorker: {} + }, + PushManager: {} + } as any) + + expect(pushManager.isWebPushSupported()).toBeTruthy() + }) + }) + + describe('isWebPushSubscribed', () => { + let windowMock: jest.SpyInstance + + beforeAll(() => { + windowMock = jest.spyOn(globalThis, 'window', 'get') + }) + + afterAll(() => { + windowMock.mockReset() + }) + + it('returns `false` when Web Push is not supported', async () => { + windowMock.mockReturnValue({} as any) + + expect(await pushManager.isWebPushSubscribed()).toBeFalsy() + }) + + it('returns `false` with no registration', async () => { + windowMock.mockReturnValue({ + navigator: { + serviceWorker: { + getRegistration: () => null + } + }, + PushManager: {} + } as any) + + expect(await pushManager.isWebPushSubscribed()).toBeFalsy() + }) + + it('returns `false` with no subscription', async () => { + windowMock.mockReturnValue({ + navigator: { + serviceWorker: { + getRegistration: () => ({ + pushManager: { + getSubscription: () => null + } + }) + } + }, + PushManager: {} + } as any) + + expect(await pushManager.isWebPushSubscribed()).toBeFalsy() + }) + + it('returns `true` when there is subscription', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + getRegistration: () => ({ + pushManager: { + getSubscription: () => ({ + endpoint: 'test' + }) + } + }) + } + }, + PushManager: {} + } as any) + + expect(await pushManager.isWebPushSubscribed()).toBeTruthy() + expect(createRequestSpy).toHaveBeenCalledTimes(1) + }) + + it('updates subscription on server with new subscription', async () => { + let subscription: any = null + const registration = { + pushManager: { + getSubscription: () => subscription, + subscribe: () => subscription + } + } + + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + getRegistration: () => registration, + register: () => registration + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + subscription = { + endpoint: 'old_subscription' + } + + await pushManager.subscribeUser() + + subscription = { + endpoint: 'new_subscription' + } + + await pushManager.isWebPushSubscribed() + + expect(createRequestSpy).toHaveBeenCalledTimes(2) + }) + }) + + describe('register', () => { + let windowMock: jest.SpyInstance + const callback = jest.fn() + + beforeAll(() => { + windowMock = jest.spyOn(globalThis, 'window', 'get') + }) + + afterAll(() => { + windowMock.mockReset() + }) + + afterEach(() => { + LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) + callback.mockClear() + }) + + it('calls callback with `false` when Web Push is not supported', async () => { + windowMock.mockReturnValue({} as any) + + jest.spyOn(console, 'log').mockImplementationOnce(() => {}) + await pushManager.register('', callback) + + expect(callback).toHaveBeenCalledTimes(1) + expect(callback).toHaveBeenCalledWith(false) + }) + + it('calls callback with `false` when there is an error', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: null // cause an exception + }) + } + }, + PushManager: {} + } as any) + + jest.spyOn(console, 'log').mockImplementationOnce(() => {}) + await pushManager.register('', callback) + + expect(callback).toHaveBeenCalledTimes(1) + expect(callback).toHaveBeenCalledWith(false) + }) + + it('calls callback with `false` when not subscribed', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => null + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', callback) + + expect(callback).toHaveBeenCalledTimes(1) + expect(callback).toHaveBeenCalledWith(false) + }) + + it('calls callback with `true` when subscribed', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => ({ + endpoint: 'test' + }) + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', callback) + + expect(callback).toHaveBeenCalledTimes(1) + expect(callback).toHaveBeenCalledWith(true) + }) + + it('uses default SW URL when empty provided', async () => { + const register = jest.fn().mockReturnValue({ + pushManager: { + getSubscription: () => null + } + }) + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register + } + }, + PushManager: {} + } as any) + + await pushManager.register('', callback) + + expect(register).toHaveBeenCalledTimes(1) + expect(register).toHaveBeenCalledWith('/sw.min.js', null) + }) + + it('does not update subscription on server when not subscribed', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => null + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + expect(createRequestSpy).toHaveBeenCalledTimes(0) + }) + + it('updates subscription on server when subscribed', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => ({ + endpoint: 'test' + }) + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + expect(createRequestSpy).toHaveBeenCalledTimes(1) + }) + }) + + describe('subscribeUser', () => { + let windowMock: jest.SpyInstance + + beforeAll(() => { + windowMock = jest.spyOn(globalThis, 'window', 'get') + }) + + afterAll(() => { + windowMock.mockReset() + }) + + afterEach(() => { + LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) + }) + + it('throws error when error occurs', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: undefined // cause an exception + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + await expect(pushManager.subscribeUser()).rejects.toThrowError() + }) + + it('throws error when not subscribed', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: () => null + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + await expect(pushManager.subscribeUser()).rejects.toThrowError() + }) + + it('returns `true` on success', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: () => ({ + endpoint: 'test' + }) + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + expect(await pushManager.subscribeUser()).toBe(true) + }) + + it('does not update subscription on server when not subscribed', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: () => null + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + await pushManager.subscribeUser().catch(() => { /* noop - expected */ }) + + expect(createRequestSpy).toHaveBeenCalledTimes(0) + }) + + it('updates subscription on server when subscribed', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: () => ({ + endpoint: 'test' + }) + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + await pushManager.subscribeUser() + + expect(createRequestSpy).toHaveBeenCalledTimes(1) + }) + }) + + describe('unsubscribeUser', () => { + let windowMock: jest.SpyInstance + + beforeAll(() => { + windowMock = jest.spyOn(globalThis, 'window', 'get') + }) + + afterAll(() => { + windowMock.mockReset() + }) + + afterEach(() => { + LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) + }) + + it('throws error when error occurs', async () => { + let subscriptionValues: any[] = [null, { endpoint: 'test' }, {}] + + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => subscriptionValues.shift() + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + await expect(pushManager.unsubscribeUser()).rejects.toThrowError() + }) + + it('throws error when no subscription', async () => { + let subscriptionValues: any[] = [null, { endpoint: 'test' }, null] + + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => subscriptionValues.shift() + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + await expect(pushManager.unsubscribeUser()).rejects.toThrowError() + }) + + it('resolves when not subscribed', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => null + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + await expect(pushManager.unsubscribeUser()).resolves.not.toThrowError() + }) + + it('resolves when unsubscribe was successful', async () => { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker: { + register: () => ({ + pushManager: { + getSubscription: () => ({ + endpoint: 'test', + unsubscribe: () => Promise.resolve(true) + }) + } + }) + } + }, + PushManager: {} + } as any) + + await pushManager.register('', (x) => Promise.resolve(x)) + + await expect(pushManager.unsubscribeUser()).resolves.not.toThrowError() + }) + }) +}) From 8ae57270ef6df0ce78463bd59f891270292d5a15 Mon Sep 17 00:00:00 2001 From: Alex Gyoshev Date: Tue, 31 Mar 2020 15:45:07 +0300 Subject: [PATCH 4/7] refactor: extract test mock function --- test/specs/PushManager.test.ts | 431 ++++++++++----------------------- 1 file changed, 130 insertions(+), 301 deletions(-) diff --git a/test/specs/PushManager.test.ts b/test/specs/PushManager.test.ts index c8123067..c2feeca4 100644 --- a/test/specs/PushManager.test.ts +++ b/test/specs/PushManager.test.ts @@ -4,27 +4,20 @@ import PushManager from '../../src/PushManager' describe(PushManager, () => { let pushManager: PushManager + let windowMock: jest.SpyInstance const createRequestSpy: jest.Mock<() => void> = jest.fn() beforeEach(() => { pushManager = new PushManager(createRequestSpy) + windowMock = jest.spyOn(globalThis, 'window', 'get') }) afterEach(() => { createRequestSpy.mockClear() + windowMock.mockReset() }) describe('isWebPushSupported', () => { - let windowMock: jest.SpyInstance - - beforeAll(() => { - windowMock = jest.spyOn(globalThis, 'window', 'get') - }) - - afterAll(() => { - windowMock.mockReset() - }) - it('returns `false` when navigator is undefined', () => { windowMock.mockReturnValue({ PushManager: {} } as any) @@ -44,28 +37,13 @@ describe(PushManager, () => { }) it('returns `true` when supported', () => { - windowMock.mockReturnValue({ - navigator: { - serviceWorker: {} - }, - PushManager: {} - } as any) + mockServiceWorker({}) expect(pushManager.isWebPushSupported()).toBeTruthy() }) }) describe('isWebPushSubscribed', () => { - let windowMock: jest.SpyInstance - - beforeAll(() => { - windowMock = jest.spyOn(globalThis, 'window', 'get') - }) - - afterAll(() => { - windowMock.mockReset() - }) - it('returns `false` when Web Push is not supported', async () => { windowMock.mockReturnValue({} as any) @@ -73,52 +51,35 @@ describe(PushManager, () => { }) it('returns `false` with no registration', async () => { - windowMock.mockReturnValue({ - navigator: { - serviceWorker: { - getRegistration: () => null - } - }, - PushManager: {} - } as any) + mockServiceWorker({ + getRegistration: () => null + }) expect(await pushManager.isWebPushSubscribed()).toBeFalsy() }) it('returns `false` with no subscription', async () => { - windowMock.mockReturnValue({ - navigator: { - serviceWorker: { - getRegistration: () => ({ - pushManager: { - getSubscription: () => null - } - }) + mockServiceWorker({ + getRegistration: () => ({ + pushManager: { + getSubscription: () => null } - }, - PushManager: {} - } as any) + }) + }) expect(await pushManager.isWebPushSubscribed()).toBeFalsy() }) it('returns `true` when there is subscription', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - getRegistration: () => ({ - pushManager: { - getSubscription: () => ({ - endpoint: 'test' - }) - } + mockServiceWorker({ + getRegistration: () => ({ + pushManager: { + getSubscription: () => ({ + endpoint: 'test' }) } - }, - PushManager: {} - } as any) + }) + }) expect(await pushManager.isWebPushSubscribed()).toBeTruthy() expect(createRequestSpy).toHaveBeenCalledTimes(1) @@ -133,17 +94,10 @@ describe(PushManager, () => { } } - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - getRegistration: () => registration, - register: () => registration - } - }, - PushManager: {} - } as any) + mockServiceWorker({ + getRegistration: () => registration, + register: () => registration + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -164,17 +118,8 @@ describe(PushManager, () => { }) describe('register', () => { - let windowMock: jest.SpyInstance const callback = jest.fn() - beforeAll(() => { - windowMock = jest.spyOn(globalThis, 'window', 'get') - }) - - afterAll(() => { - windowMock.mockReset() - }) - afterEach(() => { LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) callback.mockClear() @@ -191,18 +136,11 @@ describe(PushManager, () => { }) it('calls callback with `false` when there is an error', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: null // cause an exception - }) - } - }, - PushManager: {} - } as any) + mockServiceWorker({ + register: () => ({ + pushManager: null // cause an exception + }) + }) jest.spyOn(console, 'log').mockImplementationOnce(() => {}) await pushManager.register('', callback) @@ -212,20 +150,13 @@ describe(PushManager, () => { }) it('calls callback with `false` when not subscribed', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => null - } - }) + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => null } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', callback) @@ -234,22 +165,15 @@ describe(PushManager, () => { }) it('calls callback with `true` when subscribed', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => ({ - endpoint: 'test' - }) - } + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => ({ + endpoint: 'test' }) } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', callback) @@ -263,16 +187,7 @@ describe(PushManager, () => { getSubscription: () => null } }) - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register - } - }, - PushManager: {} - } as any) + mockServiceWorker({ register }) await pushManager.register('', callback) @@ -281,20 +196,13 @@ describe(PushManager, () => { }) it('does not update subscription on server when not subscribed', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => null - } - }) + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => null } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -302,22 +210,15 @@ describe(PushManager, () => { }) it('updates subscription on server when subscribed', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => ({ - endpoint: 'test' - }) - } + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => ({ + endpoint: 'test' }) } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -326,36 +227,19 @@ describe(PushManager, () => { }) describe('subscribeUser', () => { - let windowMock: jest.SpyInstance - - beforeAll(() => { - windowMock = jest.spyOn(globalThis, 'window', 'get') - }) - - afterAll(() => { - windowMock.mockReset() - }) - afterEach(() => { LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) }) it('throws error when error occurs', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => null, - subscribe: undefined // cause an exception - } - }) + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: undefined // cause an exception } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -363,21 +247,14 @@ describe(PushManager, () => { }) it('throws error when not subscribed', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => null, - subscribe: () => null - } - }) + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: () => null } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -385,23 +262,16 @@ describe(PushManager, () => { }) it('returns `true` on success', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => null, - subscribe: () => ({ - endpoint: 'test' - }) - } + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: () => ({ + endpoint: 'test' }) } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -409,21 +279,14 @@ describe(PushManager, () => { }) it('does not update subscription on server when not subscribed', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => null, - subscribe: () => null - } - }) + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: () => null } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) await pushManager.subscribeUser().catch(() => { /* noop - expected */ }) @@ -432,23 +295,16 @@ describe(PushManager, () => { }) it('updates subscription on server when subscribed', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => null, - subscribe: () => ({ - endpoint: 'test' - }) - } + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => null, + subscribe: () => ({ + endpoint: 'test' }) } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) await pushManager.subscribeUser() @@ -458,16 +314,6 @@ describe(PushManager, () => { }) describe('unsubscribeUser', () => { - let windowMock: jest.SpyInstance - - beforeAll(() => { - windowMock = jest.spyOn(globalThis, 'window', 'get') - }) - - afterAll(() => { - windowMock.mockReset() - }) - afterEach(() => { LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) }) @@ -475,20 +321,13 @@ describe(PushManager, () => { it('throws error when error occurs', async () => { let subscriptionValues: any[] = [null, { endpoint: 'test' }, {}] - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => subscriptionValues.shift() - } - }) + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => subscriptionValues.shift() } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -498,20 +337,13 @@ describe(PushManager, () => { it('throws error when no subscription', async () => { let subscriptionValues: any[] = [null, { endpoint: 'test' }, null] - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => subscriptionValues.shift() - } - }) + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => subscriptionValues.shift() } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -519,20 +351,13 @@ describe(PushManager, () => { }) it('resolves when not subscribed', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => null - } - }) + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => null } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) @@ -540,27 +365,31 @@ describe(PushManager, () => { }) it('resolves when unsubscribe was successful', async () => { - windowMock.mockReturnValue({ - atob, - btoa, - navigator: { - serviceWorker: { - register: () => ({ - pushManager: { - getSubscription: () => ({ - endpoint: 'test', - unsubscribe: () => Promise.resolve(true) - }) - } + mockServiceWorker({ + register: () => ({ + pushManager: { + getSubscription: () => ({ + endpoint: 'test', + unsubscribe: () => Promise.resolve(true) }) } - }, - PushManager: {} - } as any) + }) + }) await pushManager.register('', (x) => Promise.resolve(x)) await expect(pushManager.unsubscribeUser()).resolves.not.toThrowError() }) }) + + function mockServiceWorker(serviceWorker: any): void { + windowMock.mockReturnValue({ + atob, + btoa, + navigator: { + serviceWorker + }, + PushManager: {} + } as any) + } }) From 0902c35620635535d8797c62f064622e30bd1233 Mon Sep 17 00:00:00 2001 From: Alex Gyoshev Date: Tue, 31 Mar 2020 15:52:44 +0300 Subject: [PATCH 5/7] test: remove implementation details The specific storage mechanism is not relevant in the context of the tests. --- test/specs/PushManager.test.ts | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/test/specs/PushManager.test.ts b/test/specs/PushManager.test.ts index c2feeca4..069c980e 100644 --- a/test/specs/PushManager.test.ts +++ b/test/specs/PushManager.test.ts @@ -1,5 +1,3 @@ -import Constants from '../../src/Constants' -import LocalStorageManager from '../../src/LocalStorageManager' import PushManager from '../../src/PushManager' describe(PushManager, () => { @@ -15,6 +13,7 @@ describe(PushManager, () => { afterEach(() => { createRequestSpy.mockClear() windowMock.mockReset() + localStorage.clear() }) describe('isWebPushSupported', () => { @@ -118,14 +117,8 @@ describe(PushManager, () => { }) describe('register', () => { - const callback = jest.fn() - - afterEach(() => { - LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) - callback.mockClear() - }) - it('calls callback with `false` when Web Push is not supported', async () => { + const callback = jest.fn() windowMock.mockReturnValue({} as any) jest.spyOn(console, 'log').mockImplementationOnce(() => {}) @@ -136,6 +129,7 @@ describe(PushManager, () => { }) it('calls callback with `false` when there is an error', async () => { + const callback = jest.fn() mockServiceWorker({ register: () => ({ pushManager: null // cause an exception @@ -150,6 +144,7 @@ describe(PushManager, () => { }) it('calls callback with `false` when not subscribed', async () => { + const callback = jest.fn() mockServiceWorker({ register: () => ({ pushManager: { @@ -165,6 +160,7 @@ describe(PushManager, () => { }) it('calls callback with `true` when subscribed', async () => { + const callback = jest.fn() mockServiceWorker({ register: () => ({ pushManager: { @@ -182,6 +178,7 @@ describe(PushManager, () => { }) it('uses default SW URL when empty provided', async () => { + const callback = jest.fn() const register = jest.fn().mockReturnValue({ pushManager: { getSubscription: () => null @@ -227,10 +224,6 @@ describe(PushManager, () => { }) describe('subscribeUser', () => { - afterEach(() => { - LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) - }) - it('throws error when error occurs', async () => { mockServiceWorker({ register: () => ({ @@ -314,10 +307,6 @@ describe(PushManager, () => { }) describe('unsubscribeUser', () => { - afterEach(() => { - LocalStorageManager.removeFromLocalStorage(Constants.DEFAULT_KEYS.PUSH_SUBSCRIPTION) - }) - it('throws error when error occurs', async () => { let subscriptionValues: any[] = [null, { endpoint: 'test' }, {}] From c386b69d808ec2f34cdab46db7bbd6d1df76900c Mon Sep 17 00:00:00 2001 From: Alex Gyoshev Date: Tue, 31 Mar 2020 15:55:05 +0300 Subject: [PATCH 6/7] refactor: reduce code nesting --- src/PushManager.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/PushManager.ts b/src/PushManager.ts index 37a3e3f7..18b68a1a 100644 --- a/src/PushManager.ts +++ b/src/PushManager.ts @@ -55,22 +55,24 @@ export default class PushManager { * @return {Promise} True if subscribed, else false. */ public async isWebPushSubscribed(): Promise { - if (this.isWebPushSupported()) { - const registration = await this.getServiceWorkerRegistration() + if (!this.isWebPushSupported()) { + return false + } - if (registration) { - const subscription = await registration.pushManager.getSubscription() - const isSubscribed = subscription !== null + const registration = await this.getServiceWorkerRegistration() - if (isSubscribed) { - this.updateNewSubscriptionOnServer(subscription) - } + if (!registration) { + return false + } - return isSubscribed - } + const subscription = await registration.pushManager.getSubscription() + const isSubscribed = subscription !== null + + if (isSubscribed) { + this.updateNewSubscriptionOnServer(subscription) } - return false + return isSubscribed } /** From 806442237df96813d1fa708a7b8950b6d871546f Mon Sep 17 00:00:00 2001 From: Alex Gyoshev Date: Tue, 31 Mar 2020 15:56:20 +0300 Subject: [PATCH 7/7] chore: regenerate dist --- dist/leanplum.js | 4 ++-- dist/leanplum.min.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/leanplum.js b/dist/leanplum.js index c6451d7c..19de8959 100644 --- a/dist/leanplum.js +++ b/dist/leanplum.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Leanplum=t():e.Leanplum=t()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=27)}([function(e,t,n){var r=n(18),o="object"==typeof self&&self&&self.Object===Object&&self,a=r||o||Function("return this")();e.exports=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={METHODS:{START:"start",STOP:"stop",ADVANCE:"advance",TRACK:"track",PAUSE_SESSION:"pauseSession",RESUME_SESSION:"resumeSession",PAUSE_STATE:"pauseState",RESUME_STATE:"resumeState",DOWNLOAD_FILE:"downloadFile",MULTI:"multi",SET_VARS:"setVars",GET_VARS:"getVars",SET_USER_ATTRIBUTES:"setUserAttributes",SET_DEVICE_ATTRIBUTES:"setDeviceAttributes",UPLOAD_FILE:"uploadFile",REGISTER_DEVICE:"registerDevice"},SDK_VERSION:"1.4.0",CLIENT:"js",PARAMS:{ACTION:"action",APP_ID:"appId",CLIENT:"client",CLIENT_KEY:"clientKey",DEVICE_ID:"deviceId",SDK_VERSION:"sdkVersion",USER_ID:"userId",NEW_USER_ID:"newUserId",DEV_MODE:"devMode",VERSION_NAME:"versionName",SYSTEM_NAME:"systemName",SYSTEM_VERSION:"systemVersion",BROWSER_NAME:"browserName",BROWSER_VERSION:"browserVersion",DEVICE_NAME:"deviceName",DEVICE_MODEL:"deviceModel",USER_ATTRIBUTES:"userAttributes",LOCALE:"locale",COUNTRY:"country",REGION:"region",CITY:"city",LOCATION:"location",STATE:"state",INFO:"info",EVENT:"event",VALUE:"value",FILENAME:"filename",TIME:"time",DATA:"data",VARS:"vars",FILE:"file",SIZE:"size",VARIATION:"variation",HASH:"hash",EMAIL:"email",VARIABLES:"vars",PARAMS:"params",INCLUDE_DEFAULTS:"includeDefaults",INCLUDE_VARIANT_DEBUG_INFO:"includeVariantDebugInfo",WEB_PUSH_SUBSCRIPTION:"webPushSubscription"},KEYS:{IS_REGISTERED:"isRegistered",LATEST_VERSION:"latestVersion",VARS:"vars",VARIANTS:"variants",VARIANT_DEBUG_INFO:"variantDebugInfo",ACTION_METADATA:"actionMetadata",TOKEN:"token"},DEFAULT_KEYS:{COUNT:"__leanplum_unsynced",ITEM:"__leanplum_unsynced_",VARIABLES:"__leanplum_variables",VARIANTS:"__leanplum_variants",VARIANT_DEBUG_INFO:"__leanplum_variant_debug_info",ACTION_METADATA:"__leanplum_action_metadata",TOKEN:"__leanplum_token",DEVICE_ID:"__leanplum_device_id",USER_ID:"__leanplum_user_id",PUSH_SUBSCRIPTION:"__leanplum_push_subscription"},VALUES:{DETECT:"(detect)"}}},function(e,t,n){var r=n(46),o=n(52);e.exports=function(e,t){var n=o(e,t);return r(n)?n:void 0}},function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(n(1)),a=function(){function e(){this.argString="",this.argValues={}}return e.prototype.add=function(e,t){return void 0===t?this:(this.argString&&(this.argString+="&"),this.argString+=e+"="+encodeURIComponent(t),this.argValues[e]=t,this)},e.prototype.body=function(e){return e?(this._body=e,this):this._body},e.prototype.attachApiKeys=function(e,t){return this.add(o.default.PARAMS.APP_ID,e).add(o.default.PARAMS.CLIENT,o.default.CLIENT).add(o.default.PARAMS.CLIENT_KEY,t)},e.prototype.build=function(){return this.argString},e.prototype.buildDict=function(){return this.argValues},e}();t.default=a},function(e,t,n){"use strict";var r;Object.defineProperty(t,"__esModule",{value:!0});var o={},a=function(){function e(){}return e.getFromLocalStorage=function(e){return!1===r?o[e]:localStorage[e]},e.saveToLocalStorage=function(e,t){if(!1!==r)try{localStorage[e]=t}catch(n){r=!1,o[e]=t}else o[e]=t},e.removeFromLocalStorage=function(e){if(!1!==r)try{localStorage.removeItem(e)}catch(t){r=!1,delete o[e]}else delete o[e]},e}();t.default=a},function(e,t,n){var r=n(36),o=n(37),a=n(38),i=n(39),s=n(40);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t=200&&f.status<300?setTimeout((function(){i&&i(t,f)}),0):setTimeout((function(){s&&s(t,f)}),0)),u&&(e.runningRequest=!1,e.dequeueRequest())}},f.open(t,n,!0),f.setRequestHeader("Content-Type","text/plain"),f.send(o),setTimeout((function(){l||f.abort()}),1e3*a)},e.ajaxIE8=function(t,n,r,o,i,s,u){var c=new XDomainRequest;c.onload=function(){var t,n=!1;if(u)t=c.responseText;else try{t=JSON.parse(c.responseText)}catch(e){setTimeout((function(){i&&i(null,c)}),0),n=!0}n||setTimeout((function(){o&&o(t,c)}),0),s&&(e.runningRequest=!1,e.dequeueRequest())},c.onerror=c.ontimeout=function(){setTimeout((function(){i&&i(null,c)}),0),s&&(e.runningRequest=!1,e.dequeueRequest())},c.onprogress=function(){},c.open(t,n),c.timeout=1e3*a,c.send(r)},e.enqueueRequest=function(e){o.push(e)},e.dequeueRequest=function(){var t=o.shift();t&&r.call(e.ajax,null,t)},e.runningRequest=!1,e}();t.default=i},function(e,t,n){var r=n(33);e.exports=function(e,t){return r(e,t)}},function(e,t){e.exports=function(e,t){return e===t||e!=e&&t!=t}},function(e,t,n){var r=n(7),o=n(19);e.exports=function(e){if(!o(e))return!1;var t=r(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},function(e,t,n){(function(t){var n="object"==typeof t&&t&&t.Object===Object&&t;e.exports=n}).call(this,n(47))},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t){var n=Function.prototype.toString;e.exports=function(e){if(null!=e){try{return n.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},function(e,t,n){var r=n(53),o=n(60),a=n(62),i=n(63),s=n(64);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++tl))return!1;var d=u.get(e);if(d&&u.get(t))return d==t;var p=-1,h=!0,v=2&n?new r:void 0;for(u.set(e,t),u.set(t,e);++p-1&&e%1==0&&e<=9007199254740991}},function(e,t,n){var r=n(28);e.exports=r.default},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=0&&this.startHandlers.splice(t,1)},e.prototype.triggerStartHandlers=function(){for(var e=0;e0){var t=JSON.stringify({data:e}),i=(new o.default).attachApiKeys(r.appId,r.clientKey).add(a.default.PARAMS.SDK_VERSION,a.default.SDK_VERSION).add(a.default.PARAMS.ACTION,a.default.METHODS.MULTI).add(a.default.PARAMS.TIME,((new Date).getTime()/1e3).toString().toString()).build();s.default.ajax("POST",r.apiPath+"?"+i,t,f,d,n.queued)}};if(!h&&this.batchCooldown){var S=(new Date).getTime()/1e3;!this.lastRequestTime||S-this.lastRequestTime>=this.batchCooldown?(h=!0,this.lastRequestTime=S):this.cooldownTimeout||(this.cooldownTimeout=setTimeout((function(){r.cooldownTimeout=null,r.lastRequestTime=(new Date).getTime()/1e3,v()}),1e3*(this.batchCooldown-(S-this.lastRequestTime))))}this.saveRequestForLater(l.buildDict()),h&&v()}},e.prototype.setNetworkTimeout=function(e){s.default.setNetworkTimeout(e)},e.prototype.getLastResponse=function(e){var t,n,r,o,a,i=null!=(r=null===(n=null===(t=e)||void 0===t?void 0:t.response)||void 0===n?void 0:n.length)?r:0;return i>0?null===(a=null===(o=e)||void 0===o?void 0:o.response)||void 0===a?void 0:a[i-1]:null},e.prototype.isResponseSuccess=function(e){var t;return Boolean(null===(t=e)||void 0===t?void 0:t.success)},e.prototype.saveRequestForLater=function(e){var t=this.loadLocal(a.default.DEFAULT_KEYS.COUNT)||0,n=a.default.DEFAULT_KEYS.ITEM+t;this.saveLocal(n,JSON.stringify(e)),t++,this.saveLocal(a.default.DEFAULT_KEYS.COUNT,t)},e.prototype.popUnsentRequests=function(){var e=[],t=this.loadLocal(a.default.DEFAULT_KEYS.COUNT)||0;this.removeLocal(a.default.DEFAULT_KEYS.COUNT);for(var n=0;n-1}},function(e,t,n){var r=n(6);e.exports=function(e,t){var n=this.__data__,o=r(n,e);return o<0?(++this.size,n.push([e,t])):n[o][1]=t,this}},function(e,t,n){var r=n(5);e.exports=function(){this.__data__=new r,this.size=0}},function(e,t){e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},function(e,t){e.exports=function(e){return this.__data__.get(e)}},function(e,t){e.exports=function(e){return this.__data__.has(e)}},function(e,t,n){var r=n(5),o=n(11),a=n(21);e.exports=function(e,t){var n=this.__data__;if(n instanceof r){var i=n.__data__;if(!o||i.length<199)return i.push([e,t]),this.size=++n.size,this;n=this.__data__=new a(i)}return n.set(e,t),this.size=n.size,this}},function(e,t,n){var r=n(17),o=n(50),a=n(19),i=n(20),s=/^\[object .+?Constructor\]$/,u=Function.prototype,c=Object.prototype,l=u.toString,f=c.hasOwnProperty,d=RegExp("^"+l.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=function(e){return!(!a(e)||o(e))&&(r(e)?d:s).test(i(e))}},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r=n(12),o=Object.prototype,a=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=a.call(e,s),n=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=n:delete e[s]),o}},function(e,t){var n=Object.prototype.toString;e.exports=function(e){return n.call(e)}},function(e,t,n){var r,o=n(51),a=(r=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";e.exports=function(e){return!!a&&a in e}},function(e,t,n){var r=n(0)["__core-js_shared__"];e.exports=r},function(e,t){e.exports=function(e,t){return null==e?void 0:e[t]}},function(e,t,n){var r=n(54),o=n(5),a=n(11);e.exports=function(){this.size=0,this.__data__={hash:new r,map:new(a||o),string:new r}}},function(e,t,n){var r=n(55),o=n(56),a=n(57),i=n(58),s=n(59);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]=u.length;)u.push(null);u[r]=e(u[r],o)})),u}var c={};return o((function(e){null!==n[e]&&void 0!==n[e]||(c[e]=t[e])})),a((function(r){c[r]=e(null===t?null:t[r]||{},n[r])})),c}(this.variables,e),this.saveDiffs(),this.onUpdate&&this.onUpdate()},e.prototype.loadDiffs=function(){try{this.applyDiffs(JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIABLES)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIANTS)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.ACTION_METADATA)||null)),this.token=this.loadLocal(a.default.DEFAULT_KEYS.TOKEN),this.variantDebugInfo=this.loadLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO)}catch(e){console.log("Leanplum: Invalid diffs: "+e)}},e.prototype.saveDiffs=function(){this.saveLocal(a.default.DEFAULT_KEYS.VARIABLES,JSON.stringify(this.diffs||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANTS,JSON.stringify(this.variants||[])),this.saveLocal(a.default.DEFAULT_KEYS.ACTION_METADATA,JSON.stringify(this.actionMetadata||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO,JSON.stringify(this.variantDebugInfo||{})),this.saveLocal(a.default.DEFAULT_KEYS.TOKEN,this.token)},e.prototype.getVariables=function(){return void 0!==this.merged?this.merged:this.variables},e.prototype.setVariables=function(e){this.variables=e},e.prototype.addVariablesChangedHandler=function(e){this.variablesChangedHandlers.push(e),this.hasReceivedDiffs&&e()},e.prototype.removeVariablesChangedHandler=function(e){var t=this.variablesChangedHandlers.indexOf(e);t>=0&&this.variablesChangedHandlers.splice(t,1)},e.prototype.triggerVariablesChangedHandlers=function(){for(var e=0;e=200&&f.status<300?setTimeout((function(){i&&i(t,f)}),0):setTimeout((function(){s&&s(t,f)}),0)),u&&(e.runningRequest=!1,e.dequeueRequest())}},f.open(t,n,!0),f.setRequestHeader("Content-Type","text/plain"),f.send(o),setTimeout((function(){l||f.abort()}),1e3*a)},e.ajaxIE8=function(t,n,r,o,i,s,u){var c=new XDomainRequest;c.onload=function(){var t,n=!1;if(u)t=c.responseText;else try{t=JSON.parse(c.responseText)}catch(e){setTimeout((function(){i&&i(null,c)}),0),n=!0}n||setTimeout((function(){o&&o(t,c)}),0),s&&(e.runningRequest=!1,e.dequeueRequest())},c.onerror=c.ontimeout=function(){setTimeout((function(){i&&i(null,c)}),0),s&&(e.runningRequest=!1,e.dequeueRequest())},c.onprogress=function(){},c.open(t,n),c.timeout=1e3*a,c.send(r)},e.enqueueRequest=function(e){o.push(e)},e.dequeueRequest=function(){var t=o.shift();t&&r.call(e.ajax,null,t)},e.runningRequest=!1,e}();t.default=i},function(e,t,n){var r=n(33);e.exports=function(e,t){return r(e,t)}},function(e,t){e.exports=function(e,t){return e===t||e!=e&&t!=t}},function(e,t,n){var r=n(7),o=n(19);e.exports=function(e){if(!o(e))return!1;var t=r(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},function(e,t,n){(function(t){var n="object"==typeof t&&t&&t.Object===Object&&t;e.exports=n}).call(this,n(47))},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t){var n=Function.prototype.toString;e.exports=function(e){if(null!=e){try{return n.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},function(e,t,n){var r=n(53),o=n(60),a=n(62),i=n(63),s=n(64);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++tl))return!1;var d=u.get(e);if(d&&u.get(t))return d==t;var p=-1,h=!0,v=2&n?new r:void 0;for(u.set(e,t),u.set(t,e);++p-1&&e%1==0&&e<=9007199254740991}},function(e,t,n){var r=n(28);e.exports=r.default},function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n=0&&this.startHandlers.splice(t,1)},e.prototype.triggerStartHandlers=function(){for(var e=0;e0){var t=JSON.stringify({data:e}),i=(new o.default).attachApiKeys(r.appId,r.clientKey).add(a.default.PARAMS.SDK_VERSION,a.default.SDK_VERSION).add(a.default.PARAMS.ACTION,a.default.METHODS.MULTI).add(a.default.PARAMS.TIME,((new Date).getTime()/1e3).toString().toString()).build();s.default.ajax("POST",r.apiPath+"?"+i,t,f,d,n.queued)}};if(!h&&this.batchCooldown){var S=(new Date).getTime()/1e3;!this.lastRequestTime||S-this.lastRequestTime>=this.batchCooldown?(h=!0,this.lastRequestTime=S):this.cooldownTimeout||(this.cooldownTimeout=setTimeout((function(){r.cooldownTimeout=null,r.lastRequestTime=(new Date).getTime()/1e3,v()}),1e3*(this.batchCooldown-(S-this.lastRequestTime))))}this.saveRequestForLater(l.buildDict()),h&&v()}},e.prototype.setNetworkTimeout=function(e){s.default.setNetworkTimeout(e)},e.prototype.getLastResponse=function(e){var t,n,r,o,a,i=null!=(r=null===(n=null===(t=e)||void 0===t?void 0:t.response)||void 0===n?void 0:n.length)?r:0;return i>0?null===(a=null===(o=e)||void 0===o?void 0:o.response)||void 0===a?void 0:a[i-1]:null},e.prototype.isResponseSuccess=function(e){var t;return Boolean(null===(t=e)||void 0===t?void 0:t.success)},e.prototype.saveRequestForLater=function(e){var t=this.loadLocal(a.default.DEFAULT_KEYS.COUNT)||0,n=a.default.DEFAULT_KEYS.ITEM+t;this.saveLocal(n,JSON.stringify(e)),t++,this.saveLocal(a.default.DEFAULT_KEYS.COUNT,t)},e.prototype.popUnsentRequests=function(){var e=[],t=this.loadLocal(a.default.DEFAULT_KEYS.COUNT)||0;this.removeLocal(a.default.DEFAULT_KEYS.COUNT);for(var n=0;n-1}},function(e,t,n){var r=n(6);e.exports=function(e,t){var n=this.__data__,o=r(n,e);return o<0?(++this.size,n.push([e,t])):n[o][1]=t,this}},function(e,t,n){var r=n(5);e.exports=function(){this.__data__=new r,this.size=0}},function(e,t){e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},function(e,t){e.exports=function(e){return this.__data__.get(e)}},function(e,t){e.exports=function(e){return this.__data__.has(e)}},function(e,t,n){var r=n(5),o=n(11),a=n(21);e.exports=function(e,t){var n=this.__data__;if(n instanceof r){var i=n.__data__;if(!o||i.length<199)return i.push([e,t]),this.size=++n.size,this;n=this.__data__=new a(i)}return n.set(e,t),this.size=n.size,this}},function(e,t,n){var r=n(17),o=n(50),a=n(19),i=n(20),s=/^\[object .+?Constructor\]$/,u=Function.prototype,c=Object.prototype,l=u.toString,f=c.hasOwnProperty,d=RegExp("^"+l.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=function(e){return!(!a(e)||o(e))&&(r(e)?d:s).test(i(e))}},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r=n(12),o=Object.prototype,a=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=a.call(e,s),n=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=n:delete e[s]),o}},function(e,t){var n=Object.prototype.toString;e.exports=function(e){return n.call(e)}},function(e,t,n){var r,o=n(51),a=(r=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";e.exports=function(e){return!!a&&a in e}},function(e,t,n){var r=n(0)["__core-js_shared__"];e.exports=r},function(e,t){e.exports=function(e,t){return null==e?void 0:e[t]}},function(e,t,n){var r=n(54),o=n(5),a=n(11);e.exports=function(){this.size=0,this.__data__={hash:new r,map:new(a||o),string:new r}}},function(e,t,n){var r=n(55),o=n(56),a=n(57),i=n(58),s=n(59);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e0&&o[o.length-1])&&(6===a[0]||2===a[0])){i=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]=u.length;)u.push(null);u[r]=e(u[r],o)})),u}var c={};return o((function(e){null!==n[e]&&void 0!==n[e]||(c[e]=t[e])})),a((function(r){c[r]=e(null===t?null:t[r]||{},n[r])})),c}(this.variables,e),this.saveDiffs(),this.onUpdate&&this.onUpdate()},e.prototype.loadDiffs=function(){try{this.applyDiffs(JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIABLES)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIANTS)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.ACTION_METADATA)||null)),this.token=this.loadLocal(a.default.DEFAULT_KEYS.TOKEN),this.variantDebugInfo=this.loadLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO)}catch(e){console.log("Leanplum: Invalid diffs: "+e)}},e.prototype.saveDiffs=function(){this.saveLocal(a.default.DEFAULT_KEYS.VARIABLES,JSON.stringify(this.diffs||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANTS,JSON.stringify(this.variants||[])),this.saveLocal(a.default.DEFAULT_KEYS.ACTION_METADATA,JSON.stringify(this.actionMetadata||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO,JSON.stringify(this.variantDebugInfo||{})),this.saveLocal(a.default.DEFAULT_KEYS.TOKEN,this.token)},e.prototype.getVariables=function(){return void 0!==this.merged?this.merged:this.variables},e.prototype.setVariables=function(e){this.variables=e},e.prototype.addVariablesChangedHandler=function(e){this.variablesChangedHandlers.push(e),this.hasReceivedDiffs&&e()},e.prototype.removeVariablesChangedHandler=function(e){var t=this.variablesChangedHandlers.indexOf(e);t>=0&&this.variablesChangedHandlers.splice(t,1)},e.prototype.triggerVariablesChangedHandlers=function(){for(var e=0;e=this.batchCooldown?(f=!0,this.lastRequestTime=p):this.cooldownTimeout||(this.cooldownTimeout=setTimeout(function(){o.cooldownTimeout=null,o.lastRequestTime=(new Date).getTime()/1e3,d()},1e3*(this.batchCooldown-(p-this.lastRequestTime))))}this.saveRequestForLater(s.buildDict()),f&&d()}},i.prototype.setNetworkTimeout=function(e){S.default.setNetworkTimeout(e)},i.prototype.getLastResponse=function(e){var t,n,r,o=null!=(n=null===(t=null==e?void 0:e.response)||void 0===t?void 0:t.length)?n:0;return 0i[0]&&t[1]=u.length;)u.push(null);u[t]=r(u[t],n)}),u}var c={};return n(function(e){null!==o[e]&&void 0!==o[e]||(c[e]=t[e])}),a(function(e){c[e]=r(null===t?null:t[e]||{},o[e])}),c}(this.variables,e),this.saveDiffs(),this.onUpdate&&this.onUpdate()},u.prototype.loadDiffs=function(){try{this.applyDiffs(JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIABLES)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIANTS)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.ACTION_METADATA)||null)),this.token=this.loadLocal(a.default.DEFAULT_KEYS.TOKEN),this.variantDebugInfo=this.loadLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO)}catch(e){console.log("Leanplum: Invalid diffs: "+e)}},u.prototype.saveDiffs=function(){this.saveLocal(a.default.DEFAULT_KEYS.VARIABLES,JSON.stringify(this.diffs||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANTS,JSON.stringify(this.variants||[])),this.saveLocal(a.default.DEFAULT_KEYS.ACTION_METADATA,JSON.stringify(this.actionMetadata||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO,JSON.stringify(this.variantDebugInfo||{})),this.saveLocal(a.default.DEFAULT_KEYS.TOKEN,this.token)},u.prototype.getVariables=function(){return void 0!==this.merged?this.merged:this.variables},u.prototype.setVariables=function(e){this.variables=e},u.prototype.addVariablesChangedHandler=function(e){this.variablesChangedHandlers.push(e),this.hasReceivedDiffs&&e()},u.prototype.removeVariablesChangedHandler=function(e){var t=this.variablesChangedHandlers.indexOf(e);0<=t&&this.variablesChangedHandlers.splice(t,1)},u.prototype.triggerVariablesChangedHandlers=function(){for(var e=0;e=this.batchCooldown?(f=!0,this.lastRequestTime=p):this.cooldownTimeout||(this.cooldownTimeout=setTimeout(function(){o.cooldownTimeout=null,o.lastRequestTime=(new Date).getTime()/1e3,d()},1e3*(this.batchCooldown-(p-this.lastRequestTime))))}this.saveRequestForLater(s.buildDict()),f&&d()}},i.prototype.setNetworkTimeout=function(e){S.default.setNetworkTimeout(e)},i.prototype.getLastResponse=function(e){var t,n,r,o=null!=(n=null===(t=null==e?void 0:e.response)||void 0===t?void 0:t.length)?n:0;return 0i[0]&&t[1]=u.length;)u.push(null);u[t]=r(u[t],n)}),u}var c={};return n(function(e){null!==o[e]&&void 0!==o[e]||(c[e]=t[e])}),a(function(e){c[e]=r(null===t?null:t[e]||{},o[e])}),c}(this.variables,e),this.saveDiffs(),this.onUpdate&&this.onUpdate()},u.prototype.loadDiffs=function(){try{this.applyDiffs(JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIABLES)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.VARIANTS)||null),JSON.parse(this.loadLocal(a.default.DEFAULT_KEYS.ACTION_METADATA)||null)),this.token=this.loadLocal(a.default.DEFAULT_KEYS.TOKEN),this.variantDebugInfo=this.loadLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO)}catch(e){console.log("Leanplum: Invalid diffs: "+e)}},u.prototype.saveDiffs=function(){this.saveLocal(a.default.DEFAULT_KEYS.VARIABLES,JSON.stringify(this.diffs||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANTS,JSON.stringify(this.variants||[])),this.saveLocal(a.default.DEFAULT_KEYS.ACTION_METADATA,JSON.stringify(this.actionMetadata||{})),this.saveLocal(a.default.DEFAULT_KEYS.VARIANT_DEBUG_INFO,JSON.stringify(this.variantDebugInfo||{})),this.saveLocal(a.default.DEFAULT_KEYS.TOKEN,this.token)},u.prototype.getVariables=function(){return void 0!==this.merged?this.merged:this.variables},u.prototype.setVariables=function(e){this.variables=e},u.prototype.addVariablesChangedHandler=function(e){this.variablesChangedHandlers.push(e),this.hasReceivedDiffs&&e()},u.prototype.removeVariablesChangedHandler=function(e){var t=this.variablesChangedHandlers.indexOf(e);0<=t&&this.variablesChangedHandlers.splice(t,1)},u.prototype.triggerVariablesChangedHandlers=function(){for(var e=0;e