From 1791eb84811268736613f09e47c971d0d6e59627 Mon Sep 17 00:00:00 2001 From: Vivian A Goodrich <101133187+vgoodric@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:10:48 -0600 Subject: [PATCH] MWPW-158674 [MEP] Support nested placholders in MEP placeholders (#2908) * MWPW-158674 [MEP] Support nested placholders in MEP placeholders * unit test * move match functionality to reusable function * add default value for info in getManifestConfig declaration * MWPW-158142 [MEP] check for MEP placeholders as fragmentless content is inserted (#2919) * Initial checkin. Working state. * Code refactor. * Unit test initial checkin. * Refactor into reusable function. * Removed old code. * Linting. * update unit test to call create content --------- Co-authored-by: vgoodric --------- Co-authored-by: Dave Linhart <132396886+AdobeLinhart@users.noreply.github.com> --- .../personalization/personalization.js | 30 ++++++++++++++++-- .../parseNestedPlaceholders.test.js | 31 +++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 test/features/personalization/parseNestedPlaceholders.test.js diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js index dc0ae2c1fb..66fd2fbd69 100644 --- a/libs/features/personalization/personalization.js +++ b/libs/features/personalization/personalization.js @@ -148,6 +148,17 @@ const createFrag = (el, action, content, manifestId, targetManifestId) => { return frag; }; +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); @@ -158,11 +169,16 @@ export const createContent = (el, content, manifestId, targetManifestId, action, return el; } if (getSelectorType(content) !== 'fragment') { + const config = getConfig(); + const newContent = replacePlaceholders(content, config.placeholders); + 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; } @@ -727,7 +743,7 @@ export const addMepAnalytics = (config, header) => { } }); }; -export async function getManifestConfig(info, variantOverride = false) { +export async function getManifestConfig(info = {}, variantOverride = false) { const { name, manifestData, @@ -926,6 +942,13 @@ export function handleFragmentCommand(command, a) { return false; } +export function parseNestedPlaceholders({ placeholders }) { + if (!placeholders) return; + Object.entries(placeholders).forEach(([key, value]) => { + placeholders[key] = replacePlaceholders(value, placeholders); + }); +} + export async function applyPers(manifests, postLCP = false) { if (!manifests?.length) return; let experiments = manifests; @@ -935,6 +958,7 @@ export async function applyPers(manifests, postLCP = false) { } experiments = cleanAndSortManifestList(experiments); + parseNestedPlaceholders(config); let results = []; diff --git a/test/features/personalization/parseNestedPlaceholders.test.js b/test/features/personalization/parseNestedPlaceholders.test.js new file mode 100644 index 0000000000..43a5d05071 --- /dev/null +++ b/test/features/personalization/parseNestedPlaceholders.test.js @@ -0,0 +1,31 @@ +import { expect } from '@esm-bundle/chai'; +import { parseNestedPlaceholders, createContent } from '../../../libs/features/personalization/personalization.js'; +import { getConfig } from '../../../libs/utils/utils.js'; + +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 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'); + }); +});