From 970a19b2e5e8035a7abd04b03f2cb623fc154e91 Mon Sep 17 00:00:00 2001 From: Connor Anderson Date: Thu, 4 May 2023 14:07:22 -0400 Subject: [PATCH] Support EU Cloud Region Add a cloud region config option to the global_config to allow either 'us' (default), or 'eu' to be set as the cloud region. The cloud region determines where the search assets and ytag are sourced from. J=BACK-2277 TEST=manual Using the test site, set the cloudRegion to eu and confirmed the assets are loaded from the eu cdn. Currently there is a cors error, but I will retest them once Aether fixes it. --- .gitignore | 1 + global_config.json | 1 + hbshelpers/sdkAssetUrl.js | 24 +++++++++---- layouts/html.hbs | 22 ++++++++---- script/core.hbs | 5 +-- script/partials/sdk-js-script-tags.hbs | 7 ++-- test-site/config/global_config.json | 3 +- tests/hbshelpers/sdkAssetUrl.js | 18 +++++++++- tests/script/partials/sdk-js-script-tags.js | 38 +++++++++++++++++++++ 9 files changed, 98 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 1e91b7a90..b844ea603 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ static/node_modules/ static/dist/ node_modules **/.DS_Store +.idea/ \ No newline at end of file diff --git a/global_config.json b/global_config.json index 5c856e0a6..780bfbdda 100644 --- a/global_config.json +++ b/global_config.json @@ -4,6 +4,7 @@ // "apiKey": "", // The answers api key found on the experiences page. This will be provided automatically by the Yext CI system // "experienceVersion": "", // the Answers Experience version to use for API requests. This will be provided automatically by the Yext CI system // "environment": "production", // The environment to run on for this Answers Experience. (i.e. 'production' or 'sandbox') + // "cloudRegion": "us", // The cloud region to use for this Answers Experience. (i.e. 'us' or 'eu') // "businessId": "", // The business ID of the account. This will be provided automatically by the Yext CI system // "initializeManually": true, // If true, the experience must be started by calling AnswersExperience.init() or AnswersExperienceFrame.init() for iframe integrations. // "useJWT": true, // Whether or not to enable JWT. If true, the apiKey will be hidden from the build output and the token must be specified through manual initialization. diff --git a/hbshelpers/sdkAssetUrl.js b/hbshelpers/sdkAssetUrl.js index df840240e..cc34b4364 100644 --- a/hbshelpers/sdkAssetUrl.js +++ b/hbshelpers/sdkAssetUrl.js @@ -6,13 +6,19 @@ const SEM_VER_REGEX = /^[1-9]+$|^[1-9]+\.[0-9]+$|^[1-9]+\.[0-9]+\.[0-9]+$/; /** * Given a branch (or release) of the SDK and a locale, this helper provides the correct * URL in the CDN for the asset. - * + * * @param {string} branch The branch (or release) of the SDK. * @param {string} locale The locale to use. * @param {string} assetName The name of the desired asset. + * @param {string} cloudRegion The cloud region to use. * @returns {string} The CDN URL of the localized asset. */ -module.exports = function sdkAssetUrl(branch, locale, assetName) { +module.exports = function sdkAssetUrl( + branch, + locale, + assetName, + cloudRegion = 'us' +) { const isReleasedBranch = SEM_VER_REGEX.test(branch); let parsedBranch; @@ -24,17 +30,21 @@ module.exports = function sdkAssetUrl(branch, locale, assetName) { parsedBranch = `dev/${branch.replace(/\//g, '-')}`; } - const isPreReleaseBranch = + const isPreReleaseBranch = RELEASE_BRANCH_REGEX.test(branch) || HOTFIX_BRANCH_REGEX.test(branch); const isI18nFeatureBranch = I18N_FEATURE_BRANCH_REGEX.test(branch); const isDevelopBranch = branch === 'develop'; - const isLocalizationSupported = - (isReleasedBranch || isPreReleaseBranch || isI18nFeatureBranch || isDevelopBranch) && + const isLocalizationSupported = + (isReleasedBranch || isPreReleaseBranch || isI18nFeatureBranch || isDevelopBranch) && !(locale.startsWith('en') || assetName === 'answers.css') ; - + const parsedAssetName = isLocalizationSupported ? `${locale}-${assetName}` : assetName; - return `https://assets.sitescdn.net/answers/${parsedBranch}/${parsedAssetName}`; + const domain = cloudRegion === 'eu' + ? 'assets.eu.sitescdn.net' + : 'assets.sitescdn.net'; + + return `https://${domain}/answers/${parsedBranch}/${parsedAssetName}`; }; diff --git a/layouts/html.hbs b/layouts/html.hbs index 2125fbef6..837600a39 100644 --- a/layouts/html.hbs +++ b/layouts/html.hbs @@ -24,8 +24,12 @@ - - + {{#ifeq global_config.cloudRegion 'eu'}} + + {{else}} + + {{/ifeq}} + {{> layouts/preload-fonts }} + {{#ifeq global_config.cloudRegion "eu"}} + + {{else}} + + {{/ifeq}} {{/if}} - + \ No newline at end of file diff --git a/test-site/config/global_config.json b/test-site/config/global_config.json index 071d83e33..be2b502c7 100644 --- a/test-site/config/global_config.json +++ b/test-site/config/global_config.json @@ -1,9 +1,10 @@ { - "sdkVersion": "develop", // The version of the Answers SDK to use + "sdkVersion": "1.15", // The version of the Answers SDK to use // "token": "", // The auth token to access Answers experience. "apiKey": "2d8c550071a64ea23e263118a2b0680b", // The answers api key found on the experiences page. This will be provided automatically by the Yext CI system // "experienceVersion": "", // the Answers Experience version to use for API requests. This will be provided automatically by the Yext CI system // "environment": "production", // The environment to run on for this Answers Experience. (i.e. 'production' or 'sandbox') + // "cloudRegion": "us", // The cloud region to use for this Answers Experience. (i.e. 'us' or 'eu') "businessId": "3350634", // The business ID of the account. This will be provided automatically by the Yext CI system // "initializeManually": true, // If true, the experience must be started by calling AnswersExperience.init() or AnswersExperienceFrame.init() for iframe integrations. // "useJWT": true, // Whether or not to enable JWT. If true, the apiKey will be hidden from the build and the token must be specified through the runtime config. diff --git a/tests/hbshelpers/sdkAssetUrl.js b/tests/hbshelpers/sdkAssetUrl.js index b106a5a3d..c907af539 100644 --- a/tests/hbshelpers/sdkAssetUrl.js +++ b/tests/hbshelpers/sdkAssetUrl.js @@ -16,6 +16,22 @@ describe('URLs are computed properly for released versions', () => { expect(sdkAssetUrl('1.8', 'fr', 'answers.min.js')).toEqual(expectedJSUrl); expect(sdkAssetUrl('1.8', 'fr', 'answers.css')).toEqual(expectedCSSUrl); }); + + it('works correctly when locale is "en" and cloudRegion is "eu"', () => { + const expectedJSUrl = 'https://assets.eu.sitescdn.net/answers/v1.8/answers.min.js'; + const expectedCSSUrl = 'https://assets.eu.sitescdn.net/answers/v1.8/answers.css' + + expect(sdkAssetUrl('1.8', 'en', 'answers.min.js', 'eu')).toEqual(expectedJSUrl); + expect(sdkAssetUrl('1.8', 'en', 'answers.css', 'eu')).toEqual(expectedCSSUrl); + }); + + it('works correctly when locale is not "en" and cloudRegion is "eu"', () => { + const expectedJSUrl = 'https://assets.eu.sitescdn.net/answers/v1.8/fr-answers.min.js'; + const expectedCSSUrl = 'https://assets.eu.sitescdn.net/answers/v1.8/answers.css' + + expect(sdkAssetUrl('1.8', 'fr', 'answers.min.js', 'eu')).toEqual(expectedJSUrl); + expect(sdkAssetUrl('1.8', 'fr', 'answers.css', 'eu')).toEqual(expectedCSSUrl); + }); }); describe('URLs are computed properly for release branches', () => { @@ -88,4 +104,4 @@ describe('URLs are computed properly for all other branches', () => { expect(sdkAssetUrl('feature/foo', 'fr', 'answers.min.js')).toEqual(expectedJSUrl); expect(sdkAssetUrl('feature/foo', 'fr', 'answers.css')).toEqual(expectedCSSUrl); }); -}); \ No newline at end of file +}); diff --git a/tests/script/partials/sdk-js-script-tags.js b/tests/script/partials/sdk-js-script-tags.js index c3e47dd97..6d0c8974c 100644 --- a/tests/script/partials/sdk-js-script-tags.js +++ b/tests/script/partials/sdk-js-script-tags.js @@ -20,6 +20,26 @@ const jaOutput = ``; +const entOutputEu = ` +`; + +const jaOutputEu = ` +`; + it('creates correct tags for en', () => { const partialUsage = `{{> script/partials/sdk-js-script-tags sdkVersion=1.8 @@ -35,3 +55,21 @@ it('creates correct tags for ja', () => { }}` expect(hbs.compile(partialUsage)()).toEqual(jaOutput); }); + +it('creates correct tags for en in eu', () => { + const partialUsage = `{{> script/partials/sdk-js-script-tags + sdkVersion=1.8 + locale="en" + cloudRegion="eu" + }}` + expect(hbs.compile(partialUsage)()).toEqual(entOutputEu); +}); + +it('creates correct tags for ja in eu', () => { + const partialUsage = `{{> script/partials/sdk-js-script-tags + sdkVersion=1.8 + locale="ja" + cloudRegion="eu" + }}` + expect(hbs.compile(partialUsage)()).toEqual(jaOutputEu); +});