From 3a04022cb865c38b90232957af4863b3c98eedf1 Mon Sep 17 00:00:00 2001 From: AdobeLinhart Date: Wed, 18 Sep 2024 14:36:48 -0600 Subject: [PATCH 1/7] Initial checkin. Working state. --- .../personalization/personalization.js | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js index b51101f720..31a51009b2 100644 --- a/libs/features/personalization/personalization.js +++ b/libs/features/personalization/personalization.js @@ -150,6 +150,21 @@ const createFrag = (el, action, content, manifestId, targetManifestId) => { return frag; }; +export const checkCustomPlaceholders = (content) => { + //check if content has {{}}, move into new function and export + // reference modifyNonFragmentSelector.test for unit testing + let newContent = content; + + if (newContent.match(/{{(.*)}}/)) { + const config = getConfig(); + const regEx = new RegExp(Object.keys(config.placeholders).map((item) => `{{${item}}}`).join('|'), 'gi'); + + newContent = newContent.replace(regEx, (matched) => config.placeholders[matched.replace(/[\]{}]/g, '')]); + } + + return newContent; +}; + export const createContent = (el, content, manifestId, targetManifestId, action, modifiers) => { if (action === 'replace') { addIds(el, manifestId, targetManifestId); @@ -160,11 +175,15 @@ export const createContent = (el, content, manifestId, targetManifestId, action, return el; } if (getSelectorType(content) !== 'fragment') { + const newContent = checkCustomPlaceholders(content); + if (action === 'replace') { - el.innerHTML = content; + el.innerHTML = newContent; + return el; } - const container = createTag('div', {}, content); + + const container = createTag('div', {}, newContent); addIds(container, manifestId, targetManifestId); return container; } From 54cb6ba60ac9cc7011d5b57ab491f0a28312bdfd Mon Sep 17 00:00:00 2001 From: AdobeLinhart Date: Wed, 18 Sep 2024 18:31:19 -0600 Subject: [PATCH 2/7] Code refactor. --- libs/features/personalization/personalization.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js index 31a51009b2..770d182777 100644 --- a/libs/features/personalization/personalization.js +++ b/libs/features/personalization/personalization.js @@ -151,16 +151,17 @@ const createFrag = (el, action, content, manifestId, targetManifestId) => { }; export const checkCustomPlaceholders = (content) => { - //check if content has {{}}, move into new function and export - // reference modifyNonFragmentSelector.test for unit testing let newContent = content; - if (newContent.match(/{{(.*)}}/)) { - const config = getConfig(); - const regEx = new RegExp(Object.keys(config.placeholders).map((item) => `{{${item}}}`).join('|'), 'gi'); + const config = getConfig(); + const regex = /{{(.*?)}}/g; - newContent = newContent.replace(regEx, (matched) => config.placeholders[matched.replace(/[\]{}]/g, '')]); - } + newContent = newContent.replace(regex, (match, prop) => { + if (Object.prototype.hasOwnProperty.call(config.placeholders, prop)) { + return config.placeholders[prop]; + } + return match; + }); return newContent; }; From 7219977f087053eaaa1a583aef842e7bc7f3e089 Mon Sep 17 00:00:00 2001 From: AdobeLinhart Date: Thu, 19 Sep 2024 10:46:13 -0600 Subject: [PATCH 3/7] Unit test initial checkin. --- .../placeholderPerformance.test.js | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 test/features/personalization/placeholderPerformance.test.js diff --git a/test/features/personalization/placeholderPerformance.test.js b/test/features/personalization/placeholderPerformance.test.js new file mode 100644 index 0000000000..9554a88e9d --- /dev/null +++ b/test/features/personalization/placeholderPerformance.test.js @@ -0,0 +1,36 @@ +import { expect } from '@esm-bundle/chai'; +import { getConfig } from '../../../libs/utils/utils.js'; +import { checkCustomPlaceholders } from '../../../libs/features/personalization/personalization.js'; + +const values = [ + { + b: 'This is a string with no placeholders.', + a: 'This is a string with no placeholders.', + }, + { + b: 'This is a string with custom placeholders {{test-placeholder}} and {{marquee-headline}}.', + a: 'This is a string with custom placeholders value1-us and hello-us.', + }, + { + b: 'This is a string with custom placeholders {{test-placeholder}} and {{marquee-headline}}, then the standard placeholder {{buy-now}}.', + a: 'This is a string with custom placeholders value1-us and hello-us, then the standard placeholder {{buy-now}}.', + }, +]; +describe('test different values', () => { + before(() => { + // Add custom keys so tests doesn't rely on real data + const config = getConfig(); + config.placeholders = { + 'test-placeholder': 'value1-us', + 'marquee-headline': 'hello-us', + }; + }); + + values.forEach((value) => { + it(`should return the expected value for ${value.b}`, async () => { + const { modifiedSelector, modifiers } = checkCustomPlaceholders(value.b); + expect(modifiedSelector).to.equal(value.a); + expect(modifiers).to.deep.equal(value.m || []); + }); + }); +}); From 3bd6955e9294aac6d0bbceac1539d18d98919a43 Mon Sep 17 00:00:00 2001 From: AdobeLinhart Date: Thu, 19 Sep 2024 10:58:54 -0600 Subject: [PATCH 4/7] Refactor into reusable function. --- .../personalization/personalization.js | 25 +++++++------ .../placeholderPerformance.test.js | 36 ------------------- 2 files changed, 14 insertions(+), 47 deletions(-) delete mode 100644 test/features/personalization/placeholderPerformance.test.js diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js index c1c2a4da2f..05a20d6b3a 100644 --- a/libs/features/personalization/personalization.js +++ b/libs/features/personalization/personalization.js @@ -164,6 +164,17 @@ export const checkCustomPlaceholders = (content) => { return newContent; }; +export function replacePlaceholders(value, placeholders) { + let val = value; + const matches = val.match(/{{(.*?)}}/g); + if (!matches) return val; + matches.forEach((match) => { + const key = match.replace(/{{|}}/g, '').trim(); + if (placeholders[key]) val = val.replace(match, placeholders[key]); + }); + return val; +} + export const createContent = (el, content, manifestId, targetManifestId, action, modifiers) => { if (action === 'replace') { addIds(el, manifestId, targetManifestId); @@ -174,7 +185,8 @@ export const createContent = (el, content, manifestId, targetManifestId, action, return el; } if (getSelectorType(content) !== 'fragment') { - const newContent = checkCustomPlaceholders(content); + const config = getConfig(); + const newContent = replacePlaceholders(content, config.placeholders); if (action === 'replace') { el.innerHTML = newContent; @@ -946,16 +958,7 @@ export function handleFragmentCommand(command, a) { return false; } -function replacePlaceholders(value, placeholders) { - let val = value; - const matches = val.match(/{{(.*?)}}/g); - if (!matches) return val; - matches.forEach((match) => { - const key = match.replace(/{{|}}/g, '').trim(); - if (placeholders[key]) val = val.replace(match, placeholders[key]); - }); - return val; -} + export function parseNestedPlaceholders({ placeholders }) { if (!placeholders) return; diff --git a/test/features/personalization/placeholderPerformance.test.js b/test/features/personalization/placeholderPerformance.test.js deleted file mode 100644 index 9554a88e9d..0000000000 --- a/test/features/personalization/placeholderPerformance.test.js +++ /dev/null @@ -1,36 +0,0 @@ -import { expect } from '@esm-bundle/chai'; -import { getConfig } from '../../../libs/utils/utils.js'; -import { checkCustomPlaceholders } from '../../../libs/features/personalization/personalization.js'; - -const values = [ - { - b: 'This is a string with no placeholders.', - a: 'This is a string with no placeholders.', - }, - { - b: 'This is a string with custom placeholders {{test-placeholder}} and {{marquee-headline}}.', - a: 'This is a string with custom placeholders value1-us and hello-us.', - }, - { - b: 'This is a string with custom placeholders {{test-placeholder}} and {{marquee-headline}}, then the standard placeholder {{buy-now}}.', - a: 'This is a string with custom placeholders value1-us and hello-us, then the standard placeholder {{buy-now}}.', - }, -]; -describe('test different values', () => { - before(() => { - // Add custom keys so tests doesn't rely on real data - const config = getConfig(); - config.placeholders = { - 'test-placeholder': 'value1-us', - 'marquee-headline': 'hello-us', - }; - }); - - values.forEach((value) => { - it(`should return the expected value for ${value.b}`, async () => { - const { modifiedSelector, modifiers } = checkCustomPlaceholders(value.b); - expect(modifiedSelector).to.equal(value.a); - expect(modifiers).to.deep.equal(value.m || []); - }); - }); -}); From 52c00aae7a40d1002ddb5b4fee7bd62316c95fdd Mon Sep 17 00:00:00 2001 From: AdobeLinhart Date: Thu, 19 Sep 2024 12:09:46 -0600 Subject: [PATCH 5/7] Removed old code. --- libs/features/personalization/personalization.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js index 24f816e246..7a05ef0ab3 100644 --- a/libs/features/personalization/personalization.js +++ b/libs/features/personalization/personalization.js @@ -148,22 +148,6 @@ const createFrag = (el, action, content, manifestId, targetManifestId) => { return frag; }; -export const checkCustomPlaceholders = (content) => { - let newContent = content; - - const config = getConfig(); - const regex = /{{(.*?)}}/g; - - newContent = newContent.replace(regex, (match, prop) => { - if (Object.prototype.hasOwnProperty.call(config.placeholders, prop)) { - return config.placeholders[prop]; - } - return match; - }); - - return newContent; -}; - export function replacePlaceholders(value, placeholders) { let val = value; const matches = val.match(/{{(.*?)}}/g); From 63847826223237260c5c5f6d7b32d7a8281f80d0 Mon Sep 17 00:00:00 2001 From: AdobeLinhart Date: Thu, 19 Sep 2024 12:15:38 -0600 Subject: [PATCH 6/7] Linting. --- libs/features/personalization/personalization.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js index 7a05ef0ab3..66fd2fbd69 100644 --- a/libs/features/personalization/personalization.js +++ b/libs/features/personalization/personalization.js @@ -942,8 +942,6 @@ export function handleFragmentCommand(command, a) { return false; } - - export function parseNestedPlaceholders({ placeholders }) { if (!placeholders) return; Object.entries(placeholders).forEach(([key, value]) => { From ffb0fb1699f9a3a05a0a97e4bedf08076ec9e515 Mon Sep 17 00:00:00 2001 From: vgoodric Date: Thu, 19 Sep 2024 12:39:28 -0600 Subject: [PATCH 7/7] update unit test to call create content --- .../parseNestedPlaceholders.test.js | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/test/features/personalization/parseNestedPlaceholders.test.js b/test/features/personalization/parseNestedPlaceholders.test.js index e53d080d92..43a5d05071 100644 --- a/test/features/personalization/parseNestedPlaceholders.test.js +++ b/test/features/personalization/parseNestedPlaceholders.test.js @@ -1,19 +1,31 @@ import { expect } from '@esm-bundle/chai'; -import { parseNestedPlaceholders } from '../../../libs/features/personalization/personalization.js'; +import { parseNestedPlaceholders, createContent } from '../../../libs/features/personalization/personalization.js'; +import { getConfig } from '../../../libs/utils/utils.js'; -const config = { - placeholders: { - 'promo-product-name': 'CC All Apps', - 'promo-header': 'Buy now and save {{promo-discount}}% off {{promo-product-name}}.', - 'promo-discount': '50', - 'promo-description': 'For just {{promo-price}}, get 20+...', - 'promo-price': 'US$49.99', - }, +const config = getConfig(); +config.placeholders = { + 'promo-product-name': 'CC All Apps', + 'promo-header': 'Buy now and save {{promo-discount}}% off {{promo-product-name}}.', + 'promo-discount': '50', + 'promo-description': 'For just {{promo-price}}, get 20+...', + 'promo-price': 'US$49.99', }; -describe('test different values', () => { +describe('test different values for parseNestedPlaceholders', () => { it('should update placeholders', () => { parseNestedPlaceholders(config); expect(config.placeholders['promo-header']).to.equal('Buy now and save 50% off CC All Apps.'); expect(config.placeholders['promo-description']).to.equal('For just US$49.99, get 20+...'); }); }); +describe('test createContent', () => { + const el = document.createElement('div'); + it('append action', () => { + const newContent = createContent(el, '{{promo-discount}}', false, false, 'append', []); + expect(newContent.innerHTML).to.equal('50'); + }); + it('replace action', () => { + el.innerHTML = 'Hello World'; + const newContent = createContent(el, '{{promo-discount}}', false, false, 'replace', []); + expect(newContent.innerHTML).to.equal('50'); + }); +});