From c56840dab6ab6ebb98780c981cce7eb413c9e327 Mon Sep 17 00:00:00 2001
From: "milo-pr-merge[bot]"
<169241390+milo-pr-merge[bot]@users.noreply.github.com>
Date: Thu, 16 Jan 2025 11:01:11 +0100
Subject: [PATCH 02/17] [Release] Stage to Main (#3497)
MWPW-165774 [Mobile-GNAV] page is not scrollable in live page (#3495)
* check for new nav when disabling ios scroll
* shortened the check from the previous commit
Co-authored-by: Raghav Sharma <118168183+sharmrj@users.noreply.github.com>
---
libs/blocks/global-navigation/utilities/utilities.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js
index 2ab1b87e295..137939d20e2 100644
--- a/libs/blocks/global-navigation/utilities/utilities.js
+++ b/libs/blocks/global-navigation/utilities/utilities.js
@@ -337,7 +337,8 @@ export function trigger({ element, event, type } = {}) {
closeAllDropdowns({ type });
if (isOpen) return false;
element.setAttribute('aria-expanded', 'true');
- if (!isDesktop.matches && type === 'dropdown') disableMobileScroll();
+ if (!isDesktop.matches && type === 'dropdown'
+ && !!document.querySelector('header.new-nav')) disableMobileScroll();
return true;
}
From ec4bdff74d7ac49a5046db5dc88748a7e30476b7 Mon Sep 17 00:00:00 2001
From: "milo-pr-merge[bot]"
<169241390+milo-pr-merge[bot]@users.noreply.github.com>
Date: Fri, 14 Mar 2025 12:13:47 +0100
Subject: [PATCH 03/17] [Release] Stage to Main (#3817)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* ENB-7820: Add values for event95 (#3782)
* Add values for event95
* Fix failing test case
* Remove spaces
* Minimal Impact: Add extra key for other features
* Minimal Impact: change function name
* [MWPW-168691] - Aside cta shrink JP (#3785)
* [MWPW-168691] cta shrink fix
* [MWPW-168691] update
* [MWPW-168691] update
* [MWPW-168691] update
* [MWPW-168691] update
* [MWPW-168691] update
* [MWPW-168691] update
* [MWPW-168691] update
* [MWPW-168691] updated solution
* Revert "[MWPW-168691]"
This reverts commit a70f9ca77c4680a96348f1c69e175d7a46a00f05.
Revert "[MWPW-168691] update"
This reverts commit 6aac2bc7adf073958a1fb454b6417a749ed01ccf.
Revert "[MWPW-168691] update"
This reverts commit c0c6a3436ed9b8827e36d48c9dd389d301e14153.
Revert "[MWPW-168691] update"
This reverts commit 017edf08e23a8d6d38b48e3fd961a95d090681ec.
Revert "[MWPW-168691] update"
This reverts commit 219e5fd39b245a09d855aede9d3e5116bf69a66d.
Revert "[MWPW-168691] update"
This reverts commit a7df2b53c7e07dc7917ce2c3d8f8a9bb8a9b05b9.
Revert "[MWPW-168691] update"
This reverts commit 299a7d7eab0ba14508cab16c723a437b341bde18.
Revert "[MWPW-168691] update"
This reverts commit 67095158a5df1db00bea41dfd29ada59d16db966.
Revert "[MWPW-168691] cta shrink fix"
This reverts commit c90eea64042193a3ac97a7fbc363159069d9114f.
* MWPW-168691: Prevent cta jp word wrap on large screens
* MWPW-168691: Fix notification jp cta
* MWPW-168691: Hide wbr cta for tablet and desktop
---------
Co-authored-by: Ratko Zagorac
* MWPW-169371 : Adding countryCode config to UNav (#3793)
* Adding countryCode config to UNav
* Updating countryCode for uk
* Updating for upperCase
* Passing countryCode according to MAS mapping for UCv3 cart
---------
Co-authored-by: Snehal Sonawane
Co-authored-by: Snehal Sonawane
* MWPW-167716 Remove await from both gnav and georouting (#3680)
Made georouting and globalnavigation non blocking
* Lnav title and headline text overflow support (#3781)
* Lnav title text overflow support
* Fix for chevron icon top position
* Adding white space break for localnav menus
* Adding white space break for localnav menus
* Adding white space break for localnav list menus
* Inclufing white spaces to non menu items
* [MWPW-169500] SEO- Links check failing breaks Preflight (#3803)
fixed preflight seo links check
* MWPW-169732 Fetch resources from adobe.com/federal instead of https://main--federal--adobecom.aem.live/federal (#3813)
* on prod federal content for the standalone gnav and footer needs to come from
* handled situations where we're stage and when we're neither stage nor prod
* MWPW-169416 [MEP] stop treating remove action differently in preview (#3789)
* truly remove elements, even in preview
* unit test update
* fix for MWPW-169416, new remove action in MEP
* lint clean-up
---------
Co-authored-by: John Pratt
---------
Co-authored-by: Swati Mukherjee
Co-authored-by: Dušan Kosanović
Co-authored-by: Ratko Zagorac
Co-authored-by: sonawanesnehal3 <152426902+sonawanesnehal3@users.noreply.github.com>
Co-authored-by: Snehal Sonawane
Co-authored-by: Snehal Sonawane
Co-authored-by: Raghav Sharma <118168183+sharmrj@users.noreply.github.com>
Co-authored-by: Bandana Laishram
Co-authored-by: Robert Bogos <146744221+robert-bogos@users.noreply.github.com>
Co-authored-by: Vivian A Goodrich <101133187+vgoodric@users.noreply.github.com>
Co-authored-by: John Pratt
---
libs/blocks/aside/aside.css | 5 ++++
.../global-navigation/global-navigation.css | 8 +++++-
.../global-navigation/global-navigation.js | 4 +++
.../global-navigation/utilities/menu/menu.css | 1 +
libs/blocks/preflight/panels/seo.js | 3 +-
.../personalization/personalization.js | 15 ++--------
libs/martech/helpers.js | 28 +++++++++++++++----
libs/navigation/navigation.js | 11 ++++++--
libs/utils/utils.js | 8 ++++--
.../personalization/mep-actions.test.js | 15 +++++-----
.../merch-card-collection.test.js | 2 +-
test/features/personalization/actions.test.js | 27 ------------------
12 files changed, 68 insertions(+), 59 deletions(-)
diff --git a/libs/blocks/aside/aside.css b/libs/blocks/aside/aside.css
index 7f1491ae902..954e67c04bf 100644
--- a/libs/blocks/aside/aside.css
+++ b/libs/blocks/aside/aside.css
@@ -954,6 +954,11 @@
align-items: center;
text-align: center;
}
+
+ .aside.promobar .action-area wbr,
+ .aside.notification .action-area wbr {
+ display: none;
+ }
}
@media (min-width: 600px) and (max-width: 1199px) {
diff --git a/libs/blocks/global-navigation/global-navigation.css b/libs/blocks/global-navigation/global-navigation.css
index dd5a2b6ebd7..cf4109810f8 100644
--- a/libs/blocks/global-navigation/global-navigation.css
+++ b/libs/blocks/global-navigation/global-navigation.css
@@ -1228,9 +1228,15 @@ header.new-nav .feds-breadcrumbs li:first-child:not(:nth-last-child(-n+3)):after
background: var(--feds-background-popup);
font-weight: 400;
border-bottom: 0;
- padding: 12px 38px;
+ padding: 12px 46px 12px 38px;
outline-offset: -1px;
color: var(--feds-color-link);
+ white-space: break-spaces;
+}
+
+.feds-localnav .feds-localnav-items .feds-navLink-content .feds-navLink-title,
+.feds-localnav .feds-localnav-items li .feds-navLink {
+ white-space: break-spaces;
}
.feds-localnav .feds-localnav-items .feds-navItem--centered {
diff --git a/libs/blocks/global-navigation/global-navigation.js b/libs/blocks/global-navigation/global-navigation.js
index 175e64b6abc..621a9f2a6ca 100644
--- a/libs/blocks/global-navigation/global-navigation.js
+++ b/libs/blocks/global-navigation/global-navigation.js
@@ -49,6 +49,8 @@ import {
import { replaceKey, replaceKeyArray } from '../../features/placeholders.js';
+import { getMiloLocaleSettings } from '../merch/merch.js';
+
const SIGNIN_CONTEXT = getConfig()?.signInContext;
function getHelpChildren() {
@@ -776,6 +778,7 @@ class Gnav {
target: this.blocks.universalNav,
env: environment,
locale,
+ countryCode: getMiloLocaleSettings(getConfig().locale)?.country || 'US',
imsClientId: window.adobeid?.client_id,
theme: isDarkMode() ? 'dark' : 'light',
analyticsContext: {
@@ -1158,6 +1161,7 @@ class Gnav {
elem?.addEventListener('click', (e) => {
trigger({ element: e.currentTarget, event: e, type: 'headline' });
});
+ elem.textContent = elem.textContent?.trim();
});
}
};
diff --git a/libs/blocks/global-navigation/utilities/menu/menu.css b/libs/blocks/global-navigation/utilities/menu/menu.css
index 630bf102408..3ca3d61a665 100644
--- a/libs/blocks/global-navigation/utilities/menu/menu.css
+++ b/libs/blocks/global-navigation/utilities/menu/menu.css
@@ -73,6 +73,7 @@
.feds-localnav-items .feds-menu-headline:after {
right: 38px;
+ top: 20px;
}
[dir = "rtl"] .feds-menu-headline:after {
diff --git a/libs/blocks/preflight/panels/seo.js b/libs/blocks/preflight/panels/seo.js
index 67118905d31..f5c266b62e8 100644
--- a/libs/blocks/preflight/panels/seo.js
+++ b/libs/blocks/preflight/panels/seo.js
@@ -256,7 +256,8 @@ async function checkLinks() {
badResults.push(...spidyResults);
}
- badLinks.value = badResults.map((result) => links.find((link) => compareResults(result, link)));
+ badLinks.value = badResults.map((result) => links.find((link) => compareResults(result, link)))
+ .filter(Boolean);
// Format the results for display
const count = badLinks.value.length;
diff --git a/libs/features/personalization/personalization.js b/libs/features/personalization/personalization.js
index 12aaaf0554d..9c1fdf40fce 100644
--- a/libs/features/personalization/personalization.js
+++ b/libs/features/personalization/personalization.js
@@ -220,13 +220,8 @@ export const createContent = (el, { content, manifestId, targetManifestId, actio
};
const COMMANDS = {
- [COMMANDS_KEYS.remove]: (el, { content, manifestId }) => {
- if (content === 'false') return;
- if (manifestId && !el.href?.includes('/tools/ost')) {
- el.dataset.removedManifestId = manifestId;
- return;
- }
- el.classList.add(CLASS_EL_DELETE);
+ [COMMANDS_KEYS.remove]: (el, { content }) => {
+ if (content !== 'false') el.classList.add(CLASS_EL_DELETE);
},
[COMMANDS_KEYS.replace]: (el, cmd) => {
if (!el || el.classList.contains(CLASS_EL_REPLACE)) return;
@@ -1111,11 +1106,7 @@ export function handleFragmentCommand(command, a) {
return fragment;
}
if (action === COMMANDS_KEYS.remove) {
- if (manifestId) {
- a.parentElement.dataset.removedManifestId = manifestId;
- } else {
- a.parentElement.remove();
- }
+ a.parentElement.remove();
}
return false;
}
diff --git a/libs/martech/helpers.js b/libs/martech/helpers.js
index 53333ee22eb..20c8a9ed55b 100644
--- a/libs/martech/helpers.js
+++ b/libs/martech/helpers.js
@@ -149,6 +149,22 @@ function getOrGenerateUserId() {
};
}
+function getUpdatedVisitAttempt() {
+ const { hostname } = window.location;
+ const secondVisitAttempt = Number(localStorage.getItem('secondHit')) || 0;
+
+ const isAdobeDomain = hostname === 'www.adobe.com' || hostname === 'www.stage.adobe.com';
+ const consentCookieValue = getCookie('OptanonConsent');
+
+ if (consentCookieValue?.includes('C0002:1') && isAdobeDomain) {
+ const updatedVisitAttempt = secondVisitAttempt === 0 ? 1 : secondVisitAttempt + 1;
+ localStorage.setItem('secondHit', updatedVisitAttempt);
+ return updatedVisitAttempt;
+ }
+
+ return secondVisitAttempt;
+}
+
function getPageNameForAnalytics({ locale }) {
const { host, pathname } = new URL(window.location.href);
const [modifiedPath] = pathname.split('/').filter((x) => x !== locale.prefix).join(':').split('.');
@@ -240,6 +256,7 @@ function createRequestPayload({ updatedContext, pageName, locale, env, hitType }
approach: 'martech-API',
edgeConfigIdLaunch: dataStreamId,
edgeConfigId: dataStreamId,
+ personalisation: 'hybrid',
},
},
},
@@ -269,6 +286,12 @@ function createRequestPayload({ updatedContext, pageName, locale, env, hitType }
data.web = { webPageDetails };
data.eventType = hitTypeEventTypeMap[hitType];
+ if (getUpdatedVisitAttempt() === 2) {
+ digitalData.adobe = {
+ libraryVersions: 'alloy-api',
+ experienceCloud: { secondVisits: 'setEvent' },
+ };
+ }
xdm.implementationDetails = {
name: 'https://ns.adobe.com/experience/alloy/reactor',
version: '1.0',
@@ -496,22 +519,17 @@ export const loadAnalyticsAndInteractionData = async (
const CURRENT_DATE = new Date();
const localTime = CURRENT_DATE.toISOString();
-
const timezoneOffset = CURRENT_DATE.getTimezoneOffset();
if (hybridPersEnabled) {
window.hybridPers = true;
}
const hitType = hybridPersEnabled ? 'pageView' : 'propositionFetch';
-
const pageName = getPageNameForAnalytics({ locale });
-
const updatedContext = getUpdatedContext({ ...getDeviceInfo(), localTime, timezoneOffset });
-
const requestUrl = createRequestUrl({
env,
hitType,
});
-
const requestPayload = { updatedContext, pageName, locale, env, hitType };
const requestBody = createRequestPayload(requestPayload);
diff --git a/libs/navigation/navigation.js b/libs/navigation/navigation.js
index 3d9eb800160..6acfac6eba8 100644
--- a/libs/navigation/navigation.js
+++ b/libs/navigation/navigation.js
@@ -112,6 +112,13 @@ export default async function loadBlock(configs, customLib) {
import('../utils/utils.js'),
]);
const paramConfigs = getParamsConfigs(configs);
+ const origin = (() => {
+ switch (env) {
+ case 'prod': return 'https://www.adobe.com';
+ case 'stage': return 'https://www.stage.adobe.com';
+ default: return 'https://main--federal--adobecom.aem.page';
+ }
+ })();
const clientConfig = {
theme,
prodDomains,
@@ -122,8 +129,8 @@ export default async function loadBlock(configs, customLib) {
locales: configs.locales || locales,
contentRoot: authoringPath || footer?.authoringPath,
stageDomainsMap: getStageDomainsMap(stageDomainsMap),
- origin: `https://main--federal--adobecom.aem.${env === 'prod' ? 'live' : 'page'}`,
- allowedOrigins: [...allowedOrigins, `https://main--federal--adobecom.aem.${env === 'prod' ? 'live' : 'page'}`],
+ origin,
+ allowedOrigins: [...allowedOrigins, origin],
onFooterReady: footer?.onReady,
onFooterError: footer?.onError,
...paramConfigs,
diff --git a/libs/utils/utils.js b/libs/utils/utils.js
index e7edae37413..0bac53b77eb 100644
--- a/libs/utils/utils.js
+++ b/libs/utils/utils.js
@@ -1257,13 +1257,15 @@ async function loadPostLCP(config) {
const georouting = getMetadata('georouting') || config.geoRouting;
if (georouting === 'on') {
const jsonPromise = fetch(`${config.contentRoot ?? ''}/georoutingv2.json`);
- const { default: loadGeoRouting } = await import('../features/georoutingv2/georoutingv2.js');
- await loadGeoRouting(config, createTag, getMetadata, loadBlock, loadStyle, jsonPromise);
+ import('../features/georoutingv2/georoutingv2.js')
+ .then(({ default: loadGeoRouting }) => {
+ loadGeoRouting(config, createTag, getMetadata, loadBlock, loadStyle, jsonPromise);
+ });
}
const header = document.querySelector('header');
if (header) {
header.classList.add('gnav-hide');
- await loadBlock(header);
+ loadBlock(header);
header.classList.remove('gnav-hide');
}
loadTemplate();
diff --git a/nala/features/personalization/mep-actions.test.js b/nala/features/personalization/mep-actions.test.js
index cc257b867b9..edde208bcc9 100644
--- a/nala/features/personalization/mep-actions.test.js
+++ b/nala/features/personalization/mep-actions.test.js
@@ -7,6 +7,7 @@ import TextBlock from '../../blocks/text/text.page.js';
import MarqueeBlock from '../../blocks/marquee/marquee.page.js';
const miloLibs = process.env.MILO_LIBS || '';
+const sec5Loc = 'main:has-text("Section 5")';
// Test 0: confirm the default page
test(`[Test Id - ${features[0].tcid}] ${features[0].name},${features[0].tags}`, async ({ page, baseURL }) => {
@@ -17,6 +18,7 @@ test(`[Test Id - ${features[0].tcid}] ${features[0].name},${features[0].tags}`,
await page.goto(URL);
await expect(textBlock1.headlineAlt).toHaveText('Base page text. Section 2');
await expect(textBlock7.headlineAlt).toHaveText('Base page text fragment');
+ await expect(page.locator(sec5Loc)).toHaveCount(1);
});
// Test 1: confirm various MEP actions on the personalized page
@@ -33,7 +35,6 @@ test(`[Test Id - ${features[1].tcid}] ${features[1].name},${features[1].tags}`,
const textBlock10 = new TextBlock(page, 10);
const textBlock11 = new TextBlock(page, 11);
const textBlock12 = new TextBlock(page, 12);
- const textBlock13 = new TextBlock(page, 13);
const URL = `${baseURL}${features[1].path}${miloLibs}`;
console.info(`[Test Page]: ${URL}`);
await page.goto(URL);
@@ -44,12 +45,12 @@ test(`[Test Id - ${features[1].tcid}] ${features[1].name},${features[1].tags}`,
await expect(textBlock5.headlineAlt).toHaveText('Appended to 3');
await expect(textBlock6.headlineAlt).toHaveText('Prepended to 4');
await expect(textBlock7.headlineAlt).toHaveText('Base page text. Section 4');
- await expect(textBlock8.headlineAlt).not.toBeVisible();
- await expect(textBlock9.headlineAlt).toHaveText('Section 6 replacement');
- await expect(textBlock10.headlineAlt).toHaveText('Base page text. Section 7');
- await expect(textBlock11.headlineAlt).toHaveText('Replaced basepage fragment');
- await expect(textBlock12.headlineAlt).toHaveText('Inserted after basepage fragment');
- await expect(textBlock13.headlineAlt).toHaveText('Inserted after replaced fragment');
+ await expect(page.locator(sec5Loc)).toHaveCount(0);
+ await expect(textBlock8.headlineAlt).toHaveText('Section 6 replacement');
+ await expect(textBlock9.headlineAlt).toHaveText('Base page text. Section 7');
+ await expect(textBlock10.headlineAlt).toHaveText('Replaced basepage fragment');
+ await expect(textBlock11.headlineAlt).toHaveText('Inserted after basepage fragment');
+ await expect(textBlock12.headlineAlt).toHaveText('Inserted after replaced fragment');
});
// Test 2: confirm insertScript (make text orange)
diff --git a/test/blocks/merch-card-collection/merch-card-collection.test.js b/test/blocks/merch-card-collection/merch-card-collection.test.js
index e70d4513fc0..dae60aafe00 100644
--- a/test/blocks/merch-card-collection/merch-card-collection.test.js
+++ b/test/blocks/merch-card-collection/merch-card-collection.test.js
@@ -235,7 +235,7 @@ describe('Merch Cards', async () => {
const merchCards = await init(el);
expect(merchCards.filter).to.equal('all');
await delay(500);
- expect(merchCards.querySelectorAll('h3[data-removed-manifest-id]').length).to.equal(4);
+ expect(merchCards.querySelectorAll('h3').length).to.equal(0);
});
it('should localize the query-index url', async () => {
diff --git a/test/features/personalization/actions.test.js b/test/features/personalization/actions.test.js
index 9c4110ba5df..0508c10d8e6 100644
--- a/test/features/personalization/actions.test.js
+++ b/test/features/personalization/actions.test.js
@@ -244,33 +244,6 @@ describe('remove action', () => {
await initFragments(removeMeFrag);
expect(document.querySelector('a[href="/fragments/removeme"]')).to.be.null;
});
-
- it('removeContent should tag but not remove content in preview', async () => {
- document.body.innerHTML = await readFile({ path: './mocks/personalization.html' });
-
- let manifestJson = await readFile({ path: './mocks/actions/manifestRemove.json' });
- manifestJson = JSON.parse(manifestJson);
- setFetchResponse(manifestJson);
- delete config.mep;
-
- expect(document.querySelector('.z-pattern')).to.not.be.null;
- await init({
- mepParam: '',
- mepHighlight: false,
- mepButton: false,
- pzn: '/path/to/manifest.json',
- promo: false,
- target: false,
- });
-
- expect(document.querySelector('.z-pattern')).to.not.be.null;
- expect(document.querySelector('.z-pattern').dataset.removedManifestId).to.equal('manifest.json');
-
- const removeMeFrag = document.querySelector('a[href="/fragments/removeme"]');
- await initFragments(removeMeFrag);
- expect(document.querySelector('a[href="/fragments/removeme"]')).to.not.be.null;
- expect(document.querySelector('a[href="/fragments/removeme"]').dataset.removedManifestId).to.not.be.null;
- });
});
describe('useBlockCode action', async () => {
From c4840835cb16f9bea341afa6f88d3dcc0ed1e0d8 Mon Sep 17 00:00:00 2001
From: Okan Sahin <39759830+mokimo@users.noreply.github.com>
Date: Sat, 15 Mar 2025 07:44:59 +0100
Subject: [PATCH 04/17] MWPW-167191 Removed an unnecessary css url() that was
causing a console error (#3824)
MWPW-167191 Removed an unnecessary css url() that was causing a console error (#3630)
* updated an svg inside a url() in the globalnav css to have data:image/svg+xml;utf8 inorder to prevent a console error
* changed a ; to a ,
* Removed the svg as it was unnecessary
Co-authored-by: Raghav Sharma <118168183+sharmrj@users.noreply.github.com>
---
libs/blocks/global-navigation/global-navigation.css | 1 -
1 file changed, 1 deletion(-)
diff --git a/libs/blocks/global-navigation/global-navigation.css b/libs/blocks/global-navigation/global-navigation.css
index cf4109810f8..eaf5503dd48 100644
--- a/libs/blocks/global-navigation/global-navigation.css
+++ b/libs/blocks/global-navigation/global-navigation.css
@@ -859,7 +859,6 @@ header.new-nav .feds-nav > section.feds-navItem > button.feds-navLink {
}
header.new-nav .feds-nav > section.feds-navItem > button.feds-navLink::after {
- content: url('');
width: 9.271px;
height: 9.179px;
transform: rotate(-45deg);
From 01b4dab6e6bad808c8702fae06545d7514e9b1dd Mon Sep 17 00:00:00 2001
From: Chris Peyer
Date: Wed, 14 May 2025 17:03:11 -0400
Subject: [PATCH 05/17] Reduce gnav lana sampleRate to 0.01% (#4150)
---
libs/blocks/global-navigation/utilities/utilities.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js
index dc38ec0ffad..42e46752cd7 100644
--- a/libs/blocks/global-navigation/utilities/utilities.js
+++ b/libs/blocks/global-navigation/utilities/utilities.js
@@ -95,7 +95,7 @@ export const logPerformance = (
.join(',');
window.lana.log(measureStr, {
clientId: LANA_CLIENT_ID,
- sampleRate: 50,
+ sampleRate: 0.01,
});
} catch (e) {
console.error(e);
From 025a1e989b512490d1876031aa52dfa8280dbb50 Mon Sep 17 00:00:00 2001
From: Okan Sahin <39759830+mokimo@users.noreply.github.com>
Date: Tue, 20 May 2025 10:30:20 +0200
Subject: [PATCH 06/17] Revert "Improve carousel accessibility (#4103)" from
prod (#4195)
Revert "Improve carousel accessibility (#4103)"
This reverts commit 34d2016b56d19a2e496dc216e9c7c3e8f4ef06a2.
---
libs/blocks/carousel/carousel.css | 11 -----
libs/blocks/carousel/carousel.js | 61 +++++++++------------------
nala/blocks/carousel/carousel.page.js | 4 +-
nala/blocks/carousel/carousel.test.js | 12 +++---
4 files changed, 27 insertions(+), 61 deletions(-)
diff --git a/libs/blocks/carousel/carousel.css b/libs/blocks/carousel/carousel.css
index 5814302650d..bc5acf9bdf1 100644
--- a/libs/blocks/carousel/carousel.css
+++ b/libs/blocks/carousel/carousel.css
@@ -193,10 +193,6 @@ html[dir="rtl"] .carousel-slides .section.carousel-slide {
opacity: 1;
}
-.carousel-slide.non-visible-slide {
- visibility: hidden;
-}
-
.carousel-slides.is-ready,
.carousel-slides.is-ready.is-reversing,
.carousel[class*='show-'] .carousel-slides.is-ready,
@@ -726,10 +722,3 @@ html[dir="rtl"] .carousel .move-indicators {
transform: translateX(calc(round(down, (var(--offset) / (var(--slides) - 1)), 2px) * -1));
}
}
-
-.carousel .aria-live-container {
- position: absolute;
- width: 0;
- height: 0;
- overflow: hidden;
-}
diff --git a/libs/blocks/carousel/carousel.js b/libs/blocks/carousel/carousel.js
index b39315b4c12..ea15efac496 100644
--- a/libs/blocks/carousel/carousel.js
+++ b/libs/blocks/carousel/carousel.js
@@ -67,7 +67,7 @@ function decorateLightboxButtons() {
return [expandBtn, closeBtn];
}
-function decorateSlideIndicators(slides) {
+function decorateSlideIndicators(slides, jumpTo) {
const indicatorDots = [];
for (let i = 0; i < slides.length; i += 1) {
@@ -76,16 +76,17 @@ function decorateSlideIndicators(slides) {
'data-index': i,
});
- li.setAttribute('role', 'tab');
- li.setAttribute('tabindex', -1);
- li.setAttribute('aria-selected', false);
- li.setAttribute('aria-label', `Slide ${i + 1} of ${slides.length}`);
+ if (jumpTo) {
+ li.setAttribute('role', 'tab');
+ li.setAttribute('tabindex', -1);
+ li.setAttribute('aria-selected', false);
+ li.setAttribute('aria-labelledby', `Viewing Slide ${i + 1}`);
+ }
// Set inital active state
if (i === 0) {
li.classList.add('active');
- li.setAttribute('aria-current', 'location');
- li.setAttribute('tabindex', 0);
+ if (jumpTo) li.setAttribute('tabindex', 0);
}
indicatorDots.push(li);
}
@@ -178,13 +179,6 @@ function setIndicatorMultiplyer(carouselElements, activeSlideIndicator, event) {
}
}
-function updateAriaLive(ariaLive, slide) {
- slide.querySelectorAll(':scope > :not(.section-metadata')?.forEach((el) => {
- ariaLive.textContent += el.textContent;
- });
-}
-
-let hiddenSlideTimeout;
function moveSlides(event, carouselElements, jumpToIndex) {
const {
slideContainer,
@@ -193,12 +187,9 @@ function moveSlides(event, carouselElements, jumpToIndex) {
slideIndicators,
controlsContainer,
direction,
- ariaLive,
+ jumpTo,
} = carouselElements;
- clearTimeout(hiddenSlideTimeout);
- ariaLive.textContent = '';
-
let referenceSlide = slideContainer.querySelector('.reference-slide');
let activeSlide = slideContainer.querySelector('.active');
let activeSlideIndicator = controlsContainer.querySelector('.active');
@@ -219,8 +210,7 @@ function moveSlides(event, carouselElements, jumpToIndex) {
activeSlide.classList.remove('active');
activeSlide.querySelectorAll('a, video').forEach((focusableElement) => focusableElement.setAttribute('tabindex', -1));
activeSlideIndicator.classList.remove('active');
- activeSlideIndicator.setAttribute('tabindex', -1);
- activeSlideIndicator.removeAttribute('aria-current');
+ if (jumpTo) activeSlideIndicator.setAttribute('tabindex', -1);
/*
* If indicator dot buttons are clicked update:
@@ -267,10 +257,7 @@ function moveSlides(event, carouselElements, jumpToIndex) {
referenceSlide.classList.add('reference-slide');
referenceSlide.style.order = '1';
- updateAriaLive(ariaLive, activeSlide);
-
// Update active slide and indicator dot attributes
- activeSlide.classList.remove('non-visible-slide');
activeSlide.classList.add('active');
const indexOfActive = [...activeSlide.parentElement.children]
.findIndex((ele) => activeSlide.isSameNode(ele));
@@ -291,8 +278,7 @@ function moveSlides(event, carouselElements, jumpToIndex) {
.forEach((focusableElement) => { focusableElement.setAttribute('tabindex', 0); });
}
activeSlideIndicator.classList.add('active');
- activeSlideIndicator.setAttribute('tabindex', 0);
- activeSlideIndicator.setAttribute('aria-current', 'location');
+ if (jumpTo) activeSlideIndicator.setAttribute('tabindex', 0);
setIndicatorMultiplyer(carouselElements, activeSlideIndicator, event);
// Loop over all slide siblings to update their order
@@ -309,12 +295,7 @@ function moveSlides(event, carouselElements, jumpToIndex) {
*/
const slideDelay = 25;
slideContainer.classList.remove('is-ready');
- hiddenSlideTimeout = setTimeout(() => {
- slides[activeSlideIndex].classList.add('non-visible-slide');
- }, 625);
- return setTimeout(() => {
- slideContainer.classList.add('is-ready');
- }, slideDelay);
+ return setTimeout(() => slideContainer.classList.add('is-ready'), slideDelay);
}
export function getSwipeDistance(start, end) {
@@ -433,7 +414,7 @@ export default function init(el) {
const slides = [...candidateKeys].reduce((rdx, key) => {
if (key.textContent === 'carousel' && key.nextElementSibling.textContent === carouselName) {
const slide = key.closest('.section');
- slide.classList.add('carousel-slide', 'non-visible-slide');
+ slide.classList.add('carousel-slide');
rdx.push(slide);
slide.setAttribute('data-index', rdx.indexOf(slide));
}
@@ -444,17 +425,12 @@ export default function init(el) {
const fragment = new DocumentFragment();
const nextPreviousBtns = decorateNextPreviousBtns();
const nextPreviousContainer = createTag('div', { class: 'carousel-button-container' });
- const slideIndicators = decorateSlideIndicators(slides);
+ const slideIndicators = decorateSlideIndicators(slides, jumpTo);
const controlsContainer = createTag('div', { class: 'carousel-controls is-delayed' });
convertMpcMp4(slides);
fragment.append(...slides);
const slideWrapper = createTag('div', { class: 'carousel-wrapper' });
- const ariaLive = createTag('div', {
- class: 'aria-live-container',
- 'aria-live': 'polite',
- });
- slideWrapper.appendChild(ariaLive);
const slideContainer = createTag('div', { class: 'carousel-slides' }, fragment);
const carouselElements = {
el,
@@ -465,7 +441,6 @@ export default function init(el) {
controlsContainer,
direction: undefined,
jumpTo,
- ariaLive,
};
if (el.classList.contains('lightbox')) {
@@ -487,8 +462,11 @@ export default function init(el) {
el.append(slideWrapper);
const dotsUl = createTag('ul', { class: 'carousel-indicators' });
- dotsUl.setAttribute('role', 'tablist');
- dotsUl.setAttribute('tabindex', 0);
+ if (jumpTo) {
+ dotsUl.setAttribute('role', 'tablist');
+ dotsUl.setAttribute('tabindex', 0);
+ }
+
dotsUl.append(...slideIndicators);
controlsContainer.append(dotsUl);
nextPreviousContainer.append(...nextPreviousBtns, controlsContainer);
@@ -503,7 +481,6 @@ export default function init(el) {
}
parentArea.addEventListener(MILO_EVENTS.DEFERRED, handleDeferredImages, true);
- slides[0].classList.remove('non-visible-slide');
slides[0].classList.add('active');
const IndexOfShowClass = [...el.classList].findIndex((ele) => ele.includes('show-'));
let NoOfVisibleSlides = 1;
diff --git a/nala/blocks/carousel/carousel.page.js b/nala/blocks/carousel/carousel.page.js
index 654bc18e45f..bd7a0e29616 100644
--- a/nala/blocks/carousel/carousel.page.js
+++ b/nala/blocks/carousel/carousel.page.js
@@ -150,14 +150,14 @@ export default class Carousel {
* @param {string} tagOrClass - The tag name or class name of the element containing the text.
* @returns {Promise} The text content of the specified carousel slide.
*/
- async getSlideText(index, tagOrClass, elVisibility = 'visible') {
+ async getSlideText(index, tagOrClass) {
let slideSelector = `.carousel-slide:nth-child(${index}) `;
if (tagOrClass.startsWith('.')) {
slideSelector += tagOrClass;
} else {
slideSelector += `${tagOrClass}`;
}
- await this.page.waitForSelector(slideSelector, { state: elVisibility });
+ await this.page.waitForSelector(slideSelector);
const slide = await this.page.$(slideSelector);
const text = await slide.textContent();
return text;
diff --git a/nala/blocks/carousel/carousel.test.js b/nala/blocks/carousel/carousel.test.js
index fbed94cec07..93fdf25e95a 100644
--- a/nala/blocks/carousel/carousel.test.js
+++ b/nala/blocks/carousel/carousel.test.js
@@ -32,7 +32,7 @@ test.describe('Milo Carousel Block test suite', () => {
// verify carousel indictor and active indicator
expect(await carousel.areIndicatorsDisplayed()).toBeTruthy();
expect(await carousel.getNumberOfIndicators()).toBe(4);
- expect(await carousel.getCurrentIndicatorIndex()).toBe('0');
+ expect(await carousel.getCurrentIndicatorIndex()).toBeNull();
// verify carousel next and previous buttons
expect(await carousel.isNextButtonlVisible()).toBeTruthy();
@@ -43,12 +43,12 @@ test.describe('Milo Carousel Block test suite', () => {
// move to next slide by clicking next button and verify h2 tag header
await carousel.moveToNextSlide();
expect(await carousel.getCurrentSlideIndex()).toBe('1');
- expect(await carousel.getSlideText(1, 'h2', 'hidden')).toBeTruthy();
+ expect(await carousel.getSlideText(1, 'h2', 'Orange Slices')).toBeTruthy();
// move to 3rd slide by clicking indicator and verify h2 tag header
await carousel.moveToIndicator(3);
- expect(await carousel.getCurrentIndicatorIndex()).toBe('0');
- expect(await carousel.getSlideText(3, 'h2', 'hidden')).toBeTruthy();
+ expect(await carousel.getCurrentIndicatorIndex()).toBeNull();
+ expect(await carousel.getSlideText(3, 'h2', 'Apples')).toBeTruthy();
});
await test.step('step-4: Verify the accessibility test on the carousel block', async () => {
@@ -76,7 +76,7 @@ test.describe('Milo Carousel Block test suite', () => {
// verify indicator visibility, count and index of active slide
expect(await carousel.areIndicatorsDisplayed()).toBeTruthy();
expect(await carousel.getNumberOfIndicators()).toBe(4);
- expect(await carousel.getCurrentIndicatorIndex()).toBe('0');
+ expect(await carousel.getCurrentIndicatorIndex()).toBeNull();
expect(await carousel.isNextButtonlVisible()).toBeTruthy();
expect(await carousel.isPreviousButtonlVisible()).toBeTruthy();
@@ -119,7 +119,7 @@ test.describe('Milo Carousel Block test suite', () => {
await test.step('step-3: Perform carousel slides and controls operation and verify contents', async () => {
// move to next slide by clicking next button and verify h2 tag header
await carousel.moveToNextSlide();
- expect(await carousel.getSlideText(1, 'h2')).toBeTruthy();
+ expect(await carousel.getSlideText(1, 'h2', 'Melon')).toBeTruthy();
});
await test.step('step-3: Verify the accessibility test on the carousel show-2 container block', async () => {
From 9549475381e66a90a9da1c2eb9fbfc379e4f97b0 Mon Sep 17 00:00:00 2001
From: Okan Sahin <39759830+mokimo@users.noreply.github.com>
Date: Fri, 23 May 2025 10:31:47 +0200
Subject: [PATCH 07/17] Revert "[MWPW-173470] - Korea free trial restrict"
(main) (#4236)
Revert "[MWPW-173470] - Korea free trial restrict (#4185)"
This reverts commit 351cfe6d66e95e351b7b2137121aa8087fd3f2f5.
---
libs/blocks/global-navigation/utilities/utilities.js | 8 +-------
libs/blocks/merch/merch.js | 6 ------
libs/utils/decorate.js | 6 +-----
libs/utils/utils.js | 12 ------------
4 files changed, 2 insertions(+), 30 deletions(-)
diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js
index 34016ecb102..64e12513a47 100644
--- a/libs/blocks/global-navigation/utilities/utilities.js
+++ b/libs/blocks/global-navigation/utilities/utilities.js
@@ -10,7 +10,6 @@ import {
getFederatedContentRoot,
getFederatedUrl,
getFedsPlaceholderConfig,
- shouldBlockFreeTrialLinks,
} from '../../../utils/utils.js';
import { processTrackingLabels } from '../../../martech/attributes.js';
import { replaceKey, replaceText } from '../../../features/placeholders.js';
@@ -102,7 +101,7 @@ export const logPerformance = (
sampleRate: 0.01,
});
} catch (e) {
- // eslint-disable-next-line no-empty
+ console.error(e);
}
};
@@ -247,11 +246,6 @@ export async function loadDecorateMenu() {
}
export function decorateCta({ elem, type = 'primaryCta', index } = {}) {
- if (shouldBlockFreeTrialLinks({
- button: elem,
- localePrefix: getConfig()?.locale?.prefix,
- parent: elem.parentElement,
- })) return null;
const modifier = type === 'secondaryCta' ? 'secondary' : 'primary';
const clone = elem.cloneNode(true);
diff --git a/libs/blocks/merch/merch.js b/libs/blocks/merch/merch.js
index 42c94d6dae9..fbf8c1d8816 100644
--- a/libs/blocks/merch/merch.js
+++ b/libs/blocks/merch/merch.js
@@ -844,12 +844,6 @@ export async function buildCta(el, params) {
cta.setAttribute('aria-label', ariaLabel);
});
}
-
- // @see https://jira.corp.adobe.com/browse/MWPW-173470
- cta.onceSettled().then(() => {
- if (getConfig()?.locale?.prefix === '/kr' && cta.value[0]?.offerType === OFFER_TYPE_TRIAL) cta.remove();
- });
-
return cta;
}
diff --git a/libs/utils/decorate.js b/libs/utils/decorate.js
index 3fbd83f993f..6210cd0c2ea 100644
--- a/libs/utils/decorate.js
+++ b/libs/utils/decorate.js
@@ -5,7 +5,6 @@ import {
createIntersectionObserver,
getFederatedContentRoot,
getFedsPlaceholderConfig,
- shouldBlockFreeTrialLinks,
} from './utils.js';
const { miloLibs, codeRoot } = getConfig();
@@ -24,12 +23,9 @@ export function decorateButtons(el, size) {
const buttons = el.querySelectorAll('em a, strong a, p > a strong');
if (buttons.length === 0) return;
const buttonTypeMap = { STRONG: 'blue', EM: 'outline', A: 'blue' };
- const localePrefix = getConfig()?.locale?.prefix;
-
buttons.forEach((button) => {
- const parent = button.parentElement;
- if (shouldBlockFreeTrialLinks({ button, localePrefix, parent })) return;
let target = button;
+ const parent = button.parentElement;
const buttonType = buttonTypeMap[parent.nodeName] || 'outline';
if (button.nodeName === 'STRONG') {
target = parent;
diff --git a/libs/utils/utils.js b/libs/utils/utils.js
index 8b91193918c..99b55448273 100644
--- a/libs/utils/utils.js
+++ b/libs/utils/utils.js
@@ -415,18 +415,6 @@ export const getFedsPlaceholderConfig = ({ useCache = true } = {}) => {
return fedsPlaceholderConfig;
};
-export const shouldBlockFreeTrialLinks = ({ button, localePrefix, parent }) => {
- if (localePrefix !== '/kr' || (!button.dataset?.modalPath?.includes('/kr/cc-shared/fragments/trial-modals')
- && !['free-trial', 'free trial', '무료 체험판', '무료 체험하기', '{{try-for-free}}']
- .some((pattern) => button.textContent?.toLowerCase()?.includes(pattern.toLowerCase())))) {
- return false;
- }
-
- const elementToRemove = (parent?.tagName === 'STRONG' || parent?.tagName === 'EM') && parent?.children?.length === 1 ? parent : button;
- elementToRemove.remove();
- return true;
-};
-
export function isInTextNode(node) {
return (node.parentElement.childNodes.length > 1 && node.parentElement.firstChild.tagName === 'A') || node.parentElement.firstChild.nodeType === Node.TEXT_NODE;
}
From 4fb87b7c41a9d8a74e02997601f948e450219741 Mon Sep 17 00:00:00 2001
From: Angelo Statescu
Date: Fri, 23 May 2025 13:40:02 +0300
Subject: [PATCH 08/17] MWPW-173888 + MWPW-173919: Appending extra options for
relative urls & multiple cta reopen fix (#4237)
---
libs/blocks/merch/merch.js | 12 ++++++++++--
test/blocks/merch/merch.test.js | 30 ++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/libs/blocks/merch/merch.js b/libs/blocks/merch/merch.js
index fbf8c1d8816..8bdf76e754d 100644
--- a/libs/blocks/merch/merch.js
+++ b/libs/blocks/merch/merch.js
@@ -521,7 +521,8 @@ export function appendExtraOptions(url, extraOptions) {
const extraOptionsObj = JSON.parse(extraOptions);
let urlWithExtraOptions;
try {
- urlWithExtraOptions = new URL(url);
+ const fullUrl = url.startsWith('/') ? `${window.location.origin}${url}` : url;
+ urlWithExtraOptions = new URL(fullUrl);
} catch (err) {
window.lana?.log(`Invalid URL ${url} : ${err}`);
return url;
@@ -539,7 +540,7 @@ export function appendExtraOptions(url, extraOptions) {
}
async function openExternalModal(url, getModal, extraOptions) {
- await loadStyle(`${getConfig().base}/blocks/iframe/iframe.css`);
+ loadStyle(`${getConfig().base}/blocks/iframe/iframe.css`);
const root = createTag('div', { class: 'milo-iframe' });
const urlWithExtraOptions = appendExtraOptions(url, extraOptions);
const urlWithTabName = appendTabName(urlWithExtraOptions);
@@ -796,12 +797,19 @@ export async function getPriceContext(el, params) {
};
}
+let modalReopened = false;
export function reopenModal(cta) {
+ if (modalReopened) return;
if (cta && cta.getAttribute('data-modal-id') === window.location.hash.replace('#', '')) {
cta.click();
+ modalReopened = true;
}
}
+export function resetReopenStatus() {
+ modalReopened = false;
+}
+
export async function buildCta(el, params) {
const large = !!el.closest('.marquee');
const strong = el.firstElementChild?.tagName === 'STRONG' || el.parentElement?.tagName === 'STRONG';
diff --git a/test/blocks/merch/merch.test.js b/test/blocks/merch/merch.test.js
index 19e4f03a2f7..76ddf72a06f 100644
--- a/test/blocks/merch/merch.test.js
+++ b/test/blocks/merch/merch.test.js
@@ -25,6 +25,7 @@ import merch, {
appendExtraOptions,
getMiloLocaleSettings,
reopenModal,
+ resetReopenStatus,
setCtaHash,
openModal,
PRICE_TEMPLATE_LEGAL,
@@ -494,6 +495,29 @@ describe('Merch Block', () => {
reopenModal(cta);
expect(clickSpy.called).to.be.true;
window.location.hash = prevHash;
+ resetReopenStatus();
+ });
+
+ it('only reopens one modal if multiples hashes match', async () => {
+ const prevHash = window.location.hash;
+ window.location.hash = '#try-photoshop';
+
+ const cta1 = document.createElement('a');
+ cta1.setAttribute('data-modal-id', 'try-photoshop');
+ const clickSpy1 = sinon.spy(cta1, 'click');
+
+ const cta2 = document.createElement('a');
+ cta1.setAttribute('data-modal-id', 'try-photoshop');
+ const clickSpy2 = sinon.spy(cta2, 'click');
+
+ reopenModal(cta1);
+ reopenModal(cta2);
+
+ expect(clickSpy1.called).to.be.true;
+ expect(clickSpy2.called).to.be.false;
+
+ window.location.hash = prevHash;
+ resetReopenStatus();
});
});
@@ -861,6 +885,12 @@ describe('Merch Block', () => {
const resultUrl2 = appendExtraOptions(invalidUrl);
expect(resultUrl2).to.equal(invalidUrl);
});
+
+ it('appends extra options if the provided url is relative', () => {
+ const relativeUrl = '/plans-fragments/modals/individual/modals-content-rich/all-apps/master.modal.html';
+ const resultUrl = appendExtraOptions(relativeUrl, JSON.stringify({ promoid: 'test' }));
+ expect(resultUrl).to.include('?promoid=test');
+ });
});
describe('locale settings', () => {
From fa991168a7402e89be072bb8951e636d0fa55614 Mon Sep 17 00:00:00 2001
From: Blaine Gunn
Date: Fri, 23 May 2025 09:14:03 -0600
Subject: [PATCH 09/17] MWPW-173875 direct to main
---
libs/utils/logWebVitals.js | 24 ++++++++++++++----------
test/utils/logWebVitals.test.js | 2 +-
test/utils/logWebVitalsUtils.test.js | 2 +-
3 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/libs/utils/logWebVitals.js b/libs/utils/logWebVitals.js
index 6c74f7e8940..a236d59b6ee 100644
--- a/libs/utils/logWebVitals.js
+++ b/libs/utils/logWebVitals.js
@@ -8,7 +8,7 @@ function sendToLana(lanaData) {
Object.assign(lanaData, {
chromeVer: ua.match(/Chrome\/(\d+\.\d+\.\d+\.\d+)/)?.[1] || '',
- country: sessionStorage.getItem('akamai') || '',
+ country: sessionStorage.getItem('akamai') || sessionStorage.getItem('feds_location') || '',
// eslint-disable-next-line compat/compat
downlink: window.navigator?.connection?.downlink || '',
loggedIn: window.adobeIMS?.isSignedInUser() || false,
@@ -19,7 +19,7 @@ function sendToLana(lanaData) {
|| (ua.match(/Linux/) && 'linux')
|| '',
tablet: (ua.match(/(ipad|iPad|tablet|(android(?!.*mobile))|(windows(?!.*phone).*touch))/) && 'yes')
- || '',
+ || 'no',
windowHeight: window.innerHeight,
windowWidth: window.innerWidth,
url: `${window.location.host}${window.location.pathname}`,
@@ -88,15 +88,19 @@ function observeLCP(lanaData, delay, mep) {
const lastEntry = entries[entries.length - 1]; // Use the latest LCP candidate
lanaData.lcp = parseInt(lastEntry.startTime, 10);
const lcpEl = lastEntry.element;
- lanaData.lcpElType = lcpEl?.nodeName?.toLowerCase() || 'Element Was Replaced';
- lanaData.lcpEl = getElementInfo(lcpEl);
- lanaData.lcpSectionOne = boolStr(sectionOne.contains(lcpEl));
- const closestFrag = lcpEl.closest('.fragment');
- lanaData.isFrag = boolStr(closestFrag);
- if (closestFrag) {
- lanaData.isMep = boolStr(isFragmentFromMep(closestFrag.dataset.path, mep));
+ lanaData.lcpElType = lcpEl?.nodeName?.toLowerCase();
+ if (lanaData.lcpElType) {
+ lanaData.lcpEl = getElementInfo(lcpEl);
+ lanaData.lcpSectionOne = boolStr(sectionOne.contains(lcpEl));
+ const closestFrag = lcpEl.closest('.fragment');
+ lanaData.isFrag = boolStr(closestFrag);
+ if (closestFrag) {
+ lanaData.isMep = boolStr(isFragmentFromMep(closestFrag.dataset.path, mep));
+ } else {
+ lanaData.isMep = 'false';
+ }
} else {
- lanaData.isMep = 'false';
+ lanaData.lcpElType = 'Element Was Replaced';
}
setTimeout(() => {
diff --git a/test/utils/logWebVitals.test.js b/test/utils/logWebVitals.test.js
index 5fc8c42deb7..9bed313aee3 100644
--- a/test/utils/logWebVitals.test.js
+++ b/test/utils/logWebVitals.test.js
@@ -34,7 +34,7 @@ describe('Log Web Vitals', () => {
expect(vitals.manifest4path).to.equal('/cc-shared/fragments/tests/2024/q2/ace0875/ace0875.json');
expect(vitals.manifest4selected).to.equal('target-var-marqueelink');
expect(vitals.os).to.be.oneOf(['mac', 'iOS', 'win', 'android', 'linux', '']);
- expect(vitals.tablet).to.be.oneOf(['yes', '']);
+ expect(vitals.tablet).to.be.oneOf(['yes', 'no']);
expect(vitals.url).to.equal('localhost:2000/');
expect(vitals.isMep).to.equal('false');
expect(vitals.isFrag).to.equal('false');
diff --git a/test/utils/logWebVitalsUtils.test.js b/test/utils/logWebVitalsUtils.test.js
index 31948a54852..9e74690b4d0 100644
--- a/test/utils/logWebVitalsUtils.test.js
+++ b/test/utils/logWebVitalsUtils.test.js
@@ -50,7 +50,7 @@ describe('Log Web Vitals Utils', () => {
expect(vitals.loggedIn).to.equal('false');
expect(vitals.os).to.be.oneOf(['mac', 'iOS', 'win', 'android', 'linux', '']);
- expect(vitals.tablet).to.be.oneOf(['yes', '']);
+ expect(vitals.tablet).to.be.oneOf(['yes', 'no']);
expect(vitals.url).to.equal('localhost:2000/');
expect(parseInt(vitals.windowHeight, 10)).to.be.greaterThan(200);
expect(parseInt(vitals.windowWidth, 10)).to.be.greaterThan(200);
From 3735184a12139f638e7bc848113bd236e742a535 Mon Sep 17 00:00:00 2001
From: Rares Munteanu
Date: Mon, 2 Jun 2025 12:37:31 +0200
Subject: [PATCH 10/17] Korea free trial restrict (#4282)
* [MWPW-173016] - block korea free trial links/buttons
* [MWPW-173016] - korea text filter added
* [MWPW-173016] - update if
* [MWPW-173016] - code optimization
* [MWPW-173016] - improve import
* [MWPW-173016] - modal check, string check added
* [MWPW-173016] - strings added
* [MWPW-173470] - update logic
* [MWPW-173470] - update logic
* [MWPW-173470] - update logic
* [MWPW-173470] - remove whitespace
* [MWPW-173470] - optimize
* [MWPW-173470] - remove variable
* [MWPW-173016] - optimize code
* [MWPW-173016] - group logic
* [MWPW-173016] - merch solution added
* [MWPW-173016] - merch ref comment added
* [MWPW-173470] - null safe
* [MWPW-173470] - code optimization
* [MWPW-173470] - nav korea restrict coverage
* [MWPW-173470] - fix eslint console error
---------
Co-authored-by: Dusan Kosanovic
---
libs/blocks/global-navigation/utilities/utilities.js | 8 +++++++-
libs/blocks/merch/merch.js | 6 ++++++
libs/utils/decorate.js | 6 +++++-
libs/utils/utils.js | 12 ++++++++++++
4 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js
index 4c6e919d08a..a7b752cf72c 100644
--- a/libs/blocks/global-navigation/utilities/utilities.js
+++ b/libs/blocks/global-navigation/utilities/utilities.js
@@ -10,6 +10,7 @@ import {
getFederatedContentRoot,
getFederatedUrl,
getFedsPlaceholderConfig,
+ shouldBlockFreeTrialLinks,
} from '../../../utils/utils.js';
import { processTrackingLabels } from '../../../martech/attributes.js';
import { replaceKey, replaceText } from '../../../features/placeholders.js';
@@ -102,7 +103,7 @@ export const logPerformance = (
sampleRate: 0.01,
});
} catch (e) {
- console.error(e);
+ // eslint-disable-next-line no-empty
}
};
@@ -247,6 +248,11 @@ export async function loadDecorateMenu() {
}
export function decorateCta({ elem, type = 'primaryCta', index } = {}) {
+ if (shouldBlockFreeTrialLinks({
+ button: elem,
+ localePrefix: getConfig()?.locale?.prefix,
+ parent: elem.parentElement,
+ })) return null;
const modifier = type === 'secondaryCta' ? 'secondary' : 'primary';
const clone = elem.cloneNode(true);
diff --git a/libs/blocks/merch/merch.js b/libs/blocks/merch/merch.js
index 8bdf76e754d..f11a9325845 100644
--- a/libs/blocks/merch/merch.js
+++ b/libs/blocks/merch/merch.js
@@ -852,6 +852,12 @@ export async function buildCta(el, params) {
cta.setAttribute('aria-label', ariaLabel);
});
}
+
+ // @see https://jira.corp.adobe.com/browse/MWPW-173470
+ cta.onceSettled().then(() => {
+ if (getConfig()?.locale?.prefix === '/kr' && cta.value[0]?.offerType === OFFER_TYPE_TRIAL) cta.remove();
+ });
+
return cta;
}
diff --git a/libs/utils/decorate.js b/libs/utils/decorate.js
index 6210cd0c2ea..3fbd83f993f 100644
--- a/libs/utils/decorate.js
+++ b/libs/utils/decorate.js
@@ -5,6 +5,7 @@ import {
createIntersectionObserver,
getFederatedContentRoot,
getFedsPlaceholderConfig,
+ shouldBlockFreeTrialLinks,
} from './utils.js';
const { miloLibs, codeRoot } = getConfig();
@@ -23,9 +24,12 @@ export function decorateButtons(el, size) {
const buttons = el.querySelectorAll('em a, strong a, p > a strong');
if (buttons.length === 0) return;
const buttonTypeMap = { STRONG: 'blue', EM: 'outline', A: 'blue' };
+ const localePrefix = getConfig()?.locale?.prefix;
+
buttons.forEach((button) => {
- let target = button;
const parent = button.parentElement;
+ if (shouldBlockFreeTrialLinks({ button, localePrefix, parent })) return;
+ let target = button;
const buttonType = buttonTypeMap[parent.nodeName] || 'outline';
if (button.nodeName === 'STRONG') {
target = parent;
diff --git a/libs/utils/utils.js b/libs/utils/utils.js
index 99b55448273..8b91193918c 100644
--- a/libs/utils/utils.js
+++ b/libs/utils/utils.js
@@ -415,6 +415,18 @@ export const getFedsPlaceholderConfig = ({ useCache = true } = {}) => {
return fedsPlaceholderConfig;
};
+export const shouldBlockFreeTrialLinks = ({ button, localePrefix, parent }) => {
+ if (localePrefix !== '/kr' || (!button.dataset?.modalPath?.includes('/kr/cc-shared/fragments/trial-modals')
+ && !['free-trial', 'free trial', '무료 체험판', '무료 체험하기', '{{try-for-free}}']
+ .some((pattern) => button.textContent?.toLowerCase()?.includes(pattern.toLowerCase())))) {
+ return false;
+ }
+
+ const elementToRemove = (parent?.tagName === 'STRONG' || parent?.tagName === 'EM') && parent?.children?.length === 1 ? parent : button;
+ elementToRemove.remove();
+ return true;
+};
+
export function isInTextNode(node) {
return (node.parentElement.childNodes.length > 1 && node.parentElement.firstChild.tagName === 'A') || node.parentElement.firstChild.nodeType === Node.TEXT_NODE;
}
From 7c3650fdbf0d51259953ceec081812bb4772ce65 Mon Sep 17 00:00:00 2001
From: Narcis Radu
Date: Wed, 4 Jun 2025 10:33:12 +0300
Subject: [PATCH 11/17] Revert "[MWPW-173717] Hyphenate large headings on
mobile (#4199)"
This reverts commit 7b8282100a4ae343406bf2a07e7efae7d9abe7eb.
---
libs/styles/styles.css | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/libs/styles/styles.css b/libs/styles/styles.css
index b1a8fc98421..ec9310ef201 100644
--- a/libs/styles/styles.css
+++ b/libs/styles/styles.css
@@ -930,12 +930,7 @@ a.static:active {
}
/* mobile only */
-@media (max-width: 599px) {
- :root:not(:lang(ja-JP), :lang(ja)) :is(.heading-xxxl, .heading-xxl) {
- hyphens: auto;
- hyphenate-limit-chars: 15 5 5;
- }
-
+@media (max-width: 600px) {
.con-button.button-justified-mobile {
display: block;
text-align: center;
From 3c04f4b37a3196867c94708a8a3977104a85960a Mon Sep 17 00:00:00 2001
From: Raghav Sharma <118168183+sharmrj@users.noreply.github.com>
Date: Wed, 4 Jun 2025 18:43:19 +0530
Subject: [PATCH 12/17] Update utilities.js (#4312)
Making a change to the utilities file
Co-authored-by: Saloni Jain <6162294+salonijain3@users.noreply.github.com>
---
libs/blocks/global-navigation/utilities/utilities.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js
index 0eda63e2a28..ef300dfd1f3 100644
--- a/libs/blocks/global-navigation/utilities/utilities.js
+++ b/libs/blocks/global-navigation/utilities/utilities.js
@@ -20,7 +20,7 @@ loadLana();
const FEDERAL_PATH_KEY = 'federal';
// Set a default height for LocalNav,
-// as sticky blocks position themselves before LocalNav loads into the DOM.
+// as sticky blocks position themselves before LocalNav loads into the document object model(DOM).
const DEFAULT_LOCALNAV_HEIGHT = 40;
const LANA_CLIENT_ID = 'feds-milo';
From d053a22faebb4e710a1c66da257f3bb2e27a0f6a Mon Sep 17 00:00:00 2001
From: Bandana Laishram
Date: Mon, 16 Jun 2025 16:00:56 +0530
Subject: [PATCH 13/17] Revert "Adding mutation observer to support viewport
change" (#4408)
Revert "Adding mutation observer to support viewport change (#4388)"
This reverts commit 8af16b44377b23505d533e79c6d65430c7a705c0.
---
libs/blocks/global-navigation/global-navigation.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libs/blocks/global-navigation/global-navigation.js b/libs/blocks/global-navigation/global-navigation.js
index fd309b1e5f3..ddd7e74f28a 100644
--- a/libs/blocks/global-navigation/global-navigation.js
+++ b/libs/blocks/global-navigation/global-navigation.js
@@ -1172,12 +1172,12 @@ class Gnav {
if (this.elements.aside.clientHeight > fedsPromoWrapper.clientHeight) {
lanaLog({ message: 'Promo height is more than expected, potential CLS', tags: 'gnav-promo', errorType: 'i' });
+ updateLayout();
+
+ this.promoResizeObserver?.disconnect();
+ this.promoResizeObserver = new ResizeObserver(updateLayout);
+ this.promoResizeObserver.observe(this.elements.aside);
}
- this.promoResizeObserver?.disconnect();
- this.promoResizeObserver = new ResizeObserver(updateLayout);
- this.promoResizeObserver.observe(this.elements.aside);
- updateLayout();
- isDesktop.addEventListener('change', updateLayout);
performance.mark('Gnav-Aside-End');
logPerformance('Gnav-Aside-Time', 'Gnav-Aside-Start', 'Gnav-Aside-End');
return this.elements.aside;
From 679c8e6c060ff920f8a07db8ceda29b3f41b36d1 Mon Sep 17 00:00:00 2001
From: Ryan Clayton
Date: Mon, 16 Jun 2025 13:54:21 -0600
Subject: [PATCH 14/17] Revert "[Fire-Drill] This will have to get reverted by
ryan (#4368)"
This reverts commit fdbaea6ac2d17a0342fa1a6a655d0b3bd8cc73ee.
---
test/blocks/fire-drill-ryan/README.md | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 test/blocks/fire-drill-ryan/README.md
diff --git a/test/blocks/fire-drill-ryan/README.md b/test/blocks/fire-drill-ryan/README.md
deleted file mode 100644
index 9afbd5c1cd9..00000000000
--- a/test/blocks/fire-drill-ryan/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Let's revert this after this is on production.
\ No newline at end of file
From 961a7b7b6da3a0506266d0967246145cb12ef740 Mon Sep 17 00:00:00 2001
From: Narcis Radu
Date: Thu, 26 Jun 2025 15:14:27 +0300
Subject: [PATCH 15/17] Revert "MWPW-174987: Change DOM order of elements based
on viewport (#4438)"
This reverts commit 9d02d5391a7aa2c26c46724840c9e47a4b7c73b1.
---
libs/blocks/hero-marquee/hero-marquee.css | 12 ++++
libs/blocks/hero-marquee/hero-marquee.js | 48 ----------------
test/blocks/hero-marquee/hero-marquee.test.js | 24 --------
test/blocks/hero-marquee/mocks/body.html | 56 -------------------
4 files changed, 12 insertions(+), 128 deletions(-)
diff --git a/libs/blocks/hero-marquee/hero-marquee.css b/libs/blocks/hero-marquee/hero-marquee.css
index d4e84e061b1..d9095227b35 100644
--- a/libs/blocks/hero-marquee/hero-marquee.css
+++ b/libs/blocks/hero-marquee/hero-marquee.css
@@ -379,6 +379,12 @@ html[dir="rtl"] .hero-marquee li.icon-item span.icon {
/* min height */
.hero-marquee.s-min-height-tablet { min-height: var(--s-min-height);}
.hero-marquee.l-min-height-tablet { min-height: var(--l-min-height);}
+
+ /* helper classes */
+ .hero-marquee .order-0-tablet { order: 0; }
+ .hero-marquee .order-1-tablet { order: 1; }
+ .hero-marquee .order-2-tablet { order: 2; }
+ .hero-marquee .order-3-tablet { order: 3; }
}
@media screen and (min-width: 920px) {
@@ -468,4 +474,10 @@ html[dir="rtl"] .hero-marquee li.icon-item span.icon {
/* min height */
.hero-marquee.s-min-height-desktop { min-height: var(--s-min-height);}
.hero-marquee.l-min-height-desktop { min-height: var(--l-min-height);}
+
+ /* helper classes */
+ .hero-marquee .order-0-desktop { order: 0; }
+ .hero-marquee .order-1-desktop { order: 1; }
+ .hero-marquee .order-2-desktop { order: 2; }
+ .hero-marquee .order-3-desktop { order: 3; }
}
diff --git a/libs/blocks/hero-marquee/hero-marquee.js b/libs/blocks/hero-marquee/hero-marquee.js
index 1664f0cc7c2..f747559e297 100644
--- a/libs/blocks/hero-marquee/hero-marquee.js
+++ b/libs/blocks/hero-marquee/hero-marquee.js
@@ -166,53 +166,6 @@ function loadBreakpointThemes() {
loadStyle(`${base}/styles/breakpoint-theme.css`);
}
-export function getViewportOrder(viewport, content, previousViewportOrder) {
- const orderEls = [...content.querySelectorAll(':scope > div[class*="order-"]')];
- const nonOrderEls = [...content.querySelectorAll(':scope > div:not([class*="order-"])')];
- const viewportOrder = Array(orderEls.length).fill(null);
- orderEls.forEach((el) => {
- let order;
- el.classList.forEach((className) => {
- if (!className.startsWith('order-') || !className.endsWith(viewport)) return;
- order = parseInt(className.split('-')[1], 10);
- });
- if (Number.isInteger(order)) viewportOrder[order] = el;
- });
- const nonEmpty = viewportOrder.every((el) => el);
- return nonEmpty ? [...nonOrderEls, ...viewportOrder] : previousViewportOrder;
-}
-
-function handleViewportOrder(content) {
- const hasOrder = content.querySelector(':scope > div[class*="order-"]');
- if (!hasOrder) return;
-
- const mobileOrder = [...content.children];
- const tabletOrder = getViewportOrder('tablet', content, mobileOrder);
- const viewports = {
- mobile: {
- media: '(max-width: 599px)',
- elements: mobileOrder,
- },
- tablet: {
- media: '(min-width: 600px) and (max-width: 1199px)',
- elements: tabletOrder,
- },
- desktop: {
- media: '(min-width: 1200px)',
- elements: getViewportOrder('desktop', content, tabletOrder),
- },
- };
-
- Object.entries(viewports).forEach(([viewport, { media, elements }]) => {
- const mediaQuery = window.matchMedia(media);
- if (mediaQuery.matches && viewport !== 'mobile') content.replaceChildren(...elements);
- mediaQuery.addEventListener('change', (e) => {
- if (!e.matches) return;
- content.replaceChildren(...elements);
- });
- });
-}
-
export default async function init(el) {
el.classList.add('con-block');
let rows = el.querySelectorAll(':scope > div');
@@ -315,7 +268,6 @@ export default async function init(el) {
}
});
decorateTextOverrides(el, ['-heading', '-body', '-detail'], mainCopy);
- handleViewportOrder(copy);
if (el.classList.contains('countdown-timer')) {
promiseArr.push(loadCDT(copy, el.classList));
diff --git a/test/blocks/hero-marquee/hero-marquee.test.js b/test/blocks/hero-marquee/hero-marquee.test.js
index b664f172b7d..063f9b7631a 100644
--- a/test/blocks/hero-marquee/hero-marquee.test.js
+++ b/test/blocks/hero-marquee/hero-marquee.test.js
@@ -3,7 +3,6 @@ import { expect } from '@esm-bundle/chai';
import { stub } from 'sinon';
import { waitForElement } from '../../helpers/waitfor.js';
import { setConfig } from '../../../libs/utils/utils.js';
-import { getViewportOrder } from '../../../libs/blocks/hero-marquee/hero-marquee.js';
window.lana = { log: stub() };
@@ -36,27 +35,4 @@ describe('Hero Marquee', () => {
const hr = await waitForElement('.has-divider');
expect(hr).to.exist;
});
- it('sorts con-block elements based on order class and viewport', async () => {
- const orderMarquee = document.querySelector('#hero-order');
- const orderCopy = orderMarquee.querySelector('.copy');
- const mobileOrder = [...orderCopy.children];
- const tabletOrder = getViewportOrder('tablet', orderCopy, mobileOrder);
- const desktopOrder = getViewportOrder('desktop', orderCopy, tabletOrder);
- expect(tabletOrder[0].classList.contains('main-copy')).to.be.true;
- expect(desktopOrder[0].classList.contains('main-copy')).to.be.true;
- tabletOrder.splice(0, 1);
- desktopOrder.splice(0, 1);
- // eslint-disable-next-line no-plusplus
- for (let i = 0; i < tabletOrder.length; i++) {
- expect(tabletOrder[i].classList.contains(`order-${i}-tablet`)).to.be.true;
- expect(desktopOrder[i].classList.contains(`order-${i}-desktop`)).to.be.true;
- }
- });
- it('order of con-blocks is the same as mobile if there is no order class', async () => {
- const nonOrderMarquee = document.querySelector('#hero-all');
- const nonOrderCopy = nonOrderMarquee.querySelector('.copy');
- const mobileOrder = [...nonOrderCopy.children];
- const tabletOrder = getViewportOrder('tablet', nonOrderCopy, mobileOrder);
- for (const [index, el] of tabletOrder.entries()) expect(el === mobileOrder[index]).to.be.true;
- });
});
diff --git a/test/blocks/hero-marquee/mocks/body.html b/test/blocks/hero-marquee/mocks/body.html
index abdaf013d73..013471e69b1 100644
--- a/test/blocks/hero-marquee/mocks/body.html
+++ b/test/blocks/hero-marquee/mocks/body.html
@@ -121,59 +121,3 @@ Hero w/ Adobe.tv link
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
con-block-row-lockup (xl-icon-size, order-3-tablet, order-2-desktop)
-
XL Icon Size
-
-
-
con-block-row-lockup (xl-lockup, order-1-tablet, order-3-desktop)
-
XL Icon Size
-
-
-
-
con-block-row-list (max-width-6-tablet, order-0-tablet, order-1-desktop)
-
-
- - Small
- - Medium length text
- - Long length text that may break onto a new line, what will happen, keep it going so this is even longer and really wraps?
- - Another list
-
-
-
-
-
con-block-row-qrcode(order-2-tablet, order-0-desktop)
-
-
-
From 872fa645b34363698d44d4f881d1b85b624c3204 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ilyas=20T=C3=BCrkben?=