From 78b30d87772b3aba6a03009918be4dcd9b2f8c16 Mon Sep 17 00:00:00 2001 From: Jason Wesson Date: Mon, 18 Mar 2024 20:55:06 +0000 Subject: [PATCH 1/4] feat: add js config compatibility to mfe prod build --- .gitignore | 2 +- package-lock.json | 171 +++++++++++++++++- package.json | 1 + patches/@openedx+frontend-build+13.0.28.patch | 58 ++++++ src/setupTest.jsx | 4 + 5 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 patches/@openedx+frontend-build+13.0.28.patch diff --git a/.gitignore b/.gitignore index 5f4d4c56..5e215a9a 100755 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .DS_Store .eslintcache -env.config.js +env.config.* node_modules npm-debug.log coverage diff --git a/package-lock.json b/package-lock.json index 1ac1dd79..5b885e10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,7 @@ "jest-when": "^3.6.0", "lodash": "^4.17.21", "moment": "^2.29.4", + "patch-package": "^8.0.0", "prop-types": "15.7.2", "query-string": "7.0.1", "react": "^17.0.2", @@ -8451,6 +8452,11 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -13659,6 +13665,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -20730,6 +20744,14 @@ "node": ">=0.10.0" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -24832,7 +24854,6 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" @@ -25148,6 +25169,154 @@ "node": ">=0.10.0" } }, + "node_modules/patch-package": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", + "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/patch-package/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/patch-package/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/patch-package/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/patch-package/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/patch-package/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/patch-package/node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", diff --git a/package.json b/package.json index 1d8623dc..1342a540 100755 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "jest-when": "^3.6.0", "lodash": "^4.17.21", "moment": "^2.29.4", + "patch-package": "^8.0.0", "prop-types": "15.7.2", "query-string": "7.0.1", "react": "^17.0.2", diff --git a/patches/@openedx+frontend-build+13.0.28.patch b/patches/@openedx+frontend-build+13.0.28.patch new file mode 100644 index 00000000..679f8732 --- /dev/null +++ b/patches/@openedx+frontend-build+13.0.28.patch @@ -0,0 +1,58 @@ +diff --git a/node_modules/@openedx/frontend-build/config/jest.config.js b/node_modules/@openedx/frontend-build/config/jest.config.js +index ac5f730..ddce396 100644 +--- a/node_modules/@openedx/frontend-build/config/jest.config.js ++++ b/node_modules/@openedx/frontend-build/config/jest.config.js +@@ -3,11 +3,16 @@ const fs = require('fs'); + + const presets = require('../lib/presets'); + ++// This assigns the envConfigPath filepath based on whether env.config exists, otherwise it uses the fallback filepath. ++ + let envConfigPath = path.resolve(__dirname, './jest/fallback.env.config.js'); +-const appEnvConfigPath = path.resolve(process.cwd(), './env.config.js'); ++const appEnvConfigPathJs = path.resolve(process.cwd(), './env.config.js'); ++const appEnvConfigPathJsx = path.resolve(process.cwd(), './env.config.jsx'); + +-if (fs.existsSync(appEnvConfigPath)) { +- envConfigPath = appEnvConfigPath; ++if (fs.existsSync(appEnvConfigPathJs)) { ++ envConfigPath = appEnvConfigPathJs; ++} else if (fs.existsSync(appEnvConfigPathJsx)) { ++ envConfigPath = appEnvConfigPathJsx; + } + + module.exports = { +diff --git a/node_modules/@openedx/frontend-build/config/webpack.prod.config.js b/node_modules/@openedx/frontend-build/config/webpack.prod.config.js +index 2879dd9..dd819bc 100644 +--- a/node_modules/@openedx/frontend-build/config/webpack.prod.config.js ++++ b/node_modules/@openedx/frontend-build/config/webpack.prod.config.js +@@ -11,6 +11,7 @@ const dotenv = require('dotenv'); + const NewRelicSourceMapPlugin = require('@edx/new-relic-source-map-webpack-plugin'); + const HtmlWebpackPlugin = require('html-webpack-plugin'); + const MiniCssExtractPlugin = require('mini-css-extract-plugin'); ++const fs = require('fs'); + const path = require('path'); + const PostCssAutoprefixerPlugin = require('autoprefixer'); + const PostCssRTLCSS = require('postcss-rtlcss'); +@@ -23,6 +24,21 @@ const HtmlWebpackNewRelicPlugin = require('../lib/plugins/html-webpack-new-relic + const commonConfig = require('./webpack.common.config'); + const presets = require('../lib/presets'); + ++/** This condition confirms whether the configuration for the MFE has switched to a JS-based configuration ++ * as previously implemented in frontend-build and frontend-platform. If the environment variable exists, then ++ * an env.config.js file will be created at the root directory and its env variables can be accessed with getConfig(). ++ * ++ * https://github.com/openedx/frontend-build/blob/master/docs/0002-js-environment-config.md ++ * https://github.com/openedx/frontend-platform/blob/master/docs/decisions/0007-javascript-file-configuration.rst ++ */ ++ ++const envConfigPath = process.env.JS_CONFIG_FILEPATH; ++ ++if (envConfigPath) { ++ const envConfigFilename = envConfigPath.slice(envConfigPath.indexOf('env.config')); ++ fs.copyFileSync(envConfigPath, envConfigFilename); ++} ++ + // Add process env vars. Currently used only for setting the PUBLIC_PATH. + dotenv.config({ + path: path.resolve(process.cwd(), '.env'), diff --git a/src/setupTest.jsx b/src/setupTest.jsx index b2ada929..81e81cfb 100755 --- a/src/setupTest.jsx +++ b/src/setupTest.jsx @@ -1,6 +1,10 @@ /* eslint-disable import/no-extraneous-dependencies */ import '@testing-library/jest-dom'; import '@testing-library/jest-dom/extend-expect'; +import { mergeConfig } from '@edx/frontend-platform'; +import envConfig from '../env.config'; + +mergeConfig(envConfig); jest.mock('react', () => ({ ...jest.requireActual('react'), From 8d6204a4a608e0d9190b312a8f2448a984664b85 Mon Sep 17 00:00:00 2001 From: Jason Wesson Date: Mon, 18 Mar 2024 21:19:21 +0000 Subject: [PATCH 2/4] fix: mock variables for jest test --- src/setupTest.jsx | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/setupTest.jsx b/src/setupTest.jsx index 81e81cfb..cb89f959 100755 --- a/src/setupTest.jsx +++ b/src/setupTest.jsx @@ -1,10 +1,10 @@ /* eslint-disable import/no-extraneous-dependencies */ import '@testing-library/jest-dom'; import '@testing-library/jest-dom/extend-expect'; -import { mergeConfig } from '@edx/frontend-platform'; -import envConfig from '../env.config'; +// import { mergeConfig } from '@edx/frontend-platform'; +// import envConfig from '../env.config'; -mergeConfig(envConfig); +// mergeConfig(envConfig); jest.mock('react', () => ({ ...jest.requireActual('react'), @@ -72,16 +72,16 @@ When .env.test is removed, uncomment the env vars below and add any environment Context: Snapshot is not currently set up to be able to parse the environment variables in env.config.js */ -// jest.mock('@edx/frontend-platform', () => ({ -// getConfig: jest.fn(() => ({ -// LMS_BASE_URL: 'http://localhost:18000', -// LOGOUT_URL: 'http://localhost:18000/logout', -// LOGO_URL: 'https://edx-cdn.org/v3/default/logo.svg', -// MARKETING_SITE_BASE_URL: 'http://localhost:18000', -// SUPPORT_URL: 'http://localhost:18000/support', -// OPTIMIZELY_FULL_STACK_SDK_KEY: 'SDK Key', -// })), -// })); +jest.mock('@edx/frontend-platform', () => ({ + getConfig: jest.fn(() => ({ + LMS_BASE_URL: 'http://localhost:18000', + LOGOUT_URL: 'http://localhost:18000/logout', + LOGO_URL: 'https://edx-cdn.org/v3/default/logo.svg', + MARKETING_SITE_BASE_URL: 'http://localhost:18000', + SUPPORT_URL: 'http://localhost:18000/support', + OPTIMIZELY_FULL_STACK_SDK_KEY: 'SDK Key', + })), +})); jest.mock('@openedx/paragon', () => jest.requireActual('testUtils').mockNestedComponents({ Alert: { From ef4b7ecb5d5515342f0406f2be05ed41c0d11b41 Mon Sep 17 00:00:00 2001 From: Jason Wesson Date: Thu, 28 Mar 2024 16:43:59 +0000 Subject: [PATCH 3/4] feat: merge JS config variables in initialized config --- src/config/index.js | 6 ++++++ src/setupTest.jsx | 21 --------------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/config/index.js b/src/config/index.js index 5efd3d13..4430482e 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,3 +1,6 @@ +import { mergeConfig } from '@edx/frontend-platform'; +import envConfig from 'env.config'; + const configuration = { // BASE_URL: process.env.BASE_URL, LMS_BASE_URL: process.env.LMS_BASE_URL, @@ -20,6 +23,9 @@ const configuration = { ENABLE_EDX_PERSONAL_DASHBOARD: process.env.ENABLE_EDX_PERSONAL_DASHBOARD === 'true', }; +// This mergeConfig ensures that any variables assigned by process.env are still overwritten if declared in JS config +mergeConfig(envConfig); + const features = {}; export { configuration, features }; diff --git a/src/setupTest.jsx b/src/setupTest.jsx index cb89f959..1218eaa1 100755 --- a/src/setupTest.jsx +++ b/src/setupTest.jsx @@ -1,10 +1,6 @@ /* eslint-disable import/no-extraneous-dependencies */ import '@testing-library/jest-dom'; import '@testing-library/jest-dom/extend-expect'; -// import { mergeConfig } from '@edx/frontend-platform'; -// import envConfig from '../env.config'; - -// mergeConfig(envConfig); jest.mock('react', () => ({ ...jest.requireActual('react'), @@ -66,23 +62,6 @@ jest.mock('@edx/frontend-platform/i18n', () => { }; }); -/* -When .env.test is removed, uncomment the env vars below and add any environment variables for testing with Jest - -Context: Snapshot is not currently set up to be able to parse the environment variables in env.config.js -*/ - -jest.mock('@edx/frontend-platform', () => ({ - getConfig: jest.fn(() => ({ - LMS_BASE_URL: 'http://localhost:18000', - LOGOUT_URL: 'http://localhost:18000/logout', - LOGO_URL: 'https://edx-cdn.org/v3/default/logo.svg', - MARKETING_SITE_BASE_URL: 'http://localhost:18000', - SUPPORT_URL: 'http://localhost:18000/support', - OPTIMIZELY_FULL_STACK_SDK_KEY: 'SDK Key', - })), -})); - jest.mock('@openedx/paragon', () => jest.requireActual('testUtils').mockNestedComponents({ Alert: { Heading: 'Alert.Heading', From 57d3b5a276f81759c29be407ca848c01b373d4bd Mon Sep 17 00:00:00 2001 From: Jason Wesson Date: Thu, 28 Mar 2024 17:27:58 +0000 Subject: [PATCH 4/4] refactor: remove over-write of environment variables in configuration.js --- src/config/index.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/config/index.js b/src/config/index.js index 4430482e..5efd3d13 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,6 +1,3 @@ -import { mergeConfig } from '@edx/frontend-platform'; -import envConfig from 'env.config'; - const configuration = { // BASE_URL: process.env.BASE_URL, LMS_BASE_URL: process.env.LMS_BASE_URL, @@ -23,9 +20,6 @@ const configuration = { ENABLE_EDX_PERSONAL_DASHBOARD: process.env.ENABLE_EDX_PERSONAL_DASHBOARD === 'true', }; -// This mergeConfig ensures that any variables assigned by process.env are still overwritten if declared in JS config -mergeConfig(envConfig); - const features = {}; export { configuration, features };