diff --git a/.eslintrc-code-compatibility.js b/.eslintrc-code-compatibility.js
index 92080c6c42..c2a8c26aca 100644
--- a/.eslintrc-code-compatibility.js
+++ b/.eslintrc-code-compatibility.js
@@ -14,6 +14,7 @@ module.exports = {
],
ignorePatterns: [
'/libs/deps/*',
+ '/libs/navigation/dist/*',
'/tools/loc/*',
],
};
diff --git a/.eslintrc.js b/.eslintrc.js
index f24adfa387..e7c17dc5fb 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -62,6 +62,7 @@ module.exports = {
'/libs/features/mas/*',
'/tools/loc/*',
'/libs/features/spectrum-web-components/*',
+ '/libs/navigation/dist/*',
],
plugins: [
'chai-friendly',
diff --git a/.github/workflows/release-standalone-feds.yml b/.github/workflows/release-standalone-feds.yml
new file mode 100644
index 0000000000..89a11a1886
--- /dev/null
+++ b/.github/workflows/release-standalone-feds.yml
@@ -0,0 +1,55 @@
+name: Create a Release for Standalone Feds GlobalNav and Footer
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Version'
+ required: true
+ type: string
+
+permissions:
+ contents: write
+
+jobs:
+ release-feds:
+ name: Release Standalone Feds
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ node-version: [20.x]
+ defaults:
+ run:
+ working-directory: ./libs/navigation
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 2
+
+ - name: Set up Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Build Files
+ run: node ./build.mjs
+
+ - name: Generate tarball
+ run: npm pack
+
+ - name: Create Release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh release create "feds-standalone-v${{ inputs.version }}" \
+ --repo="$GITHUB_REPOSITORY" \
+ --title="@adobecom/standalone-feds v${{ inputs.version }} Release" \
+ --generate-notes
+
+ - name: Upload Files to Release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: gh release upload "feds-standalone-v${{ inputs.version }}" "adobecom-standalone-feds-${{ inputs.version }}.tgz"
diff --git a/.gitignore b/.gitignore
index 168ba7ef67..4952087964 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@ logs/*
test-html-results/
test-results/
test-a11y-results/
+libs/navigation/dist/
diff --git a/libs/blocks/global-footer/global-footer.css b/libs/blocks/global-footer/global-footer.css
index 5f32030e01..951a1d72d3 100644
--- a/libs/blocks/global-footer/global-footer.css
+++ b/libs/blocks/global-footer/global-footer.css
@@ -252,6 +252,20 @@
height: 12px;
}
+@media (min-width: 600px) {
+ dialog.feds-dialog {
+ max-width: 80vw;
+ width: fit-content;
+ }
+}
+
+@media (min-width: 1200px) {
+ dialog.feds-dialog {
+ width: 1200px;
+ max-width: calc((100% - 6px) - 2em);
+ }
+}
+
@media (min-width: 900px) {
/* If there is too much content, float it on multiple rows */
.feds-footer-wrapper .feds-menu-content {
diff --git a/libs/blocks/global-footer/global-footer.js b/libs/blocks/global-footer/global-footer.js
index 776e8586f7..051bda37e4 100644
--- a/libs/blocks/global-footer/global-footer.js
+++ b/libs/blocks/global-footer/global-footer.js
@@ -4,8 +4,8 @@ import {
decorateLinks,
getMetadata,
getConfig,
- loadBlock,
localizeLink,
+ loadStyle,
} from '../../utils/utils.js';
import {
@@ -217,6 +217,8 @@ class Footer {
${regionPickerTextElem}
`;
+ regionPickerElem.dataset.modalPath = `${url.pathname}#_inline`;
+ regionPickerElem.dataset.modalHash = url.hash;
const regionPickerWrapperClass = 'feds-regionPicker-wrapper';
this.elements.regionPicker = toFragment`
${regionPickerElem}
@@ -230,24 +232,48 @@ class Footer {
// Hash -> region selector opens a modal
decorateAutoBlock(regionPickerElem); // add modal-specific attributes
// TODO remove logs after finding the root cause for the region picker 404s -> MWPW-143627
+ regionPickerElem.href = url.hash;
if (regionPickerElem.classList[0] !== 'modal') {
lanaLog({
message: `Modal block class missing from region picker pre loading the block; locale: ${locale}; regionPickerElem: ${regionPickerElem.outerHTML}`,
tags: 'errorType=warn,module=global-footer',
});
}
- await loadBlock(regionPickerElem); // load modal logic and styles
+ loadStyle(`${base}/blocks/modal/modal.css`);
+ const { default: initModal } = await import('../modal/modal.js');
+ const modal = await initModal(regionPickerElem);
+
+ const loadRegionNav = async () => {
+ const block = document.querySelector('.region-nav');
+ if (block && getConfig().standaloneGnav) {
+ // on standalone the region-nav will fail to load automatically through
+ // the modal calling fragment.js. In that case we will have data-failed=true
+ // and we should manually load region nav
+ // If that's not the case then we're not a standalone gnav
+ // and we mustn't load region-nav twice.
+ if (block.getAttribute('data-failed') !== 'true') return;
+ block.classList.add('hide');
+ loadStyle(`${base}/blocks/region-nav/region-nav.css`);
+ const { default: initRegionNav } = await import('../region-nav/region-nav.js');
+ initRegionNav(block);
+ // decoratePlaceholders(block, getConfig());
+ block.classList.remove('hide');
+ }
+ };
+
+ if (modal) await loadRegionNav(); // just in case the modal is already open
+
if (regionPickerElem.classList[0] !== 'modal') {
lanaLog({
message: `Modal block class missing from region picker post loading the block; locale: ${locale}; regionPickerElem: ${regionPickerElem.outerHTML}`,
tags: 'errorType=warn,module=global-footer',
});
}
- // 'decorateAutoBlock' logic replaces class name entirely, need to add it back
- regionPickerElem.classList.add(regionPickerClass);
regionPickerElem.addEventListener('click', () => {
if (!isRegionPickerExpanded()) {
regionPickerElem.setAttribute('aria-expanded', 'true');
+ // wait for the modal to load before we load the region nav
+ window.addEventListener('milo:modal:loaded', loadRegionNav, { once: true });
}
});
// Set aria-expanded to false when region modal is closed
@@ -262,7 +288,8 @@ class Footer {
regionSelector.href = localizeLink(regionSelector.href);
decorateAutoBlock(regionSelector); // add fragment-specific class(es)
this.elements.regionPicker.append(regionSelector); // add fragment after regionPickerElem
- await loadBlock(regionSelector); // load fragment and replace original link
+ const { default: initFragment } = await import('../fragment/fragment.js');
+ await initFragment(regionSelector); // load fragment and replace original link
// Update aria-expanded on click
regionPickerElem.addEventListener('click', (e) => {
e.preventDefault();
@@ -271,6 +298,7 @@ class Footer {
});
// Close region picker dropdown on outside click
document.addEventListener('click', (e) => {
+ e.preventDefault();
if (isRegionPickerExpanded()
&& !e.target.closest(`.${regionPickerWrapperClass}`)) {
regionPickerElem.setAttribute('aria-expanded', false);
@@ -278,7 +306,7 @@ class Footer {
});
}
- return this.regionPicker;
+ return this.elements.regionPicker;
};
decorateSocial = () => {
diff --git a/libs/blocks/global-navigation/base.css b/libs/blocks/global-navigation/base.css
index 1eb4d98d29..15a7925834 100644
--- a/libs/blocks/global-navigation/base.css
+++ b/libs/blocks/global-navigation/base.css
@@ -118,8 +118,8 @@
align-items: center;
}
-header.global-navigation {
- visibility: visible;
+header.global-navigation.ready {
+ visibility: visible !important;
}
/* Desktop styles */
diff --git a/libs/blocks/global-navigation/global-navigation.js b/libs/blocks/global-navigation/global-navigation.js
index f632adbe72..dd8dbe3179 100644
--- a/libs/blocks/global-navigation/global-navigation.js
+++ b/libs/blocks/global-navigation/global-navigation.js
@@ -1,3 +1,4 @@
+/* eslint import/no-relative-packages: 0 */
/* eslint-disable no-async-promise-executor */
import {
getConfig,
@@ -20,7 +21,6 @@ import {
isTangentToViewport,
lanaLog,
loadBaseStyles,
- loadBlock,
loadDecorateMenu,
rootPath,
loadStyles,
@@ -222,7 +222,7 @@ const decorateProfileTrigger = async ({ avatar }) => {
let keyboardNav;
const setupKeyboardNav = async () => {
keyboardNav = keyboardNav || new Promise(async (resolve) => {
- const KeyboardNavigation = await loadBlock('./keyboard/index.js');
+ const { default: KeyboardNavigation } = await import('./utilities/keyboard/index.js');
const instance = new KeyboardNavigation();
resolve(instance);
});
@@ -428,17 +428,17 @@ class Gnav {
this.block.removeEventListener('keydown', this.loadDelayed);
if (this.searchPresent()) {
const [
- Search,
+ { default: Search },
] = await Promise.all([
- loadBlock('../features/search/gnav-search.js'),
+ import('./features/search/gnav-search.js'),
loadStyles(rootPath('features/search/gnav-search.css')),
]);
this.Search = Search;
}
if (!this.useUniversalNav) {
- const [ProfileDropdown] = await Promise.all([
- loadBlock('../features/profile/dropdown.js'),
+ const [{ default: ProfileDropdown }] = await Promise.all([
+ import('./features/profile/dropdown.js'),
loadStyles(rootPath('features/profile/dropdown.css')),
]);
this.ProfileDropdown = ProfileDropdown;
@@ -543,7 +543,7 @@ class Gnav {
const unavVersion = new URLSearchParams(window.location.search).get('unavVersion') || '1.3';
await Promise.all([
loadScript(`https://${environment}.adobeccstatic.com/unav/${unavVersion}/UniversalNav.js`),
- loadStyles(`https://${environment}.adobeccstatic.com/unav/${unavVersion}/UniversalNav.css`),
+ loadStyles(`https://${environment}.adobeccstatic.com/unav/${unavVersion}/UniversalNav.css`, true),
]);
const getChildren = () => {
@@ -913,7 +913,7 @@ class Gnav {
const menuLogic = await loadDecorateMenu();
- menuLogic.decorateMenu({
+ await menuLogic.decorateMenu({
item,
template,
type: itemType,
@@ -1024,7 +1024,7 @@ class Gnav {
const breadcrumbsElem = this.block.querySelector('.breadcrumbs');
// Breadcrumbs are not initially part of the nav, need to decorate the links
if (breadcrumbsElem) decorateLinks(breadcrumbsElem);
- const createBreadcrumbs = await loadBlock('../features/breadcrumbs/breadcrumbs.js');
+ const { default: createBreadcrumbs } = await import('./features/breadcrumbs/breadcrumbs.js');
this.elements.breadcrumbsWrapper = await createBreadcrumbs(breadcrumbsElem);
return this.elements.breadcrumbsWrapper;
};
@@ -1094,5 +1094,6 @@ export default async function init(block) {
const mepMartech = mep?.martech || '';
block.setAttribute('daa-lh', `gnav|${getExperienceName()}${mepMartech}`);
if (isDarkMode()) block.classList.add('feds--dark');
+ block.classList.add('ready');
return gnav;
}
diff --git a/libs/blocks/global-navigation/utilities/getUserEntitlements.js b/libs/blocks/global-navigation/utilities/getUserEntitlements.js
index 1166146179..b9812236b6 100644
--- a/libs/blocks/global-navigation/utilities/getUserEntitlements.js
+++ b/libs/blocks/global-navigation/utilities/getUserEntitlements.js
@@ -1,3 +1,4 @@
+/* eslint import/no-relative-packages: 0 */
/* eslint-disable camelcase */
import { getConfig } from '../../../utils/utils.js';
diff --git a/libs/blocks/global-navigation/utilities/getUserEventHistory.js b/libs/blocks/global-navigation/utilities/getUserEventHistory.js
index e1fcc23fee..25937e34a2 100644
--- a/libs/blocks/global-navigation/utilities/getUserEventHistory.js
+++ b/libs/blocks/global-navigation/utilities/getUserEventHistory.js
@@ -1,3 +1,4 @@
+/* eslint import/no-relative-packages: 0 */
/* eslint-disable no-promise-executor-return, no-async-promise-executor */
import { getConfig } from '../../../utils/utils.js';
diff --git a/libs/blocks/global-navigation/utilities/utilities.js b/libs/blocks/global-navigation/utilities/utilities.js
index 9e9b6c457c..ed7fcb3491 100644
--- a/libs/blocks/global-navigation/utilities/utilities.js
+++ b/libs/blocks/global-navigation/utilities/utilities.js
@@ -1,3 +1,4 @@
+/* eslint import/no-relative-packages: 0 */
import {
getConfig, getMetadata, loadStyle, loadLana, decorateLinks, localizeLink,
} from '../../../utils/utils.js';
@@ -134,7 +135,9 @@ export function rootPath(path) {
return url;
}
-export function loadStyles(url) {
+export function loadStyles(url, override = false) {
+ const { standaloneGnav } = getConfig();
+ if (standaloneGnav && !override) return;
loadStyle(url, (e) => {
if (e === 'error') {
lanaLog({
@@ -155,6 +158,8 @@ export function isDarkMode() {
// since they can be independent of each other.
// CSS imports were not used due to duplication of file include
export async function loadBaseStyles() {
+ const { standaloneGnav } = getConfig();
+ if (standaloneGnav) return;
if (isDarkMode()) {
new Promise((resolve) => { loadStyle(rootPath('base.css'), resolve); })
.then(() => loadStyles(rootPath('dark-nav.css')));
@@ -164,10 +169,6 @@ export async function loadBaseStyles() {
}
}
-export function loadBlock(path) {
- return import(path).then((module) => module.default);
-}
-
let cachedDecorateMenu;
export async function loadDecorateMenu() {
if (cachedDecorateMenu) return cachedDecorateMenu;
@@ -177,15 +178,12 @@ export async function loadDecorateMenu() {
resolve = _resolve;
});
- const [{ decorateMenu, decorateLinkGroup }] = await Promise.all([
- loadBlock('./menu/menu.js'),
+ const [menu] = await Promise.all([
+ import('./menu/menu.js'),
loadStyles(rootPath('utilities/menu/menu.css')),
]);
- resolve({
- decorateMenu,
- decorateLinkGroup,
- });
+ resolve(menu.default);
return cachedDecorateMenu;
}
diff --git a/libs/blocks/region-nav/region-nav.css b/libs/blocks/region-nav/region-nav.css
index b3a9859c0b..a996434f33 100644
--- a/libs/blocks/region-nav/region-nav.css
+++ b/libs/blocks/region-nav/region-nav.css
@@ -56,6 +56,10 @@
column-count: 1;
}
+.region-nav.hide {
+ display: none;
+}
+
@media (min-width: 600px) {
.region-nav > div:nth-of-type(2) {
column-count: 3;
diff --git a/libs/navigation/base.css b/libs/navigation/base.css
new file mode 100644
index 0000000000..6df2730955
--- /dev/null
+++ b/libs/navigation/base.css
@@ -0,0 +1 @@
+@import '../blocks/global-navigation/base.css';
diff --git a/libs/navigation/bootstrapper.js b/libs/navigation/bootstrapper.js
index 4f19bb3ffd..55778464cc 100644
--- a/libs/navigation/bootstrapper.js
+++ b/libs/navigation/bootstrapper.js
@@ -1,10 +1,7 @@
-export default async function bootstrapBlock(miloLibs, blockConfig) {
+/* eslint import/no-relative-packages: 0 */
+export default async function bootstrapBlock(initBlock, blockConfig) {
const { name, targetEl, layout, noBorder, jarvis } = blockConfig;
- const { getConfig, createTag, loadLink, loadScript } = await import(`${miloLibs}/utils/utils.js`);
- const { default: initBlock } = await import(`${miloLibs}/blocks/${name}/${name}.js`);
-
- const styles = [`${miloLibs}/blocks/${name}/${name}.css`, `${miloLibs}/navigation/navigation.css`];
- styles.forEach((url) => loadLink(url, { rel: 'stylesheet' }));
+ const { getConfig, createTag, loadScript } = await import('../utils/utils.js');
const setNavLayout = () => {
const element = document.querySelector(targetEl);
@@ -41,7 +38,7 @@ export default async function bootstrapBlock(miloLibs, blockConfig) {
await initBlock(document.querySelector(targetEl));
if (blockConfig.targetEl === 'footer') {
- const { loadPrivacy } = await import(`${miloLibs}/scripts/delayed.js`);
+ const { loadPrivacy } = await import('../scripts/delayed.js');
setTimeout(() => {
loadPrivacy(getConfig, loadScript);
}, blockConfig.delay);
diff --git a/libs/navigation/build.mjs b/libs/navigation/build.mjs
new file mode 100755
index 0000000000..f94fb1f657
--- /dev/null
+++ b/libs/navigation/build.mjs
@@ -0,0 +1,57 @@
+import * as esbuild from 'esbuild'; // eslint-disable-line
+import fs from 'node:fs';
+
+fs.rmSync('./dist/', { recursive: true, force: true });
+
+await esbuild.build({
+ entryPoints: ['navigation.css', 'footer.css', 'dark-nav.css', 'base.css'],
+ bundle: true,
+ minify: true,
+ outdir: './dist/',
+});
+
+// This function behaves slightly different
+// than the built in split function in
+// that it only splits the array xs into two arrays
+// on the first occurence of y only
+const splitAt = (xs, y) => {
+ if (!xs.length) return null;
+ const splitInternal = (before, after) => {
+ if (!after.length) return [before, []];
+ const [x, ...rest] = after;
+ if (x === y) return [before, rest];
+ return splitInternal(before.concat([x]), rest);
+ };
+ return splitInternal([], xs);
+};
+
+const StyleLoader = {
+ name: 'inline-style',
+ setup({ onLoad }) {
+ const template = (css) => `
+ typeof document<'u'&&
+ document.head
+ .appendChild(document.createElement('style'))
+ .appendChild(document.createTextNode(${JSON.stringify(css)}))`;
+ onLoad({ filter: /\.css$/ }, async (args) => {
+ const { path } = args;
+ const [before, after] = splitAt(path.split('/'), 'navigation');
+ const newPath = before
+ .concat(['navigation', 'dist'])
+ .concat(after)
+ .join('/');
+ const css = await fs.promises.readFile(newPath, 'utf8');
+ return { contents: template(css) };
+ });
+ },
+};
+
+await esbuild.build({
+ entryPoints: ['navigation.js'],
+ bundle: true,
+ splitting: true,
+ format: 'esm',
+ sourcemap: true,
+ outdir: './dist/',
+ plugins: [StyleLoader],
+});
diff --git a/libs/navigation/dark-nav.css b/libs/navigation/dark-nav.css
new file mode 100644
index 0000000000..8cf31dba0e
--- /dev/null
+++ b/libs/navigation/dark-nav.css
@@ -0,0 +1 @@
+@import '../blocks/global-navigation/dark-nav.css';
diff --git a/libs/navigation/footer.css b/libs/navigation/footer.css
new file mode 100644
index 0000000000..802e676252
--- /dev/null
+++ b/libs/navigation/footer.css
@@ -0,0 +1,2 @@
+@import '../blocks/global-footer/global-footer.css';
+@import '../blocks/modal/modal.css';
diff --git a/libs/navigation/navigation.css b/libs/navigation/navigation.css
index cca872ed0b..ce0aae2d06 100644
--- a/libs/navigation/navigation.css
+++ b/libs/navigation/navigation.css
@@ -1,3 +1,8 @@
+@import '../blocks/global-navigation/global-navigation.css';
+@import '../blocks/global-navigation/features/profile/dropdown.css';
+@import '../blocks/global-navigation/features/search/gnav-search.css';
+@import '../blocks/global-navigation/utilities/menu/menu.css';
+
/* Extracting the essential styles required for rendering the component independently */
:root {
--navigation-link-color: #035FE6;
diff --git a/libs/navigation/navigation.js b/libs/navigation/navigation.js
index 23ecc702a0..3c26aabb6d 100644
--- a/libs/navigation/navigation.js
+++ b/libs/navigation/navigation.js
@@ -1,3 +1,5 @@
+import { loadStyle } from '../utils/utils.js';
+
const blockConfig = [
{
key: 'header',
@@ -53,6 +55,8 @@ function getParamsConfigs(configs) {
return acc;
}, {});
}
+
+/* eslint import/no-relative-packages: 0 */
export default async function loadBlock(configs, customLib) {
const {
header,
@@ -64,21 +68,40 @@ export default async function loadBlock(configs, customLib) {
allowedOrigins,
stageDomainsMap = {},
} = configs || {};
- const branch = new URLSearchParams(window.location.search).get('navbranch');
- const miloLibs = branch ? `https://${branch}--milo--adobecom.aem.page` : customLib || envMap[env];
if (!header && !footer) {
// eslint-disable-next-line no-console
console.error('Global navigation Error: header and footer configurations are missing.');
return;
}
- // Relative path can't be used, as the script will run on consumer's app
+ const branch = new URLSearchParams(window.location.search).get('navbranch');
+ const miloLibs = branch ? `https://${branch}--milo--adobecom.aem.page` : customLib || envMap[env];
+
+ // The below css imports will fail when using the non-bundled standalone gnav
+ // and fallback to using loadStyle. On the other hand, the bundler will rewrite
+ // the css imports to attach the styles to the head (and point to the dist folder
+ // using the custom StyleLoader plugin found in build.mjs
+ try {
+ await import('./base.css');
+ if (theme === 'dark') {
+ await import('./dark-nav.css');
+ }
+ await import('./navigation.css');
+ } catch (e) {
+ if (theme === 'dark') {
+ loadStyle(`${miloLibs}/libs/navigation/base.css`, () => loadStyle(`${miloLibs}/libs/navigation/dark-nav.css`));
+ } else {
+ loadStyle(`${miloLibs}/libs/navigation/base.css`);
+ }
+ loadStyle(`${miloLibs}/libs/navigation/navigation.css`);
+ }
+
+ // Relative paths work just fine since they exist in the context of this file's origin
const [{ default: bootstrapBlock }, { default: locales }, { setConfig }] = await Promise.all([
- import(`${miloLibs}/libs/navigation/bootstrapper.js`),
- import(`${miloLibs}/libs/utils/locales.js`),
- import(`${miloLibs}/libs/utils/utils.js`),
+ import('./bootstrapper.js'),
+ import('../utils/locales.js'),
+ import('../utils/utils.js'),
]);
-
- const paramConfigs = getParamsConfigs(configs, miloLibs);
+ const paramConfigs = getParamsConfigs(configs);
const clientConfig = {
clientEnv: env,
origin: `https://main--federal--adobecom.aem.${env === 'prod' ? 'live' : 'page'}`,
@@ -90,6 +113,7 @@ export default async function loadBlock(configs, customLib) {
...paramConfigs,
prodDomains,
allowedOrigins,
+ standaloneGnav: true,
stageDomainsMap: getStageDomainsMap(stageDomainsMap),
};
setConfig(clientConfig);
@@ -97,16 +121,25 @@ export default async function loadBlock(configs, customLib) {
const configBlock = configs[block.key];
try {
if (configBlock) {
- await bootstrapBlock(`${miloLibs}/libs`, {
- ...block,
- ...(block.key === 'header' && {
+ if (block.key === 'header') {
+ const { default: init } = await import('../blocks/global-navigation/global-navigation.js');
+ await bootstrapBlock(init, {
+ ...block,
unavComponents: configBlock.unav?.unavComponents,
redirect: configBlock.redirect,
layout: configBlock.layout,
noBorder: configBlock.noBorder,
jarvis: configBlock.jarvis,
- }),
- });
+ });
+ } else if (block.key === 'footer') {
+ try {
+ await import('./footer.css');
+ } catch (e) {
+ loadStyle(`${miloLibs}/libs/navigation/footer.css`);
+ }
+ const { default: init } = await import('../blocks/global-footer/global-footer.js');
+ await bootstrapBlock(init, { ...block });
+ }
configBlock.onReady?.();
}
} catch (e) {
diff --git a/libs/navigation/package-lock.json b/libs/navigation/package-lock.json
new file mode 100644
index 0000000000..f29d7ac225
--- /dev/null
+++ b/libs/navigation/package-lock.json
@@ -0,0 +1,439 @@
+{
+ "name": "navigation",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "navigation",
+ "version": "1.0.0",
+ "license": "ISC",
+ "devDependencies": {
+ "esbuild": "0.24.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz",
+ "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz",
+ "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz",
+ "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz",
+ "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz",
+ "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz",
+ "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz",
+ "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz",
+ "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz",
+ "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz",
+ "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz",
+ "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz",
+ "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz",
+ "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz",
+ "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz",
+ "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz",
+ "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz",
+ "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz",
+ "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz",
+ "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz",
+ "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz",
+ "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz",
+ "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz",
+ "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz",
+ "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz",
+ "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.24.0",
+ "@esbuild/android-arm": "0.24.0",
+ "@esbuild/android-arm64": "0.24.0",
+ "@esbuild/android-x64": "0.24.0",
+ "@esbuild/darwin-arm64": "0.24.0",
+ "@esbuild/darwin-x64": "0.24.0",
+ "@esbuild/freebsd-arm64": "0.24.0",
+ "@esbuild/freebsd-x64": "0.24.0",
+ "@esbuild/linux-arm": "0.24.0",
+ "@esbuild/linux-arm64": "0.24.0",
+ "@esbuild/linux-ia32": "0.24.0",
+ "@esbuild/linux-loong64": "0.24.0",
+ "@esbuild/linux-mips64el": "0.24.0",
+ "@esbuild/linux-ppc64": "0.24.0",
+ "@esbuild/linux-riscv64": "0.24.0",
+ "@esbuild/linux-s390x": "0.24.0",
+ "@esbuild/linux-x64": "0.24.0",
+ "@esbuild/netbsd-x64": "0.24.0",
+ "@esbuild/openbsd-arm64": "0.24.0",
+ "@esbuild/openbsd-x64": "0.24.0",
+ "@esbuild/sunos-x64": "0.24.0",
+ "@esbuild/win32-arm64": "0.24.0",
+ "@esbuild/win32-ia32": "0.24.0",
+ "@esbuild/win32-x64": "0.24.0"
+ }
+ }
+ }
+}
diff --git a/libs/navigation/package.json b/libs/navigation/package.json
new file mode 100644
index 0000000000..9323d847cd
--- /dev/null
+++ b/libs/navigation/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "@adobecom/standalone-feds",
+ "version": "0.0.1",
+ "description": "",
+ "main": "dist/navigation.js",
+ "type": "module",
+ "scripts": {
+ "build": "node ./build.mjs"
+ },
+ "files": ["dist"],
+ "author": "",
+ "license": "ISC",
+ "devDependencies": {
+ "esbuild": "0.24.0"
+ }
+}
diff --git a/libs/utils/utils.js b/libs/utils/utils.js
index a22c7af550..c96169a3de 100644
--- a/libs/utils/utils.js
+++ b/libs/utils/utils.js
@@ -831,7 +831,7 @@ const findReplaceableNodes = (area) => {
};
let placeholderRequest;
-async function decoratePlaceholders(area, config) {
+export async function decoratePlaceholders(area, config) {
if (!area) return;
const nodes = findReplaceableNodes(area);
if (!nodes.length) return;
diff --git a/test/blocks/global-footer/global-footer.test.js b/test/blocks/global-footer/global-footer.test.js
index 3ab306b9ce..8e8ed697d8 100644
--- a/test/blocks/global-footer/global-footer.test.js
+++ b/test/blocks/global-footer/global-footer.test.js
@@ -187,6 +187,11 @@ describe('global footer', () => {
const regionPickerElem = document.querySelector(allSelectors.regionPicker);
regionPickerElem.dispatchEvent(new Event('click'));
+ const regionNavModal = document.createElement('div');
+ regionNavModal.classList.add('region-nav'); // pretend that the modal was added to the body
+ // since clicking on the regionpicker elem apparently doesnt set the hash
+ document.body.append(regionNavModal);
+ window.dispatchEvent(new Event('milo:modal:loaded'));
expect(regionPickerElem.getAttribute('href') === '#langnav').to.equal(true);
expect(regionPickerElem.getAttribute('aria-expanded')).to.equal('true');
@@ -433,4 +438,27 @@ describe('global footer', () => {
expect(document.querySelector('footer').classList.contains('feds--dark')).to.be.true;
});
});
+ describe('standalone footer', async () => {
+ it('should still load the regionnav if it\'s a standalone footer', async () => {
+ await createFullGlobalFooter({
+ waitForDecoration: true,
+ customConfig: { standaloneGnav: true },
+ });
+
+ const regionPickerElem = document.querySelector(allSelectors.regionPicker);
+ regionPickerElem.dispatchEvent(new Event('click'));
+ const regionNavModal = document.createElement('div');
+ regionNavModal.classList.add('region-nav'); // pretend that the modal was added to the body
+ regionNavModal.setAttribute('data-failed', 'true');
+ // since clicking on the regionpicker elem apparently doesnt set the hash
+ document.body.append(regionNavModal);
+ window.dispatchEvent(new Event('milo:modal:loaded'));
+
+ expect(regionPickerElem.getAttribute('href') === '#langnav').to.equal(true);
+ expect(regionPickerElem.getAttribute('aria-expanded')).to.equal('true');
+
+ window.dispatchEvent(new Event('milo:modal:closed'));
+ expect(regionPickerElem.getAttribute('aria-expanded')).to.equal('false');
+ });
+ });
});
diff --git a/test/blocks/global-navigation/keyboard/mocks/global-nav-mobile.html b/test/blocks/global-navigation/keyboard/mocks/global-nav-mobile.html
index 4b4c984091..0d3eb2cb36 100644
--- a/test/blocks/global-navigation/keyboard/mocks/global-nav-mobile.html
+++ b/test/blocks/global-navigation/keyboard/mocks/global-nav-mobile.html
@@ -1,5 +1,5 @@
diff --git a/test/blocks/global-navigation/keyboard/mocks/global-nav.html b/test/blocks/global-navigation/keyboard/mocks/global-nav.html
index 5028fc9841..10e1e6c748 100644
--- a/test/blocks/global-navigation/keyboard/mocks/global-nav.html
+++ b/test/blocks/global-navigation/keyboard/mocks/global-nav.html
@@ -1,5 +1,5 @@
diff --git a/test/navigation/bootstrapper.test.js b/test/navigation/bootstrapper.test.js
index b16743b57b..d524c82fda 100644
--- a/test/navigation/bootstrapper.test.js
+++ b/test/navigation/bootstrapper.test.js
@@ -1,3 +1,4 @@
+/* eslint import/no-relative-packages: 0 */
import { readFile } from '@web/test-runner-commands';
import { expect } from '@esm-bundle/chai';
import { stub, useFakeTimers, restore, spy } from 'sinon';
@@ -57,7 +58,8 @@ describe('Bootstrapper', async () => {
});
it('Renders the footer block', async () => {
- await loadBlock(miloLibs, blockConfig.footer);
+ const { default: init } = await import('../../libs/blocks/global-footer/global-footer.js');
+ await loadBlock(init, blockConfig.footer);
const clock = useFakeTimers({
toFake: ['setTimeout'],
shouldAdvanceTime: true,
@@ -68,21 +70,24 @@ describe('Bootstrapper', async () => {
});
it('Renders the header block', async () => {
- await loadBlock(miloLibs, blockConfig.header);
+ const { default: init } = await import('../../libs/blocks/global-navigation/global-navigation.js');
+ await loadBlock(init, blockConfig.header);
const el = document.getElementsByTagName('header');
expect(el).to.exist;
});
it('Renders the header with full width', async () => {
blockConfig.header.layout = 'fullWidth';
- await loadBlock(miloLibs, blockConfig.header);
+ const { default: init } = await import('../../libs/blocks/global-navigation/global-navigation.js');
+ await loadBlock(init, blockConfig.header);
const el = document.querySelector('header');
expect(el.classList.contains('feds--full-width')).to.be.true;
});
it('Renders the header with no border bottom', async () => {
blockConfig.header.noBorder = true;
- await loadBlock(miloLibs, blockConfig.header);
+ const { default: init } = await import('../../libs/blocks/global-navigation/global-navigation.js');
+ await loadBlock(init, blockConfig.header);
const el = document.querySelector('header');
expect(el.classList.contains('feds--no-border')).to.be.true;
});
@@ -91,7 +96,8 @@ describe('Bootstrapper', async () => {
blockConfig.header.jarvis = { id: '1.1' };
stub(window.AdobeMessagingExperienceClient, 'isAdobeMessagingClientInitialized').returns(true);
stub(window.AdobeMessagingExperienceClient, 'getMessagingExperienceState').returns({ windowState: 'hidden' });
- await loadBlock(miloLibs, blockConfig.header);
+ const { default: init } = await import('../../libs/blocks/global-navigation/global-navigation.js');
+ await loadBlock(init, blockConfig.header);
const el = document.querySelector('.feds-cta[href*="#open-jarvis-chat"]');
const event = new CustomEvent('click', { bubbles: true });
el.dispatchEvent(event);
@@ -101,7 +107,8 @@ describe('Bootstrapper', async () => {
it('should not call openMessagingWindow when chat dialog is already open', async () => {
stub(window.AdobeMessagingExperienceClient, 'isAdobeMessagingClientInitialized').returns(true);
stub(window.AdobeMessagingExperienceClient, 'getMessagingExperienceState').returns({ windowState: 'docked' });
- await loadBlock(miloLibs, blockConfig.header);
+ const { default: init } = await import('../../libs/blocks/global-navigation/global-navigation.js');
+ await loadBlock(init, blockConfig.header);
const el = document.querySelector('.feds-cta[href*="#open-jarvis-chat"]');
const event = new CustomEvent('click', { bubbles: true });
el.dispatchEvent(event);
diff --git a/test/navigation/navigation.test.js b/test/navigation/navigation.test.js
index 0ed7ed1fcc..1ea752635f 100644
--- a/test/navigation/navigation.test.js
+++ b/test/navigation/navigation.test.js
@@ -1,3 +1,4 @@
+/* eslint import/no-relative-packages: 0 */
import { readFile } from '@web/test-runner-commands';
import { expect } from '@esm-bundle/chai';
import { stub, restore } from 'sinon';
@@ -60,7 +61,7 @@ describe('Navigation component', async () => {
});
it('Does not render either header or footer if configs is not passed', async () => {
- document.body.innerHTML = await readFile({ path: './mocks/body.html' });
+ document.body.innerHTML = await readFile({ path: './mocks/body.html' }, 'http://localhost:2000');
await loadBlock();
const header = document.getElementsByTagName('header');
const footer = document.getElementsByTagName('footer');