diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js index 66d5936c15..4a092127b4 100644 --- a/libs/features/personalization/personalization.js +++ b/libs/features/personalization/personalization.js @@ -169,21 +169,19 @@ const fetchData = async (url, type = DATA_TYPE.JSON) => { return null; }; -const getBlockProps = (fVal) => { +const getBlockProps = (fVal, miloLibs, origin) => { let val = fVal; if (val?.includes('\\')) val = val?.split('\\').join('/'); if (!val?.startsWith('/')) val = `/${val}`; const blockSelector = val?.split('/').pop(); - const { origin } = PAGE_URL; - if (origin.includes('.hlx.') || origin.includes('localhost')) { - if (val.startsWith('/libs/')) { - /* c8 ignore next 2 */ - const { miloLibs, codeRoot } = getConfig(); - val = `${miloLibs || codeRoot}${val.replace('/libs', '')}`; - } else { - val = `${origin}${val}`; - } + + if (val.startsWith('/libs/')) { + /* c8 ignore next 1 */ + val = `${miloLibs}${val.replace('/libs', '')}`; + } else { + val = `${origin}${val}`; } + return { blockSelector, blockTarget: val }; }; @@ -457,6 +455,7 @@ const getVariantInfo = (line, variantNames, variants, manifestPath, manifestOver if (pageFilter && !matchGlob(pageFilter, new URL(window.location).pathname)) return; if (!config.mep?.preview) manifestId = false; + const { origin } = PAGE_URL; variantNames.forEach((vn) => { const targetManifestId = vn.startsWith(TARGET_EXP_PREFIX) ? targetId : false; if (!line[vn] || line[vn].toLowerCase() === 'false') return; @@ -483,7 +482,7 @@ const getVariantInfo = (line, variantNames, variants, manifestPath, manifestOver variants[vn][action] = variants[vn][action] || []; if (action === 'useblockcode') { - const { blockSelector, blockTarget } = getBlockProps(line[vn]); + const { blockSelector, blockTarget } = getBlockProps(line[vn], config.miloLibs, origin); variants[vn][action].push({ selector: blockSelector, val: blockTarget, @@ -578,20 +577,26 @@ const checkForParamMatch = (paramStr) => { return false; }; +function trimNames(arr) { + return arr.map((v) => v.trim()).filter(Boolean); +} +export function buildVariantInfo(variantNames) { + return variantNames.reduce((acc, name) => { + let nameArr = [name]; + if (!name.startsWith(TARGET_EXP_PREFIX)) nameArr = name.split(','); + acc[name] = trimNames(nameArr); + acc.allNames = [...acc.allNames, ...trimNames(name.split(/[,&]|\bnot\b/))]; + return acc; + }, { allNames: [] }); +} + async function getPersonalizationVariant(manifestPath, variantNames = [], variantLabel = null) { const config = getConfig(); if (config.mep?.variantOverride?.[manifestPath]) { return config.mep.variantOverride[manifestPath]; } - const variantInfo = variantNames.reduce((acc, name) => { - let nameArr = [name]; - if (!name.startsWith(TARGET_EXP_PREFIX)) nameArr = name.split(','); - const vNames = nameArr.map((v) => v.trim()).filter(Boolean); - acc[name] = vNames; - acc.allNames = [...acc.allNames, ...vNames]; - return acc; - }, { allNames: [] }); + const variantInfo = buildVariantInfo(variantNames); const entitlementKeys = Object.values(await getEntitlementMap()); const hasEntitlementTag = entitlementKeys.some((tag) => variantInfo.allNames.includes(tag)); diff --git a/libs/utils/utils.js b/libs/utils/utils.js index f791165d38..74dfed7776 100644 --- a/libs/utils/utils.js +++ b/libs/utils/utils.js @@ -852,6 +852,9 @@ export async function loadIms() { if (!window.adobeIMS?.isSignedInUser()) { getConfig().entitlements([]); } + }).catch((e) => { + getConfig().entitlements([]); + throw e; }); return imsLoaded; diff --git a/test/features/personalization/personalization.test.js b/test/features/personalization/personalization.test.js index d2554b7734..b396befa72 100644 --- a/test/features/personalization/personalization.test.js +++ b/test/features/personalization/personalization.test.js @@ -4,7 +4,7 @@ import { assert, stub } from 'sinon'; import { getConfig, setConfig } from '../../../libs/utils/utils.js'; import { handleFragmentCommand, applyPers, - init, matchGlob, createFrag, combineMepSources, + init, matchGlob, createFrag, combineMepSources, buildVariantInfo, } from '../../../libs/features/personalization/personalization.js'; import spoofParams from './spoofParams.js'; import mepSettings from './mepSettings.js'; @@ -175,6 +175,109 @@ describe('Functional Test', () => { expect(getConfig().mep?.martech).to.equal('|fireflies|manifest'); }); + it('should resolve variants correctly with entitlements and tags exist', async () => { + expect(buildVariantInfo(['cc-all-apps-any & desktop'])).to.deep.equal({ + allNames: [ + 'cc-all-apps-any', + 'desktop', + ], + 'cc-all-apps-any & desktop': [ + 'cc-all-apps-any & desktop', + ], + }); + expect(buildVariantInfo(['desktop & cc-all-apps-any'])).to.deep.equal({ + allNames: [ + 'desktop', + 'cc-all-apps-any', + ], + 'desktop & cc-all-apps-any': [ + 'desktop & cc-all-apps-any', + ], + }); + expect(buildVariantInfo(['cc-all-apps-any'])).to.deep.equal({ + allNames: [ + 'cc-all-apps-any', + ], + 'cc-all-apps-any': [ + 'cc-all-apps-any', + ], + }); + expect(buildVariantInfo(['phone, cc-all-apps-any'])).to.deep.equal({ + allNames: [ + 'phone', + 'cc-all-apps-any', + ], + 'phone, cc-all-apps-any': [ + 'phone', + 'cc-all-apps-any', + ], + }); + expect(buildVariantInfo(['cc-all-apps-any, not desktop'])).to.deep.equal({ + allNames: [ + 'cc-all-apps-any', + 'desktop', + ], + 'cc-all-apps-any, not desktop': [ + 'cc-all-apps-any', + 'not desktop', + ], + }); + expect(buildVariantInfo(['phone & not cc-all-apps-any'])).to.deep.equal({ + allNames: [ + 'phone', + 'cc-all-apps-any', + ], + 'phone & not cc-all-apps-any': [ + 'phone & not cc-all-apps-any', + ], + }); + expect(buildVariantInfo(['not phone & not cc-all-apps-any'])).to.deep.equal({ + allNames: [ + 'phone', + 'cc-all-apps-any', + ], + 'not phone & not cc-all-apps-any': [ + 'not phone & not cc-all-apps-any', + ], + }); + expect(buildVariantInfo(['not cc-free & not cc-all-apps-any'])).to.deep.equal({ + allNames: [ + 'cc-free', + 'cc-all-apps-any', + ], + 'not cc-free & not cc-all-apps-any': [ + 'not cc-free & not cc-all-apps-any', + ], + }); + expect(buildVariantInfo(['not cc-free, not cc-all-apps-any'])).to.deep.equal({ + allNames: [ + 'cc-free', + 'cc-all-apps-any', + ], + 'not cc-free, not cc-all-apps-any': [ + 'not cc-free', + 'not cc-all-apps-any', + ], + }); + expect(buildVariantInfo(['not cc-free, not cc-all-apps-any', 'desktop & cc-paid, ios'])).to.deep.equal({ + allNames: [ + 'cc-free', + 'cc-all-apps-any', + 'desktop', + 'cc-paid', + 'ios', + ], + 'not cc-free, not cc-all-apps-any': [ + 'not cc-free', + 'not cc-all-apps-any', + ], + 'desktop & cc-paid, ios': [ + 'desktop & cc-paid', + 'ios', + ], + }); + }); + it('invalid selector should output error to console', async () => { window.console.log = stub();