From edb93c32543e358330231c21f3c7b83194a11a9e Mon Sep 17 00:00:00 2001 From: SbDove <100377552+SbDove@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:29:46 -0700 Subject: [PATCH] Refactor and increase testing --- src/common.js | 51 ++++++++++++--- src/identity-handler.js | 15 +++-- src/initialization.js | 4 +- test/src/tests.js | 136 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 188 insertions(+), 18 deletions(-) diff --git a/src/common.js b/src/common.js index f7bbee4..bf292fb 100644 --- a/src/common.js +++ b/src/common.js @@ -26,14 +26,19 @@ Common.prototype.buildPartnerData = function (mParticleUser) { var pdKeys = {}; var userIdentities = mParticleUser.getUserIdentities(); - var email = userIdentities.userIdentities['email']; + var email = this.normalizeEmail(userIdentities.userIdentities['email']); + var phone = this.normalizePhone(userIdentities.userIdentities['mobile_number']); + + if (!email && !phone) { + return null; + } + if (email) { - pdKeys[1] = SHA256(this.normalizeEmail(email)); + pdKeys[1] = SHA256(email); } - var phone = userIdentities.userIdentities['mobile_number']; if (phone) { - pdKeys[2]= SHA256(this.normalizePhone(phone)); + pdKeys[2]= SHA256(phone); } var pdRaw = Object.keys(pdKeys).map(function(key){ @@ -44,6 +49,9 @@ Common.prototype.buildPartnerData = function (mParticleUser) { } Common.prototype.normalizeEmail = function(email) { + if (!email || !this.validateEmail(email)) { + return null; + } var parts = email.split("@") var charactersToRemove = ['+', '.'] @@ -51,19 +59,29 @@ Common.prototype.normalizeEmail = function(email) { return email; } - parts[0]= replace(parts[0], charactersToRemove); + parts[0]= this.replace(parts[0], charactersToRemove); return parts.join('@'); } Common.prototype.normalizePhone = function(phone) { + if (!phone) { + return null; + } var charactersToRemove = [' ', '-', '(', ')'] + var normalizedPhone = this.replace(phone, charactersToRemove); + + if (normalizedPhone[0] !== '+') { + normalizedPhone = '+' + normalizedPhone + } - return replace(phone, charactersToRemove); + if (!this.validatePhone(normalizedPhone)) { + return null; + } + return normalizedPhone; } -function replace(string, targets) { - debugger; +Common.prototype.replace = function(string, targets) { var newString = ''; for(var i = 0; i < string.length; i++){ var char = string[i]; @@ -73,4 +91,21 @@ function replace(string, targets) { } return newString.toLowerCase(); } + +Common.prototype.validateEmail = function(email){ + if (!email) { + return false; + } + var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); +} + +Common.prototype.validatePhone = function(phone) { + if (!phone){ + return false; + } + var e164Regex = /^\+?[1-9]\d{1,14}$/; + + return e164Regex.test(phone); +} module.exports = Common; diff --git a/src/identity-handler.js b/src/identity-handler.js index dd70ea1..21cbb8c 100644 --- a/src/identity-handler.js +++ b/src/identity-handler.js @@ -24,18 +24,23 @@ function IdentityHandler(common) { IdentityHandler.prototype.onUserIdentified = function() {}; IdentityHandler.prototype.onIdentifyComplete = function() {}; +//Must re-initialize ID5 with partner identities(pd) in the config file on login IdentityHandler.prototype.onLoginComplete = function( mParticleUser ) { var partnerData = this.common.buildPartnerData(mParticleUser); - var id5Instance = window.ID5.init({partnerId: this.common.partnerId, pd: partnerData}) - var logId5Id = this.common.logId5Id; - id5Instance.onAvailable(function(status){ - logId5Id(status.getUserId()); - }.bind(logId5Id)); + if (partnerData) { + var id5Instance = window.ID5.init({partnerId: this.common.partnerId, pd: partnerData}) + var logId5Id = this.common.logId5Id; + + id5Instance.onAvailable(function(status){ + logId5Id(status.getUserId()); + }.bind(logId5Id)); + } }; +//Must re-initialize ID5 without partner identities (pd) in the config on logout complete IdentityHandler.prototype.onLogoutComplete = function( ) { var id5Instance = window.ID5.init({partnerId: this.common.partnerId}) diff --git a/src/initialization.js b/src/initialization.js index bc54d91..aedb3fc 100644 --- a/src/initialization.js +++ b/src/initialization.js @@ -16,9 +16,9 @@ var initialization = { /* Load your Web SDK here using a variant of your snippet from your readme that your customers would generally put into their tags Generally, our integrations create script tags and append them to the . Please follow the following format as a guide: */ - + //ID5 docs on initialization can be found here: https://github.com/id5io/id5-api.js/blob/master/README.md var id5Script = document.createElement('script'); - id5Script.src = 'https://cdn.id5-sync.com/api/1.0/id5-api.js'; // <---- Update this to be your script + id5Script.src = 'https://cdn.id5-sync.com/api/1.0/id5-api.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(id5Script); common.id5Id = null; diff --git a/test/src/tests.js b/test/src/tests.js index d6db125..ecbf72b 100644 --- a/test/src/tests.js +++ b/test/src/tests.js @@ -122,6 +122,22 @@ describe('ID5 Forwarder', function () { done(); }); + it('should call ID5.init only once on userLoginComplete with a user without email or phone', function(done){ + var user = { + getUserIdentities: function () { + return { + userIdentities: { + customerId: 'testId1234', + }, + }; + }, + }; + mParticle.forwarder.onLoginComplete(user); + + window.ID5.numberOfInitsCalled.should.equal(1); + done(); + }) + it('should call ID5.init twice on userLogoutComplete', function(done){ var user = { getUserIdentities: function () { @@ -157,7 +173,7 @@ describe('ID5 Forwarder', function () { return { userIdentities: { email: 'test@email.com', - phone: '123-456-7890', + mobile_number: '123-456-7890', } } }, @@ -166,10 +182,82 @@ describe('ID5 Forwarder', function () { var pd = mParticle.forwarder.common.buildPartnerData(user) pd.should.exist; - pd.should.equal('MT03MzA2MmQ4NzI5MjZjMmE1NTZmMTdiMzZmNTBlMzI4ZGRmOWJmZjlkNDAzOTM5YmQxNGI2YzNiN2Y1YTMzZmMy') done(); }); + it ('should build null pd when build PartnerData is called with an empty users', function(done){ + var user = { + getUserIdentities: function() { + return { + userIdentities: {} + } + }, + }; + var pd = mParticle.forwarder.common.buildPartnerData(user) + debugger; + expect(pd).to.be.null; + done(); + }); + + it ('should return null pd when buildPartnerData is called with a user only having an invalid phone number', function(done) { + var user = { + getUserIdentities: function() { + return { + userIdentities: { + mobile_number: '1234567890112233' + } + } + }, + } + var pd = mParticle.forwarder.common.buildPartnerData(user) + + expect(pd).to.be.null; + done(); + }); + + it ('should return null pd when buildPartnerData is called with a user only having an invalid email', function(done) { + var user = { + getUserIdentities: function() { + return { + userIdentities: { + email: 'test@test@test.com' + } + } + }, + } + var pd = mParticle.forwarder.common.buildPartnerData(user) + + expect(pd).to.be.null; + done(); + }); + + it ('should omit invalid identities when building PD when buildPartnerData is called', function(done) { + var user1 = { + getUserIdentities: function() { + return { + userIdentities: { + email: 'test@test@test.com', //note: invalid email address + mobile_number: '123-456-7890', + } + } + }, + } + var user2 = { + getUserIdentities: function() { + return { + userIdentities: { + mobile_number: '123-456-7890', + } + } + }, + } + var pd1 = mParticle.forwarder.common.buildPartnerData(user1); + var pd2 = mParticle.forwarder.common.buildPartnerData(user2); + + pd1.should.equal(pd2); + done(); + }) + it ('should normalize an gmail when normalizeEmail is called', function(done) { var normalizedGmail = mParticle.forwarder.common.normalizeEmail('test+test.2@gmail.com'); @@ -186,11 +274,53 @@ describe('ID5 Forwarder', function () { done(); }); + it ('should return null when normalizeEmail is called with a null value', function(done){ + var normalized = mParticle.forwarder.common.normalizeEmail() + + expect(normalized).to.be.null; + done(); + }); + it ('should normalize phone numbers when normalizePhone is called', function(done) { var normalizedPhone = mParticle.forwarder.common.normalizePhone('(123) 456-7890'); normalizedPhone.should.exist; - normalizedPhone.should.equal('1234567890'); + normalizedPhone.should.equal('+1234567890'); + done(); + }); + + it ('should return null when normalizePhone is called with a null value', function(done){ + var normalizedPhone = mParticle.forwarder.common.normalizePhone(); + + expect(normalizedPhone).to.be.null; + done(); + }); + + it ('should return true when a valid e.164 phone number is passed to validatePhone', function(done) { + var validated = mParticle.forwarder.common.validatePhone('+1234567890'); + + validated.should.equal(true); + done(); + }); + + it ('should return false when an invalid e.164 phone number is passed to validatePhone', function(done) { + var validated = mParticle.forwarder.common.validatePhone('1234567890112233'); + + validated.should.equal(false); + done(); + }); + + it ('should return true when a valid email is passed to validateEmail', function(done) { + var validated = mParticle.forwarder.common.validateEmail('test@test.com'); + + validated.should.equal(true); + done(); + }) + + it ('should return false when an invalid email is passed to validateEmail', function(done) { + var validated = mParticle.forwarder.common.validateEmail('test@test@test.com') + + validated.should.equal(false); done(); }) })