From a0f279590076e34d3a88df5d2a4cbeb5aa64b1cc Mon Sep 17 00:00:00 2001 From: Elan Bartholomew Date: Mon, 5 Aug 2024 12:05:19 -0600 Subject: [PATCH] update icon size naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert "MWPW-147867 - [marquee] support RTL for loc" (#2662) Revert "MWPW-147867 - [marquee] support RTL for loc (#2640)" This reverts commit 49df5f752ff7eb41a260fbb1fd7d4405f50b64c6. Revert "[MWPW-145131] Send locale and language code to analytics" (#2661) Revert "[MWPW-145131] Send locale and language code to analytics (#2600)" This reverts commit 04e687f44ba660750be880f8f0192efc9ad4f1a7. MWPW-155079 [MILO][MEP] Manifests not changing domains (#2626) * replace overridePersonalizationVariant function * Fix chaining * Move parseMepParam * add additional optional chaining operator Co-authored-by: Vivian A Goodrich <101133187+vgoodric@users.noreply.github.com> * Refactor personalization.js * Remove comment * Add TargetManifestId * Remove comment * Add targetManifestId test * Refactor addMepHighlightAndTargetManifestIdGnav * Remove console.log from test * Shorten function name * Limits targetManifestId to target exp and adds missing name to manifestId * Fix test * Handle default selectedVariant issue * Mostly done * Merging in prop display update * Unit tests fixed * Add targetmanifestid to useblockcode * refactor to remove unnecessary import * Remove commented code * Removing unused functions * Update tests, not including replacePage * Shorten Function Name * move insert inline back to fragment.js * additional cleanup and unit tests * Fix adobeTargetTestId issues * add optional chaining * Update condition for addAnalyticsForUseBlockCode * Refactor to handle analytics for updatemetadata * Fix useBlockCode test * Fix merged merged test * Remove applyPers from preload fragments test * Fix martech init post-merge * Fix tests and martech merge cleanup * Dynamically import personalization.js * add 2 ignore comments * add conditional chaining * Remove mwpw-146528 temp files * MWPW-152275 Move manifest.json request up while waiting on sstats / etc. (#2608) * add preload * shorten if and and conditional chaining * run loop even if Target is off * Add nullish coalescing assignment suggestion * MWPW-154998 [MEP][MILO] Manifests do not execute in the right order when there is a disabled manifest (#2616) * add default execution order * unit test * normalizePath * add normalizePath back into preload * MWPW-155568 [MILO][MEP] If MEP is completely off, mep param should still show button (#2658) don't return if param is present but empty --------- Co-authored-by: markpadbe Co-authored-by: Mark Perry <124626043+markpadbe@users.noreply.github.com> MWPW-146030 and MWPW-143704 Add fresco-any and cc-paid-no-stock (#2657) add entitlements Attaching loadblock to window to provide alternative way of loading the script (#2660) Attaching loadblock to window MWPW-155316 - Fixing Pill Notification edge cases (#2639) * handling pill edge cases * pill edge case styles * update tests to fix coverage * correction to previous commit * updates based on PR feedback * more simplifying * adding an additional filter * style tweak * change inline size for desktop pills * revert of icon sizing * revert of ribbon revert Correctly pass on the dataset (#2651) MWPW-155289: Fixed filtering and sorting in catalog sidenav (#2653) handled empty hash case in deeplink MWPW-154124: use preview index (#2654) * MWPW-154124: use preview index * should remove both links [AUTOMATED-PR] Update imslib.min.js dependency (#2659) Update self hosted dependency Co-authored-by: GitHub Action [MWPW-152181] Tabbing gets "stuck" after second instance of merch-card CTAs, within a segment blade (#2650) * Allow the default tab action to proceed if the current focused element is from the last merch card * ran "npm run build" * Updated readme * fix vulnerability * Revert "fix vulnerability" This reverts commit e34d131ed16dbef30629fe0bb58419485fd85e2f. * allow tabbing across section for merch cards --------- Co-authored-by: Rohit Sahu [MWPW-145131] Send locale and language code to analytics (#2670) MWPW-147867 - [marquee] support RTL for loc - RePost (#2676) added `support-rtl` selectors MWPW-155691 [MILO][MEP] Also use region in placeholders decision (#2680) * use region for placeholders * move region to it's own line * move value to last and add other MWPW-154901 Set debug=true on categories container (#2624) * MWPW-154901: enables debug=true based on container type * Update libs/blocks/caas/utils.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: milo-pr-merge[bot] <169241390+milo-pr-merge[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> [MWPW-136406] Tabs block enhancement: deep linking (#2652) * query param for focused tab * addressed feedback add lockup support lockup improvements updating button defaults fix button size logic update default btn size for banners MWPW-154981: adds a new Created Date option to details text (#2685) Co-authored-by: milo-pr-merge[bot] <169241390+milo-pr-merge[bot]@users.noreply.github.com> MWPW-155781 [MILO] Geo Modal Tracking on BACOM - Missing custom link (#2694) add analytic MWPW-154898 No wait for modal fragment (#2607) No wait for modal fragment MWPW-154191: Ability to have green promo text on merch-card to bottom of the card (under description) (#2663) added promo-text slot to all merch cards MWPW-155654 Open TWP modal with preselected tab (#2691) * MWPW-155654 Open TWP modal with preselected tab * MWPW-155654 Open TWP modal with preselected tab * MWPW-155654 Open TWP modal with preselected tab * MWPW-155654 Open TWP modal with preselected tab * MWPW-155654 Open TWP modal with preselected tab * Trigger Build * MWPW-155654 Open TWP modal with preselected tab * MWPW-155654 Open TWP modal with preselected tab * MWPW-155654 Open TWP modal with preselected tab --------- Co-authored-by: Bozo Jovicic MWPW-154893 - [editorial-card] bugs (#2656) * added .support-rtl variant for easier rtl loc support * moved support-rtl to tablet up selector * remove right * removed margin-top bottom tablet styles * added empty class and updated has-footer to equal-height to expose that as a variant * s spacing gap default * action column-gap * no footer test coverage * PR feedback * revert marquee changes * updated .footer class to .card-footer to prevent naming colision * updated test ref * linting whitespace, test label clarity * revert icon block changes derp ENB-6995 Query Params update & sendTargetResponse function update Resubmit for #2664 (#2682) * Query Parms update & sendTargetResponse function update (#2664) * Query Parms update & sendTargetResponse function update - sendTargetResponse: Added Check for window._satellite and changed direct alloy call to _satellite call - Added additional parameter as marketingtech to disable analytics calls * Query Parms update & sendTargetResponse function update - Updated conditional chaining --------- Co-authored-by: milo-pr-merge[bot] <169241390+milo-pr-merge[bot]@users.noreply.github.com> * Update martech.js * not caching values --------- Co-authored-by: theankit-sinha Co-authored-by: milo-pr-merge[bot] <169241390+milo-pr-merge[bot]@users.noreply.github.com> MWPW-153810 media image is seen loaded twice in product page urls in desktop (#2647) * placeholderChanges * placeholderChanges * Update utils.js * Update utils.js * Update utils.js * lint errors * Update utils.js * Update utils.js * Adding promise.all * Update utils.js * Update utils.js --------- Co-authored-by: Suhani [MWPW-155627] Merch Callout feature: Missing font cascade (#2679) add fallback to "Adobe Clean" font for callout text Co-authored-by: Rohit Sahu MWPW-153955 [PEP ] dismiss tool tip text is seen chopped in RTL locale in ipad and iphone in landscape mode (#2687) * Fixed pep dismissal tooltip in rtl locales * Update libs/features/webapp-prompt/webapp-prompt.css Co-authored-by: Rares Munteanu --------- Co-authored-by: Rares Munteanu MWPW-154969 Log LCP and key user attributes (#2686) * MWPW-154969 Log LCP and key user attributes This adds the ability to log performance data back to Lana. To enable the feature, metadata `pageperf = ‘on’ ` must be set for the page. This feature only works in Chrome browsers. Additionally `pageperf-rate` can be set to determine what percentage of pages will send data. E.g `pageperf-rate=15` would have 15% of the pages send perf data. The default rate is `50`%. The sending of the data to Lana is delayed so as to not affect any parts of the page load. Data sent: * Chrome Version * CLS Score * Country (only if georouting is enabled via geo2) * Downlink: Mbps - Chrome caps value at `10` * LCP Score * LCP Element Type * LCP URL * If there is no identifying url, the element html will be used. * Adobe IMS Logged In Status * OS * URL of page * Window Width & Height * MEP Manifest Data * Manifest(s) Used (only the ones that have been applied to the page) * Selected Target in the manifest * Update logWebVitalsUtils.test.js * Address PR feedback --------- Co-authored-by: Okan Sahin [MWPW-150579] Update supported browser list (#2696) MWPW-152952 Allow message for Marketo form success (#2545) MWPW-146237: Repurpose seotech-structured-data feature for arbitrary JSON-LD (#2578) * Add necessary helper functions * Fix two checks * Replace getStructuredData * Move things around * Fix regex? * Add env * Support localhost * Update paths * Fix test * Use seotech api instead * Update env/subdomain * Fix test properly * Update endoint * Add homepage * Update README * Rework endpoint handling * Add class to script tags * More doc updates revert PR of placeholder function as placeholder value is seen displayed with additional nbsp text in locale product pages in stage (#2709) Update utils.js Standalone GNav for Non-Milo Consumers (#2669) * Adding configuration for header component * Adding test cases * Adding css changes * Updated for css * Setting the origin to federal * Removing promise array * Adding redirect uri in meta * Updating meta insert function * Lint fix * Making error message descriptive --------- Co-authored-by: Snehal Sonawane Making new GNAV experience default (#2689) Fix: Load gnav search files only if it is authored (#2700) [MWPW-154102] Accordion RTL alignment (#2704) [MWPW-156163] Send additional Slack notifications for high impact PRs (#2713) MWPW-156388 [MILO][MEP] fix for martech=off when page has manifest with enablements (#2720) * initial fix * Update libs/features/personalization/personalization.js Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * move where martech=off is used * move logic to handleEntitlements function --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> MWPW-156220: Support pa code and product code for (#2712) * MWPW-156220: Support pa code and product code for checkout link configuration in addition to product family. * optimize perf * PR feedback * PR feedback Added download and open-in spectrum icons (#2595) adde download and open-in spectrum icons Co-authored-by: Dragana Trajkovic MWPW-142166 One Page Gated (#2673) * MWPW-142166 One Page Gated * PR Changes MWPW-153987 [MILO][MEP] looks in wrong location for MEP test block code on stage (#2693) * calculate even on stage, find miloLibs and origin outside of loop * MWPW-155314 [MEP] Enable Entitlements + Operator (#2638) port over fixes --------- Co-authored-by: Jingle Huang <32369333+JingleH@users.noreply.github.com> [MWPW-154969] Performance consent (#2714) * Require consent * Improve the check * Apply suggestions from code review Co-authored-by: Narcis Radu * Fix linting issues * Fix linting and unit tests * Return faster * Track once consent is given * Fix unit tests * Remove defaults * Only listen to privacy once. --------- Co-authored-by: Narcis Radu --- .browserslistrc | 4 +- .github/workflows/high-impact-alert.js | 5 +- .github/workflows/high-impact-alert.yml | 1 + .github/workflows/label-zero-impact.js | 1 + libs/blocks/accordion/accordion.css | 2 +- libs/blocks/adobetv/adobetv.js | 4 +- libs/blocks/caas-config/caas-config.js | 1 + libs/blocks/caas/utils.js | 4 +- libs/blocks/editorial-card/editorial-card.css | 38 +- libs/blocks/editorial-card/editorial-card.js | 7 +- libs/blocks/fragment/fragment.js | 19 +- .../global-navigation/global-navigation.js | 28 +- .../global-navigation/utilities/menu/menu.js | 4 +- .../global-navigation/utilities/utilities.js | 12 +- libs/blocks/marketo/marketo.js | 95 +++-- libs/blocks/marquee/marquee.css | 8 +- .../merch-card-collection.js | 10 +- libs/blocks/merch/merch.js | 77 +++- libs/blocks/modal/modal.js | 5 +- libs/blocks/notification/notification.css | 58 ++- libs/blocks/notification/notification.js | 47 ++- libs/blocks/tabs/tabs.js | 5 + libs/deps/imslib.min.js | 4 +- libs/deps/mas/merch-card-all.js | 126 +++---- libs/deps/mas/merch-card-collection.js | 2 +- libs/deps/mas/merch-card.js | 44 ++- libs/deps/mas/merch-sidenav.js | 2 +- libs/deps/mas/plans-modal.js | 2 +- libs/features/mas/package-lock.json | 2 - libs/features/mas/web-components/README.md | 9 +- .../mas/web-components/src/deeplink.js | 2 +- .../mas/web-components/src/global.css.js | 2 +- .../mas/web-components/src/merch-card.js | 31 +- .../mas/web-components/test/deeplink.test.js | 12 +- libs/features/personalization/entitlements.js | 3 + .../personalization/personalization.js | 356 +++++++++++------- libs/features/personalization/preview.js | 1 + .../personalization/stage-entitlements.js | 1 + libs/features/seotech/README.md | 12 +- libs/features/seotech/seotech.js | 73 ++-- .../dist/icons-workflow.js | 48 ++- .../src/icons-workflow.js | 2 + libs/features/webapp-prompt/webapp-prompt.css | 7 +- libs/martech/martech.js | 45 +-- libs/mep/mwpw-142224/marquee/marquee.js | 3 - .../marquee/marquee.css | 0 libs/mep/sample-block-code/marquee/marquee.js | 3 + libs/navigation/bootstrapper.js | 24 +- libs/navigation/navigation.css | 15 +- libs/navigation/navigation.js | 69 +++- libs/styles/styles.css | 4 - libs/utils/decorate.js | 3 +- libs/utils/logWebVitals.js | 110 ++++++ libs/utils/utils.js | 135 ++++--- .../editorial-card/editorial-card.test.js | 2 +- test/blocks/editorial-card/mocks/body.html | 4 +- test/blocks/marketo/marketo.test.html | 26 +- test/blocks/marketo/marketo.test.js | 6 + .../merch-card-collection.test.js | 22 +- .../mocks/merch-card-collection.html | 15 + test/blocks/merch/merch.test.js | 149 ++++++-- test/blocks/merch/mocks/body.html | 4 + test/blocks/notification/mocks/body.html | 13 + test/features/personalization/actions.test.js | 55 ++- .../actionsTargetManifestId.test.js | 164 ++++++++ .../personalization/deprecatedActions.test.js | 15 +- test/features/personalization/mepSettings.js | 10 + .../personalization/mepTargetSettings.js | 10 + .../actions/manifestAppendToSection.json | 1 + .../mocks/actions/manifestCustomAction.json | 4 + .../mocks/actions/manifestInsertAfter.json | 3 + .../mocks/actions/manifestInsertBefore.json | 2 + .../actions/manifestPrependToSection.json | 3 +- .../mocks/actions/manifestRemove.json | 2 + .../mocks/actions/manifestReplace.json | 4 + .../mocks/actions/manifestTargetReplace.json | 48 +++ .../mocks/actions/manifestUseBlockCode.json | 1 + .../mocks/actions/manifestUseBlockCode2.json | 1 + ...replace-content-target-howto-h2.plain.html | 1 + .../personalization/pageFilter.test.js | 7 +- .../personalization/personalization.test.js | 200 +++++++++- .../personalization/replacePage.test.js | 5 +- test/features/seotech/seotech.test.js | 34 +- test/navigation/bootstrapper.test.js | 31 +- test/navigation/navigation.test.js | 17 +- test/utils/logWebVitals.test.js | 62 +++ test/utils/logWebVitalsUtils.test.js | 64 ++++ test/utils/utils-mep.test.js | 3 +- test/utils/utils-partition.test.js | 27 ++ test/utils/utils.test.js | 2 +- 90 files changed, 1912 insertions(+), 692 deletions(-) delete mode 100644 libs/mep/mwpw-142224/marquee/marquee.js rename libs/mep/{mwpw-142224 => sample-block-code}/marquee/marquee.css (100%) create mode 100644 libs/mep/sample-block-code/marquee/marquee.js create mode 100644 libs/utils/logWebVitals.js create mode 100644 test/features/personalization/actionsTargetManifestId.test.js create mode 100644 test/features/personalization/mepSettings.js create mode 100644 test/features/personalization/mepTargetSettings.js create mode 100644 test/features/personalization/mocks/actions/manifestTargetReplace.json create mode 100644 test/features/personalization/mocks/fragments/milo-replace-content-target-howto-h2.plain.html create mode 100644 test/utils/logWebVitals.test.js create mode 100644 test/utils/logWebVitalsUtils.test.js create mode 100644 test/utils/utils-partition.test.js diff --git a/.browserslistrc b/.browserslistrc index 46438bbd49..347d887abc 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -1,5 +1,5 @@ last 1 chrome version last 1 firefox version last 1 edge version -safari >= 14 -ios_saf >= 14 +safari >= 15 +ios_saf >= 15 diff --git a/.github/workflows/high-impact-alert.js b/.github/workflows/high-impact-alert.js index 9a5a5833fb..5858af61b5 100644 --- a/.github/workflows/high-impact-alert.js +++ b/.github/workflows/high-impact-alert.js @@ -13,9 +13,12 @@ const main = async (params) => { } const { html_url, number, title } = context.payload.pull_request; - console.log('High impact label detected, sending Slack notification'); + console.log('High impact label detected, sending Slack notifications'); slackNotification(`:alert: High Impact PR has been opened: <${html_url}|#${number}: ${title}>.` + ` Please prioritize testing the proposed changes.`, process.env.SLACK_HIGH_IMPACT_PR_WEBHOOK); + slackNotification(`:alert: High Impact PR has been opened: <${html_url}|#${number}: ${title}>.` + + ` Please review the PR details promptly and raise any concerns or questions.`, + process.env.SLACK_MILO_UPDATES_WEBHOOK); } catch (error) { console.error(error); } diff --git a/.github/workflows/high-impact-alert.yml b/.github/workflows/high-impact-alert.yml index 9fa01dacc2..3c3ea56f2d 100644 --- a/.github/workflows/high-impact-alert.yml +++ b/.github/workflows/high-impact-alert.yml @@ -7,6 +7,7 @@ on: env: SLACK_HIGH_IMPACT_PR_WEBHOOK: ${{ secrets.SLACK_HIGH_IMPACT_PR_WEBHOOK }} + SLACK_MILO_UPDATES_WEBHOOK: ${{ secrets.SLACK_MILO_UPDATES_WEBHOOK }} jobs: send_alert: diff --git a/.github/workflows/label-zero-impact.js b/.github/workflows/label-zero-impact.js index fd5bb393ba..24068eee33 100644 --- a/.github/workflows/label-zero-impact.js +++ b/.github/workflows/label-zero-impact.js @@ -4,6 +4,7 @@ const zeroImpactDirs = [ '.kodiak', '.vscode', '.test', + '.browserslistrc', 'libs/mep', '.eslintrc.js', 'CODEOWNERS', diff --git a/libs/blocks/accordion/accordion.css b/libs/blocks/accordion/accordion.css index 16a9f4a11b..0cdc4e2c2d 100644 --- a/libs/blocks/accordion/accordion.css +++ b/libs/blocks/accordion/accordion.css @@ -32,7 +32,7 @@ dl.accordion { line-height: var(--type-heading-s-lh); padding: var(--spacing-s) var(--spacing-m) var(--spacing-s) var(--spacing-xs); position: relative; - text-align: left; + text-align: start; width: 100%; -webkit-text-size-adjust: 100%; } diff --git a/libs/blocks/adobetv/adobetv.js b/libs/blocks/adobetv/adobetv.js index 17ba78ef7d..31cfc7a368 100644 --- a/libs/blocks/adobetv/adobetv.js +++ b/libs/blocks/adobetv/adobetv.js @@ -7,8 +7,8 @@ const loadAdobeTv = (a) => { const bgBlocks = ['aside', 'marquee', 'hero-marquee']; if (a.href.includes('.mp4') && bgBlocks.some((b) => a.closest(`.${b}`))) { a.classList.add('hide'); - const { href, hash } = a; - const attrs = getVideoAttrs(hash || 'autoplay'); + const { href, hash, dataset } = a; + const attrs = getVideoAttrs(hash || 'autoplay', dataset); const video = ``; diff --git a/libs/blocks/caas-config/caas-config.js b/libs/blocks/caas-config/caas-config.js index 92b5b566c7..c1bec7e45d 100644 --- a/libs/blocks/caas-config/caas-config.js +++ b/libs/blocks/caas-config/caas-config.js @@ -212,6 +212,7 @@ const defaultOptions = { }, detailsTextOption: { default: 'Default', + createdDate: 'Created Date', modifiedDate: 'Modified Date', }, cardHoverEffect: { diff --git a/libs/blocks/caas/utils.js b/libs/blocks/caas/utils.js index 68ab6c5819..7ea5fcbf41 100644 --- a/libs/blocks/caas/utils.js +++ b/libs/blocks/caas/utils.js @@ -551,7 +551,9 @@ export const getConfig = async (originalState, strs = {}) => { && state.targetActivity ? `/${encodeURIComponent(state.targetActivity)}.json` : ''; const flatFile = targetActivity ? '&flatFile=false' : ''; const localesQueryParam = locales ? `&locales=${locales}` : ''; - const debug = state.showIds && document.location.pathname.includes('/tools/caas') ? '&debug=true' : ''; + const debug = (state.showIds && document.location.pathname.includes('/tools/caas')) + || state.container === 'categories' + ? '&debug=true' : ''; const collectionTags = state.includeTags ? state.includeTags.join(',') : ''; const excludeContentWithTags = state.excludeTags ? state.excludeTags.join(',') : ''; diff --git a/libs/blocks/editorial-card/editorial-card.css b/libs/blocks/editorial-card/editorial-card.css index effea939c6..8191393f80 100644 --- a/libs/blocks/editorial-card/editorial-card.css +++ b/libs/blocks/editorial-card/editorial-card.css @@ -55,7 +55,7 @@ min-width: initial; } -.editorial-card.has-footer { +.editorial-card.equal-height { height: 100%; } @@ -79,7 +79,7 @@ } .editorial-card .foreground, -.editorial-card .footer { +.editorial-card .card-footer { padding: var(--spacing-xs); } @@ -87,12 +87,12 @@ padding: 0 var(--spacing-xs); } -.editorial-card .footer { +.editorial-card .card-footer { padding-top: 0; margin-top: auto; } -.editorial-card .footer > div { +.editorial-card .card-footer > div { display: flex; flex-direction: column; text-align: end; @@ -100,6 +100,8 @@ row-gap: var(--spacing-xxs); } +.editorial-card .card-footer.empty { padding: 0; } + .editorial-card.no-bg.no-border .foreground { padding: var(--spacing-s) 0; } @@ -109,7 +111,7 @@ } .editorial-card.no-bg.no-border .static, -.editorial-card.no-bg.no-border .footer { +.editorial-card.no-bg.no-border .card-footer { padding-inline: 0; } @@ -127,8 +129,8 @@ line-height: 0; } -.editorial-card.footer-align-left .footer > div { text-align: start; } -.editorial-card.footer-align-center .footer > div { text-align: center; } +.editorial-card.footer-align-left .card-footer > div { text-align: start; } +.editorial-card.footer-align-center .card-footer > div { text-align: center; } .editorial-card.no-bg.no-border .foreground > div { row-gap: var(--spacing-xs); @@ -154,11 +156,11 @@ } .editorial-card .action-area, -.editorial-card .footer > .action-area { +.editorial-card .card-footer > .action-area { display: flex; align-items: center; justify-content: right; - gap: var(--spacing-xxs); + gap: var(--spacing-xs) var(--spacing-s); flex-flow: wrap; flex-direction: row; } @@ -171,16 +173,13 @@ justify-content: center; } -.editorial-card.right .action-area { - justify-content: right; -} .editorial-card hr { background-color: currentcolor; border: none; height: 1px; width: 100%; - margin: var(--spacing-xs) 0; + margin: var(--spacing-xxs) 0; } .editorial-card .background { @@ -204,6 +203,11 @@ position: relative; } +.editorial-card:is(.media-square, .media-wide, .media-standard, .media-tall) .media-area .milo-video { + height: auto; + padding: 0; +} + /* Aspect Ratio */ .editorial-card.media-square .media-area img, .editorial-card.media-square .media-area video { @@ -224,7 +228,8 @@ } .editorial-card.media-tall .media-area img, -.editorial-card.media-tall .media-area video { +.editorial-card.media-tall .media-area video, +.editorial-card.media-tall .media-area .milo-video { aspect-ratio: var(--aspect-ratio-tall); max-height: unset; } @@ -241,10 +246,5 @@ justify-items: center; } -.editorial-card.right { - text-align: end; - justify-items: end; -} - .editorial-card.footer-align-left .action-area { justify-content: start; } .editorial-card.footer-align-center .action-area { justify-content: center; } diff --git a/libs/blocks/editorial-card/editorial-card.js b/libs/blocks/editorial-card/editorial-card.js index 9451f6ea88..9cd9a31d2b 100644 --- a/libs/blocks/editorial-card/editorial-card.js +++ b/libs/blocks/editorial-card/editorial-card.js @@ -46,7 +46,8 @@ const decorateForeground = async (el, rows) => { row.classList.add('foreground'); await decorateLockupFromContent(row); } else if (i === (rows.length - 1)) { - row.classList.add('footer'); + row.classList.add('card-footer'); + if (!row.textContent.trim()) row.classList.add('empty'); } else { row.classList.add('extra-row'); } @@ -86,12 +87,12 @@ const init = async (el) => { if (![...el.classList].some((c) => c.endsWith('-lockup'))) el.classList.add('m-lockup'); let rows = el.querySelectorAll(':scope > div'); const [head, middle, ...tail] = rows; - if (rows.length === 4) el.classList.add('has-footer'); + if (rows.length === 4) el.classList.add('equal-height'); if (rows.length >= 1) { const count = rows.length >= 3 ? 'three-plus' : rows.length; switch (count) { case 'three-plus': - // 3+ rows (0:bg, 1:media, 2:copy, ...3:static, last:footer) + // 3+ rows (0:bg, 1:media, 2:copy, ...3:static, last:card-footer) decorateBgRow(el, head); rows = tail; await decorateForeground(el, rows); diff --git a/libs/blocks/fragment/fragment.js b/libs/blocks/fragment/fragment.js index 2bca02da83..84a922d6f5 100644 --- a/libs/blocks/fragment/fragment.js +++ b/libs/blocks/fragment/fragment.js @@ -32,12 +32,6 @@ const updateFragMap = (fragment, a, href) => { } }; -const setManifestIdOnChildren = (sections, manifestId) => { - [...sections[0].children].forEach( - (child) => (child.dataset.manifestId = manifestId), - ); -}; - const insertInlineFrag = (sections, a, relHref) => { // Inline fragments only support one section, other sections are ignored const fragChildren = [...sections[0].children]; @@ -79,7 +73,7 @@ export default async function init(a) { } const path = new URL(a.href).pathname; - if (mep?.fragments?.[path] && mep) { + if (mep?.fragments?.[path]) { relHref = mep.handleFragmentCommand(mep?.fragments[path], a); if (!relHref) return; } @@ -122,15 +116,10 @@ export default async function init(a) { } updateFragMap(fragment, a, relHref); - - if (a.dataset.manifestId) { - if (inline) { - setManifestIdOnChildren(sections, a.dataset.manifestId); - } else { - fragment.dataset.manifestId = a.dataset.manifestId; - } + if (a.dataset.manifestId || a.dataset.adobeTargetTestid) { + const { updateFragDataProps } = await import('../../features/personalization/personalization.js'); + updateFragDataProps(a, inline, sections, fragment); } - if (inline) { insertInlineFrag(sections, a, relHref); } else { diff --git a/libs/blocks/global-navigation/global-navigation.js b/libs/blocks/global-navigation/global-navigation.js index dbd6c14f49..a83ba5d6bc 100644 --- a/libs/blocks/global-navigation/global-navigation.js +++ b/libs/blocks/global-navigation/global-navigation.js @@ -33,7 +33,7 @@ import { toFragment, trigger, yieldToMain, - addMepHighlight, + addMepHighlightAndTargetId, } from './utilities/utilities.js'; import { replaceKey, replaceKeyArray } from '../../features/placeholders.js'; @@ -405,13 +405,15 @@ class Gnav { try { this.block.removeEventListener('click', this.loadDelayed); this.block.removeEventListener('keydown', this.loadDelayed); - const [ - Search, - ] = await Promise.all([ - loadBlock('../features/search/gnav-search.js'), - loadStyles(rootPath('features/search/gnav-search.css')), - ]); - this.Search = Search; + if (this.searchPresent()) { + const [ + Search, + ] = await Promise.all([ + loadBlock('../features/search/gnav-search.js'), + loadStyles(rootPath('features/search/gnav-search.css')), + ]); + this.Search = Search; + } if (!this.useUniversalNav) { const [ProfileDropdown] = await Promise.all([ @@ -919,14 +921,14 @@ class Gnav { observer.observe(dropdownTrigger, { attributeFilter: ['aria-expanded'] }); delayDropdownDecoration({ template: triggerTemplate }); - return addMepHighlight(triggerTemplate, item); + return addMepHighlightAndTargetId(triggerTemplate, item); } case 'primaryCta': case 'secondaryCta': // Remove its 'em' or 'strong' wrapper item.parentElement.replaceWith(item); - return addMepHighlight(toFragment`
+ return addMepHighlightAndTargetId(toFragment`
${decorateCta({ elem: item, type: itemType, index: index + 1 })}
`, item); case 'link': { @@ -945,15 +947,15 @@ class Gnav {
${linkElem}
`; - return addMepHighlight(linkTemplate, item); + return addMepHighlightAndTargetId(linkTemplate, item); } case 'text': - return addMepHighlight(toFragment`
+ return addMepHighlightAndTargetId(toFragment`
${item.textContent}
`, item); default: /* c8 ignore next 3 */ - return addMepHighlight(toFragment`
+ return addMepHighlightAndTargetId(toFragment`
${item}
`, item); } diff --git a/libs/blocks/global-navigation/utilities/menu/menu.js b/libs/blocks/global-navigation/utilities/menu/menu.js index d5f6d8fabb..aa2a21e704 100644 --- a/libs/blocks/global-navigation/utilities/menu/menu.js +++ b/libs/blocks/global-navigation/utilities/menu/menu.js @@ -11,7 +11,7 @@ import { toFragment, trigger, yieldToMain, - addMepHighlight, + addMepHighlightAndTargetId, } from '../utilities.js'; const decorateHeadline = (elem, index) => { @@ -317,7 +317,7 @@ const decorateMenu = (config) => logErrorFor(async () => { ${menuContent}
`; - addMepHighlight(menuTemplate, content); + addMepHighlightAndTargetId(menuTemplate, content); decorateCrossCloudMenu(menuTemplate); diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js index fcc3c24f74..a4c73212f7 100644 --- a/libs/blocks/global-navigation/utilities/utilities.js +++ b/libs/blocks/global-navigation/utilities/utilities.js @@ -47,13 +47,12 @@ export const logErrorFor = async (fn, message, tags) => { } }; -export function addMepHighlight(el, source) { - let { manifestId } = source.dataset; - if (!manifestId) { - const closestManifestId = source?.closest('[data-manifest-id]'); - if (closestManifestId) manifestId = closestManifestId.dataset.manifestId; - } +export function addMepHighlightAndTargetId(el, source) { + let { manifestId, targetManifestId } = source.dataset; + manifestId ??= source?.closest('[data-manifest-id]')?.dataset?.manifestId; + targetManifestId ??= source?.closest('[data-adobe-target-testid]')?.dataset?.adobeTargetTestid; if (manifestId) el.dataset.manifestId = manifestId; + if (targetManifestId) el.dataset.adobeTargetTestid = targetManifestId; return el; } @@ -310,6 +309,7 @@ export async function fetchAndProcessPlainHtml({ url, shouldDecorateLinks = true const text = await res.text(); const { body } = new DOMParser().parseFromString(text, 'text/html'); if (mepFragment?.manifestId) body.dataset.manifestId = mepFragment.manifestId; + if (mepFragment?.targetManifestId) body.dataset.adobeTargetTestid = mepFragment.targetManifestId; const commands = mepGnav?.commands; if (commands?.length) { const { handleCommands, deleteMarkedEls } = await import('../../../features/personalization/personalization.js'); diff --git a/libs/blocks/marketo/marketo.js b/libs/blocks/marketo/marketo.js index e496345174..1602d0694a 100644 --- a/libs/blocks/marketo/marketo.js +++ b/libs/blocks/marketo/marketo.js @@ -19,19 +19,27 @@ const ROOT_MARGIN = 1000; const FORM_ID = 'form id'; const BASE_URL = 'marketo host'; const MUNCHKIN_ID = 'marketo munckin'; +const SUCCESS_TYPE = 'form.success.type'; +const SUCCESS_CONTENT = 'form.success.content'; +const SUCCESS_SECTION = 'form.success.section'; const FORM_MAP = { - 'destination-url': 'form.success.content', + 'success-type': SUCCESS_TYPE, + 'destination-type': SUCCESS_TYPE, + 'success-content': SUCCESS_CONTENT, + 'destination-url': SUCCESS_CONTENT, + 'success-section': SUCCESS_SECTION, 'co-partner-names': 'program.copartnernames', 'sfdc-campaign-id': 'program.campaignids.sfdc', }; -export const formValidate = (form) => { - const formEl = form.getFormElem().get(0); +export const formValidate = (formEl) => { formEl.classList.remove('hide-errors'); formEl.classList.add('show-warnings'); }; export const decorateURL = (destination, baseURL = window.location) => { + if (!(destination.startsWith('http') || destination.startsWith('/'))) return null; + try { let destinationUrl = new URL(destination, baseURL.origin); const { hostname, pathname, search, hash } = destinationUrl; @@ -59,9 +67,24 @@ export const decorateURL = (destination, baseURL = window.location) => { return null; }; -export const formSuccess = (form) => { - const formEl = form.getFormElem().get(0); - const parentModal = formEl.closest('.dialog-modal'); +const setPreference = (key = '', value = '') => { + if (!value || !key.includes('.')) return; + const keyParts = key.split('.'); + const lastKey = keyParts.pop(); + const formDataObject = keyParts.reduce((obj, part) => { + obj[part] = obj[part] || {}; + return obj[part]; + }, window.mcz_marketoForm_pref); + formDataObject[lastKey] = value; +}; + +export const setPreferences = (formData) => { + window.mcz_marketoForm_pref = window.mcz_marketoForm_pref || {}; + Object.entries(formData).forEach(([key, value]) => setPreference(key, value)); +}; + +export const formSuccess = (formEl, formData) => { + const parentModal = formEl?.closest('.dialog-modal'); const mktoSubmit = new Event('mktoSubmit'); window.dispatchEvent(mktoSubmit); @@ -74,10 +97,23 @@ export const formSuccess = (form) => { return false; } - return true; + if (formData?.[SUCCESS_TYPE] !== 'section') return true; + + try { + const section = formData[SUCCESS_SECTION].toLowerCase().replaceAll(' ', '-'); + const success = document.querySelector(`.section.${section}`); + success.classList.remove('hide-block'); + success.scrollIntoView({ behavior: 'smooth' }); + setPreference(SUCCESS_TYPE, 'message'); + } catch (e) { + /* c8 ignore next 2 */ + window.lana?.log('Error showing Marketo success section', { tags: 'errorType=warn,module=marketo' }); + } + + return false; }; -const readyForm = (form) => { +const readyForm = (form, formData) => { const formEl = form.getFormElem().get(0); const isDesktop = matchMedia('(min-width: 900px)'); @@ -93,41 +129,27 @@ const readyForm = (form) => { const offsetPosition = targetPosition + window.pageYOffset - pageTop - window.innerHeight / 2; window.scrollTo(0, offsetPosition); }, true); - form.onValidate(() => formValidate(form)); - form.onSuccess(() => formSuccess(form)); -}; - -const setPreference = (key, value) => { - if (value && key?.includes('.')) { - const keyParts = key.split('.'); - const lastKey = keyParts.pop(); - const formDataObject = keyParts.reduce((obj, part) => { - obj[part] = obj[part] || {}; - return obj[part]; - }, window.mcz_marketoForm_pref); - formDataObject[lastKey] = value; - } -}; - -export const setPreferences = (formData) => { - window.mcz_marketoForm_pref = window.mcz_marketoForm_pref || {}; - Object.entries(formData).forEach(([key, value]) => setPreference(key, value)); + form.onValidate(() => formValidate(formEl)); + form.onSuccess(() => formSuccess(formEl, formData)); }; export const loadMarketo = (el, formData) => { const baseURL = formData[BASE_URL]; + const munchkinID = formData[MUNCHKIN_ID]; + const formID = formData[FORM_ID]; loadScript(`https://${baseURL}/js/forms2/js/forms2.min.js`) .then(() => { const { MktoForms2 } = window; if (!MktoForms2) throw new Error('Marketo forms not loaded'); - MktoForms2.loadForm(`//${baseURL}`, formData[MUNCHKIN_ID], formData[FORM_ID]); + MktoForms2.loadForm(`//${baseURL}`, munchkinID, formID); MktoForms2.whenReady((form) => { readyForm(form, formData); }); }) .catch(() => { - /* c8 ignore next */ + /* c8 ignore next 2 */ el.style.display = 'none'; + window.lana?.log(`Error loading Marketo form for ${munchkinID}_${formID}`, { tags: 'errorType=error,module=marketo' }); }); }; @@ -135,7 +157,6 @@ export default function init(el) { const children = Array.from(el.querySelectorAll(':scope > div')); const encodedConfigDiv = children.shift(); const link = encodedConfigDiv.querySelector('a'); - let formData = {}; if (!link?.href) { el.style.display = 'none'; @@ -143,8 +164,7 @@ export default function init(el) { } const encodedConfig = link.href.split('#')[1]; - - formData = parseEncodedConfig(encodedConfig); + const formData = parseEncodedConfig(encodedConfig); children.forEach((element) => { const key = element.children[0]?.textContent.trim().toLowerCase().replaceAll(' ', '-'); @@ -166,13 +186,12 @@ export default function init(el) { return; } - if (formData['form.success.content']) { - const destinationUrl = decorateURL(formData['form.success.content']); + formData[SUCCESS_TYPE] = formData[SUCCESS_TYPE] || 'redirect'; - if (destinationUrl) { - formData['form.success.type'] = 'redirect'; - formData['form.success.content'] = destinationUrl; - } + if (formData[SUCCESS_TYPE] === 'redirect') { + const destinationUrl = decorateURL(formData[SUCCESS_CONTENT]); + + if (destinationUrl) formData[SUCCESS_CONTENT] = destinationUrl; } setPreferences(formData); diff --git a/libs/blocks/marquee/marquee.css b/libs/blocks/marquee/marquee.css index cf14ac03e0..3b6b17569a 100644 --- a/libs/blocks/marquee/marquee.css +++ b/libs/blocks/marquee/marquee.css @@ -448,6 +448,10 @@ padding: var(--spacing-xl) 0; } + html[dir="rtl"] .marquee.split .foreground.container { + flex-direction: row-reverse; + } + .marquee.split .foreground.container .text { max-width: calc(50% - var(--grid-column-width)); } @@ -487,10 +491,6 @@ justify-content: flex-end; } - html[dir="rtl"] .marquee.split .foreground.container { - flex-direction: row-reverse; - } - html[dir="rtl"] .marquee.split.row-reversed .foreground.container { justify-content: flex-start; } diff --git a/libs/blocks/merch-card-collection/merch-card-collection.js b/libs/blocks/merch-card-collection/merch-card-collection.js index 3932d1b0ae..73657d1a97 100644 --- a/libs/blocks/merch-card-collection/merch-card-collection.js +++ b/libs/blocks/merch-card-collection/merch-card-collection.js @@ -27,8 +27,9 @@ const LITERAL_SLOTS = [ // allows improve TBT by returning control to the main thread. // eslint-disable-next-line no-promise-executor-return const makePause = async (timeout = 0) => new Promise((resolve) => setTimeout(resolve, timeout)); - const BLOCK_NAME = 'merch-card-collection'; +const PROD_INDEX = 'query-index-cards.json'; +const PREVIEW_INDEX = 'query-index-cards-preview.json'; const fail = (el, err = '') => { window.lana?.log(`Failed to initialize merch cards: ${err}`); @@ -131,11 +132,14 @@ export function parsePreferences(elements) { /** Retrieve cards from query-index */ async function fetchCardsData(config, type, el) { let cardsData; - const endpointElement = el.querySelector('a[href*="query-index-cards.json"]'); + const usePreviewIndex = config.env.name === 'stage' && !window.location.host.includes('.live'); + const endpointElement = el.querySelector(`a[href*="${usePreviewIndex ? PREVIEW_INDEX : PROD_INDEX}"]`) + ?? el.querySelector(`a[href*="${PROD_INDEX}"]`); if (!endpointElement) { throw new Error('No query-index endpoint provided'); } - endpointElement.remove(); + el.querySelector(`a[href*="${PROD_INDEX}"]`)?.remove(); + el.querySelector(`a[href*="${PREVIEW_INDEX}"]`)?.remove(); let queryIndexCardPath = localizeLink(endpointElement.getAttribute('href'), config); if (/\.json$/.test(queryIndexCardPath)) { queryIndexCardPath = `${queryIndexCardPath}?sheet=${type}`; diff --git a/libs/blocks/merch/merch.js b/libs/blocks/merch/merch.js index 0d04b7e61f..138fbbce71 100644 --- a/libs/blocks/merch/merch.js +++ b/libs/blocks/merch/merch.js @@ -192,28 +192,48 @@ export async function fetchCheckoutLinkConfigs(base = '') { ?? fetch(`${base}${CHECKOUT_LINK_CONFIG_PATH}`).catch((e) => { log?.error('Failed to fetch checkout link configs', e); }).then((mappings) => { - if (!mappings?.ok) return undefined; + if (!mappings?.ok) return { data: [] }; return mappings.json(); }); return fetchCheckoutLinkConfigs.promise; } -export async function getCheckoutLinkConfig(productFamily) { +export async function getCheckoutLinkConfig(productFamily, productCode, paCode) { let { base } = getConfig(); if (/\.page$/.test(document.location.origin)) { /* c8 ignore next 2 */ base = base.replace('.live', '.page'); } const checkoutLinkConfigs = await fetchCheckoutLinkConfigs(base); + if (!checkoutLinkConfigs.data.length) return undefined; const { locale: { region } } = getConfig(); - const productFamilyConfigs = checkoutLinkConfigs.data?.filter( - ({ [NAME_PRODUCT_FAMILY]: mappingProductFamily }) => mappingProductFamily === productFamily, - ); - if (productFamilyConfigs.length === 0) return undefined; - const checkoutLinkConfig = productFamilyConfigs.find( + + const { + paCodeConfigs, + productCodeConfigs, + productFamilyConfigs, + } = checkoutLinkConfigs.data.reduce((acc, config) => { + if (config[NAME_PRODUCT_FAMILY] === paCode) { + acc.paCodeConfigs.push(config); + } else if (config[NAME_PRODUCT_FAMILY] === productCode) { + acc.productCodeConfigs.push(config); + } else if (config[NAME_PRODUCT_FAMILY] === productFamily) { + acc.productFamilyConfigs.push(config); + } + return acc; + }, { paCodeConfigs: [], productCodeConfigs: [], productFamilyConfigs: [] }); + + // helps to fallback to product family config + // if no locale specific config is found below. + const productCheckoutLinkConfigs = [ + ...paCodeConfigs, ...productCodeConfigs, ...productFamilyConfigs, + ]; + + if (!productCheckoutLinkConfigs.length) return undefined; + const checkoutLinkConfig = productCheckoutLinkConfigs.find( ({ [NAME_LOCALE]: locale }) => locale === '', ); - const checkoutLinkConfigOverride = productFamilyConfigs.find( + const checkoutLinkConfigOverride = productCheckoutLinkConfigs.find( ({ [NAME_LOCALE]: locale }) => locale === region, ) ?? {}; const overrides = Object.fromEntries( @@ -231,14 +251,22 @@ export async function getCheckoutLinkConfig(productFamily) { export async function getDownloadAction( options, imsSignedInPromise, - [{ offerType, productArrangement: { productFamily: offerFamily } = {} }], + [{ + offerType, + productArrangementCode, + productArrangement: { productCode, productFamily: offerFamily } = {}, + }], ) { if (options.entitlement !== true) return undefined; const loggedIn = await imsSignedInPromise; if (!loggedIn) return undefined; const entitlements = await fetchEntitlements(); if (!entitlements?.length) return undefined; - const checkoutLinkConfig = await getCheckoutLinkConfig(offerFamily); + const checkoutLinkConfig = await getCheckoutLinkConfig( + offerFamily, + productCode, + productArrangementCode, + ); if (!checkoutLinkConfig?.DOWNLOAD_URL) return undefined; const offer = entitlements.find(( { offer: { product_arrangement: { family: subscriptionFamily } } }, @@ -302,11 +330,26 @@ async function openFragmentModal(path, getModal) { return modal; } +export function appendTabName(url) { + const metaPreselectPlan = document.querySelector('meta[name="preselect-plan"]'); + if (!metaPreselectPlan?.content) return url; + let urlWithPlan; + try { + urlWithPlan = new URL(url); + } catch (err) { + window.lana?.log(`Invalid URL ${url} : ${err}`); + return url; + } + urlWithPlan.searchParams.set('plan', metaPreselectPlan.content); + return urlWithPlan.href; +} + async function openExternalModal(url, getModal) { await loadStyle(`${getConfig().base}/blocks/iframe/iframe.css`); const root = createTag('div', { class: 'milo-iframe' }); + const urlWithTabName = appendTabName(url); createTag('iframe', { - src: url, + src: urlWithTabName, frameborder: '0', marginwidth: '0', marginheight: '0', @@ -340,9 +383,17 @@ export async function openModal(e, url, offerType) { } export async function getModalAction(offers, options) { - const [{ offerType, productArrangement: { productFamily: offerFamily } = {} }] = offers ?? [{}]; + const [{ + offerType, + productArrangementCode, + productArrangement: { productCode, productFamily: offerFamily } = {}, + }] = offers ?? [{}]; if (options.modal !== true) return undefined; - const checkoutLinkConfig = await getCheckoutLinkConfig(offerFamily); + const checkoutLinkConfig = await getCheckoutLinkConfig( + offerFamily, + productCode, + productArrangementCode, + ); if (!checkoutLinkConfig) return undefined; const columnName = (offerType === OFFER_TYPE_TRIAL) ? FREE_TRIAL_PATH : BUY_NOW_PATH; let url = checkoutLinkConfig[columnName]; diff --git a/libs/blocks/modal/modal.js b/libs/blocks/modal/modal.js index 0e49e5093b..60a4e6d2ff 100644 --- a/libs/blocks/modal/modal.js +++ b/libs/blocks/modal/modal.js @@ -188,7 +188,10 @@ export async function getModal(details, custom) { if (!dialog.classList.contains('curtain-off')) { document.body.classList.add('disable-scroll'); - const curtain = createTag('div', { class: 'modal-curtain is-open' }); + const curtain = createTag('div', { + class: 'modal-curtain is-open', + 'daa-ll': `${analyticsEventName}:modalClose:curtainClose`, + }); curtain.addEventListener('click', (e) => { if (e.target === curtain) closeModal(dialog); }); diff --git a/libs/blocks/notification/notification.css b/libs/blocks/notification/notification.css index a67d29f246..ccdd780281 100644 --- a/libs/blocks/notification/notification.css +++ b/libs/blocks/notification/notification.css @@ -2,6 +2,7 @@ --min-block-size: 160px; --min-block-size-ribbon: 50px; --min-block-size-pill: 72px; + --margin-inline-pill-desktop: 80px; --margin-inline-ribbon: 30px; --max-inline-size-image: 75px; --max-inline-size-icon: 231px; @@ -10,9 +11,10 @@ --border-block-size: 10px; --close-size: 20px; --icon-size: 56px; - --icon-size-s: 40px; + --icon-size-m: 40px; + --icon-size-s: 32px; --icon-size-xs: 24px; - --icon-size-l: 64px; + --icon-size-xl: 64px; --pill-radius: 16px; display: flex; @@ -47,7 +49,7 @@ font-weight: unset; } -.notification [class*="heading-"] + p { +.notification .text p:not(.icon-area, .action-area) { margin-block-end: var(--spacing-s); } @@ -187,7 +189,19 @@ max-block-size: var(--icon-size); } -.notification:is(.ribbon.s-icon, .pill) .icon-area img { +.notification .icon-area.lockup-area img { + max-block-size: unset; +} + +.notification .lockup-area { + flex-wrap: nowrap; +} + +.notification:is(.ribbon.m-icon, .pill) .icon-area img { + max-block-size: var(--icon-size-m); +} + +.notification.s-icon:is(.ribbon, .pill) .icon-area img { max-block-size: var(--icon-size-s); } @@ -195,8 +209,8 @@ max-block-size: var(--icon-size-xs); } -.notification.ribbon.l-icon .icon-area img { - max-block-size: var(--icon-size-l); +.notification.ribbon.xl-icon .icon-area img { + max-block-size: var(--icon-size-xl); } .notification .text [class*="heading-"] + .action-area { @@ -213,6 +227,9 @@ margin-block-end: var(--spacing-xs); flex-shrink: 0; display: flex; +} + +.notification .foreground.container .icon-area:not(.lockup-area) { gap: var(--spacing-xs); } @@ -362,10 +379,6 @@ inline-size: auto; } - .notification.ribbon .foreground.container .icon-area { - flex-shrink: 1; - } - .notification.ribbon .copy-wrap { margin-inline-end: var(--spacing-s); } @@ -451,6 +464,7 @@ .notification.max-width-10-desktop .foreground.container { margin-inline: var(--grid-margins-width-10); gap: var(--spacing-l); + max-inline-size: calc(var(--grid-column-width) * 10); } .notification.full-width .foreground.container { @@ -467,6 +481,10 @@ margin-inline-end: var(--spacing-s); } + .notification .foreground.container .lockup-area { + max-inline-size: none; + } + .notification.ribbon .foreground.container .icon-area { flex-shrink: 0; } @@ -495,8 +513,12 @@ margin-inline: auto; } - .notification.pill [class*="heading-"], .notification.pill p { + inline-size: auto; + } + + .notification.pill .text [class*="heading-"], + .notification.pill .text p { flex-shrink: 0; margin-block-end: 0; } @@ -506,10 +528,6 @@ margin-block-end: 0; } - .notification.pill p { - inline-size: auto; - } - .notification.pill .close { inset-inline: auto var(--spacing-s); inset-block: 0; @@ -521,6 +539,10 @@ margin: 0; } + .notification.pill:not(.flexible) .foreground.container { + inline-size: calc(100% - var(--margin-inline-pill-desktop) * 2); + } + .notification.pill.flexible .foreground.container { padding-inline: 0; } @@ -531,7 +553,7 @@ } .notification.pill .icon-area img { - max-block-size: var(--icon-size-s); + max-block-size: var(--icon-size-m); } .notification.pill .foreground.container .action-area { @@ -555,6 +577,10 @@ text-align: start; } + .notification.pill .copy-wrap > * { + max-inline-size: 100%; + } + .notification.ribbon.space-between .foreground.container .icon-area { margin-inline-end: var(--spacing-s); } diff --git a/libs/blocks/notification/notification.js b/libs/blocks/notification/notification.js index 4a65bcb266..f407c12bcc 100644 --- a/libs/blocks/notification/notification.js +++ b/libs/blocks/notification/notification.js @@ -15,8 +15,10 @@ */ import { decorateBlockText, decorateBlockBg, decorateTextOverrides } from '../../utils/decorate.js'; -import { createTag } from '../../utils/utils.js'; +import { createTag, getConfig, loadStyle } from '../../utils/utils.js'; +const { miloLibs, codeRoot } = getConfig(); +const base = miloLibs || codeRoot; const variants = ['banner', 'ribbon', 'pill']; const sizes = ['small', 'medium', 'large']; const [banner, ribbon, pill] = variants; @@ -26,7 +28,7 @@ const defaultVariant = banner; const blockConfig = { [banner]: { [small]: ['s', 's', 's', 'm'], - [medium]: ['m', 'm', 'm', 'm'], + [medium]: ['m', 'm', 'm', 'l'], [large]: ['l', 'l', 'l', 'l'], }, [ribbon]: { @@ -65,17 +67,18 @@ function getBlockData(el) { const variant = variants.find((varClass) => el.classList.contains(varClass)) || defaultVariant; const size = sizes.find((sizeClass) => el.classList.contains(sizeClass)) || defaultSize; const fontSizes = [...blockConfig[variant][size]]; - if (el.classList.contains('s-button')) fontSizes.splice(3, 1, 'm'); + const buttonSize = el.className.match(/([xsml])+-button/); + if (buttonSize) fontSizes.splice(3, 1, buttonSize[1]); return { fontSizes, options: { ...getOpts(el) } }; } function wrapCopy(foreground) { const text = foreground.querySelector('.text'); if (!text) return; - const heading = text?.querySelector('h1, h2, h3, h4, h5, h6'); + const heading = text?.querySelector('h1, h2, h3, h4, h5, h6, p:not(.icon-area, .action-area)'); const icon = heading?.previousElementSibling; const body = heading?.nextElementSibling?.classList.contains('action-area') ? '' : heading?.nextElementSibling; - const copy = createTag('div', { class: 'copy-wrap' }, [heading, body]); + const copy = createTag('div', { class: 'copy-wrap' }, [heading, body].filter(Boolean)); text?.insertBefore(copy, icon?.nextSibling || text.children[0]); } @@ -90,12 +93,33 @@ function decorateFlexible(el) { el.querySelector('.background'), el.querySelector('.foreground'), el.querySelector('.close'), - ]; + ].filter(Boolean); const inner = createTag('div', { class: 'flexible-inner' }, innards); + if (el.style.background) { + inner.style.background = el.style.background; + el.style.removeProperty('background'); + } el.appendChild(inner); } -function decorateLayout(el) { +async function loadIconography() { + await new Promise((resolve) => { loadStyle(`${base}/styles/iconography.css`, resolve); }); +} + +async function decorateLockup(lockupArea, el) { + await loadIconography(); + const icon = lockupArea.querySelector('picture'); + const content = icon.nextElementSibling || icon.nextSibling; + const label = createTag('span', { class: 'lockup-label' }, content.nodeValue || content); + if (content.nodeType === 3) lockupArea.replaceChild(label, content); + else lockupArea.appendChild(label); + lockupArea.classList.add('lockup-area'); + const pre = el.className.match(/([xsml]+)-(lockup|icon)/); + if (!pre) el.classList.add(`${el.matches('.pill') ? 'm' : 'l'}-lockup`); + if (pre && pre[2] === 'icon') el.classList.replace(pre[0], `${pre[1]}-lockup`); +} + +async function decorateLayout(el) { const [background, ...rest] = el.querySelectorAll(':scope > div'); const foreground = rest.pop(); if (background) decorateBlockBg(el, background); @@ -104,6 +128,7 @@ function decorateLayout(el) { text?.classList.add('text'); const iconArea = text?.querySelector('p picture')?.closest('p'); iconArea?.classList.add('icon-area'); + if (iconArea?.textContent.trim()) await decorateLockup(iconArea, el); const fgMedia = foreground?.querySelector(':scope > div:not(.text) :is(img, video, a[href*=".mp4"])')?.closest('div'); const bgMedia = el.querySelector(':scope > div:not(.foreground) :is(img, video, a[href*=".mp4"])')?.closest('div'); const media = fgMedia ?? bgMedia; @@ -114,10 +139,10 @@ function decorateLayout(el) { return foreground; } -export default function init(el) { +const init = async (el) => { el.classList.add('con-block'); const { fontSizes, options } = getBlockData(el); - const blockText = decorateLayout(el); + const blockText = await decorateLayout(el); decorateBlockText(blockText, fontSizes); if (options.borderBottom) { el.append(createTag('div', { style: `background: ${options.borderBottom};`, class: 'border' })); @@ -125,4 +150,6 @@ export default function init(el) { decorateTextOverrides(el); el.querySelectorAll('a:not([class])').forEach((staticLink) => staticLink.classList.add('static')); if (el.matches(`:is(.${ribbon}, .${pill})`)) wrapCopy(blockText); -} +}; + +export default init; diff --git a/libs/blocks/tabs/tabs.js b/libs/blocks/tabs/tabs.js index df9881783d..49145e66ad 100644 --- a/libs/blocks/tabs/tabs.js +++ b/libs/blocks/tabs/tabs.js @@ -68,6 +68,11 @@ function configTabs(config, rootElem) { const sel = rootElem.querySelector(id); if (sel) sel.click(); } + const tabParam = new URLSearchParams(window.location.search).get('tab'); + if (!tabParam) return; + const dashIndex = tabParam.lastIndexOf('-'); + const [tabsId, tabIndex] = [tabParam.substring(0, dashIndex), tabParam.substring(dashIndex + 1)]; + if (tabsId === config.id) rootElem.querySelector(`#tab-${config.id}-${tabIndex}`)?.click(); } function initTabs(elm, config, rootElem) { diff --git a/libs/deps/imslib.min.js b/libs/deps/imslib.min.js index 40cefad2c9..6a22727819 100644 --- a/libs/deps/imslib.min.js +++ b/libs/deps/imslib.min.js @@ -1,4 +1,4 @@ -// Built 2024-07-23T01:16:46.077Z - Last Modified 2024-07-22T13:19:42.000Z +// Built 2024-07-31T01:04:03.854Z - Last Modified 2024-07-30T10:51:53.000Z var roll=function(){ /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. @@ -14,4 +14,4 @@ var roll=function(){ See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ -var e=function(t,r){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(t,r)};function t(t,r){function o(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(o.prototype=r.prototype,new o)}var r=function(){return(r=Object.assign||function(e){for(var t,r=1,o=arguments.length;r0&&n[n.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!n||i[1]>n[0]&&i[1]0)&&!(o=i.next()).done;)s.push(o.value)}catch(e){n={error:e}}finally{try{o&&!o.done&&(r=i.return)&&r.call(i)}finally{if(n)throw n.error}}return s}function a(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}(Object.keys(a)),u=c.next();!u.done;u=c.next()){var l=u.value;if(r===l||r.endsWith("."+l))return new e(!0,a[l],n)}}catch(e){i={error:e}}finally{try{u&&!u.done&&(s=c.return)&&s.call(c)}finally{if(i)throw i.error}}}return new e(!1,n)},e.prototype.shouldFallbackToAdobe=function(e){return!!this.proxied&&("feature_disabled"===e.error&&"cdsc"===e.error_description)},e.THIRD_PARTY_DOMAINS_PROD={"behance.net":"https://sso.behance.net"},e.THIRD_PARTY_DOMAINS_STAGE={"s2stagehance.com":"https://sso.s2stagehance.com"},e}(),m=new(function(){function e(){this.baseUrlAdobe="",this.baseUrlServices="",this.checkTokenEndpoint=new g,this.jslibver="v2-v0.42.0-10-g2e3497b"}return e.prototype.loadEnvironment=function(e,t,r){void 0===t&&(t=!1),void 0===r&&(r="");var o=e===l.STAGE;o?(this.baseUrlAdobe="https://ims-na1-stg1.adobelogin.com",this.baseUrlServices="https://adobeid-na1-stg1.services.adobe.com"):(this.baseUrlAdobe="https://ims-na1.adobelogin.com",this.baseUrlServices="https://adobeid-na1.services.adobe.com"),this.checkTokenEndpoint=g.computeEndpoint(t,r,o,this.baseUrlServices)},e}());function y(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)}function k(e,t){if(null==e)return t;if(e===t)return e;if(!y(e))return e;var r=Object.assign({},e);return y(t)&&Object.keys(t).forEach((function(o){var n,i;y(t[o])?o in e?r[o]=k(e[o],t[o]):Object.assign(r,((n={})[o]=t[o],n)):Object.assign(r,((i={})[o]=t[o],i))})),r}var w=new(function(){function e(){this.getCustomApiParameters=function(e,t){return e[t]||{}}}return e.prototype.mergeExternalParameters=function(e,t,r){return k(this.getCustomApiParameters(t,r),e)},e.prototype.toJson=function(e){try{return"string"!=typeof e?e:JSON.parse(e)}catch(e){return null}},e}()),b=function(){function e(){}return e.getInitialRedirectUri=function(e,t){var r=e.redirect_uri||t||window.location.href,o="function"==typeof r?r():r,n=o.indexOf("from_ims");return-1===n?o:("#"===o[n-1]&&n--,o.substr(0,n))},e.createDefaultRedirectUrl=function(e,t,r,o){var n=this.getInitialRedirectUri(r,e),i=this.createOldHash(n);return i.indexOf("?")>0?i+"&client_id="+t+"&api="+o:i+"?client_id="+t+"&api="+o},e.createRedirectUrl=function(e,t,r,o,n){void 0===n&&(n="");var i=this.createDefaultRedirectUrl(e,t,r,o);(n=n||r.scope||"")&&(i=i+"&scope="+n);var s=r.reauth||"";return s&&(i=i+"&reauth="+s),i},e.createOldHash=function(e){var t=e.indexOf("#");return t<0?e+"#old_hash=&from_ims=true":e.substring(0,t)+"#old_hash="+e.substring(t+1)+"&from_ims=true"},e.mergeApiParamsWithExternalParams=function(e,t,r){return k(w.getCustomApiParameters(e,r),t)},e}(),S=function(){var e=this;this.composeRedirectUrl=function(e){var t=e.apiParameters,o=e.externalParameters,n=void 0===o?{}:o,i=e.adobeIdRedirectUri,s=void 0===i?"":i,a=e.clientId,c=e.locale,u=e.state,l=void 0===u?{}:u,d=e.scope,p=void 0===d?n.scope||t.scope||"":d,h=b.mergeApiParamsWithExternalParams(t,n,"authorize");l&&(h.state=k(h.state||{},l));var f=b.createRedirectUrl(s,a,h,"authorize",p),v=n.locale||c||"",g=e.response_type,y=void 0===g?h.response_type||"":g;return r(r({},h),{client_id:a,scope:p,locale:v,response_type:y,jslVersion:m.jslibver,redirect_uri:f})},this.createRedirectUrl=function(t){var r=e.composeRedirectUrl(t),o=v.uriEncodeData(r);return m.baseUrlAdobe+"/ims/authorize/v1?"+o}},T=function(e){function r(){var t=null!==e&&e.apply(this,arguments)||this;return t.signIn=function(e){var r=t.createRedirectUrl(e);v.setHrefUrl(r)},t.authorizeToken=function(e,r){var o=t.composeRedirectUrl(r);e&&(o.user_assertion=e,o.user_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer"),t.createAuthorizeForm(o).submit()},t}return t(r,e),r.prototype.createAuthorizeForm=function(e){var t=m.baseUrlAdobe+"/ims/authorize/v1",r=document.createElement("form");r.style.display="none",r.setAttribute("method","post"),r.setAttribute("action",t);var o=null,n=null,i="";for(var s in e){if("object"==typeof(n=e[s])){if(0===Object.keys(n).length)continue;i=JSON.stringify(n)}else i=n;""!==i&&(o=this.createFormElement("input","text",s,i),r.appendChild(o))}return document.getElementsByTagName("body")[0].appendChild(r),r},r.prototype.createFormElement=function(e,t,r,o){var n=document.createElement(e);return n.setAttribute("type",t),n.setAttribute("name",r),n.setAttribute("value",o),n},r}(S),I=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/,_=["https://auth.services.adobe.com","https://auth-stg1.services.adobe.com","https://localhost.corp.adobe.com:9000"],P=new function(){var e=this;this.windowObjectReference=null,this.previousUrl="",this.openSignInWindow=function(t,r,o,n){e.onProcessLocation=n,e.allowOrigin=o.allowOrigin,e.timerId&&clearInterval(e.timerId),window.removeEventListener("message",e.receiveMessage),window.addEventListener("message",e.receiveMessage),e.broadcastChannel&&e.broadcastChannel.close(),e.broadcastChannel=new BroadcastChannel("imslib"),e.broadcastChannel.onmessage=e.receiveMessage;var i="popup=yes, width="+o.width+", height="+o.height+", top="+o.top+", left="+o.left;!e.windowObjectReference||e.windowObjectReference&&e.windowObjectReference.closed?e.windowObjectReference=window.open(t,o.title,i):e.previousUrl!==t?(e.windowObjectReference=window.open(t,o.title,i),e.windowObjectReference&&e.windowObjectReference.focus()):e.windowObjectReference.focus(),e.previousUrl=t},this.receiveMessage=function(t){if(a(_,[e.allowOrigin]).includes(t.origin)){try{if(!I.test(t.data))return void console.warn("refused to receive message containing unknown data format",t.data)}catch(e){return void console.error(e)}e.broadcastChannel&&e.broadcastChannel.close(),e.onProcessLocation&&e.onProcessLocation(t.data)}else console.warn("refused to receive message from origin not whitelisted",t.origin)}},R=function(e){function o(t,o){var n=e.call(this)||this;return n.signIn=function(e){e.state=r(r({},e.state),{imslibmodal:!0});var t=e.state.nonce,o=n.createRedirectUrl(e);P.openSignInWindow(o,t,n.popupSettings,n.onPopupMessage)},n.onPopupMessage=t,n.popupSettings=o,n}return t(o,e),o}(S),E=function(){function e(e,t){this.status=0,this.data="",this.status=e,this.data=this.toJson(t)}return e.prototype.toJson=function(e){try{return"string"!=typeof e?e:JSON.parse(e)}catch(t){return e}},e}(),A=new(function(){function e(){}return e.prototype.http=function(e){return new Promise((function(t,r){var o=new(0,window.XMLHttpRequest);"boolean"==typeof e.withCredentials?o.withCredentials=e.withCredentials:o.withCredentials=!0,"number"==typeof e.timeout&&(o.timeout=e.timeout),o.open(e.method,e.url,!0);var n;o.onload=function(){return this.status>=200&&this.status<300?t(new E(this.status,this.response)):r(new E(this.status,this.response))},o.onerror=function(){var e=new E(this.status,this.response);return r(e)},o.ontimeout=function(){var e=new E(0,"timeout");return r(e)},o.onabort=function(){var e=new E(0,"aborted");return r(e)},(n=e.headers)&&Object.keys(n).forEach((function(e){o.setRequestHeader(e,n[e])})),o.send(e.data)}))},e.prototype.post=function(e,t,r,o,n){return void 0===r&&(r={}),this.http({headers:r,method:"POST",url:e,data:t,withCredentials:o,timeout:n})},e.prototype.get=function(e,t,r,o){return void 0===t&&(t={}),this.http({headers:t,method:"GET",url:e,withCredentials:r,timeout:o})},e}()),O=function(){this.probe=function(e,t,r){if(void 0===r&&(r=2e3),!e||0===e.length)return Promise.resolve([]);for(var o={"Content-Type":"application/json","Cache-Control":"no-cache, no-store, must-revalidate",Pragma:"no-cache",Expires:0,"X-IMS-CLIENTID":t},n="/ims/cdsc_probe?"+v.uriEncodeData({client_id:t}),i=[],s=[],a=function(t){var a=e[t]+n;s.push(A.post(a,{},o,!1,r).then((function(e){return 200==e.status&&i.push(t)})).catch((function(){})))},c=0;c=0?new G("ride_pba_idle_session","",!0):null;var n=this.addRedirectUriToJump(r,o);return new G(r,n)},e.prototype.addRedirectUriToJump=function(e,t){if(!t||"string"!=typeof t)return"";var r=t;this.adobeIdThinData||(this.adobeIdThinData=new H);var o=this.adobeIdThinData.computeRideRedirectUri(e);if(!o||0===o.length)return r;try{var n=new URL(r);return n.searchParams.append("redirect_uri",o),n.toString()}catch(e){return r}},e.prototype.isUnauthorizedException=function(e){var t=e.status;return 401===(void 0===t?0:t)},e}()),K=new(function(){function e(){this.triggerOnError=null}return e.prototype.post=function(e,t,r){var o=this;void 0===r&&(r={});var n=z.getCachedApiResponse(e,t);if(n){var i=n.status,s=n.data;return 200===i?Promise.resolve(s):Promise.reject(s)}return A.post(e,t,r).then((function(r){return o.storeApiResponse(e,JSON.stringify(t),r)})).catch((function(r){return o.verifyError(e,JSON.stringify(t),r)}))},e.prototype.get=function(e,t){var r=this;void 0===t&&(t={});var o=z.getCachedApiResponse(e);if(o){var n=o.status,i=o.data;return 200===n?Promise.resolve(i):Promise.reject(i)}return A.get(e,t).then((function(t){return r.storeApiResponse(e,"",t)})).catch((function(t){return r.verifyError(e,"",t)}))},e.prototype.verifyError=function(e,t,r){this.storeApiResponse(e,t,r);var o=J.verify(r,e);return Promise.reject(o||r.data)},e.prototype.storeApiResponse=function(e,t,r){return void 0===t&&(t=""),z.storeApiResponse(e,t,r),Promise.resolve(r.data)},e}()),B=function(){function e(e){void 0===e&&(e={}),this.CONTENT_FORM_ENCODED="application/x-www-form-urlencoded;charset=utf-8",this.apiParameters=e}return e.prototype.validateToken=function(e){var t=e.token,o=e.client_id,n=e.type,i=v.uriEncodeData(r(r({},w.getCustomApiParameters(this.apiParameters,"validate_token")),{type:n||"access_token",client_id:o,token:t})),s=m.baseUrlAdobe+"/ims/validate_token/v1?jslVersion="+m.jslibver,a=this.formEncoded();return this.addClientIdInHeader(o,a),K.post(s,i,a)},e.prototype.getProfile=function(e){var t=e.token,o=e.client_id,n=r({},w.getCustomApiParameters(this.apiParameters,"profile")),i=this.createAuthorizationHeader(t);this.addClientIdInHeader(o,i);var s=v.uriEncodeData(r({client_id:o},n)),a=m.baseUrlAdobe+"/ims/profile/v1?"+s+"&jslVersion="+m.jslibver;return K.get(a,i)},e.prototype.getUserInfo=function(e){var t=e.token,o=e.client_id,n=r({},w.getCustomApiParameters(this.apiParameters,"userinfo")),i=this.createAuthorizationHeader(t);this.addClientIdInHeader(o,i);var s=v.uriEncodeData(r({client_id:o},n)),a=m.baseUrlAdobe+"/ims/userinfo/v1?"+s+"&jslVersion="+m.jslibver;return K.get(a,i)},e.prototype.logoutToken=function(e){var t=e.client_id,o=e.token,n=r({},w.getCustomApiParameters(this.apiParameters,"logout_token")),i=m.baseUrlServices+"/ims/logout/v1?jslVersion="+m.jslibver,s=this.addClientIdInHeader(t);return K.post(i,r({client_id:t,access_token:o},n),s)},e.prototype.checkStatus=function(){var e=m.baseUrlServices+"/ims/check/v1/status";return K.get(e)},e.prototype.checkToken=function(e,t,o){var n=e.client_id,i=e.scope,s=r({},w.mergeExternalParameters(t,this.apiParameters,"check_token")),a=r(r({},s),{client_id:n,scope:i});return o&&(a.user_id=o),this.callCheckToken(v.uriEncodeData(a),n,"/check/v6/token?jslVersion="+m.jslibver)},e.prototype.switchProfile=function(e,t,o){void 0===o&&(o="");var n=e.client_id,i=e.scope,s=void 0===i?"":i,a=r({},w.mergeExternalParameters(t,this.apiParameters,"check_token")),c=v.uriEncodeData(r(r({},a),{client_id:n,scope:s,user_id:o}));return this.callCheckToken(c,n,"/check/v6/token?jslVersion="+m.jslibver)},e.prototype.listSocialProviders=function(e){var t=e.client_id,o=r({},w.getCustomApiParameters(this.apiParameters,"providers")),n=v.uriEncodeData(r({client_id:t},o)),i=m.baseUrlServices+"/ims/social/v2/providers?"+n+"&jslVersion="+m.jslibver,s=this.addClientIdInHeader(t);return K.get(i,s)},e.prototype.exchangeIjt=function(e,t){var o=e.client_id,n=r({},w.getCustomApiParameters(this.apiParameters,"ijt")),i=m.baseUrlServices+"/ims/jump/implicit/"+t,s=v.uriEncodeData(r({client_id:o},n)),a=i+"?"+s+"&jslVersion="+m.jslibver;a.length>2048&&(delete n.redirect_uri,a=i+"?"+(s=v.uriEncodeData(n)));var c=this.addClientIdInHeader(o);return K.get(a,c)},e.prototype.avatarUrl=function(e){return m.baseUrlAdobe+"/ims/avatar/download/"+e},e.prototype.getReleaseFlags=function(e){var t=e.token,o=e.client_id,n=r({},w.getCustomApiParameters(this.apiParameters,"fg_value")),i=this.createAuthorizationHeader(t);this.addClientIdInHeader(o,i);var s=v.uriEncodeData(r({client_id:o},n)),a=m.baseUrlAdobe+"/ims/fg/value/v1?"+s+"&jslVersion="+m.jslibver;return K.get(a,i)},e.prototype.getTransitoryAuthorizationCode=function(e,t,o){void 0===t&&(t={});var n=r({},w.mergeExternalParameters(t,this.apiParameters,"check_token")),i=v.uriEncodeData(r(r({},n),e));return this.callCheckToken(i,o,"/check/v6/token?client_id="+o+"&jslVersion="+m.jslibver)},e.prototype.getTokenFromCode=function(e,t){void 0===t&&(t={});var o=r({},w.mergeExternalParameters(t,this.apiParameters,"token"));o.grant_type="authorization_code",delete e.other;var n=m.baseUrlServices+"/ims/token/v3?jslVersion="+m.jslibver,i=v.uriEncodeData(r(r({},o),e)),s=this.formEncoded();return this.addClientIdInHeader(e.client_id,s),K.post(n,i,s)},e.prototype.jumpToken=function(e,t,o){void 0===t&&(t={});var n=r({},w.mergeExternalParameters(t,this.apiParameters,"jumptoken")),i=m.baseUrlServices+"/ims/jumptoken/v1?client_id="+o+"&jslVersion="+m.jslibver,s=v.uriEncodeData(r(r({},n),e)),a=this.formEncoded();return this.addClientIdInHeader(o,a),K.post(i,s,a)},e.prototype.socialHeadlessSignIn=function(e,t){void 0===t&&(t={});var o=r({},w.mergeExternalParameters(t,this.apiParameters,"jumptoken")),n=m.baseUrlServices+"/ims/social/v2/native?jslVersion="+m.jslibver,i=v.uriEncodeData(r(r(r({},o),e),{response_type:"implicit_jump"}));return K.post(n,i,this.formEncoded())},e.prototype.createAuthorizationHeader=function(e){var t={};return e&&(t[d]="Bearer "+e),t},e.prototype.formEncoded=function(e){return void 0===e&&(e={}),e["content-type"]=this.CONTENT_FORM_ENCODED,e},e.prototype.addClientIdInHeader=function(e,t){return void 0===t&&(t={}),t.client_id=e,t},e.prototype.callCheckToken=function(e,t,r){var o=this.formEncoded();return this.addClientIdInHeader(t,o),K.post(m.checkTokenEndpoint.url+"/ims"+r,e,o).catch((function(t){if(!m.checkTokenEndpoint.shouldFallbackToAdobe(t))throw t;return K.post(m.checkTokenEndpoint.fallbackUrl+"/ims"+r,e,o)}))},e}();!function(e){e.INITIALIZE_ERROR="initialize_error",e.HTTP="http",e.FRAGMENT="fragment",e.CSRF="csrf",e.NOT_ALLOWED="not_allowed",e.PROFILE_EXCEPTION="profile_exception",e.TOKEN_EXPIRED="token_expired",e.SOCIAL_PROVIDERS="SOCIAL_PROVIDERS",e.RIDE_EXCEPTION="ride_exception"}(N||(N={}));var W=function(e){this.message=null,this.errorType=N.PROFILE_EXCEPTION,this.message=e},Y=/\s|,/g;function X(e){return e.split(Y).sort().join(",")}var Z,Q=function(){function e(e){this.profileServiceRequest=e,this.storage=h.getStorageByName(c.SessionStorage)}return e.prototype.getProfile=function(e){var t=this,r=this.profileServiceRequest,o=r.clientId,n=r.imsApis,i=this.getProfileFromStorage();return i?Promise.resolve(i):n.getProfile({client_id:o,token:e}).then((function(e){if(!e)throw new W("NO profile response");if(0===Object.keys(e).length)throw new W("NO profile value");return t.saveProfileToStorage(e),Promise.resolve(e)})).catch((function(e){return e instanceof q?Promise.reject(e):(t.removeProfile(),Promise.reject(e))}))},e.prototype.getProfileStorageKey=function(){var e=this.profileServiceRequest;return"adobeid_ims_profile/"+e.clientId+"/"+!1+"/"+X(e.scope)},e.prototype.getProfileFromStorage=function(){var e=this.getProfileStorageKey(),t=this.storage.getItem(e);return t&&JSON.parse(t)},e.prototype.saveProfileToStorage=function(e){var t=this.getProfileStorageKey();this.storage.setItem(t,JSON.stringify(e))},e.prototype.removeProfile=function(){var e=this.getProfileStorageKey();this.storage.removeItem(e)},e.prototype.removeProfileIfOtherUser=function(e){if(e){var t=this.getProfileFromStorage();t&&t.userId!==e&&this.removeProfile()}},e}();!function(e){e.GUEST="guest"}(Z||(Z={}));var $,ee=function(){function e(e,t){var r=this;this.REAUTH_SCOPE="reauthenticated",this.valid=!1,this.isReauth=function(){return r.scope.indexOf(r.REAUTH_SCOPE)>=0},this.client_id="",this.scope="",this.expire=new Date,this.user_id="",this.tokenValue="",this.sid="",this.state=null,this.fromFragment=!1,this.impersonatorId="",this.isImpersonatedSession=!1;var o=e.valid,n=e.tokenValue,i=e.access_token,s=e.state,a=e.other,c=n||i,u=this.parseJwt(c);if(!u)throw new Error("token cannot be decoded "+c);this.state=w.toJson(s);var l=u.client_id,d=u.user_id,p=u.scope,h=u.sid,f=u.imp_id,v=u.imp_sid,g=u.pba,m=u.atp,y=u.gse;this.atp=m,this.client_id=l,this.expire=t,this.user_id=d,this.scope=p,this.valid=o,this.tokenValue=c,this.sid=h,this.other=a,this.impersonatorId=f||"",this.isImpersonatedSession=!!v,this.pbaSatisfiedPolicies=g&&g.split(",")||[],this.isGuestToken=this.atp===Z.GUEST,this.gse=y}return e.prototype.parseJwt=function(e){if(!e)return null;try{return JSON.parse(atob(e.split(".")[1].replace(/-/g,"+").replace(/_/g,"/")))}catch(t){return p.error("error on decoding token ",e,t),null}},e.prototype.validate=function(e,t){var r,o,n,i=this.valid,s=this.client_id,a=this.scope,c=this.expire;return c0&&(r=new Array(o+1).join(e)+r),r}("0",5,e.toString(2))},le=function(e,t){if(void 0===t&&(t=!1),"string"!=typeof e)throw new Error("Data is not a string");var r=e.toLowerCase().split("");!function(e){if(e.length%8!=0)throw new Error("Data length is not a multiple of 8");e.forEach((function(e){if(!(e in ce))throw new Error("Unknown encoded character "+e)}));var t=!1;e.forEach((function(e){if("="!==e&&t)throw new Error("Found padding char in the middle of the string");"="===e&&(t=!0)}))}(r);var o=function(e){for(var t=e.length-1,r=0;"="===e[t];)++r,--t;return r}(r),n=[];r.forEach((function(e){n.push(ue(ce[e]))}));var i=n.join("");return o>0&&(i=i.slice(0,-5*o)),i.length%8!=0&&(i=i.slice(0,i.length%8*-1)),t?function(e){var t="";if(e.length%8!=0)throw new Error("Length must be a multiple of 8");for(var r=0,o=e.length;rfe.lastUserInteraction&&(fe.lastUserInteraction=n)}return o.tokenService.refreshToken(e).then((function(e){return o.onTokenProfileReceived(e)})).catch((function(e){if(p.error("refresh token error",e),e instanceof q)return Promise.reject(e);var t=o.verifyRideErrorExceptionStrict(e);return t||(o.profileService.removeProfile(),o.onTokenExpired(),Promise.reject(e))}))},this.switchProfile=function(e,t){return void 0===t&&(t={}),e?o.tokenService.switchProfile(e,t).then((function(e){return o.onTokenProfileReceived(e)})).catch((function(e){return o.verifyRideErrorException(e)})):Promise.reject(new Error("Please provide the user id for switchProfile"))},this.executeErrorCallback=function(e){if(p.info("initialize exception ended",e),!e||e.type!==$.LOGOUT){var t=o.adobeIdData.onError;t&&t(N.HTTP,"Initialization error")}},this.triggerOnImsInstance=function(e){var t=document.createEvent("CustomEvent"),r={clientId:o.adobeIdData.client_id,instance:e};t.initCustomEvent("onImsLibInstance",!1,!1,r),window.dispatchEvent(t)},this.processInitializeException=function(e){return void 0===e&&(e={}),p.warn("initialize",e),o.restoreHash(),Promise.reject(e)},this.verifyModalSignInEvent=function(e){return e instanceof ae?o.notifyParentAboutModalSignIn(e):Promise.reject(e)},this.verifyTokenExpiredException=function(e){return e instanceof ie?(o.adobeIdData.handlers.triggerOnAccessTokenHasExpired(),Promise.resolve()):Promise.reject(e)},this.verifyRideErrorException=function(e){return n(o,void 0,Promise,(function(){return i(this,(function(t){switch(t.label){case 0:return e instanceof G?this.adobeIdData.overrideErrorHandler&&!this.adobeIdData.overrideErrorHandler(e)?[2,Promise.reject(e)]:e.isPbaExpiredIdleSessionWorkaround?[4,this.signIn()]:[3,2]:[3,4];case 1:return t.sent(),[3,4];case 2:return e.jump?[4,v.replaceUrlAndWait(e.jump,1e4)]:[3,4];case 3:t.sent(),t.label=4;case 4:return[2,Promise.reject(e)]}}))}))},this.verifyRideErrorExceptionStrict=function(e){return e instanceof G?o.verifyRideErrorException(e):null},this.verifyCsrfException=function(e){var t=e.type;return t&&t===N.CSRF&&o.signOut(),Promise.reject(e)},this.processTokenResponse=function(e){var t=o.adobeIdData.handlers,r=e.tokenFields,n=e.profile,i=r.tokenValue,s=r.state,a=r.expire,c=r.sid,u=r.user_id,l=r.other,d=void 0===l?{}:l,h=r.impersonatorId,f=r.isImpersonatedSession,g=r.pbaSatisfiedPolicies,m=r.isGuestToken,y=r.gse;p.info("token",i),d.from_ims&&v.setHash(d.old_hash||""),o.profileService.removeProfileIfOtherUser(u);var k={token:i,expire:a,sid:c,impersonatorId:h,isImpersonatedSession:f,pbaSatisfiedPolicies:g,isGuestToken:m,gse:y};return r.isReauth()?t.triggerOnReauthAccessToken(k):o.tokenReceived(k),n&&o.profileService.saveProfileToStorage(n),Promise.resolve(s)},this.exchangeIjt=function(e){var t=o.adobeIdData.ijt;return e||t?o.tokenService.exchangeIjt(e||t).then((function(e){return e.profile?o.profileService.saveProfileToStorage(e.profile):o.profileService.removeProfile(),Promise.resolve(e)})):Promise.reject(new Error("please set the adobeid.ijt value"))},this.adobeIdData=new L(e),t&&(this.instanceKey=t);var s=this.adobeIdData,a=s.api_parameters,c=void 0===a?{}:a,u=s.client_id,l=s.scope,d=s.useLocalStorage,h=s.autoValidateToken,g=s.modalMode,m=s.modalSettings;this.imsApis=new B(c),this.csrfService=new f(u,this.instanceKey),this.serviceRequest={clientId:u,scope:l,imsApis:this.imsApis},this.tokenService=new pe(r(r({},this.serviceRequest),{useLocalStorage:d,autoValidateToken:h}),this.csrfService),this.profileService=new Q(this.serviceRequest),this.signInservice=g?new R(this.onPopupMessage,m):new T}return Object.defineProperty(e.prototype,"version",{get:function(){return m.jslibver},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"adobeid",{get:function(){return r({},this.adobeIdData)},enumerable:!0,configurable:!0}),e.prototype.enableLogging=function(){p.enableLogging()},e.prototype.disableLogging=function(){p.disableLogging()},e.prototype.checkInitialized=function(){this.initialized},e.prototype.signUp=function(e,t){var r=this;void 0===e&&(e={}),this.checkInitialized();var o=this.adobeIdData,n=this.csrfService;if(!o)throw new Error("no adobeId on reAuthenticate");var i=n.initialize();return o.createSignUpRedirectRequest(e,t,i).then((function(e){r.signInservice.signIn(e)}))},e.prototype.isSignedInUser=function(){var e=this.getAccessToken();return(!e||!e.isGuestToken)&&!(!e&&!this.getReauthAccessToken())},e.prototype.getProfile=function(){var e=this,t=this.profileService.getProfileFromStorage();if(t)return Promise.resolve(t);var r=this.getAccessToken()||this.getReauthAccessToken();if(!r){var o="please login before getting the profile";return Promise.reject(new W(o))}if(r.isGuestToken){o="guest account does not have a profile";return Promise.reject(new W(o))}return this.profileService.getProfile(r.token).then((function(e){return Promise.resolve(e)})).catch((function(t){return p.error("get profile exception ",t),t instanceof q?e.refreshToken().then((function(e){return Promise.resolve(e.profile)})):Promise.reject(new W(t.message||t))}))},e.prototype.avatarUrl=function(e){return this.imsApis.avatarUrl(e)},e.prototype.getReleaseFlags=function(e){return void 0===e&&(e=!1),e?this.tokenService.getDecodedReleaseFlags():this.tokenService.getReleaseFlags()},e.prototype.getAccessToken=function(){return this.getTokenFromStorage(!1)},e.prototype.getReauthAccessToken=function(){return this.getTokenFromStorage(!0)},e.prototype.getTokenFromStorage=function(e){var t=this.tokenService.getTokenFieldsFromStorage(e);return t?{token:t.tokenValue,expire:t.expire,sid:t.sid,impersonatorId:t.impersonatorId,isImpersonatedSession:t.isImpersonatedSession,pbaSatisfiedPolicies:t.pbaSatisfiedPolicies,isGuestToken:t.isGuestToken,gse:t.gse}:null},e.prototype.listSocialProviders=function(){var e=this;return new Promise((function(t,r){var o=e.adobeIdData.client_id;e.imsApis.listSocialProviders({client_id:o}).then((function(e){t(e)})).catch((function(e){r(e)}))}))},e.prototype.tokenReceived=function(e){this.adobeIdData.handlers.triggerOnAccessToken(e),fe.startAutoRefreshFlow({expire:e.expire,refreshTokenMethod:this.refreshToken})},e.prototype.onTokenProfileReceived=function(e){var t=e.tokenInfo,r=e.profile;return p.info("token",t),this.tokenReceived(t),this.profileService.saveProfileToStorage(r),Promise.resolve(e)},e.prototype.validateToken=function(){var e=this;return this.tokenService.validateToken().then((function(){return Promise.resolve(!0)})).catch((function(t){return p.warn("validate token exception",t),t instanceof q?Promise.reject(!1):(e.profileService.removeProfile(),Promise.reject(!1))}))},e.prototype.onTokenExpired=function(){var e=this.adobeIdData.handlers;this.tokenService.purge(),e.triggerOnAccessTokenHasExpired()},e.prototype.setStandAloneToken=function(e){return this.tokenService.setStandAloneToken(e)},e.prototype.initialize=function(){var e,t=this,r=this.adobeIdData,o=r.handlers,n=r.standalone,i=r.ijt,s=r.alwaysRemoveTokenFromUrl,a=r.enableGuestAccounts,c=r.enableGuestTokenForceRefresh,u=null;switch(n&&this.setStandAloneToken(n),!0){case!!i:e=this.exchangeIjt;break;case a:e=this.tokenService.getGuestToken.bind(this.tokenService,{},{enableGuestAccounts:a,enableGuestTokenForceRefresh:c});break;default:e=this.tokenService.getTokenAndProfile}return e().then(this.processTokenResponse,this.processError.apply(this)).then((function(e){u=e})).finally((function(){p.info("onReady initialization"),window.addEventListener("getImsLibInstance",(function(){t.triggerOnImsInstance(t)}),!1),s&&v.setHash(te.removeAccessToken()),o.triggerOnReady(u?u.context:null),t.triggerOnImsInstance(t),t.initialized=!0}))},e.prototype.processError=function(){var e=this;return function(t){return e.verifyModalSignInEvent(t).catch(e.processInitializeException).catch(e.verifyTokenExpiredException).catch(e.verifyRideErrorException).catch(e.verifyCsrfException).catch(e.executeErrorCallback)}},e.prototype.notifyParentAboutModalSignIn=function(e){var t=window.location.href.replace("imslibmodal","wasmodal");if(window.opener)window.opener.postMessage(t,window.location.origin),window.close();else{var r=new BroadcastChannel("imslib");r.postMessage(t),r.close(),window.close()}return Promise.reject("popup")},e.prototype.restoreHash=function(){var e=te.fragmentToObject();e&&e.from_ims&&v.setHash(e.old_hash||"")},e.prototype.getTransitoryAuthorizationCode=function(e,t){return void 0===t&&(t={}),(e=e||{}).response_type=e.response_type||"code",e.target_client_id=e.target_client_id||this.adobeIdData.client_id,e.target_scope=e.target_scope||this.adobeIdData.scope,this.imsApis.getTransitoryAuthorizationCode(e,t,this.adobeIdData.client_id)},e.prototype.jumpToken=function(e,t){return void 0===t&&(t={}),e.target_client_id=e.target_client_id||this.adobeIdData.client_id,e.target_scope=e.target_scope||this.adobeIdData.scope,this.imsApis.jumpToken(e,t,this.adobeIdData.client_id)},e.prototype.getVerifierByKey=function(e){return(new M).getVerifierByKey(e)},e.prototype.socialHeadlessSignIn=function(e,t){return void 0===t&&(t={}),n(this,void 0,Promise,(function(){var r=this;return i(this,(function(o){return[2,this.imsApis.socialHeadlessSignIn(e,t).then((function(e){return r.exchangeIjt(e.token)})).catch((function(t){return"ride_AdobeID_social"===t.error&&r.signIn({idp_flow:"social.native",provider_id:e.provider_id,idp_token:e.idp_token}),Promise.reject(t)}))]}))}))},e.prototype.getAccountType=function(){var e=this.getAccessToken();if(!e)throw new Error("please login before getting the account type");if(e.isGuestToken)return oe.GUEST;var t=this.profileService.getProfileFromStorage();if(!t)throw new Error("you need to first get the profile before getting the account type");return t.account_type},e.prototype.getSessionExpiration=function(){var e=this.getAccessToken();if(!e)throw new Error("please obtain a token before getting the session expiration");return e.gse},e}(),ge=new(function(){function e(){this.createIMSLib=function(e,t){void 0===e&&(e=null),void 0===t&&(t="adobeIMS");var r=new ve(e,t);return window[t]=r,r}}return e.prototype.initAdobeIms=function(){window.adobeImsFactory={createIMSLib:this.createIMSLib};var e=window.adobeIMS||null;if(!e){var t=window.adobeid;if(!t||!t.client_id)return;(e=this.createIMSLib(t,"adobeIMS")).initialize()}},e}());return new(function(){function e(){ge.initAdobeIms()}return e.prototype.initialize=function(){return!0},e}())}(); +var e=function(t,r){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(t,r)};function t(t,r){function o(){this.constructor=t}e(t,r),t.prototype=null===r?Object.create(r):(o.prototype=r.prototype,new o)}var r=function(){return(r=Object.assign||function(e){for(var t,r=1,o=arguments.length;r0&&n[n.length-1])&&(6===i[0]||2===i[0])){s=0;continue}if(3===i[0]&&(!n||i[1]>n[0]&&i[1]0)&&!(o=i.next()).done;)s.push(o.value)}catch(e){n={error:e}}finally{try{o&&!o.done&&(r=i.return)&&r.call(i)}finally{if(n)throw n.error}}return s}function a(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}(Object.keys(a)),u=c.next();!u.done;u=c.next()){var l=u.value;if(r===l||r.endsWith("."+l))return new e(!0,a[l],n)}}catch(e){i={error:e}}finally{try{u&&!u.done&&(s=c.return)&&s.call(c)}finally{if(i)throw i.error}}}return new e(!1,n)},e.prototype.shouldFallbackToAdobe=function(e){return!!this.proxied&&("feature_disabled"===e.error&&"cdsc"===e.error_description)},e.THIRD_PARTY_DOMAINS_PROD={"behance.net":"https://sso.behance.net"},e.THIRD_PARTY_DOMAINS_STAGE={"s2stagehance.com":"https://sso.s2stagehance.com"},e}(),m=new(function(){function e(){this.baseUrlAdobe="",this.baseUrlServices="",this.checkTokenEndpoint=new g,this.jslibver="v2-v0.43.0-3-gc3eb4d3"}return e.prototype.loadEnvironment=function(e,t,r){void 0===t&&(t=!1),void 0===r&&(r="");var o=e===l.STAGE;o?(this.baseUrlAdobe="https://ims-na1-stg1.adobelogin.com",this.baseUrlServices="https://adobeid-na1-stg1.services.adobe.com"):(this.baseUrlAdobe="https://ims-na1.adobelogin.com",this.baseUrlServices="https://adobeid-na1.services.adobe.com"),this.checkTokenEndpoint=g.computeEndpoint(t,r,o,this.baseUrlServices)},e}());function y(e){return null!=e&&"object"==typeof e&&!Array.isArray(e)}function k(e,t){if(null==e)return t;if(e===t)return e;if(!y(e))return e;var r=Object.assign({},e);return y(t)&&Object.keys(t).forEach((function(o){var n,i;y(t[o])?o in e?r[o]=k(e[o],t[o]):Object.assign(r,((n={})[o]=t[o],n)):Object.assign(r,((i={})[o]=t[o],i))})),r}var w=new(function(){function e(){this.getCustomApiParameters=function(e,t){return e[t]||{}}}return e.prototype.mergeExternalParameters=function(e,t,r){return k(this.getCustomApiParameters(t,r),e)},e.prototype.toJson=function(e){try{return"string"!=typeof e?e:JSON.parse(e)}catch(e){return null}},e}()),b=function(){function e(){}return e.getInitialRedirectUri=function(e,t){var r=e.redirect_uri||t||window.location.href,o="function"==typeof r?r():r,n=o.indexOf("from_ims");return-1===n?o:("#"===o[n-1]&&n--,o.substr(0,n))},e.createDefaultRedirectUrl=function(e,t,r,o){var n=this.getInitialRedirectUri(r,e),i=this.createOldHash(n);return i.indexOf("?")>0?i+"&client_id="+t+"&api="+o:i+"?client_id="+t+"&api="+o},e.createRedirectUrl=function(e,t,r,o,n){void 0===n&&(n="");var i=this.createDefaultRedirectUrl(e,t,r,o);(n=n||r.scope||"")&&(i=i+"&scope="+n);var s=r.reauth||"";return s&&(i=i+"&reauth="+s),i},e.createOldHash=function(e){var t=e.indexOf("#");return t<0?e+"#old_hash=&from_ims=true":e.substring(0,t)+"#old_hash="+e.substring(t+1)+"&from_ims=true"},e.mergeApiParamsWithExternalParams=function(e,t,r){return k(w.getCustomApiParameters(e,r),t)},e}(),S=function(){var e=this;this.composeRedirectUrl=function(e){var t=e.apiParameters,o=e.externalParameters,n=void 0===o?{}:o,i=e.adobeIdRedirectUri,s=void 0===i?"":i,a=e.clientId,c=e.locale,u=e.state,l=void 0===u?{}:u,d=e.scope,p=void 0===d?n.scope||t.scope||"":d,h=b.mergeApiParamsWithExternalParams(t,n,"authorize");l&&(h.state=k(h.state||{},l));var f=b.createRedirectUrl(s,a,h,"authorize",p),v=n.locale||c||"",g=e.response_type,y=void 0===g?h.response_type||"":g;return r(r({},h),{client_id:a,scope:p,locale:v,response_type:y,jslVersion:m.jslibver,redirect_uri:f})},this.createRedirectUrl=function(t){var r=e.composeRedirectUrl(t),o=v.uriEncodeData(r);return m.baseUrlAdobe+"/ims/authorize/v1?"+o}},T=function(e){function r(){var t=null!==e&&e.apply(this,arguments)||this;return t.signIn=function(e){var r=t.createRedirectUrl(e);v.setHrefUrl(r)},t.authorizeToken=function(e,r){var o=t.composeRedirectUrl(r);e&&(o.user_assertion=e,o.user_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer"),t.createAuthorizeForm(o).submit()},t}return t(r,e),r.prototype.createAuthorizeForm=function(e){var t=m.baseUrlAdobe+"/ims/authorize/v1",r=document.createElement("form");r.style.display="none",r.setAttribute("method","post"),r.setAttribute("action",t);var o=null,n=null,i="";for(var s in e){if("object"==typeof(n=e[s])){if(0===Object.keys(n).length)continue;i=JSON.stringify(n)}else i=n;""!==i&&(o=this.createFormElement("input","text",s,i),r.appendChild(o))}return document.getElementsByTagName("body")[0].appendChild(r),r},r.prototype.createFormElement=function(e,t,r,o){var n=document.createElement(e);return n.setAttribute("type",t),n.setAttribute("name",r),n.setAttribute("value",o),n},r}(S),I=/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/,_=["https://auth.services.adobe.com","https://auth-stg1.services.adobe.com","https://localhost.corp.adobe.com:9000"],P=new function(){var e=this;this.windowObjectReference=null,this.previousUrl="",this.openSignInWindow=function(t,r,o,n){e.onProcessLocation=n,e.allowOrigin=o.allowOrigin,e.timerId&&clearInterval(e.timerId),window.removeEventListener("message",e.receiveMessage),window.addEventListener("message",e.receiveMessage),e.broadcastChannel&&e.broadcastChannel.close(),e.broadcastChannel=new BroadcastChannel("imslib"),e.broadcastChannel.onmessage=e.receiveMessage;var i="popup=yes, width="+o.width+", height="+o.height+", top="+o.top+", left="+o.left;!e.windowObjectReference||e.windowObjectReference&&e.windowObjectReference.closed?e.windowObjectReference=window.open(t,o.title,i):e.previousUrl!==t?(e.windowObjectReference=window.open(t,o.title,i),e.windowObjectReference&&e.windowObjectReference.focus()):e.windowObjectReference.focus(),e.previousUrl=t},this.receiveMessage=function(t){if(a(_,[e.allowOrigin]).includes(t.origin)){try{if(!I.test(t.data))return void console.warn("refused to receive message containing unknown data format",t.data)}catch(e){return void console.error(e)}e.broadcastChannel&&e.broadcastChannel.close(),e.onProcessLocation&&e.onProcessLocation(t.data)}else console.warn("refused to receive message from origin not whitelisted",t.origin)}},R=function(e){function o(t,o){var n=e.call(this)||this;return n.signIn=function(e){e.state=r(r({},e.state),{imslibmodal:!0});var t=e.state.nonce,o=n.createRedirectUrl(e);P.openSignInWindow(o,t,n.popupSettings,n.onPopupMessage)},n.onPopupMessage=t,n.popupSettings=o,n}return t(o,e),o}(S),E=function(){function e(e,t){this.status=0,this.data="",this.status=e,this.data=this.toJson(t)}return e.prototype.toJson=function(e){try{return"string"!=typeof e?e:JSON.parse(e)}catch(t){return e}},e}(),A=new(function(){function e(){}return e.prototype.http=function(e){return new Promise((function(t,r){var o=new(0,window.XMLHttpRequest);"boolean"==typeof e.withCredentials?o.withCredentials=e.withCredentials:o.withCredentials=!0,"number"==typeof e.timeout&&(o.timeout=e.timeout),o.open(e.method,e.url,!0);var n;o.onload=function(){return this.status>=200&&this.status<300?t(new E(this.status,this.response)):r(new E(this.status,this.response))},o.onerror=function(){var e=new E(this.status,this.response);return r(e)},o.ontimeout=function(){var e=new E(0,"timeout");return r(e)},o.onabort=function(){var e=new E(0,"aborted");return r(e)},(n=e.headers)&&Object.keys(n).forEach((function(e){o.setRequestHeader(e,n[e])})),o.send(e.data)}))},e.prototype.post=function(e,t,r,o,n){return void 0===r&&(r={}),this.http({headers:r,method:"POST",url:e,data:t,withCredentials:o,timeout:n})},e.prototype.get=function(e,t,r,o){return void 0===t&&(t={}),this.http({headers:t,method:"GET",url:e,withCredentials:r,timeout:o})},e}()),O=function(){this.probe=function(e,t,r){if(void 0===r&&(r=2e3),!e||0===e.length)return Promise.resolve([]);for(var o={"Content-Type":"application/json","Cache-Control":"no-cache, no-store, must-revalidate",Pragma:"no-cache",Expires:0,"X-IMS-CLIENTID":t},n="/ims/cdsc_probe?"+v.uriEncodeData({client_id:t}),i=[],s=[],a=function(t){var a=e[t]+n;s.push(A.post(a,{},o,!1,r).then((function(e){return 200==e.status&&i.push(t)})).catch((function(){})))},c=0;c=0?new G("ride_pba_idle_session","",!0):null;var n=this.addRedirectUriToJump(r,o);return new G(r,n)},e.prototype.addRedirectUriToJump=function(e,t){if(!t||"string"!=typeof t)return"";var r=t;this.adobeIdThinData||(this.adobeIdThinData=new H);var o=this.adobeIdThinData.computeRideRedirectUri(e);if(!o||0===o.length)return r;try{var n=new URL(r);return n.searchParams.append("redirect_uri",o),n.toString()}catch(e){return r}},e.prototype.isUnauthorizedException=function(e){var t=e.status;return 401===(void 0===t?0:t)},e}()),K=new(function(){function e(){this.triggerOnError=null}return e.prototype.post=function(e,t,r){var o=this;void 0===r&&(r={});var n=z.getCachedApiResponse(e,t);if(n){var i=n.status,s=n.data;return 200===i?Promise.resolve(s):Promise.reject(s)}return A.post(e,t,r).then((function(r){return o.storeApiResponse(e,JSON.stringify(t),r)})).catch((function(r){return o.verifyError(e,JSON.stringify(t),r)}))},e.prototype.get=function(e,t){var r=this;void 0===t&&(t={});var o=z.getCachedApiResponse(e);if(o){var n=o.status,i=o.data;return 200===n?Promise.resolve(i):Promise.reject(i)}return A.get(e,t).then((function(t){return r.storeApiResponse(e,"",t)})).catch((function(t){return r.verifyError(e,"",t)}))},e.prototype.verifyError=function(e,t,r){this.storeApiResponse(e,t,r);var o=J.verify(r,e);return Promise.reject(o||r.data)},e.prototype.storeApiResponse=function(e,t,r){return void 0===t&&(t=""),z.storeApiResponse(e,t,r),Promise.resolve(r.data)},e}()),B=function(){function e(e){void 0===e&&(e={}),this.CONTENT_FORM_ENCODED="application/x-www-form-urlencoded;charset=utf-8",this.apiParameters=e}return e.prototype.validateToken=function(e){var t=e.token,o=e.client_id,n=e.type,i=v.uriEncodeData(r(r({},w.getCustomApiParameters(this.apiParameters,"validate_token")),{type:n||"access_token",client_id:o,token:t})),s=m.baseUrlAdobe+"/ims/validate_token/v1?jslVersion="+m.jslibver,a=this.formEncoded();return this.addClientIdInHeader(o,a),K.post(s,i,a)},e.prototype.getProfile=function(e){var t=e.token,o=e.client_id,n=r({},w.getCustomApiParameters(this.apiParameters,"profile")),i=this.createAuthorizationHeader(t);this.addClientIdInHeader(o,i);var s=v.uriEncodeData(r({client_id:o},n)),a=m.baseUrlAdobe+"/ims/profile/v1?"+s+"&jslVersion="+m.jslibver;return K.get(a,i)},e.prototype.getUserInfo=function(e){var t=e.token,o=e.client_id,n=r({},w.getCustomApiParameters(this.apiParameters,"userinfo")),i=this.createAuthorizationHeader(t);this.addClientIdInHeader(o,i);var s=v.uriEncodeData(r({client_id:o},n)),a=m.baseUrlAdobe+"/ims/userinfo/v1?"+s+"&jslVersion="+m.jslibver;return K.get(a,i)},e.prototype.logoutToken=function(e){var t=e.client_id,o=e.token,n=r({},w.getCustomApiParameters(this.apiParameters,"logout_token")),i=m.baseUrlServices+"/ims/logout/v1?jslVersion="+m.jslibver,s=this.addClientIdInHeader(t);return K.post(i,r({client_id:t,access_token:o},n),s)},e.prototype.checkStatus=function(){var e=m.baseUrlServices+"/ims/check/v1/status";return K.get(e)},e.prototype.checkToken=function(e,t,o){var n=e.client_id,i=e.scope,s=r({},w.mergeExternalParameters(t,this.apiParameters,"check_token")),a=r(r({},s),{client_id:n,scope:i});return o&&(a.user_id=o),this.callCheckToken(v.uriEncodeData(a),n,"/check/v6/token?jslVersion="+m.jslibver)},e.prototype.switchProfile=function(e,t,o){void 0===o&&(o="");var n=e.client_id,i=e.scope,s=void 0===i?"":i,a=r({},w.mergeExternalParameters(t,this.apiParameters,"check_token")),c=v.uriEncodeData(r(r({},a),{client_id:n,scope:s,user_id:o}));return this.callCheckToken(c,n,"/check/v6/token?jslVersion="+m.jslibver)},e.prototype.listSocialProviders=function(e){var t=e.client_id,o=r({},w.getCustomApiParameters(this.apiParameters,"providers")),n=v.uriEncodeData(r({client_id:t},o)),i=m.baseUrlServices+"/ims/social/v2/providers?"+n+"&jslVersion="+m.jslibver,s=this.addClientIdInHeader(t);return K.get(i,s)},e.prototype.exchangeIjt=function(e,t){var o=e.client_id,n=r({},w.getCustomApiParameters(this.apiParameters,"ijt")),i=m.baseUrlServices+"/ims/jump/implicit/"+t,s=v.uriEncodeData(r({client_id:o},n)),a=i+"?"+s+"&jslVersion="+m.jslibver;a.length>2048&&(delete n.redirect_uri,a=i+"?"+(s=v.uriEncodeData(n)));var c=this.addClientIdInHeader(o);return K.get(a,c)},e.prototype.avatarUrl=function(e){return m.baseUrlAdobe+"/ims/avatar/download/"+e},e.prototype.getReleaseFlags=function(e){var t=e.token,o=e.client_id,n=r({},w.getCustomApiParameters(this.apiParameters,"fg_value")),i=this.createAuthorizationHeader(t);this.addClientIdInHeader(o,i);var s=v.uriEncodeData(r({client_id:o},n)),a=m.baseUrlAdobe+"/ims/fg/value/v1?"+s+"&jslVersion="+m.jslibver;return K.get(a,i)},e.prototype.getTransitoryAuthorizationCode=function(e,t,o){void 0===t&&(t={});var n=r({},w.mergeExternalParameters(t,this.apiParameters,"check_token")),i=v.uriEncodeData(r(r({},n),e));return this.callCheckToken(i,o,"/check/v6/token?client_id="+o+"&jslVersion="+m.jslibver)},e.prototype.getTokenFromCode=function(e,t){void 0===t&&(t={});var o=r({},w.mergeExternalParameters(t,this.apiParameters,"token"));o.grant_type="authorization_code",delete e.other;var n=m.baseUrlServices+"/ims/token/v3?jslVersion="+m.jslibver,i=v.uriEncodeData(r(r({},o),e)),s=this.formEncoded();return this.addClientIdInHeader(e.client_id,s),K.post(n,i,s)},e.prototype.jumpToken=function(e,t,o){void 0===t&&(t={});var n=r({},w.mergeExternalParameters(t,this.apiParameters,"jumptoken")),i=m.baseUrlServices+"/ims/jumptoken/v1?client_id="+o+"&jslVersion="+m.jslibver,s=v.uriEncodeData(r(r({},n),e)),a=this.formEncoded();return this.addClientIdInHeader(o,a),K.post(i,s,a)},e.prototype.socialHeadlessSignIn=function(e,t){void 0===t&&(t={});var o=r({},w.mergeExternalParameters(t,this.apiParameters,"jumptoken")),n=m.baseUrlServices+"/ims/social/v2/native?jslVersion="+m.jslibver,i=v.uriEncodeData(r(r(r({},o),e),{response_type:"implicit_jump"}));return K.post(n,i,this.formEncoded())},e.prototype.createAuthorizationHeader=function(e){var t={};return e&&(t[d]="Bearer "+e),t},e.prototype.formEncoded=function(e){return void 0===e&&(e={}),e["content-type"]=this.CONTENT_FORM_ENCODED,e},e.prototype.addClientIdInHeader=function(e,t){return void 0===t&&(t={}),t.client_id=e,t},e.prototype.callCheckToken=function(e,t,r){var o=this.formEncoded();return this.addClientIdInHeader(t,o),K.post(m.checkTokenEndpoint.url+"/ims"+r,e,o).catch((function(t){if(!m.checkTokenEndpoint.shouldFallbackToAdobe(t))throw t;return K.post(m.checkTokenEndpoint.fallbackUrl+"/ims"+r,e,o)}))},e}();!function(e){e.INITIALIZE_ERROR="initialize_error",e.HTTP="http",e.FRAGMENT="fragment",e.CSRF="csrf",e.NOT_ALLOWED="not_allowed",e.PROFILE_EXCEPTION="profile_exception",e.TOKEN_EXPIRED="token_expired",e.SOCIAL_PROVIDERS="SOCIAL_PROVIDERS",e.RIDE_EXCEPTION="ride_exception"}(N||(N={}));var W=function(e){this.message=null,this.errorType=N.PROFILE_EXCEPTION,this.message=e},Y=/\s|,/g;function X(e){return e.split(Y).sort().join(",")}var Z,Q=function(){function e(e){this.profileServiceRequest=e,this.storage=h.getStorageByName(c.SessionStorage)}return e.prototype.getProfile=function(e){var t=this,r=this.profileServiceRequest,o=r.clientId,n=r.imsApis,i=this.getProfileFromStorage();return i?Promise.resolve(i):n.getProfile({client_id:o,token:e}).then((function(e){if(!e)throw new W("NO profile response");if(0===Object.keys(e).length)throw new W("NO profile value");return t.saveProfileToStorage(e),Promise.resolve(e)})).catch((function(e){return e instanceof q?Promise.reject(e):(t.removeProfile(),Promise.reject(e))}))},e.prototype.getProfileStorageKey=function(){var e=this.profileServiceRequest;return"adobeid_ims_profile/"+e.clientId+"/"+!1+"/"+X(e.scope)},e.prototype.getProfileFromStorage=function(){var e=this.getProfileStorageKey(),t=this.storage.getItem(e);return t&&JSON.parse(t)},e.prototype.saveProfileToStorage=function(e){var t=this.getProfileStorageKey();this.storage.setItem(t,JSON.stringify(e))},e.prototype.removeProfile=function(){var e=this.getProfileStorageKey();this.storage.removeItem(e)},e.prototype.removeProfileIfOtherUser=function(e){if(e){var t=this.getProfileFromStorage();t&&t.userId!==e&&this.removeProfile()}},e}();!function(e){e.GUEST="guest"}(Z||(Z={}));var $,ee=function(){function e(e,t){var r=this;this.REAUTH_SCOPE="reauthenticated",this.valid=!1,this.isReauth=function(){return r.scope.indexOf(r.REAUTH_SCOPE)>=0},this.client_id="",this.scope="",this.expire=new Date,this.user_id="",this.tokenValue="",this.sid="",this.state=null,this.fromFragment=!1,this.impersonatorId="",this.isImpersonatedSession=!1;var o=e.valid,n=e.tokenValue,i=e.access_token,s=e.state,a=e.other,c=n||i,u=this.parseJwt(c);if(!u)throw new Error("token cannot be decoded "+c);this.state=w.toJson(s);var l=u.client_id,d=u.user_id,p=u.scope,h=u.sid,f=u.imp_id,v=u.imp_sid,g=u.pba,m=u.atp,y=u.gse;this.atp=m,this.client_id=l,this.expire=t,this.user_id=d,this.scope=p,this.valid=o,this.tokenValue=c,this.sid=h,this.other=a,this.impersonatorId=f||"",this.isImpersonatedSession=!!v,this.pbaSatisfiedPolicies=g&&g.split(",")||[],this.isGuestToken=this.atp===Z.GUEST,this.gse=y}return e.prototype.parseJwt=function(e){if(!e)return null;try{return JSON.parse(atob(e.split(".")[1].replace(/-/g,"+").replace(/_/g,"/")))}catch(t){return p.error("error on decoding token ",e,t),null}},e.prototype.validate=function(e,t){var r,o,n,i=this.valid,s=this.client_id,a=this.scope,c=this.expire;return c0&&(r=new Array(o+1).join(e)+r),r}("0",5,e.toString(2))},le=function(e,t){if(void 0===t&&(t=!1),"string"!=typeof e)throw new Error("Data is not a string");var r=e.toLowerCase().split("");!function(e){if(e.length%8!=0)throw new Error("Data length is not a multiple of 8");e.forEach((function(e){if(!(e in ce))throw new Error("Unknown encoded character "+e)}));var t=!1;e.forEach((function(e){if("="!==e&&t)throw new Error("Found padding char in the middle of the string");"="===e&&(t=!0)}))}(r);var o=function(e){for(var t=e.length-1,r=0;"="===e[t];)++r,--t;return r}(r),n=[];r.forEach((function(e){n.push(ue(ce[e]))}));var i=n.join("");return o>0&&(i=i.slice(0,-5*o)),i.length%8!=0&&(i=i.slice(0,i.length%8*-1)),t?function(e){var t="";if(e.length%8!=0)throw new Error("Length must be a multiple of 8");for(var r=0,o=e.length;rfe.lastUserInteraction&&(fe.lastUserInteraction=n)}return o.tokenService.refreshToken(e).then((function(e){return o.onTokenProfileReceived(e)})).catch((function(e){if(p.error("refresh token error",e),e instanceof q)return Promise.reject(e);var t=o.verifyRideErrorExceptionStrict(e);return t||(o.profileService.removeProfile(),o.onTokenExpired(),Promise.reject(e))}))},this.switchProfile=function(e,t){return void 0===t&&(t={}),e?o.tokenService.switchProfile(e,t).then((function(e){return o.onTokenProfileReceived(e)})).catch((function(e){return o.verifyRideErrorException(e)})):Promise.reject(new Error("Please provide the user id for switchProfile"))},this.executeErrorCallback=function(e){if(p.info("initialize exception ended",e),!e||e.type!==$.LOGOUT){var t=o.adobeIdData.onError;t&&t(N.HTTP,"Initialization error")}},this.triggerOnImsInstance=function(e){var t=document.createEvent("CustomEvent"),r={clientId:o.adobeIdData.client_id,instance:e};t.initCustomEvent("onImsLibInstance",!1,!1,r),window.dispatchEvent(t)},this.processInitializeException=function(e){return void 0===e&&(e={}),p.warn("initialize",e),o.restoreHash(),Promise.reject(e)},this.verifyModalSignInEvent=function(e){return e instanceof ae?o.notifyParentAboutModalSignIn(e):Promise.reject(e)},this.verifyTokenExpiredException=function(e){return e instanceof ie?(o.adobeIdData.handlers.triggerOnAccessTokenHasExpired(),Promise.resolve()):Promise.reject(e)},this.verifyRideErrorException=function(e){return n(o,void 0,Promise,(function(){return i(this,(function(t){switch(t.label){case 0:return e instanceof G?this.adobeIdData.overrideErrorHandler&&!this.adobeIdData.overrideErrorHandler(e)?[2,Promise.reject(e)]:e.isPbaExpiredIdleSessionWorkaround?[4,this.signIn()]:[3,2]:[3,4];case 1:return t.sent(),[3,4];case 2:return e.jump?[4,v.replaceUrlAndWait(e.jump,1e4)]:[3,4];case 3:t.sent(),t.label=4;case 4:return[2,Promise.reject(e)]}}))}))},this.verifyRideErrorExceptionStrict=function(e){return e instanceof G?o.verifyRideErrorException(e):null},this.verifyCsrfException=function(e){var t=e.type;return t&&t===N.CSRF&&o.signOut(),Promise.reject(e)},this.processTokenResponse=function(e){var t=o.adobeIdData.handlers,r=e.tokenFields,n=e.profile,i=r.tokenValue,s=r.state,a=r.expire,c=r.sid,u=r.user_id,l=r.other,d=void 0===l?{}:l,h=r.impersonatorId,f=r.isImpersonatedSession,g=r.pbaSatisfiedPolicies,m=r.isGuestToken,y=r.gse;p.info("token",i),d.from_ims&&v.setHash(d.old_hash||""),o.profileService.removeProfileIfOtherUser(u);var k={token:i,expire:a,sid:c,impersonatorId:h,isImpersonatedSession:f,pbaSatisfiedPolicies:g,isGuestToken:m,gse:y};return r.isReauth()?t.triggerOnReauthAccessToken(k):o.tokenReceived(k),n&&o.profileService.saveProfileToStorage(n),Promise.resolve(s)},this.exchangeIjt=function(e){var t=o.adobeIdData.ijt;return e||t?o.tokenService.exchangeIjt(e||t).then((function(e){return e.profile?o.profileService.saveProfileToStorage(e.profile):o.profileService.removeProfile(),Promise.resolve(e)})):Promise.reject(new Error("please set the adobeid.ijt value"))},this.adobeIdData=new L(e),t&&(this.instanceKey=t);var s=this.adobeIdData,a=s.api_parameters,c=void 0===a?{}:a,u=s.client_id,l=s.scope,d=s.useLocalStorage,h=s.autoValidateToken,g=s.modalMode,m=s.modalSettings;this.imsApis=new B(c),this.csrfService=new f(u,this.instanceKey),this.serviceRequest={clientId:u,scope:l,imsApis:this.imsApis},this.tokenService=new pe(r(r({},this.serviceRequest),{useLocalStorage:d,autoValidateToken:h}),this.csrfService),this.profileService=new Q(this.serviceRequest),this.signInservice=g?new R(this.onPopupMessage,m):new T}return Object.defineProperty(e.prototype,"version",{get:function(){return m.jslibver},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"adobeid",{get:function(){return r({},this.adobeIdData)},enumerable:!0,configurable:!0}),e.prototype.enableLogging=function(){p.enableLogging()},e.prototype.disableLogging=function(){p.disableLogging()},e.prototype.checkInitialized=function(){this.initialized},e.prototype.signUp=function(e,t){var r=this;void 0===e&&(e={}),this.checkInitialized();var o=this.adobeIdData,n=this.csrfService;if(!o)throw new Error("no adobeId on reAuthenticate");var i=n.initialize();return o.createSignUpRedirectRequest(e,t,i).then((function(e){r.signInservice.signIn(e)}))},e.prototype.isSignedInUser=function(){var e=this.getAccessToken();return(!e||!e.isGuestToken)&&!(!e&&!this.getReauthAccessToken())},e.prototype.getProfile=function(){var e=this,t=this.profileService.getProfileFromStorage();if(t)return Promise.resolve(t);var r=this.getAccessToken()||this.getReauthAccessToken();if(!r){var o="please login before getting the profile";return Promise.reject(new W(o))}if(r.isGuestToken){o="guest account does not have a profile";return Promise.reject(new W(o))}return this.profileService.getProfile(r.token).then((function(e){return Promise.resolve(e)})).catch((function(t){return p.error("get profile exception ",t),t instanceof q?e.refreshToken().then((function(e){return Promise.resolve(e.profile)})):Promise.reject(new W(t.message||t))}))},e.prototype.avatarUrl=function(e){return this.imsApis.avatarUrl(e)},e.prototype.getReleaseFlags=function(e){return void 0===e&&(e=!1),e?this.tokenService.getDecodedReleaseFlags():this.tokenService.getReleaseFlags()},e.prototype.getAccessToken=function(){return this.getTokenFromStorage(!1)},e.prototype.getReauthAccessToken=function(){return this.getTokenFromStorage(!0)},e.prototype.getTokenFromStorage=function(e){var t=this.tokenService.getTokenFieldsFromStorage(e);return t?{token:t.tokenValue,expire:t.expire,sid:t.sid,impersonatorId:t.impersonatorId,isImpersonatedSession:t.isImpersonatedSession,pbaSatisfiedPolicies:t.pbaSatisfiedPolicies,isGuestToken:t.isGuestToken,gse:t.gse}:null},e.prototype.listSocialProviders=function(){var e=this;return new Promise((function(t,r){var o=e.adobeIdData.client_id;e.imsApis.listSocialProviders({client_id:o}).then((function(e){t(e)})).catch((function(e){r(e)}))}))},e.prototype.tokenReceived=function(e){this.adobeIdData.handlers.triggerOnAccessToken(e),fe.startAutoRefreshFlow({expire:e.expire,refreshTokenMethod:this.refreshToken})},e.prototype.onTokenProfileReceived=function(e){var t=e.tokenInfo,r=e.profile;return p.info("token",t),this.tokenReceived(t),this.profileService.saveProfileToStorage(r),Promise.resolve(e)},e.prototype.validateToken=function(){var e=this;return this.tokenService.validateToken().then((function(){return Promise.resolve(!0)})).catch((function(t){return p.warn("validate token exception",t),t instanceof q?Promise.reject(!1):(e.profileService.removeProfile(),Promise.reject(!1))}))},e.prototype.onTokenExpired=function(){var e=this.adobeIdData.handlers;this.tokenService.purge(),e.triggerOnAccessTokenHasExpired()},e.prototype.setStandAloneToken=function(e){return this.tokenService.setStandAloneToken(e)},e.prototype.initialize=function(){var e,t=this,r=this.adobeIdData,o=r.handlers,n=r.standalone,i=r.ijt,s=r.alwaysRemoveTokenFromUrl,a=r.enableGuestAccounts,c=r.enableGuestTokenForceRefresh,u=null;switch(n&&this.setStandAloneToken(n),!0){case!!i:e=this.exchangeIjt;break;case a:e=this.tokenService.getGuestToken.bind(this.tokenService,{},{enableGuestAccounts:a,enableGuestTokenForceRefresh:c});break;default:e=this.tokenService.getTokenAndProfile}return e().then(this.processTokenResponse,this.processError.apply(this)).then((function(e){u=e})).finally((function(){p.info("onReady initialization"),window.addEventListener("getImsLibInstance",(function(){t.triggerOnImsInstance(t)}),!1),s&&v.setHash(te.removeAccessToken()),o.triggerOnReady(u?u.context:null),t.triggerOnImsInstance(t),t.initialized=!0}))},e.prototype.processError=function(){var e=this;return function(t){return e.verifyModalSignInEvent(t).catch(e.processInitializeException).catch(e.verifyTokenExpiredException).catch(e.verifyRideErrorException).catch(e.verifyCsrfException).catch(e.executeErrorCallback)}},e.prototype.notifyParentAboutModalSignIn=function(e){var t=window.location.href.replace("imslibmodal","wasmodal");if(window.opener)window.opener.postMessage(t,window.location.origin),window.close();else{var r=new BroadcastChannel("imslib");r.postMessage(t),r.close(),window.close()}return Promise.reject("popup")},e.prototype.restoreHash=function(){var e=te.fragmentToObject();e&&e.from_ims&&v.setHash(e.old_hash||"")},e.prototype.getTransitoryAuthorizationCode=function(e,t){return void 0===t&&(t={}),(e=e||{}).response_type=e.response_type||"code",e.target_client_id=e.target_client_id||this.adobeIdData.client_id,e.target_scope=e.target_scope||this.adobeIdData.scope,this.imsApis.getTransitoryAuthorizationCode(e,t,this.adobeIdData.client_id)},e.prototype.jumpToken=function(e,t){return void 0===t&&(t={}),e.target_client_id=e.target_client_id||this.adobeIdData.client_id,e.target_scope=e.target_scope||this.adobeIdData.scope,this.imsApis.jumpToken(e,t,this.adobeIdData.client_id)},e.prototype.getVerifierByKey=function(e){return(new M).getVerifierByKey(e)},e.prototype.socialHeadlessSignIn=function(e,t){return void 0===t&&(t={}),n(this,void 0,Promise,(function(){var r=this;return i(this,(function(o){return[2,this.imsApis.socialHeadlessSignIn(e,t).then((function(e){return r.exchangeIjt(e.token)})).catch((function(t){return"ride_AdobeID_social"===t.error&&r.signIn({idp_flow:"social.native",provider_id:e.provider_id,idp_token:e.idp_token}),Promise.reject(t)}))]}))}))},e.prototype.getAccountType=function(){var e=this.getAccessToken();if(!e)throw new Error("please login before getting the account type");if(e.isGuestToken)return oe.GUEST;var t=this.profileService.getProfileFromStorage();if(!t)throw new Error("you need to first get the profile before getting the account type");return t.account_type},e.prototype.getSessionExpiration=function(){var e=this.getAccessToken();if(!e)throw new Error("please obtain a token before getting the session expiration");return e.gse},e}(),ge=new(function(){function e(){this.createIMSLib=function(e,t){void 0===e&&(e=null),void 0===t&&(t="adobeIMS");var r=new ve(e,t);return window[t]=r,r}}return e.prototype.initAdobeIms=function(){window.adobeImsFactory={createIMSLib:this.createIMSLib};var e=window.adobeIMS||null;if(!e){var t=window.adobeid;if(!t||!t.client_id)return;(e=this.createIMSLib(t,"adobeIMS")).initialize()}},e}());return new(function(){function e(){ge.initAdobeIms()}return e.prototype.initialize=function(){return!0},e}())}(); diff --git a/libs/deps/mas/merch-card-all.js b/libs/deps/mas/merch-card-all.js index 6e174d0dd2..f49164e117 100644 --- a/libs/deps/mas/merch-card-all.js +++ b/libs/deps/mas/merch-card-all.js @@ -1,6 +1,6 @@ -var I=window,q=I.ShadowRoot&&(I.ShadyCSS===void 0||I.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,ke=Symbol(),Ce=new WeakMap,j=class{constructor(e,t,r){if(this._$cssResult$=!0,r!==ke)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o,t=this.t;if(q&&e===void 0){let r=t!==void 0&&t.length===1;r&&(e=Ce.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),r&&Ce.set(t,e))}return e}toString(){return this.cssText}},Te=o=>new j(typeof o=="string"?o:o+"",void 0,ke);var ee=(o,e)=>{q?o.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(t=>{let r=document.createElement("style"),n=I.litNonce;n!==void 0&&r.setAttribute("nonce",n),r.textContent=t.cssText,o.appendChild(r)})},V=q?o=>o:o=>o instanceof CSSStyleSheet?(e=>{let t="";for(let r of e.cssRules)t+=r.cssText;return Te(t)})(o):o;var te,F=window,Re=F.trustedTypes,ft=Re?Re.emptyScript:"",ze=F.reactiveElementPolyfillSupport,ne={toAttribute(o,e){switch(e){case Boolean:o=o?ft:null;break;case Object:case Array:o=o==null?o:JSON.stringify(o)}return o},fromAttribute(o,e){let t=o;switch(e){case Boolean:t=o!==null;break;case Number:t=o===null?null:Number(o);break;case Object:case Array:try{t=JSON.parse(o)}catch{t=null}}return t}},Oe=(o,e)=>e!==o&&(e==e||o==o),re={attribute:!0,type:String,converter:ne,reflect:!1,hasChanged:Oe},oe="finalized",$=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(e){var t;this.finalize(),((t=this.h)!==null&&t!==void 0?t:this.h=[]).push(e)}static get observedAttributes(){this.finalize();let e=[];return this.elementProperties.forEach((t,r)=>{let n=this._$Ep(r,t);n!==void 0&&(this._$Ev.set(n,r),e.push(n))}),e}static createProperty(e,t=re){if(t.state&&(t.attribute=!1),this.finalize(),this.elementProperties.set(e,t),!t.noAccessor&&!this.prototype.hasOwnProperty(e)){let r=typeof e=="symbol"?Symbol():"__"+e,n=this.getPropertyDescriptor(e,r,t);n!==void 0&&Object.defineProperty(this.prototype,e,n)}}static getPropertyDescriptor(e,t,r){return{get(){return this[t]},set(n){let a=this[e];this[t]=n,this.requestUpdate(e,a,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)||re}static finalize(){if(this.hasOwnProperty(oe))return!1;this[oe]=!0;let e=Object.getPrototypeOf(this);if(e.finalize(),e.h!==void 0&&(this.h=[...e.h]),this.elementProperties=new Map(e.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){let t=this.properties,r=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(let n of r)this.createProperty(n,t[n])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let r=new Set(e.flat(1/0).reverse());for(let n of r)t.unshift(V(n))}else e!==void 0&&t.push(V(e));return t}static _$Ep(e,t){let r=t.attribute;return r===!1?void 0:typeof r=="string"?r:typeof e=="string"?e.toLowerCase():void 0}_$Eu(){var e;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),(e=this.constructor.h)===null||e===void 0||e.forEach(t=>t(this))}addController(e){var t,r;((t=this._$ES)!==null&&t!==void 0?t:this._$ES=[]).push(e),this.renderRoot!==void 0&&this.isConnected&&((r=e.hostConnected)===null||r===void 0||r.call(e))}removeController(e){var t;(t=this._$ES)===null||t===void 0||t.splice(this._$ES.indexOf(e)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((e,t)=>{this.hasOwnProperty(t)&&(this._$Ei.set(t,this[t]),delete this[t])})}createRenderRoot(){var e;let t=(e=this.shadowRoot)!==null&&e!==void 0?e:this.attachShadow(this.constructor.shadowRootOptions);return ee(t,this.constructor.elementStyles),t}connectedCallback(){var e;this.renderRoot===void 0&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(e=this._$ES)===null||e===void 0||e.forEach(t=>{var r;return(r=t.hostConnected)===null||r===void 0?void 0:r.call(t)})}enableUpdating(e){}disconnectedCallback(){var e;(e=this._$ES)===null||e===void 0||e.forEach(t=>{var r;return(r=t.hostDisconnected)===null||r===void 0?void 0:r.call(t)})}attributeChangedCallback(e,t,r){this._$AK(e,r)}_$EO(e,t,r=re){var n;let a=this.constructor._$Ep(e,r);if(a!==void 0&&r.reflect===!0){let i=(((n=r.converter)===null||n===void 0?void 0:n.toAttribute)!==void 0?r.converter:ne).toAttribute(t,r.type);this._$El=e,i==null?this.removeAttribute(a):this.setAttribute(a,i),this._$El=null}}_$AK(e,t){var r;let n=this.constructor,a=n._$Ev.get(e);if(a!==void 0&&this._$El!==a){let i=n.getPropertyOptions(a),c=typeof i.converter=="function"?{fromAttribute:i.converter}:((r=i.converter)===null||r===void 0?void 0:r.fromAttribute)!==void 0?i.converter:ne;this._$El=a,this[a]=c.fromAttribute(t,i.type),this._$El=null}}requestUpdate(e,t,r){let n=!0;e!==void 0&&(((r=r||this.constructor.getPropertyOptions(e)).hasChanged||Oe)(this[e],t)?(this._$AL.has(e)||this._$AL.set(e,t),r.reflect===!0&&this._$El!==e&&(this._$EC===void 0&&(this._$EC=new Map),this._$EC.set(e,r))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var e;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((n,a)=>this[a]=n),this._$Ei=void 0);let t=!1,r=this._$AL;try{t=this.shouldUpdate(r),t?(this.willUpdate(r),(e=this._$ES)===null||e===void 0||e.forEach(n=>{var a;return(a=n.hostUpdate)===null||a===void 0?void 0:a.call(n)}),this.update(r)):this._$Ek()}catch(n){throw t=!1,this._$Ek(),n}t&&this._$AE(r)}willUpdate(e){}_$AE(e){var t;(t=this._$ES)===null||t===void 0||t.forEach(r=>{var n;return(n=r.hostUpdated)===null||n===void 0?void 0:n.call(r)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(e){return!0}update(e){this._$EC!==void 0&&(this._$EC.forEach((t,r)=>this._$EO(r,this[r],t)),this._$EC=void 0),this._$Ek()}updated(e){}firstUpdated(e){}};$[oe]=!0,$.elementProperties=new Map,$.elementStyles=[],$.shadowRootOptions={mode:"open"},ze?.({ReactiveElement:$}),((te=F.reactiveElementVersions)!==null&&te!==void 0?te:F.reactiveElementVersions=[]).push("1.6.3");var ae,W=window,z=W.trustedTypes,Pe=z?z.createPolicy("lit-html",{createHTML:o=>o}):void 0,se="$lit$",E=`lit$${(Math.random()+"").slice(9)}$`,Be="?"+E,vt=`<${Be}>`,A=document,N=()=>A.createComment(""),L=o=>o===null||typeof o!="object"&&typeof o!="function",Ie=Array.isArray,xt=o=>Ie(o)||typeof o?.[Symbol.iterator]=="function",ie=`[ -\f\r]`,M=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Me=/-->/g,Ne=/>/g,_=RegExp(`>|${ie}(?:([^\\s"'>=/]+)(${ie}*=${ie}*(?:[^ -\f\r"'\`<>=]|("|')|))|$)`,"g"),Le=/'/g,Ue=/"/g,je=/^(?:script|style|textarea|title)$/i,qe=o=>(e,...t)=>({_$litType$:o,strings:e,values:t}),l=qe(1),Pt=qe(2),C=Symbol.for("lit-noChange"),g=Symbol.for("lit-nothing"),He=new WeakMap,S=A.createTreeWalker(A,129,null,!1);function Ve(o,e){if(!Array.isArray(o)||!o.hasOwnProperty("raw"))throw Error("invalid template strings array");return Pe!==void 0?Pe.createHTML(e):e}var bt=(o,e)=>{let t=o.length-1,r=[],n,a=e===2?"":"",i=M;for(let c=0;c"?(i=n??M,m=-1):d[1]===void 0?m=-2:(m=i.lastIndex-d[2].length,h=d[1],i=d[3]===void 0?_:d[3]==='"'?Ue:Le):i===Ue||i===Le?i=_:i===Me||i===Ne?i=M:(i=_,n=void 0);let x=i===_&&o[c+1].startsWith("/>")?" ":"";a+=i===M?s+vt:m>=0?(r.push(h),s.slice(0,m)+se+s.slice(m)+E+x):s+E+(m===-2?(r.push(void 0),c):x)}return[Ve(o,a+(o[t]||"")+(e===2?"":"")),r]},U=class o{constructor({strings:e,_$litType$:t},r){let n;this.parts=[];let a=0,i=0,c=e.length-1,s=this.parts,[h,d]=bt(e,t);if(this.el=o.createElement(h,r),S.currentNode=this.el.content,t===2){let m=this.el.content,p=m.firstChild;p.remove(),m.append(...p.childNodes)}for(;(n=S.nextNode())!==null&&s.length0){n.textContent=z?z.emptyScript:"";for(let x=0;x2||r[0]!==""||r[1]!==""?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=g}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(e,t=this,r,n){let a=this.strings,i=!1;if(a===void 0)e=O(this,e,t,0),i=!L(e)||e!==this._$AH&&e!==C,i&&(this._$AH=e);else{let c=e,s,h;for(e=a[0],s=0;s{var r,n;let a=(r=t?.renderBefore)!==null&&r!==void 0?r:e,i=a._$litPart$;if(i===void 0){let c=(n=t?.renderBefore)!==null&&n!==void 0?n:null;a._$litPart$=i=new H(e.insertBefore(N(),c),c,void 0,t??{})}return i._$AI(o),i};var G=window,K=G.ShadowRoot&&(G.ShadyCSS===void 0||G.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,pe=Symbol(),We=new WeakMap,D=class{constructor(e,t,r){if(this._$cssResult$=!0,r!==pe)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o,t=this.t;if(K&&e===void 0){let r=t!==void 0&&t.length===1;r&&(e=We.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),r&&We.set(t,e))}return e}toString(){return this.cssText}},y=o=>new D(typeof o=="string"?o:o+"",void 0,pe),k=(o,...e)=>{let t=o.length===1?o[0]:e.reduce((r,n,a)=>r+(i=>{if(i._$cssResult$===!0)return i.cssText;if(typeof i=="number")return i;throw Error("Value passed to 'css' function must be a 'css' function result: "+i+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(n)+o[a+1],o[0]);return new D(t,o,pe)},ge=(o,e)=>{K?o.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(t=>{let r=document.createElement("style"),n=G.litNonce;n!==void 0&&r.setAttribute("nonce",n),r.textContent=t.cssText,o.appendChild(r)})},Y=K?o=>o:o=>o instanceof CSSStyleSheet?(e=>{let t="";for(let r of e.cssRules)t+=r.cssText;return y(t)})(o):o;var ue,J=window,Ge=J.trustedTypes,wt=Ge?Ge.emptyScript:"",Ke=J.reactiveElementPolyfillSupport,ve={toAttribute(o,e){switch(e){case Boolean:o=o?wt:null;break;case Object:case Array:o=o==null?o:JSON.stringify(o)}return o},fromAttribute(o,e){let t=o;switch(e){case Boolean:t=o!==null;break;case Number:t=o===null?null:Number(o);break;case Object:case Array:try{t=JSON.parse(o)}catch{t=null}}return t}},Ye=(o,e)=>e!==o&&(e==e||o==o),fe={attribute:!0,type:String,converter:ve,reflect:!1,hasChanged:Ye},xe="finalized",w=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(e){var t;this.finalize(),((t=this.h)!==null&&t!==void 0?t:this.h=[]).push(e)}static get observedAttributes(){this.finalize();let e=[];return this.elementProperties.forEach((t,r)=>{let n=this._$Ep(r,t);n!==void 0&&(this._$Ev.set(n,r),e.push(n))}),e}static createProperty(e,t=fe){if(t.state&&(t.attribute=!1),this.finalize(),this.elementProperties.set(e,t),!t.noAccessor&&!this.prototype.hasOwnProperty(e)){let r=typeof e=="symbol"?Symbol():"__"+e,n=this.getPropertyDescriptor(e,r,t);n!==void 0&&Object.defineProperty(this.prototype,e,n)}}static getPropertyDescriptor(e,t,r){return{get(){return this[t]},set(n){let a=this[e];this[t]=n,this.requestUpdate(e,a,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)||fe}static finalize(){if(this.hasOwnProperty(xe))return!1;this[xe]=!0;let e=Object.getPrototypeOf(this);if(e.finalize(),e.h!==void 0&&(this.h=[...e.h]),this.elementProperties=new Map(e.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){let t=this.properties,r=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(let n of r)this.createProperty(n,t[n])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let r=new Set(e.flat(1/0).reverse());for(let n of r)t.unshift(Y(n))}else e!==void 0&&t.push(Y(e));return t}static _$Ep(e,t){let r=t.attribute;return r===!1?void 0:typeof r=="string"?r:typeof e=="string"?e.toLowerCase():void 0}_$Eu(){var e;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),(e=this.constructor.h)===null||e===void 0||e.forEach(t=>t(this))}addController(e){var t,r;((t=this._$ES)!==null&&t!==void 0?t:this._$ES=[]).push(e),this.renderRoot!==void 0&&this.isConnected&&((r=e.hostConnected)===null||r===void 0||r.call(e))}removeController(e){var t;(t=this._$ES)===null||t===void 0||t.splice(this._$ES.indexOf(e)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((e,t)=>{this.hasOwnProperty(t)&&(this._$Ei.set(t,this[t]),delete this[t])})}createRenderRoot(){var e;let t=(e=this.shadowRoot)!==null&&e!==void 0?e:this.attachShadow(this.constructor.shadowRootOptions);return ge(t,this.constructor.elementStyles),t}connectedCallback(){var e;this.renderRoot===void 0&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(e=this._$ES)===null||e===void 0||e.forEach(t=>{var r;return(r=t.hostConnected)===null||r===void 0?void 0:r.call(t)})}enableUpdating(e){}disconnectedCallback(){var e;(e=this._$ES)===null||e===void 0||e.forEach(t=>{var r;return(r=t.hostDisconnected)===null||r===void 0?void 0:r.call(t)})}attributeChangedCallback(e,t,r){this._$AK(e,r)}_$EO(e,t,r=fe){var n;let a=this.constructor._$Ep(e,r);if(a!==void 0&&r.reflect===!0){let i=(((n=r.converter)===null||n===void 0?void 0:n.toAttribute)!==void 0?r.converter:ve).toAttribute(t,r.type);this._$El=e,i==null?this.removeAttribute(a):this.setAttribute(a,i),this._$El=null}}_$AK(e,t){var r;let n=this.constructor,a=n._$Ev.get(e);if(a!==void 0&&this._$El!==a){let i=n.getPropertyOptions(a),c=typeof i.converter=="function"?{fromAttribute:i.converter}:((r=i.converter)===null||r===void 0?void 0:r.fromAttribute)!==void 0?i.converter:ve;this._$El=a,this[a]=c.fromAttribute(t,i.type),this._$El=null}}requestUpdate(e,t,r){let n=!0;e!==void 0&&(((r=r||this.constructor.getPropertyOptions(e)).hasChanged||Ye)(this[e],t)?(this._$AL.has(e)||this._$AL.set(e,t),r.reflect===!0&&this._$El!==e&&(this._$EC===void 0&&(this._$EC=new Map),this._$EC.set(e,r))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var e;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((n,a)=>this[a]=n),this._$Ei=void 0);let t=!1,r=this._$AL;try{t=this.shouldUpdate(r),t?(this.willUpdate(r),(e=this._$ES)===null||e===void 0||e.forEach(n=>{var a;return(a=n.hostUpdate)===null||a===void 0?void 0:a.call(n)}),this.update(r)):this._$Ek()}catch(n){throw t=!1,this._$Ek(),n}t&&this._$AE(r)}willUpdate(e){}_$AE(e){var t;(t=this._$ES)===null||t===void 0||t.forEach(r=>{var n;return(n=r.hostUpdated)===null||n===void 0?void 0:n.call(r)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(e){return!0}update(e){this._$EC!==void 0&&(this._$EC.forEach((t,r)=>this._$EO(r,this[r],t)),this._$EC=void 0),this._$Ek()}updated(e){}firstUpdated(e){}};w[xe]=!0,w.elementProperties=new Map,w.elementStyles=[],w.shadowRootOptions={mode:"open"},Ke?.({ReactiveElement:w}),((ue=J.reactiveElementVersions)!==null&&ue!==void 0?ue:J.reactiveElementVersions=[]).push("1.6.3");var be,ye;var b=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var e,t;let r=super.createRenderRoot();return(e=(t=this.renderOptions).renderBefore)!==null&&e!==void 0||(t.renderBefore=r.firstChild),r}update(e){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=Fe(t,this.renderRoot,this.renderOptions)}connectedCallback(){var e;super.connectedCallback(),(e=this._$Do)===null||e===void 0||e.setConnected(!0)}disconnectedCallback(){var e;super.disconnectedCallback(),(e=this._$Do)===null||e===void 0||e.setConnected(!1)}render(){return C}};b.finalized=!0,b._$litElement$=!0,(be=globalThis.litElementHydrateSupport)===null||be===void 0||be.call(globalThis,{LitElement:b});var Je=globalThis.litElementPolyfillSupport;Je?.({LitElement:b});((ye=globalThis.litElementVersions)!==null&&ye!==void 0?ye:globalThis.litElementVersions=[]).push("3.3.3");var T="(max-width: 767px)",Q="(max-width: 1199px)",f="(min-width: 768px)",u="(min-width: 1200px)",v="(min-width: 1600px)";var Qe=k` +var j=window,V=j.ShadowRoot&&(j.ShadyCSS===void 0||j.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Re=Symbol(),Te=new WeakMap,q=class{constructor(e,t,r){if(this._$cssResult$=!0,r!==Re)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o,t=this.t;if(V&&e===void 0){let r=t!==void 0&&t.length===1;r&&(e=Te.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),r&&Te.set(t,e))}return e}toString(){return this.cssText}},ze=o=>new q(typeof o=="string"?o:o+"",void 0,Re);var te=(o,e)=>{V?o.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(t=>{let r=document.createElement("style"),n=j.litNonce;n!==void 0&&r.setAttribute("nonce",n),r.textContent=t.cssText,o.appendChild(r)})},F=V?o=>o:o=>o instanceof CSSStyleSheet?(e=>{let t="";for(let r of e.cssRules)t+=r.cssText;return ze(t)})(o):o;var re,W=window,Oe=W.trustedTypes,ft=Oe?Oe.emptyScript:"",Pe=W.reactiveElementPolyfillSupport,oe={toAttribute(o,e){switch(e){case Boolean:o=o?ft:null;break;case Object:case Array:o=o==null?o:JSON.stringify(o)}return o},fromAttribute(o,e){let t=o;switch(e){case Boolean:t=o!==null;break;case Number:t=o===null?null:Number(o);break;case Object:case Array:try{t=JSON.parse(o)}catch{t=null}}return t}},Me=(o,e)=>e!==o&&(e==e||o==o),ne={attribute:!0,type:String,converter:oe,reflect:!1,hasChanged:Me},ae="finalized",$=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(e){var t;this.finalize(),((t=this.h)!==null&&t!==void 0?t:this.h=[]).push(e)}static get observedAttributes(){this.finalize();let e=[];return this.elementProperties.forEach((t,r)=>{let n=this._$Ep(r,t);n!==void 0&&(this._$Ev.set(n,r),e.push(n))}),e}static createProperty(e,t=ne){if(t.state&&(t.attribute=!1),this.finalize(),this.elementProperties.set(e,t),!t.noAccessor&&!this.prototype.hasOwnProperty(e)){let r=typeof e=="symbol"?Symbol():"__"+e,n=this.getPropertyDescriptor(e,r,t);n!==void 0&&Object.defineProperty(this.prototype,e,n)}}static getPropertyDescriptor(e,t,r){return{get(){return this[t]},set(n){let a=this[e];this[t]=n,this.requestUpdate(e,a,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)||ne}static finalize(){if(this.hasOwnProperty(ae))return!1;this[ae]=!0;let e=Object.getPrototypeOf(this);if(e.finalize(),e.h!==void 0&&(this.h=[...e.h]),this.elementProperties=new Map(e.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){let t=this.properties,r=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(let n of r)this.createProperty(n,t[n])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let r=new Set(e.flat(1/0).reverse());for(let n of r)t.unshift(F(n))}else e!==void 0&&t.push(F(e));return t}static _$Ep(e,t){let r=t.attribute;return r===!1?void 0:typeof r=="string"?r:typeof e=="string"?e.toLowerCase():void 0}_$Eu(){var e;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),(e=this.constructor.h)===null||e===void 0||e.forEach(t=>t(this))}addController(e){var t,r;((t=this._$ES)!==null&&t!==void 0?t:this._$ES=[]).push(e),this.renderRoot!==void 0&&this.isConnected&&((r=e.hostConnected)===null||r===void 0||r.call(e))}removeController(e){var t;(t=this._$ES)===null||t===void 0||t.splice(this._$ES.indexOf(e)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((e,t)=>{this.hasOwnProperty(t)&&(this._$Ei.set(t,this[t]),delete this[t])})}createRenderRoot(){var e;let t=(e=this.shadowRoot)!==null&&e!==void 0?e:this.attachShadow(this.constructor.shadowRootOptions);return te(t,this.constructor.elementStyles),t}connectedCallback(){var e;this.renderRoot===void 0&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(e=this._$ES)===null||e===void 0||e.forEach(t=>{var r;return(r=t.hostConnected)===null||r===void 0?void 0:r.call(t)})}enableUpdating(e){}disconnectedCallback(){var e;(e=this._$ES)===null||e===void 0||e.forEach(t=>{var r;return(r=t.hostDisconnected)===null||r===void 0?void 0:r.call(t)})}attributeChangedCallback(e,t,r){this._$AK(e,r)}_$EO(e,t,r=ne){var n;let a=this.constructor._$Ep(e,r);if(a!==void 0&&r.reflect===!0){let i=(((n=r.converter)===null||n===void 0?void 0:n.toAttribute)!==void 0?r.converter:oe).toAttribute(t,r.type);this._$El=e,i==null?this.removeAttribute(a):this.setAttribute(a,i),this._$El=null}}_$AK(e,t){var r;let n=this.constructor,a=n._$Ev.get(e);if(a!==void 0&&this._$El!==a){let i=n.getPropertyOptions(a),h=typeof i.converter=="function"?{fromAttribute:i.converter}:((r=i.converter)===null||r===void 0?void 0:r.fromAttribute)!==void 0?i.converter:oe;this._$El=a,this[a]=h.fromAttribute(t,i.type),this._$El=null}}requestUpdate(e,t,r){let n=!0;e!==void 0&&(((r=r||this.constructor.getPropertyOptions(e)).hasChanged||Me)(this[e],t)?(this._$AL.has(e)||this._$AL.set(e,t),r.reflect===!0&&this._$El!==e&&(this._$EC===void 0&&(this._$EC=new Map),this._$EC.set(e,r))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var e;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((n,a)=>this[a]=n),this._$Ei=void 0);let t=!1,r=this._$AL;try{t=this.shouldUpdate(r),t?(this.willUpdate(r),(e=this._$ES)===null||e===void 0||e.forEach(n=>{var a;return(a=n.hostUpdate)===null||a===void 0?void 0:a.call(n)}),this.update(r)):this._$Ek()}catch(n){throw t=!1,this._$Ek(),n}t&&this._$AE(r)}willUpdate(e){}_$AE(e){var t;(t=this._$ES)===null||t===void 0||t.forEach(r=>{var n;return(n=r.hostUpdated)===null||n===void 0?void 0:n.call(r)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(e){return!0}update(e){this._$EC!==void 0&&(this._$EC.forEach((t,r)=>this._$EO(r,this[r],t)),this._$EC=void 0),this._$Ek()}updated(e){}firstUpdated(e){}};$[ae]=!0,$.elementProperties=new Map,$.elementStyles=[],$.shadowRootOptions={mode:"open"},Pe?.({ReactiveElement:$}),((re=W.reactiveElementVersions)!==null&&re!==void 0?re:W.reactiveElementVersions=[]).push("1.6.3");var ie,G=window,O=G.trustedTypes,Ne=O?O.createPolicy("lit-html",{createHTML:o=>o}):void 0,ce="$lit$",E=`lit$${(Math.random()+"").slice(9)}$`,je="?"+E,vt=`<${je}>`,A=document,L=()=>A.createComment(""),U=o=>o===null||typeof o!="object"&&typeof o!="function",qe=Array.isArray,xt=o=>qe(o)||typeof o?.[Symbol.iterator]=="function",se=`[ +\f\r]`,N=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Le=/-->/g,Ue=/>/g,_=RegExp(`>|${se}(?:([^\\s"'>=/]+)(${se}*=${se}*(?:[^ +\f\r"'\`<>=]|("|')|))|$)`,"g"),He=/'/g,Be=/"/g,Ve=/^(?:script|style|textarea|title)$/i,Fe=o=>(e,...t)=>({_$litType$:o,strings:e,values:t}),c=Fe(1),Pt=Fe(2),C=Symbol.for("lit-noChange"),g=Symbol.for("lit-nothing"),De=new WeakMap,S=A.createTreeWalker(A,129,null,!1);function We(o,e){if(!Array.isArray(o)||!o.hasOwnProperty("raw"))throw Error("invalid template strings array");return Ne!==void 0?Ne.createHTML(e):e}var bt=(o,e)=>{let t=o.length-1,r=[],n,a=e===2?"":"",i=N;for(let h=0;h"?(i=n??N,m=-1):d[1]===void 0?m=-2:(m=i.lastIndex-d[2].length,l=d[1],i=d[3]===void 0?_:d[3]==='"'?Be:He):i===Be||i===He?i=_:i===Le||i===Ue?i=N:(i=_,n=void 0);let f=i===_&&o[h+1].startsWith("/>")?" ":"";a+=i===N?s+vt:m>=0?(r.push(l),s.slice(0,m)+ce+s.slice(m)+E+f):s+E+(m===-2?(r.push(void 0),h):f)}return[We(o,a+(o[t]||"")+(e===2?"":"")),r]},H=class o{constructor({strings:e,_$litType$:t},r){let n;this.parts=[];let a=0,i=0,h=e.length-1,s=this.parts,[l,d]=bt(e,t);if(this.el=o.createElement(l,r),S.currentNode=this.el.content,t===2){let m=this.el.content,p=m.firstChild;p.remove(),m.append(...p.childNodes)}for(;(n=S.nextNode())!==null&&s.length0){n.textContent=O?O.emptyScript:"";for(let f=0;f2||r[0]!==""||r[1]!==""?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=g}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(e,t=this,r,n){let a=this.strings,i=!1;if(a===void 0)e=P(this,e,t,0),i=!U(e)||e!==this._$AH&&e!==C,i&&(this._$AH=e);else{let h=e,s,l;for(e=a[0],s=0;s{var r,n;let a=(r=t?.renderBefore)!==null&&r!==void 0?r:e,i=a._$litPart$;if(i===void 0){let h=(n=t?.renderBefore)!==null&&n!==void 0?n:null;a._$litPart$=i=new B(e.insertBefore(L(),h),h,void 0,t??{})}return i._$AI(o),i};var K=window,Y=K.ShadowRoot&&(K.ShadyCSS===void 0||K.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,ge=Symbol(),Ke=new WeakMap,D=class{constructor(e,t,r){if(this._$cssResult$=!0,r!==ge)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o,t=this.t;if(Y&&e===void 0){let r=t!==void 0&&t.length===1;r&&(e=Ke.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),r&&Ke.set(t,e))}return e}toString(){return this.cssText}},y=o=>new D(typeof o=="string"?o:o+"",void 0,ge),k=(o,...e)=>{let t=o.length===1?o[0]:e.reduce((r,n,a)=>r+(i=>{if(i._$cssResult$===!0)return i.cssText;if(typeof i=="number")return i;throw Error("Value passed to 'css' function must be a 'css' function result: "+i+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(n)+o[a+1],o[0]);return new D(t,o,ge)},ue=(o,e)=>{Y?o.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet):e.forEach(t=>{let r=document.createElement("style"),n=K.litNonce;n!==void 0&&r.setAttribute("nonce",n),r.textContent=t.cssText,o.appendChild(r)})},J=Y?o=>o:o=>o instanceof CSSStyleSheet?(e=>{let t="";for(let r of e.cssRules)t+=r.cssText;return y(t)})(o):o;var fe,Q=window,Ye=Q.trustedTypes,wt=Ye?Ye.emptyScript:"",Je=Q.reactiveElementPolyfillSupport,xe={toAttribute(o,e){switch(e){case Boolean:o=o?wt:null;break;case Object:case Array:o=o==null?o:JSON.stringify(o)}return o},fromAttribute(o,e){let t=o;switch(e){case Boolean:t=o!==null;break;case Number:t=o===null?null:Number(o);break;case Object:case Array:try{t=JSON.parse(o)}catch{t=null}}return t}},Qe=(o,e)=>e!==o&&(e==e||o==o),ve={attribute:!0,type:String,converter:xe,reflect:!1,hasChanged:Qe},be="finalized",w=class extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this._$Eu()}static addInitializer(e){var t;this.finalize(),((t=this.h)!==null&&t!==void 0?t:this.h=[]).push(e)}static get observedAttributes(){this.finalize();let e=[];return this.elementProperties.forEach((t,r)=>{let n=this._$Ep(r,t);n!==void 0&&(this._$Ev.set(n,r),e.push(n))}),e}static createProperty(e,t=ve){if(t.state&&(t.attribute=!1),this.finalize(),this.elementProperties.set(e,t),!t.noAccessor&&!this.prototype.hasOwnProperty(e)){let r=typeof e=="symbol"?Symbol():"__"+e,n=this.getPropertyDescriptor(e,r,t);n!==void 0&&Object.defineProperty(this.prototype,e,n)}}static getPropertyDescriptor(e,t,r){return{get(){return this[t]},set(n){let a=this[e];this[t]=n,this.requestUpdate(e,a,r)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)||ve}static finalize(){if(this.hasOwnProperty(be))return!1;this[be]=!0;let e=Object.getPrototypeOf(this);if(e.finalize(),e.h!==void 0&&(this.h=[...e.h]),this.elementProperties=new Map(e.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){let t=this.properties,r=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(let n of r)this.createProperty(n,t[n])}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(e){let t=[];if(Array.isArray(e)){let r=new Set(e.flat(1/0).reverse());for(let n of r)t.unshift(J(n))}else e!==void 0&&t.push(J(e));return t}static _$Ep(e,t){let r=t.attribute;return r===!1?void 0:typeof r=="string"?r:typeof e=="string"?e.toLowerCase():void 0}_$Eu(){var e;this._$E_=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$Eg(),this.requestUpdate(),(e=this.constructor.h)===null||e===void 0||e.forEach(t=>t(this))}addController(e){var t,r;((t=this._$ES)!==null&&t!==void 0?t:this._$ES=[]).push(e),this.renderRoot!==void 0&&this.isConnected&&((r=e.hostConnected)===null||r===void 0||r.call(e))}removeController(e){var t;(t=this._$ES)===null||t===void 0||t.splice(this._$ES.indexOf(e)>>>0,1)}_$Eg(){this.constructor.elementProperties.forEach((e,t)=>{this.hasOwnProperty(t)&&(this._$Ei.set(t,this[t]),delete this[t])})}createRenderRoot(){var e;let t=(e=this.shadowRoot)!==null&&e!==void 0?e:this.attachShadow(this.constructor.shadowRootOptions);return ue(t,this.constructor.elementStyles),t}connectedCallback(){var e;this.renderRoot===void 0&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(e=this._$ES)===null||e===void 0||e.forEach(t=>{var r;return(r=t.hostConnected)===null||r===void 0?void 0:r.call(t)})}enableUpdating(e){}disconnectedCallback(){var e;(e=this._$ES)===null||e===void 0||e.forEach(t=>{var r;return(r=t.hostDisconnected)===null||r===void 0?void 0:r.call(t)})}attributeChangedCallback(e,t,r){this._$AK(e,r)}_$EO(e,t,r=ve){var n;let a=this.constructor._$Ep(e,r);if(a!==void 0&&r.reflect===!0){let i=(((n=r.converter)===null||n===void 0?void 0:n.toAttribute)!==void 0?r.converter:xe).toAttribute(t,r.type);this._$El=e,i==null?this.removeAttribute(a):this.setAttribute(a,i),this._$El=null}}_$AK(e,t){var r;let n=this.constructor,a=n._$Ev.get(e);if(a!==void 0&&this._$El!==a){let i=n.getPropertyOptions(a),h=typeof i.converter=="function"?{fromAttribute:i.converter}:((r=i.converter)===null||r===void 0?void 0:r.fromAttribute)!==void 0?i.converter:xe;this._$El=a,this[a]=h.fromAttribute(t,i.type),this._$El=null}}requestUpdate(e,t,r){let n=!0;e!==void 0&&(((r=r||this.constructor.getPropertyOptions(e)).hasChanged||Qe)(this[e],t)?(this._$AL.has(e)||this._$AL.set(e,t),r.reflect===!0&&this._$El!==e&&(this._$EC===void 0&&(this._$EC=new Map),this._$EC.set(e,r))):n=!1),!this.isUpdatePending&&n&&(this._$E_=this._$Ej())}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_}catch(t){Promise.reject(t)}let e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var e;if(!this.isUpdatePending)return;this.hasUpdated,this._$Ei&&(this._$Ei.forEach((n,a)=>this[a]=n),this._$Ei=void 0);let t=!1,r=this._$AL;try{t=this.shouldUpdate(r),t?(this.willUpdate(r),(e=this._$ES)===null||e===void 0||e.forEach(n=>{var a;return(a=n.hostUpdate)===null||a===void 0?void 0:a.call(n)}),this.update(r)):this._$Ek()}catch(n){throw t=!1,this._$Ek(),n}t&&this._$AE(r)}willUpdate(e){}_$AE(e){var t;(t=this._$ES)===null||t===void 0||t.forEach(r=>{var n;return(n=r.hostUpdated)===null||n===void 0?void 0:n.call(r)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(e){return!0}update(e){this._$EC!==void 0&&(this._$EC.forEach((t,r)=>this._$EO(r,this[r],t)),this._$EC=void 0),this._$Ek()}updated(e){}firstUpdated(e){}};w[be]=!0,w.elementProperties=new Map,w.elementStyles=[],w.shadowRootOptions={mode:"open"},Je?.({ReactiveElement:w}),((fe=Q.reactiveElementVersions)!==null&&fe!==void 0?fe:Q.reactiveElementVersions=[]).push("1.6.3");var ye,we;var b=class extends w{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){var e,t;let r=super.createRenderRoot();return(e=(t=this.renderOptions).renderBefore)!==null&&e!==void 0||(t.renderBefore=r.firstChild),r}update(e){let t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this._$Do=Ge(t,this.renderRoot,this.renderOptions)}connectedCallback(){var e;super.connectedCallback(),(e=this._$Do)===null||e===void 0||e.setConnected(!0)}disconnectedCallback(){var e;super.disconnectedCallback(),(e=this._$Do)===null||e===void 0||e.setConnected(!1)}render(){return C}};b.finalized=!0,b._$litElement$=!0,(ye=globalThis.litElementHydrateSupport)===null||ye===void 0||ye.call(globalThis,{LitElement:b});var Ze=globalThis.litElementPolyfillSupport;Ze?.({LitElement:b});((we=globalThis.litElementVersions)!==null&&we!==void 0?we:globalThis.litElementVersions=[]).push("3.3.3");var T="(max-width: 767px)",Z="(max-width: 1199px)",v="(min-width: 768px)",u="(min-width: 1200px)",x="(min-width: 1600px)";var Xe=k` :host { position: relative; display: flex; @@ -308,7 +308,7 @@ var I=window,q=I.ShadowRoot&&(I.ShadyCSS===void 0||I.ShadyCSS.nativeShadow)&&"ad height: var(--consonant-merch-card-mini-compare-top-section-height); } - @media screen and ${y(Q)} { + @media screen and ${y(Z)} { [class*'-merch-cards'] :host([variant='mini-compare-chart']) footer { flex-direction: column; align-items: stretch; @@ -374,9 +374,9 @@ var I=window,q=I.ShadowRoot&&(I.ShadyCSS===void 0||I.ShadyCSS.nativeShadow)&&"ad :host([variant='segment']) ::slotted([slot='heading-xs']) { max-width: var(--consonant-merch-card-heading-xs-max-width, 100%); } -`,Ze=()=>{let o=[k` +`,et=()=>{let o=[k` /* Tablet */ - @media screen and ${y(f)} { + @media screen and ${y(v)} { :host([size='wide']), :host([size='super-wide']) { grid-column: span 3; @@ -393,12 +393,12 @@ var I=window,q=I.ShadowRoot&&(I.ShadyCSS===void 0||I.ShadyCSS.nativeShadow)&&"ad } `];return o.push(k` /* Large desktop */ - @media screen and ${y(v)} { + @media screen and ${y(x)} { :host([size='super-wide']) { grid-column: span 4; } } - `),o};var[Xe,et,tt,rt,nt,er]=["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Enter","Tab"];var ot=document.createElement("style");ot.innerHTML=` + `),o};var[tt,rt,nt,ot,at,er]=["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Enter","Tab"];var it=document.createElement("style");it.innerHTML=` :root { --consonant-merch-card-detail-font-size: 12px; --consonant-merch-card-detail-font-weight: 500; @@ -667,7 +667,7 @@ merch-card [slot='callout-content'] > div > div { merch-card [slot='callout-content'] > div > div > div { display: inline-block; text-align: left; - font: normal normal normal var(--consonant-merch-card-callout-font-size)/var(--consonant-merch-card-callout-line-height) Adobe Clean; + font: normal normal normal var(--consonant-merch-card-callout-font-size)/var(--consonant-merch-card-callout-line-height) var(--body-font-family, 'Adobe Clean'); letter-spacing: var(--consonant-merch-card-callout-letter-spacing); color: var(--consonant-merch-card-callout-font-color); } @@ -1025,7 +1025,7 @@ div[slot='bg-image'] img { /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { :root { --consonant-merch-card-catalog-width: 302px; --consonant-merch-card-plans-width: 302px; @@ -1062,7 +1062,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.plans, .three-merch-cards.plans, .four-merch-cards.plans { @@ -1079,7 +1079,7 @@ div[slot='bg-image'] img { } /* Large desktop */ - @media screen and ${v} { + @media screen and ${x} { .four-merch-cards.plans { grid-template-columns: repeat(4, var(--consonant-merch-card-plans-width)); } @@ -1095,7 +1095,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.catalog, .three-merch-cards.catalog, .four-merch-cards.catalog { @@ -1112,7 +1112,7 @@ div[slot='bg-image'] img { } /* Large desktop */ - @media screen and ${v} { + @media screen and ${x} { .four-merch-cards.catalog { grid-template-columns: repeat(4, var(--consonant-merch-card-catalog-width)); } @@ -1128,7 +1128,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.special-offers, .three-merch-cards.special-offers, .four-merch-cards.special-offers { @@ -1144,7 +1144,7 @@ div[slot='bg-image'] img { } } -@media screen and ${v} { +@media screen and ${x} { .four-merch-cards.special-offers { grid-template-columns: repeat(4, minmax(300px, var(--consonant-merch-card-special-offers-width))); } @@ -1160,7 +1160,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.image, .three-merch-cards.image, .four-merch-cards.image { @@ -1177,7 +1177,7 @@ div[slot='bg-image'] img { } /* Large desktop */ - @media screen and ${v} { + @media screen and ${x} { .four-merch-cards.image { grid-template-columns: repeat(4, var(--consonant-merch-card-image-width)); } @@ -1193,7 +1193,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.segment, .three-merch-cards.segment, .four-merch-cards.segment { @@ -1222,7 +1222,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.product, .three-merch-cards.product, .four-merch-cards.product { @@ -1239,7 +1239,7 @@ div[slot='bg-image'] img { } /* Large desktop */ - @media screen and ${v} { + @media screen and ${x} { .four-merch-cards.product { grid-template-columns: repeat(4, var(--consonant-merch-card-product-width)); } @@ -1253,7 +1253,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .one-merch-card.twp, .two-merch-cards.twp { grid-template-columns: repeat(2, var(--consonant-merch-card-twp-width)); @@ -1275,7 +1275,7 @@ div[slot='bg-image'] img { } /* Large desktop */ - @media screen and ${v} { + @media screen and ${x} { .one-merch-card.twp .two-merch-cards.twp { grid-template-columns: repeat(2, var(--consonant-merch-card-twp-width)); @@ -1303,7 +1303,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.inline-heading, .three-merch-cards.inline-heading, .four-merch-cards.inline-heading { @@ -1320,7 +1320,7 @@ div[slot='bg-image'] img { } /* Large desktop */ - @media screen and ${v} { + @media screen and ${x} { .four-merch-cards.inline-heading { grid-template-columns: repeat(4, var(--consonant-merch-card-inline-heading-width)); } @@ -1335,7 +1335,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.ccd-action, .three-merch-cards.ccd-action, .four-merch-cards.ccd-action { @@ -1352,7 +1352,7 @@ div[slot='bg-image'] img { } /* Large desktop */ - @media screen and ${v} { + @media screen and ${x} { .four-merch-cards.ccd-action { grid-template-columns: repeat(4, var(--consonant-merch-card-ccd-action-width)); } @@ -1379,7 +1379,7 @@ div[slot='bg-image'] img { } } -@media screen and ${Q} { +@media screen and ${Z} { .three-merch-cards.mini-compare-chart merch-card [slot="footer"] a, .four-merch-cards.mini-compare-chart merch-card [slot="footer"] a { flex: 1; @@ -1387,7 +1387,7 @@ div[slot='bg-image'] img { } /* Tablet */ -@media screen and ${f} { +@media screen and ${v} { .two-merch-cards.mini-compare-chart { grid-template-columns: repeat(2, minmax(var(--consonant-merch-card-mini-compare-chart-width), var(--consonant-merch-card-mini-compare-chart-wide-width))); gap: var(--consonant-merch-spacing-m); @@ -1417,7 +1417,7 @@ div[slot='bg-image'] img { } } -@media screen and ${v} { +@media screen and ${x} { .four-merch-cards.mini-compare-chart { grid-template-columns: repeat(4, var(--consonant-merch-card-mini-compare-chart-width)); } @@ -1481,20 +1481,20 @@ body.merch-modal { scrollbar-gutter: stable; height: 100vh; } -`;document.head.appendChild(ot);var at="merch-offer-select:ready",it="merch-card:ready",st="merch-card:action-menu-toggle";var we="merch-storage:change",Ee="merch-quantity-selector:change";function ct(o){let e=[];function t(r){r.nodeType===Node.TEXT_NODE?e.push(r):r.childNodes.forEach(t)}return t(o),e}function R(o,e={},t){let r=document.createElement(o);r.innerHTML=t;for(let[n,a]of Object.entries(e))r.setAttribute(n,a);return r}var ht="MERCH-CARD",Et="merch-card",$t=32,$e="mini-compare-chart",lt=o=>`--consonant-merch-card-footer-row-${o}-min-height`,_e=class extends b{static properties={name:{type:String,attribute:"name",reflect:!0},variant:{type:String,reflect:!0},size:{type:String,attribute:"size",reflect:!0},badgeColor:{type:String,attribute:"badge-color"},borderColor:{type:String,attribute:"border-color"},badgeBackgroundColor:{type:String,attribute:"badge-background-color"},badgeText:{type:String,attribute:"badge-text"},actionMenu:{type:Boolean,attribute:"action-menu"},actionMenuContent:{type:String,attribute:"action-menu-content"},customHr:{type:Boolean,attribute:"custom-hr"},detailBg:{type:String,attribute:"detail-bg"},secureLabel:{type:String,attribute:"secure-label"},checkboxLabel:{type:String,attribute:"checkbox-label"},selected:{type:Boolean,attribute:"aria-selected",reflect:!0},storageOption:{type:String,attribute:"storage",reflect:!0},stockOfferOsis:{type:Object,attribute:"stock-offer-osis",converter:{fromAttribute:e=>{let[t,r,n]=e.split(",");return{PUF:t,ABM:r,M2M:n}}}},filters:{type:String,reflect:!0,converter:{fromAttribute:e=>Object.fromEntries(e.split(",").map(t=>{let[r,n,a]=t.split(":"),i=Number(n);return[r,{order:isNaN(i)?void 0:i,size:a}]})),toAttribute:e=>Object.entries(e).map(([t,{order:r,size:n}])=>[t,r,n].filter(a=>a!=null).join(":")).join(",")}},types:{type:String,attribute:"types",reflect:!0},merchOffer:{type:Object}};static styles=[Qe,...Ze()];customerSegment;marketSegment;constructor(){super(),this.filters={},this.types="",this.selected=!1}#e;updated(e){(e.has("badgeBackgroundColor")||e.has("borderColor"))&&(this.style.border=this.computedBorderStyle),this.updateComplete.then(async()=>{let r=Array.from(this.querySelectorAll('span[is="inline-price"][data-wcs-osi]')).filter(n=>!n.closest('[slot="callout-content"]'));await Promise.all(r.map(n=>n.onceSettled())),this.adjustTitleWidth(),this.adjustMiniCompareBodySlots(),this.adjustMiniCompareFooterRows()})}get computedBorderStyle(){return this.variant!=="twp"?`1px solid ${this.borderColor?this.borderColor:this.badgeBackgroundColor}`:""}get evergreen(){return this.classList.contains("intro-pricing")}get stockCheckbox(){return this.checkboxLabel?l`
+ +
+
+ +
+
diff --git a/test/blocks/merch/merch.test.js b/test/blocks/merch/merch.test.js index ba3a4034bd..4a7641f9c2 100644 --- a/test/blocks/merch/merch.test.js +++ b/test/blocks/merch/merch.test.js @@ -22,6 +22,7 @@ import merch, { PRICE_LITERALS_URL, PRICE_TEMPLATE_REGULAR, getMasBase, + appendTabName, } from '../../../libs/blocks/merch/merch.js'; import { mockFetch, unmockFetch, readMockText } from './mocks/fetch.js'; @@ -63,6 +64,14 @@ const CHECKOUT_LINK_CONFIGS = { BUY_NOW_PATH: '', LOCALE: '', }, + { + PRODUCT_FAMILY: 'testPaCode', + DOWNLOAD_TEXT: 'paCode', + }, + { + PRODUCT_FAMILY: 'testProductCode', + DOWNLOAD_TEXT: 'productCode', + }, ], }; @@ -488,8 +497,7 @@ describe('Merch Block', () => { fetchCheckoutLinkConfigs.promise = undefined; setCheckoutLinkConfigs(null); const mappings = await fetchCheckoutLinkConfigs('http://localhost:2000/libs'); - expect(mappings).to.be.undefined; - setCheckoutLinkConfigs(CHECKOUT_LINK_CONFIGS); + expect(mappings.data).to.empty; fetchCheckoutLinkConfigs.promise = undefined; }); @@ -521,27 +529,6 @@ describe('Merch Block', () => { expect(url).to.equal('https://creativecloud.adobe.com/apps/download'); }); - it('getModalAction: returns undefined if checkout-link config is not found', async () => { - fetchCheckoutLinkConfigs.promise = undefined; - setCheckoutLinkConfigs(CHECKOUT_LINK_CONFIGS); - const action = await getModalAction([{ productArrangement: { productFamily: 'XZY' } }], { modal: true }); - expect(action).to.be.undefined; - }); - - it('getModalAction: returns undefined if modal path is cancelled', async () => { - setConfig({ - ...config, - pathname: '/fr/test.html', - locales: { fr: { ietf: 'fr-FR' } }, - prodDomains: PROD_DOMAINS, - placeholders: { download: 'Télécharger' }, - }); - fetchCheckoutLinkConfigs.promise = undefined; - setCheckoutLinkConfigs(CHECKOUT_LINK_CONFIGS); - const action = await getModalAction([{ productArrangement: { productFamily: 'PHOTOSHOP' } }], { modal: true }); - expect(action).to.be.undefined; - }); - it('getCheckoutAction: handles errors gracefully', async () => { const imsSignedInPromise = new Promise((resolve, reject) => { setTimeout(() => { @@ -632,6 +619,122 @@ describe('Merch Block', () => { expect(modal).to.exist; document.querySelector('.modal-curtain').click(); }); + + it('renders TWP modal with preselected plan', async () => { + mockIms(); + const meta = document.createElement('meta'); + meta.setAttribute('name', 'preselect-plan'); + meta.setAttribute('content', 'edu'); + document.getElementsByTagName('head')[0].appendChild(meta); + const el = document.querySelector('.merch.cta.twp.preselected-plan'); + const cta = await merch(el); + const { nodeName } = await cta.onceSettled(); + expect(nodeName).to.equal('A'); + cta.click(); + await delay(100); + expect(document.querySelector('iframe').src).to.equal('https://www.adobe.com/mini-plans/illustrator.html?mid=ft&web=1&plan=edu'); + document.querySelector('meta[name="preselect-plan"]').remove(); + }); + + it('getCheckoutLinkConfig: finds using paCode', async () => { + let checkoutLinkConfig = await getCheckoutLinkConfig(undefined, undefined, 'testPaCode'); + expect(checkoutLinkConfig.DOWNLOAD_TEXT).to.equal('paCode'); + checkoutLinkConfig = await getCheckoutLinkConfig('', '', 'testPaCode'); + expect(checkoutLinkConfig.DOWNLOAD_TEXT).to.equal('paCode'); + }); + + it('getCheckoutLinkConfig: finds using productCode', async () => { + let checkoutLinkConfig = await getCheckoutLinkConfig(undefined, 'testProductCode', undefined); + expect(checkoutLinkConfig.DOWNLOAD_TEXT).to.equal('productCode'); + checkoutLinkConfig = await getCheckoutLinkConfig('', 'testProductCode', ''); + expect(checkoutLinkConfig.DOWNLOAD_TEXT).to.equal('productCode'); + }); + + it('getModalAction: returns undefined if modal path is cancelled', async () => { + setConfig({ + ...config, + pathname: '/fr/test.html', + locales: { fr: { ietf: 'fr-FR' } }, + prodDomains: PROD_DOMAINS, + placeholders: { download: 'Télécharger' }, + }); + fetchCheckoutLinkConfigs.promise = undefined; + setCheckoutLinkConfigs(CHECKOUT_LINK_CONFIGS); + const action = await getModalAction([{ productArrangement: { productFamily: 'PHOTOSHOP' } }], { modal: true }); + expect(action).to.be.undefined; + }); + + it('getModalAction: returns undefined if checkout-link config is not found', async () => { + fetchCheckoutLinkConfigs.promise = undefined; + setCheckoutLinkConfigs(CHECKOUT_LINK_CONFIGS); + const action = await getModalAction([{ productArrangement: { productFamily: 'XZY' } }], { modal: true }); + expect(action).to.be.undefined; + }); + + const MODAL_URLS = [ + { + url: 'https://www.adobe.com/mini-plans/illustrator1.html?mid=ft&web=1', + plan: 'edu', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator1.html?mid=ft&web=1&plan=edu', + }, + { + url: 'https://www.adobe.com/mini-plans/illustrator2.html?mid=ft&web=1&plan=abc', + plan: 'edu', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator2.html?mid=ft&web=1&plan=edu', + }, + { + url: 'https://www.adobe.com/mini-plans/illustrator3.html?mid=ft&web=1#thisishash', + plan: 'edu', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator3.html?mid=ft&web=1&plan=edu#thisishash', + }, + { + url: 'https://www.adobe.com/mini-plans/illustrator4.html', + plan: 'edu', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator4.html?plan=edu', + }, + { + url: 'https://www.adobe.com/mini-plans/illustrator5.html#thisishash', + plan: 'edu', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator5.html?plan=edu#thisishash', + }, + { + url: 'https://www.adobe.com/mini-plans/illustrator6.html?mid=ft&web=1', + plan: 'team', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator6.html?mid=ft&web=1&plan=team', + }, + { + url: 'https://www.adobe.com/mini-plans/illustrator7.html?mid=ft&web=1', + plan: '', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator7.html?mid=ft&web=1', + }, + { + url: 'https://www.adobe.com/mini-plans/illustrator8.selector.html/resource?mid=ft&web=1#thisishash', + plan: 'team', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator8.selector.html/resource?mid=ft&web=1&plan=team#thisishash', + }, + { + url: 'https://www.adobe.com/mini-plans/illustrator9.sel1.sel2.html/resource#thisishash', + plan: 'team', + urlWithPlan: 'https://www.adobe.com/mini-plans/illustrator9.sel1.sel2.html/resource?plan=team#thisishash', + }, + { + url: 'www.adobe.com/mini-plans/illustrator10.html?mid=ft&web=1', // invalid URL, protocol is missing + plan: 'edu', + urlWithPlan: 'www.adobe.com/mini-plans/illustrator10.html?mid=ft&web=1', + }, + ]; + MODAL_URLS.forEach((modalUrl) => { + it(`appends preselected plan ${modalUrl.plan} to modal URL ${modalUrl.url}`, async () => { + const meta = document.createElement('meta'); + meta.setAttribute('name', 'preselect-plan'); + meta.setAttribute('content', modalUrl.plan); + document.getElementsByTagName('head')[0].appendChild(meta); + + const resultUrl = appendTabName(modalUrl.url); + expect(resultUrl).to.equal(modalUrl.urlWithPlan); + document.querySelector('meta[name="preselect-plan"]').remove(); + }); + }); }); describe('checkout link with optional params', async () => { diff --git a/test/blocks/merch/mocks/body.html b/test/blocks/merch/mocks/body.html index 61f69a86fe..5473a3f899 100644 --- a/test/blocks/merch/mocks/body.html +++ b/test/blocks/merch/mocks/body.html @@ -128,6 +128,10 @@

CTAs

href="/tools/ost?osi=illustrator-base-abm-mult-cci&type=checkoutUrl&modal=true&entitlement=true">CTA Buy Now

+

TWP modal with preselected plan: CTA Free Trial +

+

Promo prices inside a fragment

Price without discount: Heading M 24/30

+
+
+
+
#000000
+
+
+
+

Get early-access pricing starting at AI Assistant for Acrobat when you add AI Assistant to Reader, Standard, or Pro.

+

CTA

+
+
+
+
diff --git a/test/features/personalization/actions.test.js b/test/features/personalization/actions.test.js index e9bce4b9c0..fe9e935202 100644 --- a/test/features/personalization/actions.test.js +++ b/test/features/personalization/actions.test.js @@ -3,8 +3,8 @@ import { readFile } from '@web/test-runner-commands'; import { stub } from 'sinon'; import { getConfig, loadBlock } from '../../../libs/utils/utils.js'; import initFragments from '../../../libs/blocks/fragment/fragment.js'; -import { applyPers, handleFragmentCommand } from '../../../libs/features/personalization/personalization.js'; -import spoofParams from './spoofParams.js'; +import { init, handleFragmentCommand } from '../../../libs/features/personalization/personalization.js'; +import mepSettings from './mepSettings.js'; document.head.innerHTML = await readFile({ path: './mocks/metadata.html' }); document.body.innerHTML = await readFile({ path: './mocks/personalization.html' }); @@ -35,10 +35,12 @@ describe('replace action', () => { expect(document.querySelector('.how-to')).to.not.be.null; const parentEl = document.querySelector('#features-of-milo-experimentation-platform')?.parentElement; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(document.querySelector('#features-of-milo-experimentation-platform')).to.be.null; - expect(parentEl.firstElementChild.firstElementChild.href) + const el = parentEl.firstElementChild.firstElementChild; + expect(el.href) .to.equal('http://localhost:2000/test/features/personalization/mocks/fragments/milo-replace-content-chrome-howto-h2'); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); // .how-to should not be changed as it is targeted to firefox expect(document.querySelector('.how-to')).to.not.be.null; }); @@ -52,7 +54,8 @@ describe('replace action', () => { expect(document.querySelector('a[href="/fragments/replaceme"]')).to.exist; expect(document.querySelector('a[href="/fragments/inline-replaceme#_inline"]')).to.exist; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); const fragmentResp = await readFile({ path: './mocks/fragments/fragmentReplaced.plain.html' }); const inlineFragmentResp = await readFile({ path: './mocks/fragments/inlineFragReplaced.plain.html' }); @@ -83,7 +86,8 @@ describe('insertAfter action', async () => { expect(document.querySelector('a[href="/fragments/insertafter"]')).to.be.null; expect(document.querySelector('a[href="/fragments/insertafterfragment"]')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); let fragment = document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertafter"]'); expect(fragment).to.not.be.null; @@ -105,7 +109,8 @@ describe('insertBefore action', async () => { setFetchResponse(manifestJson); expect(document.querySelector('a[href="/fragments/insertbefore"]')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); let fragment = document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertbefore"]'); expect(fragment).to.not.be.null; @@ -127,7 +132,8 @@ describe('prependToSection action', async () => { setFetchResponse(manifestJson); expect(document.querySelector('a[href="/test/features/personalization/mocks/fragments/prependToSection"]')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); const fragment = document.querySelector('main > div:nth-child(2) > div:first-child a[href="/test/features/personalization/mocks/fragments/prependToSection"]'); expect(fragment).to.not.be.null; @@ -143,7 +149,8 @@ describe('appendToSection action', async () => { setFetchResponse(manifestJson); expect(document.querySelector('a[href="/test/features/personalization/mocks/fragments/appendToSection"]')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); const fragment = document.querySelector('main > div:nth-child(2) > div:last-child a[href="/test/features/personalization/mocks/fragments/appendToSection"]'); expect(fragment).to.not.be.null; @@ -155,7 +162,9 @@ describe('remove action', () => { let manifestJson = await readFile({ path: './mocks/actions/manifestRemove.json' }); manifestJson = JSON.parse(manifestJson); setFetchResponse(manifestJson); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + mepSettings.mepButton = 'off'; + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); }); it('remove should remove content', async () => { expect(document.querySelector('.z-pattern')).to.be.null; @@ -168,7 +177,6 @@ describe('remove action', () => { }); it('removeContent should tag but not remove content in preview', async () => { - spoofParams({ mep: '' }); document.body.innerHTML = await readFile({ path: './mocks/personalization.html' }); let manifestJson = await readFile({ path: './mocks/actions/manifestRemove.json' }); @@ -177,7 +185,10 @@ describe('remove action', () => { setTimeout(async () => { expect(document.querySelector('.z-pattern')).to.not.be.null; - await applyPers([{ manifestPath: '/mocks/manifestRemove.json' }]); + mepSettings.mepButton = false; + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); + expect(document.querySelector('.z-pattern')).to.not.be.null; expect(document.querySelector('.z-pattern').dataset.removedManifestId).to.not.be.null; @@ -195,7 +206,9 @@ describe('useBlockCode action', async () => { manifestJson = JSON.parse(manifestJson); setFetchResponse(manifestJson); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); + expect(getConfig().mep.experiments[0].selectedVariant.useblockcode[0] + .targetManifestId).to.equal(false); expect(getConfig().mep.blocks).to.deep.equal({ promo: 'http://localhost:2000/test/features/personalization/mocks/promo' }); const promoBlock = document.querySelector('.promo'); @@ -209,7 +222,9 @@ describe('useBlockCode action', async () => { manifestJson = JSON.parse(manifestJson); setFetchResponse(manifestJson); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); + expect(getConfig().mep.experiments[0].selectedVariant.useblockcode[0] + .targetManifestId).to.equal(false); expect(getConfig().mep.blocks).to.deep.equal({ myblock: 'http://localhost:2000/test/features/personalization/mocks/myblock' }); const myBlock = document.querySelector('.myblock'); @@ -224,7 +239,8 @@ describe('custom actions', async () => { let manifestJson = await readFile({ path: './mocks/actions/manifestReplace.json' }); manifestJson = JSON.parse(manifestJson); setFetchResponse(manifestJson); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal(false); expect(getConfig().mep.custom).to.be.undefined; }); @@ -233,31 +249,34 @@ describe('custom actions', async () => { manifestJson = JSON.parse(manifestJson); setFetchResponse(manifestJson); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); - console.log(getConfig().mep.inBlock); + await init(mepSettings); expect(getConfig().mep.inBlock).to.deep.equal({ 'my-block': { commands: [{ action: 'replace', target: '/fragments/fragmentreplaced', manifestId: false, + targetManifestId: false, }, { action: 'replace', target: '/fragments/new-large-menu', manifestId: false, selector: '.large-menu', + targetManifestId: false, }], fragments: { '/fragments/sub-menu': { action: 'replace', target: '/fragments/even-more-new-sub-menu', manifestId: false, + targetManifestId: false, }, '/fragments/new-sub-menu': { action: 'replace', target: '/fragments/even-more-new-sub-menu', manifestId: false, + targetManifestId: false, }, }, }, @@ -280,7 +299,7 @@ describe('custom actions', async () => { expect(document.querySelector(lcpLink)).not.to.exist; expect(document.querySelector(notLcpLink)).not.to.exist; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(document.querySelector(lcpLink)).to.exist; expect(document.querySelector(notLcpLink)).not.to.exist; diff --git a/test/features/personalization/actionsTargetManifestId.test.js b/test/features/personalization/actionsTargetManifestId.test.js new file mode 100644 index 0000000000..7345cabb8b --- /dev/null +++ b/test/features/personalization/actionsTargetManifestId.test.js @@ -0,0 +1,164 @@ +import { expect } from '@esm-bundle/chai'; +import { readFile } from '@web/test-runner-commands'; +import { stub } from 'sinon'; +import { getConfig } from '../../../libs/utils/utils.js'; +import initFragments from '../../../libs/blocks/fragment/fragment.js'; +import { init, handleFragmentCommand, addMepAnalytics } from '../../../libs/features/personalization/personalization.js'; +import mepSettings from './mepTargetSettings.js'; + +document.head.innerHTML = await readFile({ path: './mocks/metadata.html' }); +document.body.innerHTML = await readFile({ path: './mocks/personalization.html' }); + +// Add custom keys so tests doesn't rely on real data +const config = getConfig(); +config.env = { name: 'prod' }; + +const getFetchPromise = (data, type = 'json') => new Promise((resolve) => { + resolve({ + ok: true, + [type]: () => data, + }); +}); + +const setFetchResponse = (data, type = 'json') => { + window.fetch = stub().returns(getFetchPromise(data, type)); +}; + +// Note that the manifestPath doesn't matter as we stub the fetch +describe('replace action', () => { + it('with a CSS Selector, it should replace an element with a fragment', async () => { + let manifestJson = await readFile({ path: './mocks/actions/manifestReplace.json' }); + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal('manifest'); + const el = document.querySelector('a[href="/test/features/personalization/mocks/fragments/milo-replace-content-chrome-howto-h2"]'); + expect(el.dataset.adobeTargetTestid).to.equal('manifest'); + }); + + it('with a fragment selector, it should replace a fragment in the document', async () => { + document.body.innerHTML = await readFile({ path: './mocks/personalization.html' }); + + let manifestJson = await readFile({ path: './mocks/actions/manifestReplace.json' }); + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + + await init(mepSettings); + expect(getConfig().mep.fragments['/fragments/replaceme'].targetManifestId).to.equal('manifest'); + const el = document.querySelector('a[href="/test/features/personalization/mocks/fragments/milo-replace-content-chrome-howto-h2"]'); + expect(el.dataset.adobeTargetTestid).to.equal('manifest'); + const fragmentResp = await readFile({ path: './mocks/fragments/fragmentReplaced.plain.html' }); + const inlineFragmentResp = await readFile({ path: './mocks/fragments/inlineFragReplaced.plain.html' }); + window.fetch = stub(); + window.fetch.withArgs('http://localhost:2000/test/features/personalization/mocks/fragments/fragmentReplaced.plain.html') + .returns(getFetchPromise(fragmentResp, 'text')); + window.fetch.withArgs('http://localhost:2000/test/features/personalization/mocks/fragments/inlineFragReplaced.plain.html') + .returns(getFetchPromise(inlineFragmentResp, 'text')); + const replacemeFrag = document.querySelector('a[href="/fragments/replaceme"]'); + await initFragments(replacemeFrag); + expect(document.querySelector('a[href="/fragments/replaceme"]')).to.be.null; + expect(document.querySelector('div[data-path="/test/features/personalization/mocks/fragments/fragmentReplaced"]')).to.exist; + + const inlineReplacemeFrag = document.querySelector('a[href="/fragments/inline-replaceme#_inline"]'); + await initFragments(inlineReplacemeFrag); + expect(document.querySelector('a[href="/fragments/inline-replaceme#_inline"]')).to.be.null; + expect(document.querySelector('.inlinefragmentreplaced')).to.exist; + }); +}); + +describe('insertAfter action', async () => { + it('insertContentAfter should add fragment after target content and fragment', async () => { + let manifestJson = await readFile({ path: './mocks/actions/manifestInsertAfter.json' }); + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal('manifest'); + const el = document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertafter"]'); + expect(el.dataset.adobeTargetTestid).to.equal('manifest'); + }); +}); + +describe('insertBefore action', async () => { + it('insertContentBefore should add fragment before target content and fragment', async () => { + let manifestJson = await readFile({ path: './mocks/actions/manifestInsertBefore.json' }); + + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal('manifest'); + const el = document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertbefore"]'); + expect(el.dataset.adobeTargetTestid).to.equal('manifest'); + }); +}); + +describe('prependToSection action', async () => { + it('appendToSection should add fragment to beginning of section', async () => { + let manifestJson = await readFile({ path: './mocks/actions/manifestPrependToSection.json' }); + + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + + expect(document.querySelector('a[href="/test/features/personalization/mocks/fragments/prependToSection"]')).to.be.null; + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal('manifest'); + const el = document.querySelector('a[href="/test/features/personalization/mocks/fragments/prependToSection"]'); + expect(el.dataset.adobeTargetTestid).to.equal('manifest'); + }); +}); + +describe('appendToSection action', async () => { + it('appendToSection should add fragment to end of section', async () => { + config.mep = { handleFragmentCommand }; + let manifestJson = await readFile({ path: './mocks/actions/manifestAppendToSection.json' }); + + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + + await init(mepSettings); + expect(getConfig().mep.commands[0].targetManifestId).to.equal('manifest'); + const el = document.querySelector('a[href="/test/features/personalization/mocks/fragments/appendToSection"]'); + expect(el.dataset.adobeTargetTestid).to.equal('manifest'); + }); +}); + +describe('useBlockCode action', async () => { + it('useBlockCode should override a current block with the custom block code provided', async () => { + let manifestJson = await readFile({ path: './mocks/actions/manifestUseBlockCode.json' }); + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + + await init(mepSettings); + expect(getConfig().mep.experiments[0].selectedVariant.useblockcode[0].targetManifestId).to.equal('manifest'); + await addMepAnalytics(config); + const el = document.querySelector('.promo'); + expect(el.dataset.adobeTargetTestid).to.equal('manifest'); + }); + + it('useBlockCode should be able to use a new type of block', async () => { + let manifestJson = await readFile({ path: './mocks/actions/manifestUseBlockCode2.json' }); + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + + await init(mepSettings); + expect(getConfig().mep.experiments[0].selectedVariant.useblockcode[0].targetManifestId).to.equal('manifest'); + await addMepAnalytics(config); + const el = document.querySelector('.myblock'); + expect(el.dataset.adobeTargetTestid).to.equal('manifest'); + }); +}); + +describe('custom actions', async () => { + it('should add a custom action configuration', async () => { + let manifestJson = await readFile({ path: './mocks/actions/manifestCustomAction.json' }); + manifestJson = JSON.parse(manifestJson); + setFetchResponse(manifestJson); + + await init(mepSettings); + expect(getConfig().mep.inBlock['my-block'].commands[0].targetManifestId).to.equal('manifest'); + expect(getConfig().mep.inBlock['my-block'].commands[1].targetManifestId).to.equal('manifest'); + expect(getConfig().mep.inBlock['my-block'].fragments['/fragments/sub-menu'].targetManifestId).to.equal('manifest'); + expect(getConfig().mep.inBlock['my-block'].fragments['/fragments/new-sub-menu'].targetManifestId).to.equal('manifest'); + }); +}); diff --git a/test/features/personalization/deprecatedActions.test.js b/test/features/personalization/deprecatedActions.test.js index b6041034ad..30ac2cb931 100644 --- a/test/features/personalization/deprecatedActions.test.js +++ b/test/features/personalization/deprecatedActions.test.js @@ -3,8 +3,9 @@ import { readFile } from '@web/test-runner-commands'; import { stub } from 'sinon'; import { getConfig } from '../../../libs/utils/utils.js'; import initFragments from '../../../libs/blocks/fragment/fragment.js'; -import { applyPers, handleFragmentCommand } from '../../../libs/features/personalization/personalization.js'; +import { init, handleFragmentCommand } from '../../../libs/features/personalization/personalization.js'; import spoofParams from './spoofParams.js'; +import mepSettings from './mepSettings.js'; document.head.innerHTML = await readFile({ path: './mocks/metadata.html' }); document.body.innerHTML = await readFile({ path: './mocks/personalization.html' }); @@ -38,7 +39,7 @@ describe('Functional Test', () => { expect(document.querySelector('.how-to')).to.not.be.null; const parentEl = document.querySelector('#features-of-milo-experimentation-platform')?.parentElement; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(document.querySelector('#features-of-milo-experimentation-platform')).to.be.null; expect(parentEl.firstElementChild.firstElementChild.href) .to.equal('http://localhost:2000/test/features/personalization/mocks/fragments/milo-replace-content-chrome-howto-h2'); @@ -52,7 +53,7 @@ describe('Functional Test', () => { setFetchResponse(manifestJson); expect(document.querySelector('.z-pattern')).to.not.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(document.querySelector('.z-pattern')).to.be.null; }); @@ -62,7 +63,7 @@ describe('Functional Test', () => { setFetchResponse(manifestJson); expect(document.querySelector('a[href="/fragments/insertafter"]')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); const fragment = document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertafter"]'); expect(fragment).to.not.be.null; @@ -77,7 +78,7 @@ describe('Functional Test', () => { setFetchResponse(manifestJson); expect(document.querySelector('a[href="/fragments/insertbefore"]')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); const fragment = document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertbefore"]'); expect(fragment).to.not.be.null; @@ -94,7 +95,7 @@ describe('Functional Test', () => { expect(document.querySelector('a[href="/fragments/replaceme"]')).to.exist; expect(document.querySelector('a[href="/fragments/inline-replaceme#_inline"]')).to.exist; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); const fragmentResp = await readFile({ path: './mocks/fragments/fragmentReplaced.plain.html' }); const inlineFragmentResp = await readFile({ path: './mocks/fragments/inlineFragReplaced.plain.html' }); @@ -126,7 +127,7 @@ describe('Functional Test', () => { setFetchResponse(manifestJson); expect(document.querySelector('.z-pattern')).to.not.be.null; - await applyPers([{ manifestPath: '/mocks/manifestRemove.json' }]); + await init(mepSettings); expect(document.querySelector('.z-pattern')).to.not.be.null; expect(document.querySelector('.z-pattern').dataset.removedManifestId).to.not.be.null; diff --git a/test/features/personalization/mepSettings.js b/test/features/personalization/mepSettings.js new file mode 100644 index 0000000000..d55161f0ae --- /dev/null +++ b/test/features/personalization/mepSettings.js @@ -0,0 +1,10 @@ +const mepSettings = { + mepParam: false, + mepHighlight: false, + mepButton: false, + pzn: '/path/to/manifest.json', + promo: false, + target: false, +}; + +export default mepSettings; diff --git a/test/features/personalization/mepTargetSettings.js b/test/features/personalization/mepTargetSettings.js new file mode 100644 index 0000000000..a5313f2cde --- /dev/null +++ b/test/features/personalization/mepTargetSettings.js @@ -0,0 +1,10 @@ +const mepSettings = { + mepParam: '/path/to/manifest.json--target-var1', + mepHighlight: false, + mepButton: false, + pzn: '/path/to/manifest.json', + promo: false, + target: false, +}; + +export default mepSettings; diff --git a/test/features/personalization/mocks/actions/manifestAppendToSection.json b/test/features/personalization/mocks/actions/manifestAppendToSection.json index 0269996cd6..9bd9bfdf47 100644 --- a/test/features/personalization/mocks/actions/manifestAppendToSection.json +++ b/test/features/personalization/mocks/actions/manifestAppendToSection.json @@ -8,6 +8,7 @@ "selector": "section2", "page filter (optional)": "", "param-newoffer=123": "", + "target-var1": "/test/features/personalization/mocks/fragments/appendToSection", "chrome": "/test/features/personalization/mocks/fragments/appendToSection" } ], diff --git a/test/features/personalization/mocks/actions/manifestCustomAction.json b/test/features/personalization/mocks/actions/manifestCustomAction.json index fafaccbe56..1de7092bbb 100644 --- a/test/features/personalization/mocks/actions/manifestCustomAction.json +++ b/test/features/personalization/mocks/actions/manifestCustomAction.json @@ -9,6 +9,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/fragments/fragmentreplaced", + "target-var1": "/fragments/fragmentreplaced", "firefox": "", "android": "", "ios": "" @@ -19,6 +20,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/fragments/new-large-menu", + "target-var1": "/fragments/new-large-menu", "firefox": "", "android": "", "ios": "" @@ -29,6 +31,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/fragments/new-sub-menu", + "target-var1": "/fragments/new-sub-menu", "firefox": "", "android": "", "ios": "" @@ -38,6 +41,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/fragments/even-more-new-sub-menu", + "target-var1": "/fragments/even-more-new-sub-menu", "firefox": "", "android": "", "ios": "" diff --git a/test/features/personalization/mocks/actions/manifestInsertAfter.json b/test/features/personalization/mocks/actions/manifestInsertAfter.json index d694ec80cc..0e40395cf9 100644 --- a/test/features/personalization/mocks/actions/manifestInsertAfter.json +++ b/test/features/personalization/mocks/actions/manifestInsertAfter.json @@ -9,6 +9,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/fragments/insertafter", + "target-var1": "/test/features/personalization/mocks/fragments/insertafter", "firefox": "", "android": "", "ios": "" @@ -19,6 +20,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/fragments/insertafterfragment", + "target-var1": "/test/features/personalization/mocks/fragments/insertafterfragment", "firefox": "", "android": "", "ios": "" @@ -29,6 +31,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/fragments/insertafterfragment", + "target-var1": "/test/features/personalization/mocks/fragments/insertafterfragment", "firefox": "", "android": "", "ios": "" diff --git a/test/features/personalization/mocks/actions/manifestInsertBefore.json b/test/features/personalization/mocks/actions/manifestInsertBefore.json index e58e39e05c..057cfaacf4 100644 --- a/test/features/personalization/mocks/actions/manifestInsertBefore.json +++ b/test/features/personalization/mocks/actions/manifestInsertBefore.json @@ -9,6 +9,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/fragments/insertbefore", + "target-var1": "/test/features/personalization/mocks/fragments/insertbefore", "firefox": "", "android": "", "ios": "" @@ -19,6 +20,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/fragments/insertbeforefragment", + "target-var1": "/test/features/personalization/mocks/fragments/insertbeforefragment", "firefox": "", "android": "", "ios": "" diff --git a/test/features/personalization/mocks/actions/manifestPrependToSection.json b/test/features/personalization/mocks/actions/manifestPrependToSection.json index cd5f43432b..c2ccb7af8b 100644 --- a/test/features/personalization/mocks/actions/manifestPrependToSection.json +++ b/test/features/personalization/mocks/actions/manifestPrependToSection.json @@ -8,7 +8,8 @@ "selector": "section2", "page filter (optional)": "", "param-newoffer=123": "", - "chrome": "/test/features/personalization/mocks/fragments/prependToSection" + "chrome": "/test/features/personalization/mocks/fragments/prependToSection", + "target-var1": "/test/features/personalization/mocks/fragments/prependToSection" } ], ":type": "sheet" diff --git a/test/features/personalization/mocks/actions/manifestRemove.json b/test/features/personalization/mocks/actions/manifestRemove.json index 8ff94af803..030c9efb0a 100644 --- a/test/features/personalization/mocks/actions/manifestRemove.json +++ b/test/features/personalization/mocks/actions/manifestRemove.json @@ -9,6 +9,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "yes", + "target-var1": "yes", "firefox": "", "android": "", "ios": "" @@ -19,6 +20,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "yes", + "target-var1": "yes", "firefox": "", "android": "", "ios": "" diff --git a/test/features/personalization/mocks/actions/manifestReplace.json b/test/features/personalization/mocks/actions/manifestReplace.json index f1feae60ca..c1d0d78d78 100644 --- a/test/features/personalization/mocks/actions/manifestReplace.json +++ b/test/features/personalization/mocks/actions/manifestReplace.json @@ -9,6 +9,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "", + "target-var1": "", "firefox": "/test/features/personalization/mocks/fragments/milo-replace-content-firefox-accordion", "android": "", "ios": "" @@ -19,6 +20,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/fragments/milo-replace-content-chrome-howto-h2", + "target-var1": "/test/features/personalization/mocks/fragments/milo-replace-content-chrome-howto-h2", "firefox": "", "android": "", "ios": "" @@ -29,6 +31,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/fragments/fragmentReplaced", + "target-var1": "/test/features/personalization/mocks/fragments/fragmentReplaced", "firefox": "", "android": "", "ios": "" @@ -39,6 +42,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/fragments/inlineFragReplaced", + "target-var1": "/test/features/personalization/mocks/fragments/inlineFragReplaced", "firefox": "", "android": "", "ios": "" diff --git a/test/features/personalization/mocks/actions/manifestTargetReplace.json b/test/features/personalization/mocks/actions/manifestTargetReplace.json new file mode 100644 index 0000000000..f1feae60ca --- /dev/null +++ b/test/features/personalization/mocks/actions/manifestTargetReplace.json @@ -0,0 +1,48 @@ +{ + "total": 5, + "offset": 0, + "limit": 5, + "data": [ + { + "action": "replace", + "selector": ".how-to", + "page filter (optional)": "", + "param-newoffer=123": "", + "chrome": "", + "firefox": "/test/features/personalization/mocks/fragments/milo-replace-content-firefox-accordion", + "android": "", + "ios": "" + }, + { + "action": "replace", + "selector": "#features-of-milo-experimentation-platform", + "page filter (optional)": "", + "param-newoffer=123": "", + "chrome": "/test/features/personalization/mocks/fragments/milo-replace-content-chrome-howto-h2", + "firefox": "", + "android": "", + "ios": "" + }, + { + "action": "replace", + "selector": "/fragments/replaceme", + "page filter (optional)": "", + "param-newoffer=123": "", + "chrome": "/test/features/personalization/mocks/fragments/fragmentReplaced", + "firefox": "", + "android": "", + "ios": "" + }, + { + "action": "replace", + "selector": "/fragments/inline-replaceme", + "page filter (optional)": "", + "param-newoffer=123": "", + "chrome": "/test/features/personalization/mocks/fragments/inlineFragReplaced", + "firefox": "", + "android": "", + "ios": "" + } + ], + ":type": "sheet" +} diff --git a/test/features/personalization/mocks/actions/manifestUseBlockCode.json b/test/features/personalization/mocks/actions/manifestUseBlockCode.json index 1d1d47764c..e8837cb45f 100644 --- a/test/features/personalization/mocks/actions/manifestUseBlockCode.json +++ b/test/features/personalization/mocks/actions/manifestUseBlockCode.json @@ -9,6 +9,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "test\\features\\personalization\\mocks\\promo", + "target-var1": "test\\features\\personalization\\mocks\\promo", "firefox": "", "android": "", "ios": "" diff --git a/test/features/personalization/mocks/actions/manifestUseBlockCode2.json b/test/features/personalization/mocks/actions/manifestUseBlockCode2.json index f377c358d9..a2a48fdd0a 100644 --- a/test/features/personalization/mocks/actions/manifestUseBlockCode2.json +++ b/test/features/personalization/mocks/actions/manifestUseBlockCode2.json @@ -9,6 +9,7 @@ "page filter (optional)": "", "param-newoffer=123": "", "chrome": "/test/features/personalization/mocks/myblock", + "target-var1": "/test/features/personalization/mocks/myblock", "firefox": "", "android": "", "ios": "" diff --git a/test/features/personalization/mocks/fragments/milo-replace-content-target-howto-h2.plain.html b/test/features/personalization/mocks/fragments/milo-replace-content-target-howto-h2.plain.html new file mode 100644 index 0000000000..a9a5c882f2 --- /dev/null +++ b/test/features/personalization/mocks/fragments/milo-replace-content-target-howto-h2.plain.html @@ -0,0 +1 @@ +mock fragment diff --git a/test/features/personalization/pageFilter.test.js b/test/features/personalization/pageFilter.test.js index 263e11cbba..0a08e45481 100644 --- a/test/features/personalization/pageFilter.test.js +++ b/test/features/personalization/pageFilter.test.js @@ -2,7 +2,8 @@ import { expect } from '@esm-bundle/chai'; import { readFile } from '@web/test-runner-commands'; import { stub } from 'sinon'; import { getConfig } from '../../../libs/utils/utils.js'; -import { applyPers } from '../../../libs/features/personalization/personalization.js'; +import { init } from '../../../libs/features/personalization/personalization.js'; +import mepSettings from './mepSettings.js'; document.body.innerHTML = await readFile({ path: './mocks/personalization.html' }); @@ -35,7 +36,7 @@ it('pageFilter should exclude page if it is not a match', async () => { expect(document.querySelector('.marquee')).to.not.be.null; expect(document.querySelector('.newpage')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); // Nothing should be changed since the pageFilter excludes this page expect(document.querySelector('.marquee')).to.not.be.null; @@ -71,7 +72,7 @@ it('pageFilter should include page if it is a match', async () => { expect(document.querySelector('.marquee')).to.not.be.null; expect(document.querySelector('.newpage')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(document.querySelector('.marquee')).to.be.null; expect(document.querySelector('.newpage')).to.not.be.null; diff --git a/test/features/personalization/personalization.test.js b/test/features/personalization/personalization.test.js index 38211b358c..b396befa72 100644 --- a/test/features/personalization/personalization.test.js +++ b/test/features/personalization/personalization.test.js @@ -2,8 +2,12 @@ import { expect } from '@esm-bundle/chai'; import { readFile } from '@web/test-runner-commands'; import { assert, stub } from 'sinon'; import { getConfig, setConfig } from '../../../libs/utils/utils.js'; -import { applyPers, matchGlob, createFrag } from '../../../libs/features/personalization/personalization.js'; +import { + handleFragmentCommand, applyPers, + init, matchGlob, createFrag, combineMepSources, buildVariantInfo, +} from '../../../libs/features/personalization/personalization.js'; import spoofParams from './spoofParams.js'; +import mepSettings from './mepSettings.js'; document.head.innerHTML = await readFile({ path: './mocks/metadata.html' }); document.body.innerHTML = await readFile({ path: './mocks/personalization.html' }); @@ -42,7 +46,7 @@ describe('Functional Test', () => { expect(document.querySelector('.marquee')).to.not.be.null; expect(document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertafter2"]')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); const fragment = document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertafter2"]'); expect(fragment).to.not.be.null; expect(fragment.parentElement.previousElementSibling.className).to.equal('marquee'); @@ -58,7 +62,7 @@ describe('Functional Test', () => { const secondMarquee = document.getElementsByClassName('marquee')[1]; expect(secondMarquee).to.not.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); const fragment = document.querySelector('a[href="/fragments/replace/marquee/r2c1"]'); expect(fragment).to.not.be.null; @@ -76,7 +80,7 @@ describe('Functional Test', () => { expect(document.querySelector('.custom-block-2')).to.not.be.null; expect(document.querySelector('.custom-block-3')).to.not.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(document.querySelector('.special-block')).to.be.null; expect(document.querySelector('.custom-block-2')).to.be.null; @@ -84,12 +88,27 @@ describe('Functional Test', () => { }); it('scheduled manifest should apply changes if active (bts)', async () => { + const config = getConfig(); + config.mep = { + handleFragmentCommand, + preview: false, + variantOverride: {}, + highlight: false, + targetEnabled: false, + experiments: [], + }; + const promoMepSettings = [ + { + manifestPath: '/promos/bts/manifest.json', + disabled: false, + event: { name: 'bts', start: new Date('2023-11-24T13:00:00+00:00'), end: new Date('2222-11-24T13:00:00+00:00') }, + }, + ]; let manifestJson = await readFile({ path: './mocks/manifestScheduledActive.json' }); manifestJson = JSON.parse(manifestJson); setFetchResponse(manifestJson); expect(document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertafter3"]')).to.be.null; - const event = { name: 'bts', start: new Date('2023-11-24T13:00:00+00:00'), end: new Date('2222-11-24T13:00:00+00:00') }; - await applyPers([{ manifestPath: '/promos/bts/manifest.json', disabled: false, event }]); + await applyPers(promoMepSettings); const fragment = document.querySelector('a[href="/test/features/personalization/mocks/fragments/insertafter3"]'); expect(fragment).to.not.be.null; @@ -98,10 +117,25 @@ describe('Functional Test', () => { }); it('scheduled manifest should not apply changes if not active (blackfriday)', async () => { + const config = getConfig(); + config.mep = { + handleFragmentCommand, + preview: false, + variantOverride: {}, + highlight: false, + targetEnabled: false, + experiments: [], + }; + const promoMepSettings = [ + { + manifestPath: '/promos/blackfriday/manifest.json', + disabled: true, + event: { name: 'blackfriday', start: new Date('2022-11-24T13:00:00+00:00'), end: new Date('2022-11-24T13:00:00+00:00') }, + }, + ]; await loadManifestAndSetResponse('./mocks/manifestScheduledInactive.json'); expect(document.querySelector('a[href="/fragments/insertafter4"]')).to.be.null; - const event = { name: 'blackfriday', start: new Date('2022-11-24T13:00:00+00:00'), end: new Date('2022-11-24T13:00:00+00:00') }; - await applyPers([{ manifestPath: '/promos/blackfriday/manifest.json', disabled: true, event }]); + await applyPers(promoMepSettings); const fragment = document.querySelector('a[href="/fragments/insertafter4"]'); expect(fragment).to.be.null; @@ -112,20 +146,20 @@ describe('Functional Test', () => { config.mep = {}; await loadManifestAndSetResponse('./mocks/manifestTestOrPromo.json'); config = getConfig(); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(config.mep?.martech).to.be.undefined; }); it('should choose chrome & logged out', async () => { await loadManifestAndSetResponse('./mocks/manifestWithAmpersand.json'); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); const config = getConfig(); expect(config.mep?.martech).to.equal('|chrome & logged|ampersand'); }); it('should choose not firefox', async () => { await loadManifestAndSetResponse('./mocks/manifestWithNot.json'); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); const config = getConfig(); expect(config.mep?.martech).to.equal('|not firefox|not'); }); @@ -137,16 +171,119 @@ describe('Functional Test', () => { config.entitlements = () => Promise.resolve(['indesign-any', 'fireflies', 'after-effects-any']); await loadManifestAndSetResponse('./mocks/manifestUseEntitlements.json'); - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); 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(); await loadManifestAndSetResponse('./mocks/manifestInvalidSelector.json'); - await applyPers([{ manifestPath: '/mocks/manifestRemove.json' }]); + await init(mepSettings); assert.calledWith(window.console.log, 'Invalid selector: ', '.bad...selector'); window.console.log.reset(); @@ -164,7 +301,7 @@ describe('Functional Test', () => { expect(document.querySelector('meta[property="og:title"]').content).to.equal('milo'); expect(document.querySelector('meta[property="og:image"]')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(geoMetadata.content).to.equal('on'); expect(document.querySelector('meta[name="mynewmetadata"]').content).to.equal('woot'); @@ -177,7 +314,7 @@ describe('Functional Test', () => { const config = getConfig(); await loadManifestAndSetResponse('./mocks/actions/manifestAppendToSection.json'); setTimeout(async () => { - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(config.mep.experiments[0].selectedVariantName).to.equal('param-newoffer=123'); }, 100); }); @@ -235,3 +372,36 @@ describe('matchGlob function', () => { expect(wrapper.classList.contains('hide-block')).to.be.true; }); }); + +describe('MEP Utils', () => { + describe('combineMepSources', async () => { + it('yields an empty list when everything is undefined', async () => { + const manifests = await combineMepSources(undefined, undefined, undefined); + expect(manifests.length).to.equal(0); + }); + it('combines promos and personalization', async () => { + document.head.innerHTML = await readFile({ path: '../../utils/mocks/mep/head-promo.html' }); + const promos = { manifestnames: 'pre-black-friday-global,black-friday-global' }; + const manifests = await combineMepSources('/pers/manifest.json', promos, undefined); + expect(manifests.length).to.equal(3); + expect(manifests[0].manifestPath).to.equal('/pers/manifest.json'); + expect(manifests[1].manifestPath).to.equal('/pre-black-friday.json'); + expect(manifests[2].manifestPath).to.equal('/black-friday.json'); + }); + it('combines promos and personalization and mep param', async () => { + document.head.innerHTML = await readFile({ path: '../../utils/mocks/mep/head-promo.html' }); + const promos = { manifestnames: 'pre-black-friday-global,black-friday-global' }; + const manifests = await combineMepSources( + '/pers/manifest.json', + promos, + '/pers/manifest.json--var1---/mep-param/manifest1.json--all---/mep-param/manifest2.json--all', + ); + expect(manifests.length).to.equal(5); + expect(manifests[0].manifestPath).to.equal('/pers/manifest.json'); + expect(manifests[1].manifestPath).to.equal('/pre-black-friday.json'); + expect(manifests[2].manifestPath).to.equal('/black-friday.json'); + expect(manifests[3].manifestPath).to.equal('/mep-param/manifest1.json'); + expect(manifests[4].manifestPath).to.equal('/mep-param/manifest2.json'); + }); + }); +}); diff --git a/test/features/personalization/replacePage.test.js b/test/features/personalization/replacePage.test.js index 3b3fed3038..3ea70387f5 100644 --- a/test/features/personalization/replacePage.test.js +++ b/test/features/personalization/replacePage.test.js @@ -2,7 +2,8 @@ import { expect } from '@esm-bundle/chai'; import { readFile } from '@web/test-runner-commands'; import { stub } from 'sinon'; import { getConfig } from '../../../libs/utils/utils.js'; -import { applyPers } from '../../../libs/features/personalization/personalization.js'; +import { init } from '../../../libs/features/personalization/personalization.js'; +import mepSettings from './mepSettings.js'; document.body.innerHTML = await readFile({ path: './mocks/personalization.html' }); @@ -35,7 +36,7 @@ it('replacePage should replace all of the main block', async () => { expect(document.querySelector('.marquee')).to.not.be.null; expect(document.querySelector('.newpage')).to.be.null; - await applyPers([{ manifestPath: '/path/to/manifest.json' }]); + await init(mepSettings); expect(document.querySelector('.marquee')).to.be.null; expect(document.querySelector('.newpage')).to.not.be.null; diff --git a/test/features/seotech/seotech.test.js b/test/features/seotech/seotech.test.js index eb5845d804..5cab47b127 100644 --- a/test/features/seotech/seotech.test.js +++ b/test/features/seotech/seotech.test.js @@ -3,7 +3,18 @@ import { stub } from 'sinon'; import { waitForElement } from '../../helpers/waitfor.js'; import { getConfig, createTag } from '../../../libs/utils/utils.js'; -import { appendScriptTag } from '../../../libs/features/seotech/seotech.js'; +import { + appendScriptTag, + sha256, +} from '../../../libs/features/seotech/seotech.js'; + +describe('sha256', () => { + it('should return a hash', async () => { + const message = 'hello'; + const hash = await sha256(message); + expect(hash).to.equal('2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'); + }); +}); describe('seotech', () => { describe('appendScriptTag + seotech-structured-data', () => { @@ -16,27 +27,28 @@ describe('seotech', () => { }); it('should not append JSON-LD', async () => { - const lanaStub = stub(window.lana, 'log'); + const locationUrl = 'https://main--cc--adobecom.hlx.page/in/creativecloud/example2?foo=bar&seotech-env=stage'; + stub(window.lana, 'log'); const getMetadata = stub().returns(null); getMetadata.withArgs('seotech-structured-data').returns('on'); + const getConfigStub = stub().returns({ imsClientId: 'adobedotcom-cc' }); const fetchStub = stub(window, 'fetch'); fetchStub.returns(Promise.resolve(Response.json( { error: 'ERROR!' }, { status: 400 }, ))); await appendScriptTag( - { locationUrl: window.location.href, getMetadata, getConfig, createTag }, + { locationUrl, getMetadata, getConfig: getConfigStub, createTag }, ); - const expectedApiCall = 'https://14257-seotech-stage.adobeioruntime.net/api/v1/web/seotech/getStructuredData?url=http%3A%2F%2Flocalhost%3A2000%2F'; - expect(fetchStub.getCall(0).firstArg).to.equal(expectedApiCall); - expect(lanaStub.getCall(0).firstArg).to.equal('SEOTECH: Failed to fetch structured data: ERROR!'); + const expectedApiCall = 'https://www.adobe.com/seotech/api/structured-data/cc/3e2d1ce8ccf0e45d42d33e0f190fc306ab1ee0f2890c8ff5da27414f8014ceb2'; + expect(fetchStub.getCall(0)?.firstArg).to.equal(expectedApiCall); }); it('should append JSON-LD', async () => { - const locationUrl = 'http://localhost:2000/?seotech-sheet-url=http://foo'; + const locationUrl = 'https://main--cc--adobecom.hlx.page/in/creativecloud/example?foo=bar'; const lanaStub = stub(window.lana, 'log'); const fetchStub = stub(window, 'fetch'); - const getConfigStub = stub().returns({ env: { name: 'prod' } }); + const getConfigStub = stub().returns({ imsClientId: 'adobedotcom-cc' }); const getMetadata = stub().returns(null); getMetadata.withArgs('seotech-structured-data').returns('on'); const expectedObject = { @@ -45,14 +57,14 @@ describe('seotech', () => { name: 'fake', }; fetchStub.returns(Promise.resolve(Response.json( - { objects: [expectedObject] }, + { ...expectedObject }, { status: 200 }, ))); await appendScriptTag( { locationUrl, getMetadata, getConfig: getConfigStub, createTag }, ); - const expectedApiCall = 'https://14257-seotech.adobeioruntime.net/api/v1/web/seotech/getStructuredData?url=http%3A%2F%2Flocalhost%3A2000%2F&sheetUrl=http%3A%2F%2Ffoo'; - expect(fetchStub.getCall(0).firstArg).to.equal(expectedApiCall); + const expectedApiCall = 'https://www.adobe.com/seotech/api/structured-data/cc/f0f5cec5d8b70cf798b602c3586da39e93b9638d9b8001b3a4298605dc5f6ebe'; + expect(fetchStub.getCall(0)?.firstArg).to.equal(expectedApiCall); const el = await waitForElement('script[type="application/ld+json"]'); const obj = JSON.parse(el.text); expect(obj).to.deep.equal(expectedObject); diff --git a/test/navigation/bootstrapper.test.js b/test/navigation/bootstrapper.test.js index 4415788452..18379d4a27 100644 --- a/test/navigation/bootstrapper.test.js +++ b/test/navigation/bootstrapper.test.js @@ -4,21 +4,25 @@ import { stub, useFakeTimers, restore } from 'sinon'; import loadBlock from '../../libs/navigation/bootstrapper.js'; import fetchedFooter from '../blocks/global-footer/mocks/fetched-footer.js'; import placeholders from '../blocks/global-navigation/mocks/placeholders.js'; +import { setConfig } from '../../libs/utils/utils.js'; document.body.innerHTML = await readFile({ path: './mocks/body.html' }); const blockConfig = { - name: 'global-footer', - targetEl: 'footer', - appendType: 'append', - footer: { authoringPath: '/federal/home', privacyLoadDelay: 0 }, + footer: { + name: 'global-footer', + targetEl: 'footer', + appendType: 'append', + }, + header: { + name: 'global-navigation', + targetEl: 'header', + appendType: 'prepend', + unavComponents: 'profile', + }, }; -const miloConfigs = { - origin: 'https://feds--milo--adobecom.hlx.page', - miloLibs: 'http://localhost:2000/libs', - pathname: '/', -}; +const miloLibs = 'http://localhost:2000/libs'; const mockRes = ({ payload, status = 200, ok = true } = {}) => new Promise((resolve) => { resolve({ @@ -43,6 +47,7 @@ describe('Bootstrapper', async () => { if (url.includes('/footer.plain.html')) return mockRes({ payload: await readFile({ path: '../blocks/region-nav/mocks/regions.html' }) }); return null; }); + setConfig({ miloLibs, contentRoot: '/federal/dev' }); }); afterEach(() => { @@ -50,7 +55,7 @@ describe('Bootstrapper', async () => { }); it('Renders the footer block', async () => { - await loadBlock(miloConfigs, blockConfig); + await loadBlock(miloLibs, blockConfig.footer); const clock = useFakeTimers({ toFake: ['setTimeout'], shouldAdvanceTime: true, @@ -59,4 +64,10 @@ describe('Bootstrapper', async () => { const el = document.getElementsByTagName('footer'); expect(el).to.exist; }); + + it('Renders the header block', async () => { + await loadBlock(miloLibs, blockConfig.header); + const el = document.getElementsByTagName('header'); + expect(el).to.exist; + }); }); diff --git a/test/navigation/navigation.test.js b/test/navigation/navigation.test.js index 28b3bacc13..466452b269 100644 --- a/test/navigation/navigation.test.js +++ b/test/navigation/navigation.test.js @@ -6,8 +6,23 @@ document.body.innerHTML = await readFile({ path: './mocks/body.html' }); describe('Navigation component', async () => { it('Renders the footer block', async () => { - await loadBlock({ footer: { authoringPath: '/federal/home' }, env: 'qa' }, 'http://localhost:2000'); + await loadBlock({ authoringPath: '/federal/dev', footer: { privacyId: '12343' }, env: 'qa' }, 'http://localhost:2000'); const el = document.getElementsByTagName('footer'); expect(el).to.exist; }); + + it('Renders the header block', async () => { + await loadBlock({ authoringPath: '/federal/dev', header: { imsClientId: 'fedsmilo' }, env: 'qa' }, 'http://localhost:2000'); + const el = document.getElementsByTagName('header'); + expect(el).to.exist; + }); + + it('Does not render either header or footer if not found in configs', async () => { + document.body.innerHTML = await readFile({ path: './mocks/body.html' }); + await loadBlock({ authoringPath: '/federal/dev', env: 'qa' }, 'http://localhost:2000'); + const header = document.getElementsByTagName('header'); + const footer = document.getElementsByTagName('footer'); + expect(header).to.be.empty; + expect(footer).to.be.empty; + }); }); diff --git a/test/utils/logWebVitals.test.js b/test/utils/logWebVitals.test.js new file mode 100644 index 0000000000..e04db9805a --- /dev/null +++ b/test/utils/logWebVitals.test.js @@ -0,0 +1,62 @@ +/* eslint-disable no-use-before-define */ +import { expect } from '@esm-bundle/chai'; +import { readFile } from '@web/test-runner-commands'; +import logWebVitals from '../../libs/utils/logWebVitals.js'; + +document.body.innerHTML = await readFile({ path: './mocks/body.html' }); + +describe('Log Web Vitals', () => { + before(() => { + window.adobePrivacy = { activeCookieGroups: () => ['C0002'] }; + }); + + after(() => { + delete window.adobePrivacy; + }); + + it('Logs data to lana', (done) => { + window.lana = { + log: (logStr, logOpts) => { + const vitals = logStr.split(',').reduce((acc, pair) => { + const [key, value] = pair.split('='); + acc[key] = value; + return acc; + }, {}); + + expect(vitals).to.have.property('chromeVer'); + const cls = parseFloat(vitals.cls); + expect(cls).to.be.within(0, 1); + expect(vitals).to.have.property('country'); + const downlink = parseFloat(vitals.downlink); + expect(downlink).to.be.within(0, 10); + expect(parseInt(vitals.lcp, 10)).to.be.greaterThan(1); + expect(vitals.lcpEl).to.be.equal('/test/utils/mocks/media_.png'); + expect(vitals.lcpElType).to.be.equal('img'); + expect(vitals.loggedIn).to.equal('false'); + expect(vitals.manifest3path).to.equal('/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/cci-all-apps-q3.json'); + expect(vitals.manifest3selected).to.equal('all'); + 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', 'win', 'android', 'linux', '']); + 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); + + expect(logOpts.clientId).to.equal('pageperf'); + expect(logOpts.sampleRate).to.equal(100); + + done(); + }, + }; + logWebVitals(mepObject, { delay: 0, sampleRate: 100 }); + window.dispatchEvent(new Event('adobePrivacy:PrivacyCustom')); + }); +}); + +// Sample log string: +// eslint-disable-next-line max-len +// chromeVer=127.0.6533.17,cls=0.1842,country=,downlink=10,lcp=82,loggedIn=false,manifest3path=/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/cci-all-apps-q3.json,manifest3selected=all,manifest4path=/cc-shared/fragments/tests/2024/q2/ace0875/ace0875.json,manifest4selected=target-var-marqueelink,os=mac,url=localhost:2000/,windowHeight=600,windowWidth=800'); + +const mepObject = JSON.parse(` +{"preview":true,"variantOverride":{"/products/illustrator.json":"default","/cc-shared/fragments/promos/2024/americas/ste-back-to-school-q3/ste-back-to-school-q3.json":"default","/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/cci-all-apps-q3.json":"all","/cc-shared/fragments/tests/2024/q2/ace0875/ace0875.json":"target-var-marqueelink"},"highlight":false,"targetEnabled":true,"experiments":[{"variantNames":["target-edu_pzn","target-b2b_pzn","target-cpro_pzn","phone & cc-all-apps-any","cc-all-apps-any","illustrator-any"],"manifestOverrideName":"","manifestType":"personalization","executionOrder":"1-0","manifestPath":"/products/illustrator.json","selectedVariantName":"default","name":"PZN | US | Illustrator","manifest":"https://main--cc--adobecom.hlx.live/products/illustrator.json"},{"variantNames":["all"],"manifestOverrideName":"","manifestType":"promo","executionOrder":"1-1","manifestPath":"/cc-shared/fragments/promos/2024/americas/ste-back-to-school-q3/ste-back-to-school-q3.json","selectedVariantName":"default","selectedVariant":"default","manifest":"https://main--cc--adobecom.hlx.page/cc-shared/fragments/promos/2024/americas/ste-back-to-school-q3/ste-back-to-school-q3.json","disabled":true,"event":{"name":"ste-bts-americas","start":"2024-08-19T14:00:00.000Z","end":"2024-09-03T14:00:00.000Z"}},{"variantNames":["all"],"manifestOverrideName":"","manifestType":"promo","executionOrder":"1-1","manifestPath":"/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/cci-all-apps-q3.json","run":true,"selectedVariantName":"all","selectedVariant":{"commands":[{"action":"replace","selector":".marquee","pageFilter":"**/products/illustrator","target":"https://main--cc--adobecom.hlx.page/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/products/illustrator/marquee-gen-ai","selectorType":"css","manifestId":"cci-all-apps-q3.json","targetManifestId":false},{"action":"insertbefore","selector":"main > div","pageFilter":"**/products/illustrator","target":"https://main--cc--adobecom.hlx.page/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/shared/creativecloud/individual/modal#modal-hash:delay=1","selectorType":"css","manifestId":"cci-all-apps-q3.json","targetManifestId":false}],"fragments":[{"selector":"/cc-shared/fragments/merch/products/illustrator/mini-compare/creativecloud/individual/default","val":"/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/products/illustrator/creativecloud/individual/mini-compare","action":"replace","manifestId":"cci-all-apps-q3.json","targetManifestId":false}]},"manifest":"https://main--cc--adobecom.hlx.page/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/cci-all-apps-q3.json","disabled":false,"event":{"name":"cci-all-apps-q3","start":"2024-07-22T14:00:00.000Z","end":"2024-08-04T14:00:00.000Z"}},{"variantNames":["target-var-marqueelink"],"manifestOverrideName":"","manifestType":"test","executionOrder":"1-2","manifestPath":"/cc-shared/fragments/tests/2024/q2/ace0875/ace0875.json","run":true,"selectedVariantName":"target-var-marqueelink","selectedVariant":{"commands":[{"action":"replace","selector":".marquee","pageFilter":"","target":"https://www.adobe.com/cc-shared/fragments/tests/2024/q2/ace0875/ace0875","selectorType":"css","manifestId":"ace0875.json","targetManifestId":"ace0875"}],"fragments":[{"selector":"/cc-shared/fragments/tests/2024/q2/ace0758/illustrator/marquee-default","val":"/cc-shared/fragments/tests/2024/q2/ace0875/ace0875","action":"replace","manifestId":"ace0875.json","targetManifestId":"ace0875"}]},"manifest":"https://www.adobe.com/cc-shared/fragments/tests/2024/q2/ace0875/ace0875.json"}],"blocks":{},"fragments":{"/cc-shared/fragments/merch/products/illustrator/mini-compare/creativecloud/individual/default":{"action":"replace","fragment":"/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/products/illustrator/creativecloud/individual/mini-compare","selector":"/cc-shared/fragments/merch/products/illustrator/mini-compare/creativecloud/individual/default","manifestPath":"/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/cci-all-apps-q3.json","manifestId":"cci-all-apps-q3.json","targetManifestId":false},"/cc-shared/fragments/tests/2024/q2/ace0758/illustrator/marquee-default":{"action":"replace","fragment":"/cc-shared/fragments/tests/2024/q2/ace0875/ace0875","selector":"/cc-shared/fragments/tests/2024/q2/ace0758/illustrator/marquee-default","manifestPath":"/cc-shared/fragments/tests/2024/q2/ace0875/ace0875.json","manifestId":"ace0875.json","targetManifestId":"ace0875"}},"commands":[{"action":"replace","selector":".marquee","pageFilter":"**/products/illustrator","target":"https://main--cc--adobecom.hlx.page/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/products/illustrator/marquee-gen-ai","selectorType":"css","manifestId":"cci-all-apps-q3.json","targetManifestId":false},{"action":"insertbefore","selector":"main > div","pageFilter":"**/products/illustrator","target":"https://main--cc--adobecom.hlx.page/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/shared/creativecloud/individual/modal#modal-hash:delay=1","selectorType":"css","manifestId":"cci-all-apps-q3.json","targetManifestId":false},{"action":"replace","selector":".marquee","pageFilter":"","target":"https://www.adobe.com/cc-shared/fragments/tests/2024/q2/ace0875/ace0875","selectorType":"css","manifestId":"ace0875.json","targetManifestId":"ace0875"}],"martech":"|nopzn|illustrator"} +`); diff --git a/test/utils/logWebVitalsUtils.test.js b/test/utils/logWebVitalsUtils.test.js new file mode 100644 index 0000000000..3028a4b89b --- /dev/null +++ b/test/utils/logWebVitalsUtils.test.js @@ -0,0 +1,64 @@ +/* eslint-disable no-use-before-define */ +import { expect } from '@esm-bundle/chai'; +import { readFile } from '@web/test-runner-commands'; +import { getConfig, loadDeferred } from '../../libs/utils/utils.js'; + +document.head.innerHTML = ` + '; + '; + '; +`; + +document.body.innerHTML = await readFile({ path: './mocks/body.html' }); + +describe('Log Web Vitals Utils', () => { + let intervalId; + before(() => { + window.adobePrivacy = { activeCookieGroups: () => ['C0002'] }; + intervalId = setInterval(() => { + window.dispatchEvent(new Event('adobePrivacy:PrivacyCustom')); + }, 100); + }); + + after(() => { + delete window.adobePrivacy; + clearInterval(intervalId); + }); + + it('Logs data to lana', (done) => { + window.lana = { + log: (logStr, logOpts) => { + const vitals = logStr.split(',').reduce((acc, pair) => { + const [key, value] = pair.split('='); + acc[key] = value; + return acc; + }, {}); + + expect(vitals).to.have.property('chromeVer'); + const cls = parseFloat(vitals.cls); + expect(cls).to.be.within(0, 1); + expect(vitals).to.have.property('country'); + const downlink = parseFloat(vitals.downlink); + expect(downlink).to.be.within(0, 10); + expect(parseInt(vitals.lcp, 10)).to.be.greaterThan(1); + expect(vitals.lcpEl).to.be.equal('/test/utils/mocks/media_.png'); + expect(vitals.lcpElType).to.be.equal('img'); + expect(vitals.loggedIn).to.equal('false'); + expect(vitals.os).to.be.oneOf(['mac', 'win', 'android', 'linux', '']); + 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); + + expect(logOpts.clientId).to.equal('pageperf'); + expect(logOpts.sampleRate).to.equal(100); + + done(); + }, + }; + loadDeferred(document, undefined, getConfig()); + }).timeout(5000); +}); + +// Sample log string: +// eslint-disable-next-line max-len +// chromeVer=127.0.6533.17,cls=0.1842,country=,downlink=10,lcp=82,loggedIn=false,manifest3path=/cc-shared/fragments/promos/2024/americas/cci-all-apps-q3/cci-all-apps-q3.json,manifest3selected=all,manifest4path=/cc-shared/fragments/tests/2024/q2/ace0875/ace0875.json,manifest4selected=target-var-marqueelink,os=mac,url=localhost:2000/,windowHeight=600,windowWidth=800'); diff --git a/test/utils/utils-mep.test.js b/test/utils/utils-mep.test.js index 53af9d1d12..fdbdd7a2e7 100644 --- a/test/utils/utils-mep.test.js +++ b/test/utils/utils-mep.test.js @@ -1,6 +1,7 @@ import { readFile } from '@web/test-runner-commands'; import { expect } from '@esm-bundle/chai'; -import { combineMepSources, getMepEnablement } from '../../libs/utils/utils.js'; +import { getMepEnablement } from '../../libs/utils/utils.js'; +import { combineMepSources } from '../../libs/features/personalization/personalization.js'; describe('MEP Utils', () => { describe('combineMepSources', async () => { diff --git a/test/utils/utils-partition.test.js b/test/utils/utils-partition.test.js new file mode 100644 index 0000000000..11c02f7ce6 --- /dev/null +++ b/test/utils/utils-partition.test.js @@ -0,0 +1,27 @@ +import { expect } from '@esm-bundle/chai'; +import { partition } from '../../libs/utils/utils.js'; + +describe('Utils Partition', () => { + it('partition array', async () => { + const arr = [ + { name: 'John', age: 23 }, + { name: 'James', age: 40 }, + { name: 'Mary', age: 31 }, + ]; + const result = partition(arr, (x) => x.age > 30); + expect(result[0]).to.have.deep.members( + [ + { name: 'Mary', age: 31 }, + { name: 'James', age: 40 }, + ], + ); + expect(result[1]).to.have.deep.members( + [{ name: 'John', age: 23 }], + ); + }); + it('empty array', async () => { + const arr = []; + const result = partition(arr, (x) => x.age > 30); + expect(result).to.eql([[], []]); + }); +}); diff --git a/test/utils/utils.test.js b/test/utils/utils.test.js index 586183ec6a..fbdfd5e184 100644 --- a/test/utils/utils.test.js +++ b/test/utils/utils.test.js @@ -634,7 +634,7 @@ describe('Utils', () => { const resultExperiment = resultConfig.mep.experiments[0]; expect(resultConfig.mep.preview).to.be.true; expect(resultConfig.mep.experiments.length).to.equal(3); - expect(resultExperiment.manifest).to.equal('/products/special-offers-manifest.json'); + expect(resultExperiment.manifest).to.equal('https://main--milo--adobecom.hlx.page/products/special-offers-manifest.json'); }); });