From 30622b86b91795c20fe93da32fd0aa2eae66f150 Mon Sep 17 00:00:00 2001 From: mt-neus Date: Wed, 11 Dec 2019 15:48:06 +0900 Subject: [PATCH] feat(customersupport): open customer support --- README.md | 11 +++++++- dist/endpoints.d.ts | 3 +++ dist/index.d.ts | 1 + dist/index.js | 2 +- sample/src/index.html | 1 + sample/src/index.ts | 9 ++++++- src/__tests__/index.ts | 57 ++++++++++++++++++++++++++++++++++++++++++ src/endpoints.ts | 5 +++- src/index.ts | 13 ++++++++++ 9 files changed, 98 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2c5f74f..a998ceb 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Config properties: locale, // string; // [optional] To force the display to a specific language (e.g.: en-AU). state, // string; // [optional] An opaque value, used for security purposes. If this request parameter is set in the request, then it is returned to the application as part of the redirect_uri. appToken, // string; // [optional] The Access Token granted through oauth - isTestEnvironment // boolean; // [optional] If you wanna use the staging or production environemnt + isTestEnvironment // boolean; // [optional] If you wanna use the staging or production environment } ``` @@ -114,3 +114,12 @@ You can pass the following options: - `backTo`: Redirect URL for some actions (back, revoke, logout, delete) - Values: A string representing a URL - Default: Current URL + +### Open the customer support to let the user contact support + +`mtLinkSdk.openCustomerSupport(options);` +You can pass the following options: + +- `newTab`: Open in a new browser tab + - Values: `true` or `false` + - Default: `false` diff --git a/dist/endpoints.d.ts b/dist/endpoints.d.ts index e2752d4..6b5a4c3 100644 --- a/dist/endpoints.d.ts +++ b/dist/endpoints.d.ts @@ -2,6 +2,9 @@ export declare const DOMAIN = "getmoneytree.com"; export declare const VAULT: { SUBDOMAIN: string; TEST_SUBDOMAIN: string; + PATHS: { + CUSTOMER_SUPPORT: string; + }; }; export declare const MY_ACCOUNT: { SUBDOMAIN: string; diff --git a/dist/index.d.ts b/dist/index.d.ts index 12cef26..18cb829 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -44,6 +44,7 @@ declare class LinkSDK { authorize({ newTab, email, authPage, backTo, showAuthToggle }?: IMyAccountOptions): void; logout({ newTab }?: IMyAccountOptions): void; openVault({ newTab, backTo }?: IVaultOptions): void; + openCustomerSupport({ newTab }?: IVaultOptions): void; openSettings({ newTab, backTo }?: IMyAccountOptions): void; } declare const _default: LinkSDK; diff --git a/dist/index.js b/dist/index.js index ffb0fe4..fb40a6a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("mtLinkSdk",[],t):"object"==typeof exports?exports.mtLinkSdk=t():e.mtLinkSdk=t()}(window,(function(){return function(e){var t={};function r(o){if(t[o])return t[o].exports;var n=t[o]={i:o,l:!1,exports:{}};return e[o].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=e,r.c=t,r.d=function(e,t,o){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(r.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(o,n,function(t){return e[t]}.bind(null,n));return o},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=2)}([function(e,t,r){"use strict";var o=Object.prototype.hasOwnProperty,n=Array.isArray,i=function(){for(var e=[],t=0;t<256;++t)e.push("%"+((t<16?"0":"")+t.toString(16)).toUpperCase());return e}(),a=function(e,t){for(var r=t&&t.plainObjects?Object.create(null):{},o=0;o1;){var t=e.pop(),r=t.obj[t.prop];if(n(r)){for(var o=[],i=0;i=48&&c<=57||c>=65&&c<=90||c>=97&&c<=122?n+=o.charAt(a):c<128?n+=i[c]:c<2048?n+=i[192|c>>6]+i[128|63&c]:c<55296||c>=57344?n+=i[224|c>>12]+i[128|c>>6&63]+i[128|63&c]:(a+=1,c=65536+((1023&c)<<10|1023&o.charCodeAt(a)),n+=i[240|c>>18]+i[128|c>>12&63]+i[128|c>>6&63]+i[128|63&c])}return n},isBuffer:function(e){return!(!e||"object"!=typeof e)&&!!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e))},isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},merge:function e(t,r,i){if(!r)return t;if("object"!=typeof r){if(n(t))t.push(r);else{if(!t||"object"!=typeof t)return[t,r];(i&&(i.plainObjects||i.allowPrototypes)||!o.call(Object.prototype,r))&&(t[r]=!0)}return t}if(!t||"object"!=typeof t)return[t].concat(r);var c=t;return n(t)&&!n(r)&&(c=a(t,i)),n(t)&&n(r)?(r.forEach((function(r,n){if(o.call(t,n)){var a=t[n];a&&"object"==typeof a&&r&&"object"==typeof r?t[n]=e(a,r,i):t.push(r)}else t[n]=r})),t):Object.keys(r).reduce((function(t,n){var a=r[n];return o.call(t,n)?t[n]=e(t[n],a,i):t[n]=a,t}),c)}}},function(e,t,r){"use strict";var o=String.prototype.replace,n=/%20/g,i=r(0),a={RFC1738:"RFC1738",RFC3986:"RFC3986"};e.exports=i.assign({default:a.RFC3986,formatters:{RFC1738:function(e){return o.call(e,n,"+")},RFC3986:function(e){return String(e)}}},a)},function(e,t,r){"use strict";var o=this&&this.__assign||function(){return(o=Object.assign||function(e){for(var t,r=1,o=arguments.length;r0?v+b:""}},function(e,t,r){"use strict";var o=r(0),n=Object.prototype.hasOwnProperty,i=Array.isArray,a={allowDots:!1,allowPrototypes:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decoder:o.decode,delimiter:"&",depth:5,ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictNullHandling:!1},c=function(e){return e.replace(/&#(\d+);/g,(function(e,t){return String.fromCharCode(parseInt(t,10))}))},l=function(e,t,r){if(e){var o=r.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e,i=/(\[[^[\]]*])/g,a=r.depth>0&&/(\[[^[\]]*])/.exec(o),c=a?o.slice(0,a.index):o,l=[];if(c){if(!r.plainObjects&&n.call(Object.prototype,c)&&!r.allowPrototypes)return;l.push(c)}for(var s=0;r.depth>0&&null!==(a=i.exec(o))&&s=0;--n){var i,a=e[n];if("[]"===a&&r.parseArrays)i=[].concat(o);else{i=r.plainObjects?Object.create(null):{};var c="["===a.charAt(0)&&"]"===a.charAt(a.length-1)?a.slice(1,-1):a,l=parseInt(c,10);r.parseArrays||""!==c?!isNaN(l)&&a!==c&&String(l)===c&&l>=0&&r.parseArrays&&l<=r.arrayLimit?(i=[])[l]=o:i[c]=o:i={0:o}}o=i}return o}(l,t,r)}};e.exports=function(e,t){var r=function(e){if(!e)return a;if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new Error("The charset option must be either utf-8, iso-8859-1, or undefined");var t=void 0===e.charset?a.charset:e.charset;return{allowDots:void 0===e.allowDots?a.allowDots:!!e.allowDots,allowPrototypes:"boolean"==typeof e.allowPrototypes?e.allowPrototypes:a.allowPrototypes,arrayLimit:"number"==typeof e.arrayLimit?e.arrayLimit:a.arrayLimit,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:a.charsetSentinel,comma:"boolean"==typeof e.comma?e.comma:a.comma,decoder:"function"==typeof e.decoder?e.decoder:a.decoder,delimiter:"string"==typeof e.delimiter||o.isRegExp(e.delimiter)?e.delimiter:a.delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:a.depth,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof e.interpretNumericEntities?e.interpretNumericEntities:a.interpretNumericEntities,parameterLimit:"number"==typeof e.parameterLimit?e.parameterLimit:a.parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:"boolean"==typeof e.plainObjects?e.plainObjects:a.plainObjects,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:a.strictNullHandling}}(t);if(""===e||null==e)return r.plainObjects?Object.create(null):{};for(var s="string"==typeof e?function(e,t){var r,l={},s=t.ignoreQueryPrefix?e.replace(/^\?/,""):e,u=t.parameterLimit===1/0?void 0:t.parameterLimit,f=s.split(t.delimiter,u),p=-1,d=t.charset;if(t.charsetSentinel)for(r=0;r-1&&(h=h.split(",")),m.indexOf("[]=")>-1&&(h=i(h)?[h]:h),n.call(l,y)?l[y]=o.combine(l[y],h):l[y]=h}return l}(e,r):e,u=r.plainObjects?Object.create(null):{},f=Object.keys(s),p=0;p1;){var t=e.pop(),r=t.obj[t.prop];if(n(r)){for(var o=[],i=0;i=48&&c<=57||c>=65&&c<=90||c>=97&&c<=122?n+=o.charAt(a):c<128?n+=i[c]:c<2048?n+=i[192|c>>6]+i[128|63&c]:c<55296||c>=57344?n+=i[224|c>>12]+i[128|c>>6&63]+i[128|63&c]:(a+=1,c=65536+((1023&c)<<10|1023&o.charCodeAt(a)),n+=i[240|c>>18]+i[128|c>>12&63]+i[128|c>>6&63]+i[128|63&c])}return n},isBuffer:function(e){return!(!e||"object"!=typeof e)&&!!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e))},isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},merge:function e(t,r,i){if(!r)return t;if("object"!=typeof r){if(n(t))t.push(r);else{if(!t||"object"!=typeof t)return[t,r];(i&&(i.plainObjects||i.allowPrototypes)||!o.call(Object.prototype,r))&&(t[r]=!0)}return t}if(!t||"object"!=typeof t)return[t].concat(r);var c=t;return n(t)&&!n(r)&&(c=a(t,i)),n(t)&&n(r)?(r.forEach((function(r,n){if(o.call(t,n)){var a=t[n];a&&"object"==typeof a&&r&&"object"==typeof r?t[n]=e(a,r,i):t.push(r)}else t[n]=r})),t):Object.keys(r).reduce((function(t,n){var a=r[n];return o.call(t,n)?t[n]=e(t[n],a,i):t[n]=a,t}),c)}}},function(e,t,r){"use strict";var o=String.prototype.replace,n=/%20/g,i=r(0),a={RFC1738:"RFC1738",RFC3986:"RFC3986"};e.exports=i.assign({default:a.RFC3986,formatters:{RFC1738:function(e){return o.call(e,n,"+")},RFC3986:function(e){return String(e)}}},a)},function(e,t,r){"use strict";var o=this&&this.__assign||function(){return(o=Object.assign||function(e){for(var t,r=1,o=arguments.length;r0?b+v:""}},function(e,t,r){"use strict";var o=r(0),n=Object.prototype.hasOwnProperty,i=Array.isArray,a={allowDots:!1,allowPrototypes:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decoder:o.decode,delimiter:"&",depth:5,ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictNullHandling:!1},c=function(e){return e.replace(/&#(\d+);/g,(function(e,t){return String.fromCharCode(parseInt(t,10))}))},l=function(e,t,r){if(e){var o=r.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e,i=/(\[[^[\]]*])/g,a=r.depth>0&&/(\[[^[\]]*])/.exec(o),c=a?o.slice(0,a.index):o,l=[];if(c){if(!r.plainObjects&&n.call(Object.prototype,c)&&!r.allowPrototypes)return;l.push(c)}for(var s=0;r.depth>0&&null!==(a=i.exec(o))&&s=0;--n){var i,a=e[n];if("[]"===a&&r.parseArrays)i=[].concat(o);else{i=r.plainObjects?Object.create(null):{};var c="["===a.charAt(0)&&"]"===a.charAt(a.length-1)?a.slice(1,-1):a,l=parseInt(c,10);r.parseArrays||""!==c?!isNaN(l)&&a!==c&&String(l)===c&&l>=0&&r.parseArrays&&l<=r.arrayLimit?(i=[])[l]=o:i[c]=o:i={0:o}}o=i}return o}(l,t,r)}};e.exports=function(e,t){var r=function(e){if(!e)return a;if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new Error("The charset option must be either utf-8, iso-8859-1, or undefined");var t=void 0===e.charset?a.charset:e.charset;return{allowDots:void 0===e.allowDots?a.allowDots:!!e.allowDots,allowPrototypes:"boolean"==typeof e.allowPrototypes?e.allowPrototypes:a.allowPrototypes,arrayLimit:"number"==typeof e.arrayLimit?e.arrayLimit:a.arrayLimit,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:a.charsetSentinel,comma:"boolean"==typeof e.comma?e.comma:a.comma,decoder:"function"==typeof e.decoder?e.decoder:a.decoder,delimiter:"string"==typeof e.delimiter||o.isRegExp(e.delimiter)?e.delimiter:a.delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:a.depth,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof e.interpretNumericEntities?e.interpretNumericEntities:a.interpretNumericEntities,parameterLimit:"number"==typeof e.parameterLimit?e.parameterLimit:a.parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:"boolean"==typeof e.plainObjects?e.plainObjects:a.plainObjects,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:a.strictNullHandling}}(t);if(""===e||null==e)return r.plainObjects?Object.create(null):{};for(var s="string"==typeof e?function(e,t){var r,l={},s=t.ignoreQueryPrefix?e.replace(/^\?/,""):e,u=t.parameterLimit===1/0?void 0:t.parameterLimit,f=s.split(t.delimiter,u),p=-1,d=t.charset;if(t.charsetSentinel)for(r=0;r-1&&(h=h.split(",")),m.indexOf("[]=")>-1&&(h=i(h)?[h]:h),n.call(l,y)?l[y]=o.combine(l[y],h):l[y]=h}return l}(e,r):e,u=r.plainObjects?Object.create(null):{},f=Object.keys(s),p=0;pWelcome to the Moneytree Link Web SDK Sample App + diff --git a/sample/src/index.ts b/sample/src/index.ts index 06d83ca..2c07d60 100644 --- a/sample/src/index.ts +++ b/sample/src/index.ts @@ -15,10 +15,11 @@ const authorizeBtn = document.getElementById('authorize-btn') as HTMLButtonEleme const logoutBtn = document.getElementById('logout-btn') as HTMLButtonElement; const goToSettingsBtn = document.getElementById('settings-btn') as HTMLButtonElement; const goToVaultBtn = document.getElementById('vault-btn') as HTMLButtonElement; +const goToCustomerSupportBtn = document.getElementById('customer-support-btn') as HTMLButtonElement; const tokenInfoLbl = document.getElementById('access-token-text') as HTMLButtonElement; const accessTokenLabel = document.getElementById('access-token-text') as HTMLParagraphElement; -if (!authorizeBtn || !logoutBtn || !goToSettingsBtn || !goToVaultBtn) { +if (!authorizeBtn || !logoutBtn || !goToSettingsBtn || !goToVaultBtn || !goToCustomerSupportBtn) { throw new Error('An error occurred'); } @@ -42,6 +43,11 @@ goToVaultBtn.onclick = () => { LinkSDK.openVault({ newTab: false }); }; +// Launch vault route when clicked +goToCustomerSupportBtn.onclick = () => { + LinkSDK.openCustomerSupport({ newTab: false }); +}; + const initializeLinkSDK = () => { LinkSDK.init({ clientId: AWESOME_APP_ID, @@ -63,6 +69,7 @@ const validateToken = async () => { goToSettingsBtn.disabled = true; goToVaultBtn.disabled = true; logoutBtn.disabled = true; + goToCustomerSupportBtn.disabled = true; return; } diff --git a/src/__tests__/index.ts b/src/__tests__/index.ts index a7a2b55..e31061b 100644 --- a/src/__tests__/index.ts +++ b/src/__tests__/index.ts @@ -287,6 +287,63 @@ describe('LinkSDK', () => { expect(url).toBe(`${host}?${qs}&configs=${configs}`); }); }); + describe('openCustomerSupport', () => { + test('Calling "openCustomerSupport" method before an init will fail', async () => { + expect(() => { + linkSDK.openCustomerSupport(); + }).toThrow('SDK not initialized'); + }); + + test('default params', async () => { + const open = (window.open = jest.fn()); + + linkSDK.init.call(mockValue, { + clientId: value, + scope: [value] + }); + // @ts-ignore Ignores missing arguments to test user passing no arguments + linkSDK.openCustomerSupport.call(mockValue); + + expect(open).toBeCalled(); + + const [[url, isNewTab]] = open.mock.calls; // [0][1] + + const host = `https://${mockValue.domains.vault}/${VAULT.PATHS.CUSTOMER_SUPPORT}`; + expect(url).toContain(host); + expect(isNewTab).toBe('_self'); + + const { params } = mockValue; + const qs = `client_id=${params.client_id}`; + const configs = encodeURIComponent(`sdk_platform=js;sdk_version=${packageJSON.version}`); + + expect(url).toBe(`${host}?${qs}&configs=${configs}`); + }); + + test('with params', async () => { + const open = (window.open = jest.fn()); + + linkSDK.init.call(mockValue, { + clientId: value, + scope: [value], + isTestEnvironment: true + }); + linkSDK.openCustomerSupport.call(mockValue, { + newTab: true + }); + + expect(open).toBeCalled(); + + const [[url, isNewTab]] = open.mock.calls; // [0][1] + expect(isNewTab).toBe('_blank'); + + const { params, domains } = mockValue; + const host = `https://${domains.vault}/${VAULT.PATHS.CUSTOMER_SUPPORT}`; + const qs = `client_id=${params.client_id}`; + const configs = encodeURIComponent(`sdk_platform=js;sdk_version=${packageJSON.version}`); + + expect(url).toBe(`${host}?${qs}&configs=${configs}`); + }); + }); describe('openSettings', () => { test('Calling "openSettings" method before an init will failed', async () => { diff --git a/src/endpoints.ts b/src/endpoints.ts index 92c4a3c..2d1b6f9 100644 --- a/src/endpoints.ts +++ b/src/endpoints.ts @@ -2,7 +2,10 @@ export const DOMAIN = 'getmoneytree.com'; export const VAULT = { SUBDOMAIN: 'vault', - TEST_SUBDOMAIN: 'vault-staging' + TEST_SUBDOMAIN: 'vault-staging', + PATHS: { + CUSTOMER_SUPPORT: 'customer-support' + } }; export const MY_ACCOUNT = { diff --git a/src/index.ts b/src/index.ts index db867c7..011782b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -155,6 +155,19 @@ class LinkSDK { window.open(`https://${this.domains.vault}${params}`, newTab ? '_blank' : '_self'); } + // Open Customer Support page + public openCustomerSupport({ newTab = false }: IVaultOptions = {}): void { + if (!this.isInitialized) { + throw new Error('SDK not initialized'); + } + + const params = encodeConfigWithParams(this.params, { + ...commonUrlConfig + }); + + window.open(`https://${this.domains.vault}/${VAULT.PATHS.CUSTOMER_SUPPORT}${params}`, newTab ? '_blank' : '_self'); + } + // Open the Guest settings page public openSettings({ newTab = false, backTo = location.href }: IMyAccountOptions = {}): void { if (!this.isInitialized) {