diff --git a/libs/features/georoutingv2/georoutingv2.js b/libs/features/georoutingv2/georoutingv2.js index de19681b39..d6c0ad8683 100644 --- a/libs/features/georoutingv2/georoutingv2.js +++ b/libs/features/georoutingv2/georoutingv2.js @@ -1,5 +1,7 @@ import { getFederatedContentRoot } from '../../utils/utils.js'; +const OLD_GEOROUTING = 'oldgeorouting'; + let config; let createTag; let getMetadata; @@ -271,6 +273,7 @@ export default async function loadGeoRouting( getMetadataFunc, loadBlockFunc, loadStyleFunc, + v2jsonPromise = null, ) { if (getGeoroutingOverride()) return; config = conf; @@ -279,25 +282,25 @@ export default async function loadGeoRouting( loadBlock = loadBlockFunc; loadStyle = loadStyleFunc; - const urls = [ - `${config.contentRoot ?? ''}/georoutingv2.json`, - `${config.contentRoot ?? ''}/georouting.json`, - `${getFederatedContentRoot()}/federal/georouting/georoutingv2.json`, - ]; - let resp; - for (const url of urls) { - resp = await fetch(url); - if (resp.ok) { - if (url.includes('georouting.json')) { - const json = await resp.json(); - // eslint-disable-next-line import/no-cycle - const { default: loadGeoRoutingOld } = await import('../georouting/georouting.js'); - loadGeoRoutingOld(config, createTag, getMetadata, json); - } - break; - } - } - const json = await resp.json(); + const v2JSON = (v2jsonPromise ?? import(`${conf.contentRoot ?? ''}/georoutingv2.json`)) + .then((r) => r.json()) + .catch(() => null); + const loadOldGeorouting = async (json) => { + const { default: loadGeoRoutingOld } = await import('../georouting/georouting.js'); + await loadGeoRoutingOld(config, createTag, getMetadata, json); + return OLD_GEOROUTING; + }; + const oldGeorouting = () => fetch(`${config.contentRoot ?? ''}/georouting.json`) + .then((r) => r.json()) + .then(loadOldGeorouting) + .catch(() => null); + const federatedJSON = () => fetch(`${getFederatedContentRoot()}/federal/georouting/georoutingv2.json`) + .then((r) => r.json()) + .catch(() => null); + + const json = (await v2JSON) ?? (await oldGeorouting()) ?? (await federatedJSON()); + if (json === OLD_GEOROUTING) return; + const { locale } = config; const urlLocale = locale.prefix.replace('/', ''); diff --git a/libs/utils/utils.js b/libs/utils/utils.js index da4d558c4a..4ae4a23c30 100644 --- a/libs/utils/utils.js +++ b/libs/utils/utils.js @@ -1250,8 +1250,9 @@ async function loadPostLCP(config) { const georouting = getMetadata('georouting') || config.geoRouting; if (georouting === 'on') { + const jsonPromise = fetch(`${config.contentRoot ?? ''}/georoutingv2.json`); const { default: loadGeoRouting } = await import('../features/georoutingv2/georoutingv2.js'); - await loadGeoRouting(config, createTag, getMetadata, loadBlock, loadStyle); + await loadGeoRouting(config, createTag, getMetadata, loadBlock, loadStyle, jsonPromise); } const header = document.querySelector('header'); if (header) { diff --git a/test/features/georoutingv2/georoutingv2.test.js b/test/features/georoutingv2/georoutingv2.test.js index 199702e833..ba831e875d 100644 --- a/test/features/georoutingv2/georoutingv2.test.js +++ b/test/features/georoutingv2/georoutingv2.test.js @@ -203,6 +203,8 @@ const ogInnerHeight = window.innerHeight; const ogFetch = window.fetch; window.fetch = stub(); +const v2JSONPromise = () => fetch('/georoutingv2.json'); + function stubHeadRequestToReturnVal(prefix, val) { const path = window.location.href.replace(`${window.location.origin}`, ''); window.fetch.withArgs(`${prefix}${path}`, { method: 'HEAD' }).returns( @@ -304,7 +306,7 @@ describe('GeoRouting', () => { it('Does create a modal if detected country from IP is CH and url prefix is US', async () => { // prepare - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.not.be.null; @@ -314,7 +316,7 @@ describe('GeoRouting', () => { // prepare setUserCountryFromIP('US'); document.cookie = 'international=us;path=/;'; - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.be.null; @@ -325,7 +327,7 @@ describe('GeoRouting', () => { it('Shows no modal if aiming for CH page and IP in Switzerland', async () => { // prepare mockConfig.locale.prefix = 'ch_de'; - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.be.null; @@ -335,7 +337,7 @@ describe('GeoRouting', () => { it('If aiming for US page but IP in Switzerland shows CH links and US continue', async () => { // prepare - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.not.be.null; @@ -367,7 +369,7 @@ describe('GeoRouting', () => { it('If aiming for US page but IP in Egypt arabic content in geo routing modal is in rtl', async () => { // prepare setUserCountryFromIP('EG'); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.not.be.null; @@ -387,7 +389,7 @@ describe('GeoRouting', () => { it('If aiming for US page but IP in Egypt english content in geo routing modal is in ltr', async () => { // prepare setUserCountryFromIP('EG'); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.not.be.null; @@ -408,7 +410,7 @@ describe('GeoRouting', () => { // prepare mockConfig.locale.prefix = 'eg_ar'; setUserCountryFromIP('US'); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); const wrapper = document.querySelector('.georouting-wrapper'); // assert @@ -425,7 +427,7 @@ describe('GeoRouting', () => { mockConfig.locale.prefix = '/ch_fr'; setUserCountryFromIP('US'); document.cookie = 'international=de;path=/;'; - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const wrapper = document.querySelector('.georouting-wrapper'); // assert const swissFrenchData = mockGeoroutingJson.georouting.data.find((d) => d.prefix === 'ch_fr'); @@ -443,7 +445,7 @@ describe('GeoRouting', () => { // prepare mockConfig.locale.prefix = 'mena_en'; setUserCountryFromIP('BW'); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const wrapper = document.querySelector('.georouting-wrapper'); // assert const tabs = wrapper.querySelectorAll('.tabpanel'); @@ -464,7 +466,7 @@ describe('GeoRouting', () => { mockConfig.locale.prefix = 'mena_en'; setUserCountryFromIP('BW'); document.cookie = 'international=ch_de;path=/'; - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const wrapper = document.querySelector('.georouting-wrapper'); // assert const tabs = wrapper.querySelectorAll('.tabpanel'); @@ -484,7 +486,7 @@ describe('GeoRouting', () => { // prepare mockConfig.locale.prefix = 'ch_de'; document.cookie = 'international=ch_fr;path=/;'; - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert mockConfig.locale.prefix = ''; @@ -494,7 +496,7 @@ describe('GeoRouting', () => { it('If IP is from an unknown country no modal is show', async () => { // prepare setUserCountryFromIP('NOEXIST'); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.be.null; @@ -506,7 +508,7 @@ describe('GeoRouting', () => { // prepare stubFallbackMetadata('off'); stubHeadRequestToReturnVal('/ch_it', false); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert const tabs = modal.querySelectorAll('.tabpanel'); @@ -533,7 +535,7 @@ describe('GeoRouting', () => { it('Will show fallback links if fallbackrouting is on and page exist request fails', async () => { // prepare stubHeadRequestToReturnVal('/ch_it', false); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.not.be.null; @@ -549,7 +551,7 @@ describe('GeoRouting', () => { stubHeadRequestToReturnVal('/ch_de', false); stubHeadRequestToReturnVal('/ch_it', false); stubHeadRequestToReturnVal('/ch_fr', false); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.be.null; @@ -561,7 +563,7 @@ describe('GeoRouting', () => { }); it('Closes picker if picker open and then clicking somewhere else within the modal', async () => { - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); const cookie = getCookie('international'); // assert @@ -582,7 +584,7 @@ describe('GeoRouting', () => { it('Add class .top to picker when there is no space to render below the trigger button', async () => { await setViewport({ width: 600, height: 100 }); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); const links = modal.querySelectorAll('a'); links[0].click(); @@ -593,7 +595,7 @@ describe('GeoRouting', () => { it('Sets international and georouting_presented cookies on link click in modal', async () => { // prepare - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); const cookie = getCookie('international'); // assert @@ -609,7 +611,7 @@ describe('GeoRouting', () => { it('Does not open georouting modal if georouting hide is active', async () => { // prepare setGeorouting('off'); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); // assert expect(modal).to.be.null; @@ -621,7 +623,7 @@ describe('GeoRouting', () => { stubFetchForGeorouting(false); stubFetchForGeoroutingOld(false); stubFetchForFederalGeorouting(); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); expect(modal).to.not.be.null; }); @@ -629,7 +631,7 @@ describe('GeoRouting', () => { it('Will load old georouting modal if georoutingv2 is not found', async () => { stubFetchForGeorouting(false); stubFetchForGeoroutingOld(true); - await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle); + await init(mockConfig, createTag, getMetadata, loadBlock, loadStyle, v2JSONPromise()); const modal = document.querySelector('.dialog-modal'); expect(modal).to.not.be.null; });