diff --git a/edsdme/scripts/personalization.js b/edsdme/scripts/personalization.js index fdfcb77..3f6669d 100644 --- a/edsdme/scripts/personalization.js +++ b/edsdme/scripts/personalization.js @@ -5,7 +5,8 @@ import { partnerIsSignedIn, getPartnerDataCookieObject, signedInNonMember, - isReseller , + isReseller, + getNodesByXPath } from './utils.js'; @@ -16,6 +17,7 @@ const PERSONALIZATION_MARKER = 'partner-personalization'; const PROGRAM = getCurrentProgramType(); const PARTNER_LEVEL = getPartnerDataCookieValue(PROGRAM, 'level'); const COOKIE_OBJECT = getPartnerDataCookieObject(PROGRAM); + const PERSONALIZATION_CONDITIONS = { 'partner-not-member': signedInNonMember(), 'partner-not-signed-in': !partnerIsSignedIn(), @@ -24,22 +26,15 @@ const PERSONALIZATION_CONDITIONS = { 'partner-level': (level) => PARTNER_LEVEL === level, }; -export function getNodesByXPath(query, context = document) { - const nodes = []; - const xpathResult = document.evaluate(query, context); - let current = xpathResult?.iterateNext(); - while (current) { - nodes.push(current); - current = xpathResult.iterateNext(); - } - return nodes; -} function personalizePlaceholders(placeholders, context = document) { Object.entries(placeholders).forEach(([key, value]) => { const placeholderValue = COOKIE_OBJECT[key]; getNodesByXPath(value, context).forEach((el) => { - if (!placeholderValue) el.remove(); + if (!placeholderValue) { + el.remove(); + return; + } el.textContent = el.textContent.replace(`$${key}`, placeholderValue); }); }); @@ -80,11 +75,11 @@ function hideSections(page) { function personalizePage(page) { const blocks = Array.from(page.getElementsByClassName(PERSONALIZATION_MARKER)); - hideSections(page); blocks.forEach((el) => { const conditions = Object.values(el.classList); hideElement(el, conditions); }); + hideSections(page); } export function applyPagePersonalization() { diff --git a/edsdme/scripts/scripts.js b/edsdme/scripts/scripts.js index 5d3cac1..68a99e9 100644 --- a/edsdme/scripts/scripts.js +++ b/edsdme/scripts/scripts.js @@ -1,4 +1,3 @@ -import { setLibs, redirectLoggedinPartner, updateIMSConfig, preloadResources, getRenewBanner } from './utils.js'; import { applyPagePersonalization } from './personalization.js'; import { setLibs, redirectLoggedinPartner, updateIMSConfig, preloadResources, getRenewBanner, updateNavigation, updateFooter } from './utils.js'; diff --git a/edsdme/scripts/utils.js b/edsdme/scripts/utils.js index eca43e3..270eac0 100644 --- a/edsdme/scripts/utils.js +++ b/edsdme/scripts/utils.js @@ -397,3 +397,14 @@ export function updateFooter(locales) { const footerLoggedIn = getMetadataContent('footer-loggedin-source'); footerMeta.content = footerLoggedIn ?? `${prefix}/edsdme/partners-shared/loggedin-footer`; } + +export function getNodesByXPath(query, context = document) { + const nodes = []; + const xpathResult = document.evaluate(query, context); + let current = xpathResult?.iterateNext(); + while (current) { + nodes.push(current); + current = xpathResult.iterateNext(); + } + return nodes; +} diff --git a/test/scripts/mocks/personalization.html b/test/scripts/mocks/personalization.html new file mode 100644 index 0000000..a1be0d6 --- /dev/null +++ b/test/scripts/mocks/personalization.html @@ -0,0 +1,114 @@ +
+
+
+
+
+ + + + + + +
+
+
+
+

+ + + + + + +

+

Heading XL Marquee standard medium left

+

Welcome $firstName

+

Body M Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.

+

Lorem ipsum Learn more Text link

+
+
+ + + + + + +
+
+
+
+
+
+
+
+

Partner NOT SIGNED IN

+

Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.

+

Explore the premium collection

+

Join Now

+
+
+
+
+
+
+

Partner NON MEMBER

+

Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.

+

Explore the premium collection

+

Join Now

+
+
+
+
+
+
+

MEMBER

+

Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.

+
+
+
+
+
+
+
+
+

Partner GOLD

+

Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.

+
+
+
+
+
+
+
+
+

Partner Platinum

+

Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.

+

Explore the premium collection

+
+
+
+ +
+
+
+
+
+

Partner Platinum section

+

Featuring over 600,000 hand-picked stock photos and graphics, curated from the world’s leading photographers, illustrators, and agencies. Our Premium collection is perfect for organizations looking for authentic, high-quality commercial content, and easy licensing plans.

+

Explore the premium collection

+
+
+
+ +
+
diff --git a/test/scripts/personalization.jest.js b/test/scripts/personalization.jest.js new file mode 100644 index 0000000..2319a18 --- /dev/null +++ b/test/scripts/personalization.jest.js @@ -0,0 +1,158 @@ +/** + * @jest-environment jsdom + */ +import path from 'path'; +import fs from 'fs'; + +const PERSONALIZATION_HIDE_CLASS = 'personalization-hide'; + +function importModules() { + const utils = require('../../edsdme/scripts/utils.js'); + const placeholderElement = document.querySelector('#welcome-firstname'); + jest.spyOn(utils, 'getNodesByXPath').mockImplementation(() => [placeholderElement]); + const { applyPagePersonalization } = require('../../edsdme/scripts/personalization.js'); + + return applyPagePersonalization; +} + +describe('Test utils.js', () => { + beforeEach(() => { + jest.clearAllMocks(); + window = Object.create(window); + Object.defineProperty(window, 'location', { + value: { + pathname:'/channelpartners', + }, + writable: true + }); + document.body.innerHTML = fs.readFileSync( + path.resolve(__dirname, './mocks/personalization.html'), + 'utf8' + ); + document.cookie = 'partner_data='; + }); + afterEach(() => { + document.body.innerHTML = ''; + }); + it('Populate placeholder if user is a member', () => { + jest.isolateModules(() => { + const cookieObject = { + CPP: { + status: 'MEMBER', + firstName: 'Test user' + } + }; + document.cookie = `partner_data=${JSON.stringify(cookieObject)}`; + const applyPagePersonalization = importModules(); + applyPagePersonalization(); + const placeholderElementAfter = document.querySelector('#welcome-firstname'); + expect(placeholderElementAfter.textContent.includes(cookieObject.CPP.firstName)).toBe(true); + }); + }); + it('Remove placeholder if user is not a member', () => { + jest.isolateModules(() => { + const cookieObject = { + SPP: { + status: 'MEMBER', + firstName: 'Test use' + } + }; + document.cookie = `partner_data=${JSON.stringify(cookieObject)}`; + const applyPagePersonalization = importModules(); + applyPagePersonalization(); + const placeholderElementAfter = document.querySelector('#welcome-firstname'); + expect(placeholderElementAfter).toBe(null); + }); + }); + it('Show partner-not-signed-in block', () => { + jest.isolateModules(() => { + const applyPagePersonalization = importModules(); + applyPagePersonalization(); + const notSignedInBlock = document.querySelector('.partner-not-signed-in'); + expect(notSignedInBlock.classList.contains(PERSONALIZATION_HIDE_CLASS)).toBe(false); + }); + }); + + it('Show partner-not-member block', () => { + jest.isolateModules(() => { + const cookieObject = { + SPP: { + status: 'MEMBER', + firstName: 'Test use' + } + }; + document.cookie = `partner_data=${JSON.stringify(cookieObject)}`; + const applyPagePersonalization = importModules(); + applyPagePersonalization(); + const notMemberBlock = document.querySelector('.partner-not-member'); + expect(notMemberBlock.classList.contains(PERSONALIZATION_HIDE_CLASS)).toBe(false); + }); + }); + it('Show partner-all-levels block', () => { + jest.isolateModules(() => { + const cookieObject = { + CPP: { + status: 'MEMBER', + firstName: 'Test use', + level: 'Gold' + } + }; + document.cookie = `partner_data=${JSON.stringify(cookieObject)}`; + const applyPagePersonalization = importModules(); + applyPagePersonalization(); + const allLevelsBlock = document.querySelector('.partner-all-levels'); + expect(allLevelsBlock.classList.contains(PERSONALIZATION_HIDE_CLASS)).toBe(false); + }); + }); + it('Show partner-level-gold block', () => { + jest.isolateModules(() => { + const cookieObject = { + CPP: { + status: 'MEMBER', + firstName: 'Test use', + level: 'Gold' + } + }; + document.cookie = `partner_data=${JSON.stringify(cookieObject)}`; + const applyPagePersonalization = importModules(); + applyPagePersonalization(); + const goldBlock = document.querySelector('.partner-level-gold'); + expect(goldBlock.classList.contains(PERSONALIZATION_HIDE_CLASS)).toBe(false); + }); + }); + it('Show partner-level-platinum but don\'t show partner-level-gold block', () => { + jest.isolateModules(() => { + const cookieObject = { + CPP: { + status: 'MEMBER', + firstName: 'Test use', + level: 'Platinum' + } + }; + document.cookie = `partner_data=${JSON.stringify(cookieObject)}`; + const applyPagePersonalization = importModules(); + applyPagePersonalization(); + const goldBlock = document.querySelector('.partner-level-gold'); + const platinumBlock = document.querySelector('.partner-level-platinum'); + expect(platinumBlock.classList.contains(PERSONALIZATION_HIDE_CLASS)).toBe(false); + expect(goldBlock.classList.contains(PERSONALIZATION_HIDE_CLASS)).toBe(true); + }); + }); + it('Show partner-level-platinum section', () => { + jest.isolateModules(() => { + const cookieObject = { + CPP: { + status: 'MEMBER', + firstName: 'Test use', + level: 'Platinum' + } + }; + document.cookie = `partner_data=${JSON.stringify(cookieObject)}`; + const applyPagePersonalization = importModules(); + applyPagePersonalization(); + const platinumBlock = document.querySelector('#platinum-section'); + expect(platinumBlock.classList.contains(PERSONALIZATION_HIDE_CLASS)).toBe(false); + }); + }); +}); +