Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create an onReady and onError callback for standalone gnav #2873

Open
wants to merge 14 commits into
base: stage
Choose a base branch
from
44 changes: 22 additions & 22 deletions libs/blocks/global-navigation/global-navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -1025,27 +1025,27 @@ const getSource = async () => {
};

export default async function init(block) {
try {
const { mep } = getConfig();
const sourceUrl = await getSource();
const [url, hash = ''] = sourceUrl.split('#');
if (hash === '_noActiveItem') {
setDisableAEDState();
}
const content = await fetchAndProcessPlainHtml({ url });
if (!content) return null;
const gnav = new Gnav({
content,
block,
});
gnav.init();
block.setAttribute('daa-im', 'true');
const mepMartech = mep?.martech || '';
block.setAttribute('daa-lh', `gnav|${getExperienceName()}${mepMartech}`);
if (isDarkMode()) block.classList.add('feds--dark');
return gnav;
} catch (e) {
lanaLog({ message: 'Could not create global navigation.', e, tags: 'errorType=error,module=gnav' });
return null;
const { mep } = getConfig();
const sourceUrl = await getSource();
const [url, hash = ''] = sourceUrl.split('#');
if (hash === '_noActiveItem') {
setDisableAEDState();
}
const content = await fetchAndProcessPlainHtml({ url });
if (!content) {
const error = new Error('Could not create global navigation. Content not found!');
error.tags = 'errorType=error,module=gnav';
error.url = url;
throw error;
}
const gnav = new Gnav({
content,
block,
});
gnav.init();
block.setAttribute('daa-im', 'true');
const mepMartech = mep?.martech || '';
block.setAttribute('daa-lh', `gnav|${getExperienceName()}${mepMartech}`);
if (isDarkMode()) block.classList.add('feds--dark');
return gnav;
}
2 changes: 2 additions & 0 deletions libs/blocks/global-navigation/utilities/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export const lanaLog = ({ message, e = '', tags = 'errorType=default' }) => {
sampleRate: 1,
tags,
});
console.error(message);
bandana147 marked this conversation as resolved.
Show resolved Hide resolved
};

export const logErrorFor = async (fn, message, tags) => {
Expand Down Expand Up @@ -330,6 +331,7 @@ export async function fetchAndProcessPlainHtml({ url, shouldDecorateLinks = true
e: `${res.statusText} url: ${res.url}`,
tags: 'errorType=info,module=utilities',
});
return null;
}
const text = await res.text();
const { body } = new DOMParser().parseFromString(text, 'text/html');
Expand Down
2 changes: 1 addition & 1 deletion libs/navigation/bootstrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default async function bootstrapBlock(miloLibs, blockConfig) {
});
}

initBlock(document.querySelector(targetEl));
await initBlock(document.querySelector(targetEl));
if (blockConfig.targetEl === 'footer') {
const { loadPrivacy } = await import(`${miloLibs}/scripts/delayed.js`);
setTimeout(() => {
Expand Down
28 changes: 19 additions & 9 deletions libs/navigation/navigation.js
bandana147 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ function getParamsConfigs(configs) {

export default async function loadBlock(configs, customLib) {
const {
header, footer, authoringPath, env = 'prod', locale = '', theme,
header,
footer,
authoringPath,
env = 'prod',
locale = '',
theme,
} = configs || {};
const branch = new URLSearchParams(window.location.search).get('navbranch');
const miloLibs = branch ? `https://${branch}--milo--adobecom.hlx.page` : customLib || envMap[env];
Expand All @@ -61,16 +66,21 @@ export default async function loadBlock(configs, customLib) {
...paramConfigs,
};
setConfig(clientConfig);

blockConfig.forEach((block) => {
for await (const block of blockConfig) {
const configBlock = configs[block.key];
if (configBlock) {
bootstrapBlock(`${miloLibs}/libs`, {
...block,
...(block.key === 'header' && { unavComponents: configBlock.unavComponents, redirect: configBlock.redirect }),
});
try {
if (configBlock) {
await bootstrapBlock(`${miloLibs}/libs`, {
...block,
...(block.key === 'header' && { unavComponents: configBlock.unavComponents, redirect: configBlock.redirect }),
});
configBlock.onReady?.();
}
} catch (e) {
configBlock.onError?.(e);
throw e;
}
});
}
}

window.loadNavigation = loadBlock;
14 changes: 11 additions & 3 deletions libs/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1054,9 +1054,17 @@
}
const header = document.querySelector('header');
if (header) {
header.classList.add('gnav-hide');
await loadBlock(header);
header.classList.remove('gnav-hide');
try {
header.classList.add('gnav-hide');
await loadBlock(header);
header.classList.remove('gnav-hide');
} catch (e) {
window.lana.log(`${e.message} | gnav-source: ${e.url} | href: ${window.location.href}`, {
clientId: 'feds-milo',
sampleRate: 1,
tags: e.tags,
});
}

Check warning on line 1067 in libs/utils/utils.js

View check run for this annotation

Codecov / codecov/patch

libs/utils/utils.js#L1057-L1067

Added lines #L1057 - L1067 were not covered by tests
}
loadTemplate();
const { default: loadFonts } = await import('./fonts.js');
Expand Down
10 changes: 9 additions & 1 deletion test/blocks/global-navigation/global-navigation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
unavVersion,
} from './test-utilities.js';
import { setConfig, getLocale } from '../../../libs/utils/utils.js';
import initGnav, { getUniversalNavLocale, osMap } from '../../../libs/blocks/global-navigation/global-navigation.js';
import initNav, { getUniversalNavLocale, osMap } from '../../../libs/blocks/global-navigation/global-navigation.js';
import { isDesktop, isTangentToViewport, toFragment } from '../../../libs/blocks/global-navigation/utilities/utilities.js';
import logoOnlyNav from './mocks/global-navigation-only-logo.plain.js';
import longNav from './mocks/global-navigation-long.plain.js';
Expand All @@ -24,6 +24,14 @@ import { getConfig } from '../../../tools/send-to-caas/send-utils.js';
// TODO
// - test localization

async function initGnav(block) {
try {
await initNav(block);
} catch (e) {
// should throw error
}
}

describe('global navigation', () => {
before(() => {
document.head.innerHTML = `<link rel="icon" href="/libs/img/favicons/favicon.ico" size="any">
Expand Down
12 changes: 3 additions & 9 deletions test/navigation/bootstrapper.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ 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';
import { mockRes } from '../blocks/global-navigation/test-utilities.js';

document.body.innerHTML = await readFile({ path: './mocks/body.html' });

Expand All @@ -24,15 +25,6 @@ const blockConfig = {

const miloLibs = 'http://localhost:2000/libs';

const mockRes = ({ payload, status = 200, ok = true } = {}) => new Promise((resolve) => {
resolve({
status,
ok,
json: () => payload,
text: () => payload,
});
});

describe('Bootstrapper', async () => {
beforeEach(async () => {
stub(window, 'fetch').callsFake(async (url) => {
Expand All @@ -45,6 +37,8 @@ describe('Bootstrapper', async () => {
}
if (url.includes('/placeholders')) return mockRes({ payload: placeholders });
if (url.includes('/footer.plain.html')) return mockRes({ payload: await readFile({ path: '../blocks/region-nav/mocks/regions.html' }) });
if (url.includes('/gnav.plain.html')) return mockRes({ payload: await readFile({ path: './mocks/gnav.html' }) });

return null;
});
setConfig({ miloLibs, contentRoot: '/federal/dev' });
Expand Down
59 changes: 59 additions & 0 deletions test/navigation/mocks/gnav.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>Gnav Brand (Logo)</title>
<link rel="canonical" href="https://main--federal--adobecom.hlx.page/federal/globalnav/drafts/blaishram/gnav">
<meta property="og:title" content="Gnav Brand (Logo)">
<meta property="og:url" content="https://main--federal--adobecom.hlx.page/federal/globalnav/drafts/blaishram/gnav">
<meta property="og:image" content="https://main--federal--adobecom.hlx.page/default-meta-image.png?width=1200&#x26;format=pjpg&#x26;optimize=medium">
<meta property="og:image:secure_url" content="https://main--federal--adobecom.hlx.page/default-meta-image.png?width=1200&#x26;format=pjpg&#x26;optimize=medium">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Gnav Brand (Logo)">
<meta name="twitter:image" content="https://main--federal--adobecom.hlx.page/default-meta-image.png?width=1200&#x26;format=pjpg&#x26;optimize=medium">
<meta name="header" content="global-navigation">
<meta name="footer" content="global-footer">
<meta name="gnav-source" content="/federal/globalnav/acom/acom-gnav">
<meta name="footer-source" content="/federal/footer/footer">
<meta name="robots" content="noindex, nofollow"><!-- Modifying this file will impact your performance -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="/scripts/fallback.js" nomodule></script>
<script src="/scripts/scripts.js" type="module"></script>
<style>body { display: none; }</style>
<link rel="icon" href="data:,">
</head>
<body>
<header></header>
<main>
<div>
<div class="gnav-brand logo">
<div>
<div><a href="/federal/assets/svgs/adobe-logo.svg">https://main--federal--adobecom.hlx.page/federal/assets/svgs/adobe-logo.svg|Adobe, Inc.</a> <a href="https://www.adobe.com/">Adobe</a></div>
</div>
</div>
</div>
<div>
<div class="large-menu section">
<div>
<div>
<h2 id="creativity--design"><a href="/federal/globalnav/drafts/blaishram/sections/section-menu-cc">Creativity &#x26; Design</a></h2>
</div>
</div>
</div>
</div>
<div>
<div class="large-menu section">
<div>
<div>
<h2 id="help--support"><a href="/federal/globalnav/drafts/blaishram/sections/section-menu-helps">Help &#x26; Support</a></h2>
</div>
</div>
</div>
</div>
<div>
<p><strong><a href="http://www.google.com/">Just link</a></strong></p>
</div>
<div></div>
</main>
<footer></footer>
</body>
</html>
50 changes: 49 additions & 1 deletion test/navigation/navigation.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,53 @@
import { readFile } from '@web/test-runner-commands';
import { expect } from '@esm-bundle/chai';
import { stub, restore } from 'sinon';
import loadBlock from '../../libs/navigation/navigation.js';
import { setConfig } from '../../libs/utils/utils.js';
import { mockRes } from '../blocks/global-navigation/test-utilities.js';

document.body.innerHTML = await readFile({ path: './mocks/body.html' });
const miloLibs = 'http://localhost:2000/libs';

describe('Navigation component', async () => {
beforeEach(async () => {
stub(window, 'fetch').callsFake(async (url) => {
if (url.includes('/footer.plain.html')) return mockRes({ payload: await readFile({ path: '../blocks/region-nav/mocks/regions.html' }) });
if (url.includes('/federal/dev/gnav.plain.html')) return mockRes({ payload: await readFile({ path: './mocks/gnav.html' }) });
if (url.includes('/federal/error/gnav.plain.html')) return mockRes({ payload: {}, status: 404 });

return null;
});
setConfig({ miloLibs, contentRoot: '/federal/dev' });
});

afterEach(() => {
restore();
});

it('Renders the footer block', async () => {
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 footer block should not load when config is not passed', async () => {
try {
const onError = stub();
await loadBlock({ authoringPath: '/federal/dev-new', env: 'qa', footer: { privacyId: '12343' }, header: { onError } }, 'http://localhost:2000');
const el = document.getElementsByTagName('footer');
expect(el).to.not.exist;
expect(onError.called).to.be.true;
} catch (e) {
// handle error
}
});

it('Renders the header block', async () => {
await loadBlock({ authoringPath: '/federal/dev', header: { imsClientId: 'fedsmilo' }, env: 'qa' }, 'http://localhost:2000');
const onReady = stub();
await loadBlock({ authoringPath: '/federal/dev', header: { imsClientId: 'fedsmilo', onReady }, env: 'prod' }, 'http://localhost:2000');
const el = document.getElementsByTagName('header');
expect(el).to.exist;
expect(onReady.called).to.be.true;
});

it('Does not render either header or footer if not found in configs', async () => {
Expand All @@ -25,4 +58,19 @@ describe('Navigation component', async () => {
expect(header).to.be.empty;
expect(footer).to.be.empty;
});

it('Does not render either header or footer if configs is not passed', async () => {
document.body.innerHTML = await readFile({ path: './mocks/body.html' });
await loadBlock();
const header = document.getElementsByTagName('header');
const footer = document.getElementsByTagName('footer');
expect(header).to.be.empty;
expect(footer).to.be.empty;
});

it('Renders the footer block with authoringpath passed in footer', async () => {
await loadBlock({ footer: { privacyId: '12343', authoringPath: '/federal/dev' }, env: 'qa' }, 'http://localhost:2000');
const el = document.getElementsByTagName('footer');
expect(el).to.exist;
});
});
Loading