From 6d6ff1b5f39301cecd72186bb12b7bb9b3b35e9f Mon Sep 17 00:00:00 2001 From: Nicolas Peltier Date: Thu, 16 Apr 2026 16:57:37 +0200 Subject: [PATCH 1/2] MWPW-192812 only considering same locale variations for pzn --- io/www/src/fragment/transformers/customize.js | 12 +-- io/www/test/fragment/customize.test.js | 80 ++++++++++++++----- 2 files changed, 67 insertions(+), 25 deletions(-) diff --git a/io/www/src/fragment/transformers/customize.js b/io/www/src/fragment/transformers/customize.js index 7c2c46c06..1f6b86c62 100644 --- a/io/www/src/fragment/transformers/customize.js +++ b/io/www/src/fragment/transformers/customize.js @@ -81,14 +81,15 @@ function deepMerge(...objects) { return result; } -function extractVariationBasedOnPath(variations, references, pathSegment) { +function extractVariationBasedOnPath(variations, references, pattern) { return variations - .filter((variationId) => references[variationId]?.value?.path?.includes(pathSegment)) + .filter((variationId) => pattern.test(references[variationId]?.value?.path)) .map((variationId) => references[variationId].value); } function findRegionalVariation(variations, references, prefix) { - const regionalVariations = extractVariationBasedOnPath(variations, references, prefix); + const pattern = new RegExp(`/content/dam/mas/${prefix}/.+`); + const regionalVariations = extractVariationBasedOnPath(variations, references, pattern); return regionalVariations.length > 0 ? regionalVariations[0] : null; } @@ -140,8 +141,9 @@ function personalizationMatchScore(pznTags, { regionLocale, country, pzn }) { } function findPersonalizationVariation(variations, customizeContext) { - const { country, pzn, references, regionLocale } = customizeContext; - const personalizationVariations = extractVariationBasedOnPath(variations, references, PZN_FOLDER); + const { country, pzn, references, regionLocale, prefix } = customizeContext; + const pattern = new RegExp(`/content/dam/mas/${prefix}/([^/]+)${PZN_FOLDER}.+`); + const personalizationVariations = extractVariationBasedOnPath(variations, references, pattern); if (personalizationVariations.length === 0) { logDebug(() => `No personalization variation found for region locale ${regionLocale}`, customizeContext); return null; diff --git a/io/www/test/fragment/customize.test.js b/io/www/test/fragment/customize.test.js index 002cf5bd9..731bf712f 100644 --- a/io/www/test/fragment/customize.test.js +++ b/io/www/test/fragment/customize.test.js @@ -151,7 +151,7 @@ describe('customize collections', function () { [pznVariationId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/intro', + path: '/content/dam/mas/sandbox/en_KW/PA-123/pzn/intro', id: pznVariationId, title: 'Intro pricing', fields: { @@ -161,7 +161,7 @@ describe('customize collections', function () { }, }, [pznOtherVariationId]: { - path: '/content/dam/mas/pzn/sandbox/pznTest', + path: '/content/dam/mas/sandbox/en_KW/PA-123/pzn/pzn-test', id: pznOtherVariationId, title: 'test variation', description: 'has en_KW too, but appears second in the list', @@ -200,7 +200,7 @@ describe('customize collections', function () { [pznVariationId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/country', + path: '/content/dam/mas/sandbox/en_KW/PA-123/pzn/country', id: pznVariationId, title: 'Country targeting', fields: { @@ -240,7 +240,7 @@ describe('customize collections', function () { [pznVariationId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/mx', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/mx', id: pznVariationId, title: 'Mexico country targeting', fields: { @@ -280,7 +280,7 @@ describe('customize collections', function () { [pznVariationId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/teams-edu', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/teams-edu', id: pznVariationId, title: 'Teams and EDU', fields: { @@ -321,7 +321,7 @@ describe('customize collections', function () { [teamsOnlyId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/teams-only', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/teams-only', id: teamsOnlyId, title: 'Teams only', fields: { @@ -333,7 +333,7 @@ describe('customize collections', function () { [teamsEduId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/teams-edu-combo', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/teams-edu-combo', id: teamsEduId, title: 'Teams and EDU combo', fields: { @@ -374,7 +374,7 @@ describe('customize collections', function () { [teamsEduOnlyId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/no-country', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/no-country', id: teamsEduOnlyId, title: 'TEAMS+EDU no country tag', fields: { @@ -386,7 +386,7 @@ describe('customize collections', function () { [teamsEduMxId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/with-mx', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/with-mx', id: teamsEduMxId, title: 'TEAMS+EDU with MX', fields: { @@ -427,7 +427,7 @@ describe('customize collections', function () { [pznVariationId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/pzn-slash', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/pzn-slash', id: pznVariationId, title: 'pzn/ token', fields: { @@ -468,7 +468,7 @@ describe('customize collections', function () { [oneTokenId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/one', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/one', id: oneTokenId, title: 'One token', fields: { @@ -480,7 +480,7 @@ describe('customize collections', function () { [twoTokenId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/two', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/two', id: twoTokenId, title: 'Two tokens', fields: { @@ -520,7 +520,7 @@ describe('customize collections', function () { [pznVariationId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/token', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/token', id: pznVariationId, title: 'Token targeting', fields: { @@ -560,7 +560,7 @@ describe('customize collections', function () { [pznVariationId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/numeric', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/numeric', id: pznVariationId, title: 'Numeric pzn', fields: { @@ -603,7 +603,7 @@ describe('customize collections', function () { [emptyArrayId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/empty-array', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/empty-array', id: emptyArrayId, title: 'Empty pznTags array', fields: { @@ -615,7 +615,7 @@ describe('customize collections', function () { [invalidArrayId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/invalid', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/invalid', id: invalidArrayId, title: 'Not an array', fields: { @@ -627,7 +627,7 @@ describe('customize collections', function () { [emptyTagsId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/empty-tags', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/empty-tags', id: emptyTagsId, title: 'Only falsy tag entries', fields: { @@ -639,7 +639,7 @@ describe('customize collections', function () { [validId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/valid', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/valid', id: validId, title: 'Valid tags', fields: { @@ -815,7 +815,7 @@ describe('customize collections', function () { [pznVariationId]: { type: 'content-fragment', value: { - path: '/content/dam/mas/pzn/sandbox/promo', + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/promo', id: pznVariationId, title: 'PZN Promo', fields: { pznTags: ['en_AE', 'fr_FR'], badge: 'Other badge' }, @@ -828,7 +828,7 @@ describe('customize collections', function () { const result = await process({ ...FAKE_CONTEXT, fragmentPath: 'pzn-test-fragment', - locale: 'en_KW', + locale: 'en_US', parsedLocale: 'en_US', body: bodyWithPzn, }); @@ -836,6 +836,46 @@ describe('customize collections', function () { expect(result.status).to.equal(200); expect(result.body.fields.badge).to.deep.include({ value: 'default badge', mimeType: 'text/html' }); }); + + it('should NOT apply a pzn variation located under en_US when the fragment is in fr_FR', async function () { + const pznVariationId = 'pzn-var-en-us-wrong-locale'; + const bodyWithPzn = { + path: '/content/dam/mas/sandbox/fr_FR/some-fr-fragment', + id: 'root-fragment', + title: 'Root', + fields: { + badge: 'default badge', + variations: [pznVariationId], + }, + references: { + [pznVariationId]: { + type: 'content-fragment', + value: { + path: '/content/dam/mas/sandbox/en_US/PA-123/pzn/en-us-variant', + id: pznVariationId, + title: 'EN US pzn variant', + fields: { + pznTags: ['en_US'], + badge: 'EN US PZN badge', + }, + }, + }, + }, + referencesTree: [], + }; + + const result = await process({ + ...FAKE_CONTEXT, + fragmentPath: 'some-fr-fragment', + locale: 'fr_FR', + parsedLocale: 'fr_FR', + body: bodyWithPzn, + }); + + expect(result.status).to.equal(200); + // pzn variation lives under en_US path, must NOT be applied to a fr_FR fragment + expect(result.body.fields.badge).to.equal('default badge'); + }); }); async function process(context) { From 1e8d25296a8e3b322889ac6247c887dcd087ee84 Mon Sep 17 00:00:00 2001 From: Nicolas Peltier Date: Fri, 24 Apr 2026 08:49:17 +0200 Subject: [PATCH 2/2] MWPW-192812 fixing pattern for pzn --- io/www/src/fragment/transformers/customize.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/io/www/src/fragment/transformers/customize.js b/io/www/src/fragment/transformers/customize.js index 1f6b86c62..83c8ea327 100644 --- a/io/www/src/fragment/transformers/customize.js +++ b/io/www/src/fragment/transformers/customize.js @@ -87,8 +87,9 @@ function extractVariationBasedOnPath(variations, references, pattern) { .map((variationId) => references[variationId].value); } -function findRegionalVariation(variations, references, prefix) { - const pattern = new RegExp(`/content/dam/mas/${prefix}/.+`); +function findRegionalVariation(variations, customizeContext) { + const { surface, regionLocale, references } = customizeContext; + const pattern = new RegExp(`/content/dam/mas/${surface}/${regionLocale}/.+`); const regionalVariations = extractVariationBasedOnPath(variations, references, pattern); return regionalVariations.length > 0 ? regionalVariations[0] : null; } @@ -141,8 +142,8 @@ function personalizationMatchScore(pznTags, { regionLocale, country, pzn }) { } function findPersonalizationVariation(variations, customizeContext) { - const { country, pzn, references, regionLocale, prefix } = customizeContext; - const pattern = new RegExp(`/content/dam/mas/${prefix}/([^/]+)${PZN_FOLDER}.+`); + const { country, pzn, references, regionLocale, surface, defaultLocale } = customizeContext; + const pattern = new RegExp(`/content/dam/mas/${surface}/${defaultLocale}/([^/]+)${PZN_FOLDER}.+`); const personalizationVariations = extractVariationBasedOnPath(variations, references, pattern); if (personalizationVariations.length === 0) { logDebug(() => `No personalization variation found for region locale ${regionLocale}`, customizeContext); @@ -171,7 +172,7 @@ function findPersonalizationVariation(variations, customizeContext) { } function mergeVariations(root, customizeContext) { - const { isRegionLocale, prefix, references } = customizeContext; + const { isRegionLocale } = customizeContext; const variations = root?.fields?.variations; if (!variations?.length) { logDebug(() => `No variations to merge for fragment ${root.id}`, customizeContext); @@ -179,7 +180,7 @@ function mergeVariations(root, customizeContext) { } logDebug(() => `found variations ${JSON.stringify(variations)} in ${root.id}`, customizeContext); if (isRegionLocale) { - const regionalVariation = findRegionalVariation(variations, references, prefix); + const regionalVariation = findRegionalVariation(variations, customizeContext); if (regionalVariation) { logDebug(() => `Merging regional variation ${regionalVariation.id} for fragment ${root.id}`, customizeContext); const merged = deepMerge(root, regionalVariation); @@ -332,11 +333,12 @@ async function customize(context) { const isRegionLocale = regionLocale !== defaultLocale; const customizeContext = { ...context, + defaultLocale, isRegionLocale, promos, regionLocale, - prefix: `${surface}/${regionLocale}`, references, + surface, }; const { fragment: customizedFragment,