From d9ee48e138160abd3e19d0d0f18e9925ef4c79ea Mon Sep 17 00:00:00 2001 From: Axel Cureno Basurto Date: Thu, 22 Feb 2024 12:42:59 -0800 Subject: [PATCH] MWPW-136885: More SEO-friendly, improved accessibility in merch cards (#1791) * MWPW-136885: More SEO-friendly, improved accessibility merch cards * unit tests fixed * addressed review comments * updated merch card dependency * conflicts resolved --- libs/blocks/merch-card/merch-card.js | 16 +++++-- test/blocks/merch-card/merch-card.test.js | 42 +++++++++---------- .../merch-card/mocks/special-offers.html | 8 ++-- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/libs/blocks/merch-card/merch-card.js b/libs/blocks/merch-card/merch-card.js index 562af4453ca..ee807e27837 100644 --- a/libs/blocks/merch-card/merch-card.js +++ b/libs/blocks/merch-card/merch-card.js @@ -53,7 +53,7 @@ const parseContent = (el, merchCard) => { const innerElements = [ ...el.querySelectorAll('h2, h3, h4, h5, p, ul, em'), ]; - let bodySlotName = 'body-xs'; + let bodySlotName = `body-${merchCard.variant !== MINI_COMPARE_CHART ? 'xs' : 'm'}`; let headingMCount = 0; if (merchCard.variant === MINI_COMPARE_CHART) { @@ -64,23 +64,31 @@ const parseContent = (el, merchCard) => { appendSlot(priceSmallType, 'price-commitment', merchCard); } + let headingSize = 3; const bodySlot = createTag('div', { slot: bodySlotName }); innerElements.forEach((element) => { - const { tagName } = element; + let { tagName } = element; if (isHeadingTag(tagName)) { let slotName = textStyles[tagName]; if (slotName) { - if (['H2', 'H4', 'H5'].includes(tagName)) { + if (['H2', 'H3', 'H4', 'H5'].includes(tagName)) { if (tagName === 'H2') { headingMCount += 1; } if (headingMCount === 2 && merchCard.variant === MINI_COMPARE_CHART) { slotName = 'heading-m-price'; } + tagName = `H${headingSize}`; + headingSize += 1; } element.setAttribute('slot', slotName); - merchCard.append(element); + const newElement = createTag(tagName); + Array.from(element.attributes).forEach((attr) => { + newElement.setAttribute(attr.name, attr.value); + }); + newElement.innerHTML = element.innerHTML; + merchCard.append(newElement); } return; } diff --git a/test/blocks/merch-card/merch-card.test.js b/test/blocks/merch-card/merch-card.test.js index 275b7919359..8778c8e16a1 100644 --- a/test/blocks/merch-card/merch-card.test.js +++ b/test/blocks/merch-card/merch-card.test.js @@ -31,8 +31,8 @@ describe('Merch Card', () => { it('Supports Special Offers card', async () => { document.body.innerHTML = await readFile({ path: './mocks/special-offers.html' }); const merchCard = await init(document.querySelector('.special-offers')); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const heading = merchCard.querySelector('h3[slot="detail-m"]'); + const headingOne = merchCard.querySelector('h4[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); const footer = merchCard.querySelector('div[slot="footer"]'); const buttons = footer.querySelectorAll('.con-button'); @@ -56,8 +56,8 @@ describe('Plans Card', () => { it('Supports COM Plans card', async () => { document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); const merchCard = await init(document.querySelector('.merch-card.plans.icons.secure')); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const heading = merchCard.querySelector('h3[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h4[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); const detail = merchCard.querySelector('h5[slot="detail-m"]'); const footer = merchCard.querySelector('div[slot="footer"]'); @@ -84,8 +84,8 @@ describe('Plans Card', () => { it('Supports EDU Plans card with stock', async () => { document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); const merchCard = await init(document.querySelector('.merch-card.plans.edu.icons.secure')); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const heading = merchCard.querySelector('h3[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h4[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); const detail = merchCard.querySelector('h5[slot="detail-m"]'); const footer = merchCard.querySelector('div[slot="footer"]'); @@ -112,8 +112,8 @@ describe('Plans Card', () => { it('should skip ribbon and altCta creation', async () => { document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); const merchCard = await init(document.querySelector('.plans.icons.skip-ribbon.skip-altCta')); - const heading = merchCard.querySelector('h2[slot=heading-m]'); - const headingXs = merchCard.querySelector('h3[slot=heading-xs]'); + const heading = merchCard.querySelector('h3[slot=heading-m]'); + const headingXs = merchCard.querySelector('h4[slot=heading-xs]'); const body = merchCard.querySelector('div[slot=body-xs]'); const detail = merchCard.querySelector('h5[slot=detail-m]'); const footer = merchCard.querySelector('div[slot="footer"]'); @@ -146,8 +146,8 @@ describe('Catalog Card', () => { it('Supports Catalog card', async () => { document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); const merchCard = await init(document.querySelector('.merch-card.ribbon')); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const heading = merchCard.querySelector('h3[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h4[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); const actionMenu = merchCard.querySelector('div[slot="action-menu-content"]'); const detail = merchCard.querySelector('h5[slot="detail-m"]'); @@ -175,8 +175,8 @@ describe('Catalog Card', () => { it('Supports Catalog card without badge', async () => { document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); const merchCard = await init(document.querySelector('.merch-card.catalog.empty-badge')); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const heading = merchCard.querySelector('h3[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h4[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); const actionMenu = merchCard.querySelector('div[slot="action-menu-content"]'); const detail = merchCard.querySelector('h5[slot="detail-m"]'); @@ -202,8 +202,8 @@ describe('Catalog Card', () => { it('Supports Catalog card without badge and action-menu', async () => { document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); const merchCard = await init(document.querySelector('.merch-card.catalog.empty-action-menu')); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const heading = merchCard.querySelector('h3[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h4[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); const actionMenu = merchCard.querySelector('div[slot="actionMenuContent"]'); const detail = merchCard.querySelector('h5[slot="detail-m"]'); @@ -229,8 +229,8 @@ describe('Catalog Card', () => { it('Supports Catalog card with badge without action-menu', async () => { document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); const merchCard = await init(document.querySelector('.merch-card.catalog.empty-badge.action-menu-exist')); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const heading = merchCard.querySelector('h3[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h4[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); const actionMenu = merchCard.querySelector('div[slot="actionMenuContent"]'); const detail = merchCard.querySelector('h5[slot="detail-m"]'); @@ -271,10 +271,10 @@ describe('Catalog Card', () => { it('Supports intro-pricing card', async () => { document.body.innerHTML = await readFile({ path: './mocks/intro-pricing.html' }); const merchCard = await init(document.querySelector('.merch-card')); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingXs = merchCard.querySelector('h3[slot="heading-xs"]'); + const heading = merchCard.querySelector('h3[slot="heading-xs"]'); + const headingXs = merchCard.querySelector('h4[slot="heading-m"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); - const detailBg = merchCard.querySelector('h4[slot="body-xxs"]'); + const detailBg = merchCard.querySelector('h5[slot="body-xxs"]'); const footer = merchCard.querySelector('div[slot="footer"]'); const buttons = footer.querySelectorAll('.con-button'); @@ -311,9 +311,9 @@ describe('Mini Compare Chart Merch Card', () => { document.body.innerHTML = await readFile({ path: './mocks/mini-compare-chart.html' }); const merchCard = await init(document.querySelector('.merch-card.mini-compare-chart')); document.querySelector('.section').removeAttribute('data-status'); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); + const heading = merchCard.querySelector('h3[slot="heading-m"]'); const body = merchCard.querySelector('div[slot="body-m"]'); - const priceHeading = merchCard.querySelector('h2[slot="heading-m-price"]'); + const priceHeading = merchCard.querySelector('h4[slot="heading-m-price"]'); const footer = merchCard.querySelector('div[slot="footer"]'); const buttons = footer.querySelectorAll('.con-button'); const footerRows = merchCard.querySelector('div[slot="footer-rows"]'); diff --git a/test/blocks/merch-card/mocks/special-offers.html b/test/blocks/merch-card/mocks/special-offers.html index 4ff855ea6e3..36a67455000 100644 --- a/test/blocks/merch-card/mocks/special-offers.html +++ b/test/blocks/merch-card/mocks/special-offers.html @@ -12,8 +12,8 @@ -

INDIVIDUALS

-

Get 10% off Photoshop.

+
INDIVIDUALS
+

Get 10% off Photoshop.

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

See terms

Learn More Save now

@@ -33,8 +33,8 @@

Get 10% off Photoshop.

-

INDIVIDUALS

-

Get 10% off Photoshop.

+
INDIVIDUALS
+

Get 10% off Photoshop.

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

Best for:

See terms