diff --git a/.flowconfig b/.flowconfig index fefe0d1d..d9ccc79f 100644 --- a/.flowconfig +++ b/.flowconfig @@ -3,6 +3,7 @@ .*/node_modules/npm .*/node_modules/jsonlint .*/dist/module +.*/test/tracker/set-user.test.js [untyped] .*/src/lib/jetlore [include] diff --git a/src/lib/get-property-id.js b/src/lib/get-property-id.js index 00d2d887..8811c5c0 100644 --- a/src/lib/get-property-id.js +++ b/src/lib/get-property-id.js @@ -1,33 +1,40 @@ +/* @flow */ import { getClientID, getMerchantID } from '@paypal/sdk-client/src'; -export const getPropertyId = ({ paramsToPropertyIdUrl }) => { - return new Promise(resolve => { - const clientId = getClientID(); - const merchantId = getMerchantID()[0]; - const propertyIdKey = `property-id-${ clientId }-${ merchantId }`; - const savedPropertyId = window.localStorage.getItem(propertyIdKey); - const currentUrl = `${ window.location.protocol }//${ window.location.host }`; - if (savedPropertyId) { - return resolve(savedPropertyId); - } - let url; - if (paramsToPropertyIdUrl) { - url = paramsToPropertyIdUrl(); - } else { - url = 'https://paypal.com/tagmanager/containers/xo'; - } - return window.fetch(`${ url }?mrid=${ merchantId }&url=${ encodeURIComponent(currentUrl) }`) - .then(res => { - if (res.status === 200) { - return res; - } - }) - .then(r => r.json()).then(container => { - window.localStorage.setItem(propertyIdKey, container.id); - resolve(container.id); - }) - .catch(() => { - // doing nothing for now since there's no logging - }); - }); -}; \ No newline at end of file +import type { + Config +} from './types'; + +export const getPropertyId = ({ paramsToPropertyIdUrl } : Config) => { + // $FlowFixMe + return new Promise(resolve => { + const clientId = getClientID(); + const merchantId = getMerchantID()[0]; + const propertyIdKey = `property-id-${ clientId }-${ merchantId }`; + const savedPropertyId = window.localStorage.getItem(propertyIdKey); + const currentUrl = `${ window.location.protocol }//${ window.location.host }`; + if (savedPropertyId) { + return resolve(savedPropertyId); + } + let url; + // $FlowFixMe + if (paramsToPropertyIdUrl) { + url = paramsToPropertyIdUrl(); + } else { + url = 'https://paypal.com/tagmanager/containers/xo'; + } + return window.fetch(`${ url }?mrid=${ merchantId }&url=${ encodeURIComponent(currentUrl) }`) + .then(res => { + if (res.status === 200) { + return res; + } + }) + .then(r => r.json()).then(container => { + window.localStorage.setItem(propertyIdKey, container.id); + resolve(container.id); + }) + .catch(() => { + // doing nothing for now since there's no logging + }); + }); +}; diff --git a/src/lib/track.js b/src/lib/track.js index 9508348f..f6cb412b 100644 --- a/src/lib/track.js +++ b/src/lib/track.js @@ -21,11 +21,6 @@ export const track = (config : Config, trackingType : TrackingType, trackingD id: getUserIdCookie() }; - // remove null, undefined values - user.id || delete user.id - user.email || delete user.email - user.name || delete user.name - const deviceInfo = getDeviceInfo(); const data = { ...trackingData, @@ -46,6 +41,8 @@ export const track = (config : Config, trackingType : TrackingType, trackingD img.src = `https://www.paypal.com/targeting/track/${ trackingType }?data=${ encodeData(data) }`; } + // TODO: this will add a new image EVERY time the 'track' method is called. There's no reason + // to clutter the DOM like this. We should replace the old image. if (document.body) { document.body.appendChild(img); } diff --git a/src/tracker-component.js b/src/tracker-component.js index 89c01abb..901e9131 100644 --- a/src/tracker-component.js +++ b/src/tracker-component.js @@ -96,6 +96,7 @@ const getJetlorePayload = (type : string, options : Object) : Object => { let trackEventQueue = []; export const clearTrackQueue = (config : Config) => { + // TODO: replace 'filter' with 'forEach' // $FlowFixMe return trackEventQueue.filter(([ trackingType, trackingData ]) => { // eslint-disable-line array-callback-return track(config, trackingType, trackingData); @@ -149,9 +150,10 @@ const clearCancelledCart = () => { window.localStorage.removeItem(storage.paypalCrCartExpiry); window.localStorage.removeItem(storage.paypalCrCart); }; - +// $FlowFixMe export const Tracker = (config? : Config = {}) => { - config = { ...defaultTrackerConfig, ...config } + // $FlowFixMe + config = { ...defaultTrackerConfig, ...config }; /* * Use the get param ?ppDebug=true to see logs * @@ -221,12 +223,12 @@ export const Tracker = (config? : Config = {}) => { }, purchase: (data : PurchaseData) => track(config, 'purchase', data), setUser: (data : UserData) => { - const user = data.user || data - const configUser = config.user || {} + const user = data.user || data; + const configUser = config.user || {}; - const userId = user.id !== undefined ? user.id : config.user.id - const userEmail = user.email !== undefined ? user.email : config.user.email - const userName = user.name !== undefined ? user.name : config.user.name + const userId = user.id !== undefined ? user.id : configUser.id; + const userEmail = user.email !== undefined ? user.email : configUser.email; + const userName = user.name !== undefined ? user.name : configUser.name; config = { ...config, diff --git a/test/tracker-component.test.js b/test/tracker-component.test.js index c0cbf31e..90837a9d 100644 --- a/test/tracker-component.test.js +++ b/test/tracker-component.test.js @@ -464,7 +464,7 @@ describe('paypal.Tracker', () => { user: { id: 'abc123', email: '__test__email9', - name: '__test__userName9', + name: '__test__userName9' }, propertyId, trackingType: 'setUser', @@ -498,7 +498,7 @@ describe('paypal.Tracker', () => { user: { id: 'abc123', email: '__test__email@gmail.com', - name: '__test__name', + name: '__test__name' }, propertyId, trackingType: 'setUser', @@ -546,7 +546,7 @@ describe('paypal.Tracker', () => { user: { id: 'abc123', email: '__test__email2', - name: '__test__name1', + name: '__test__name1' }, propertyId, trackingType: 'cartEvent', @@ -588,7 +588,7 @@ describe('paypal.Tracker', () => { total: '12345.67', currencyCode: 'USD', cartEventType: 'addToCart', - user: { id: '__test__cookie-id' }, + user: { id: '__test__cookie-id', email: null, name: null }, propertyId, trackingType: 'cartEvent', clientId: 'abcxyz123', diff --git a/test/tracker/set-user.test.js b/test/tracker/set-user.test.js index 5bca585d..a2826895 100644 --- a/test/tracker/set-user.test.js +++ b/test/tracker/set-user.test.js @@ -1,20 +1,20 @@ -/* global it describe beforeEach expect jest */ /* @flow */ +/* global it describe beforeEach afterAll expect jest */ import { Tracker } from '../../src/tracker-component'; import { getPropertyId } from '../../src/lib/get-property-id'; import { track } from '../../src/lib/track'; - import constants from '../../src/lib/constants'; -jest.mock('../../src/lib/track') +jest.mock('../../src/lib/track'); jest.mock('../../src/lib/get-property-id', () => { return { + // eslint-disable-next-line require-await getPropertyId: async () => 'mockpropertyidofsomekind' - } -}) + }; +}); describe('setUser', () => { - const { defaultTrackerConfig } = constants + const { defaultTrackerConfig } = constants; let config; let mockItem; @@ -35,7 +35,7 @@ describe('setUser', () => { price: '100.00', title: 'Best Buy', url: 'http://localhost.paypal.com:8080/us/gifts/brands/best-buy', - quantity: 1, + quantity: 1 }; }); @@ -43,21 +43,20 @@ describe('setUser', () => { track.mockReset(); window.localStorage.removeItem('paypal-cr-cart'); window.localStorage.removeItem('paypal-cr-cart-expirty'); - }) + }); afterAll(() => { track.mockRestore(); getPropertyId.mockRestore(); - }) + }); it('user should be set when the tracker is initialized', () => { const tracker = Tracker(config); - let args - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); - args = track.mock.calls + const args = track.mock.calls; expect(args[0][0].user).toEqual(config.user); expect(args[1][0].user).toEqual(config.user); @@ -65,44 +64,41 @@ describe('setUser', () => { it('no user should be set if no configuration is passed to initialization', (done) => { const tracker = Tracker(); - let args // wait for mock propertyId to resolve setTimeout(() => { - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); - args = track.mock.calls + const args = track.mock.calls; expect(args[0][0].user).toEqual(defaultTrackerConfig.user); expect(args[1][0].user).toEqual(defaultTrackerConfig.user); - done() - }, 100) + done(); + }, 100); }); it('no user should be set if no user is passed to initialization', () => { - const tracker = Tracker({propertyId: 'somevalue'}); - let args + const tracker = Tracker({ propertyId: 'somevalue' }); - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); - args = track.mock.calls + const args = track.mock.calls; expect(args[0][0].user).toEqual(defaultTrackerConfig.user); expect(args[1][0].user).toEqual(defaultTrackerConfig.user); }); it('user should be set when set user is called', () => { - const tracker = Tracker({propertyId: 'somevalue'}); - let args + const tracker = Tracker({ propertyId: 'somevalue' }); - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); - tracker.setUser(config.user) - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) + tracker.setUser(config.user); + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); - args = track.mock.calls + const args = track.mock.calls; expect(args[0][0].user).toEqual(defaultTrackerConfig.user); expect(args[1][0].user).toEqual(defaultTrackerConfig.user); expect(args[2][0].user).toEqual(config.user); @@ -115,19 +111,18 @@ describe('setUser', () => { id: 'wut', name: 'Steve Jobs', email: 'steve@apple.com' - } + }; const tracker = Tracker(config); - let args - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); - tracker.setUser(alternateUser) - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) + tracker.setUser(alternateUser); + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); - args = track.mock.calls + const args = track.mock.calls; expect(args[0][0].user).toEqual(config.user); expect(args[1][0].user).toEqual(config.user); expect(args[2][0].user).toEqual(alternateUser); @@ -141,19 +136,18 @@ describe('setUser', () => { id: 'wut', name: 'Steve Jobs', email: 'steve@apple.com' - } + }; - const tracker = Tracker({propertyId: 'somevalue'}); - let args + const tracker = Tracker({ propertyId: 'somevalue' }); - tracker.setUser(alternateUser) - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) + tracker.setUser(alternateUser); + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); - tracker.setUser({user: config.user}) - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) - args = track.mock.calls + tracker.setUser({ user: config.user }); + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); + const args = track.mock.calls; expect(args[0][0].user).toEqual(alternateUser); expect(args[1][0].user).toEqual(alternateUser); @@ -168,22 +162,21 @@ describe('setUser', () => { id: 'wut', name: 'Steve Jobs', email: 'steve@apple.com' - } + }; const tracker = Tracker(config); - let args tracker.setUser({ id: null, email: null, name: null - }) - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) - - tracker.setUser(alternateUser) - tracker.addToCart({items: [mockItem]}) - tracker.removeFromCart({items: [mockItem]}) - args = track.mock.calls + }); + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); + + tracker.setUser(alternateUser); + tracker.addToCart({ items: [ mockItem ] }); + tracker.removeFromCart({ items: [ mockItem ] }); + const args = track.mock.calls; expect(args[0][0].user).toEqual(defaultTrackerConfig.user); expect(args[1][0].user).toEqual(defaultTrackerConfig.user);