From 7c8051a440654bf7571d96a30a10eaf2f33b3cf9 Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Thu, 26 Jun 2025 19:27:23 -0300 Subject: [PATCH 01/10] test: fix a couple of tests --- site.config.test.tsx | 1 - .../tests/BaseContainer.test.jsx | 9 ++++----- .../tests/ForgotPasswordPage.test.jsx | 17 +++++++---------- .../CountryField/CountryField.test.jsx | 8 +------- .../tests/RegistrationFailure.test.jsx | 13 ++++++------- .../components/tests/ThirdPartyAuth.test.jsx | 18 ++++++------------ 6 files changed, 24 insertions(+), 42 deletions(-) diff --git a/site.config.test.tsx b/site.config.test.tsx index b7fc3f43..2a1a3279 100644 --- a/site.config.test.tsx +++ b/site.config.test.tsx @@ -37,7 +37,6 @@ const siteConfig: SiteConfig = { PRIVACY_POLICY: null, SEARCH_CATALOG_URL: null, SESSION_COOKIE_DOMAIN: 'local.openedx.io', - SHOW_CONFIGURABLE_EDX_FIELDS: false, SHOW_REGISTRATION_LINKS: false, TOS_AND_HONOR_CODE: null, TOS_LINK: null, diff --git a/src/base-container/tests/BaseContainer.test.jsx b/src/base-container/tests/BaseContainer.test.jsx index d84c143a..aa530393 100644 --- a/src/base-container/tests/BaseContainer.test.jsx +++ b/src/base-container/tests/BaseContainer.test.jsx @@ -1,8 +1,9 @@ -import { IntlProvider, mergeSiteConfig } from '@openedx/frontend-base'; +import { IntlProvider, mergeAppConfig } from '@openedx/frontend-base'; import { render } from '@testing-library/react'; import { Context as ResponsiveContext } from 'react-responsive'; import BaseContainer from '../index'; +import { testAppId } from '../../setupTest'; const LargeScreen = { wrappingComponent: ResponsiveContext.Provider, @@ -25,10 +26,8 @@ describe('Base component tests', () => { }); it('renders Image layout when ENABLE_IMAGE_LAYOUT configuration is enabled', () => { - mergeSiteConfig({ - custom: { - ENABLE_IMAGE_LAYOUT: true, - } + mergeAppConfig(testAppId, { + ENABLE_IMAGE_LAYOUT: true, }); const { container } = render( diff --git a/src/forgot-password/tests/ForgotPasswordPage.test.jsx b/src/forgot-password/tests/ForgotPasswordPage.test.jsx index 2c4516df..3fdea9a8 100644 --- a/src/forgot-password/tests/ForgotPasswordPage.test.jsx +++ b/src/forgot-password/tests/ForgotPasswordPage.test.jsx @@ -1,7 +1,7 @@ import { Provider } from 'react-redux'; import { - configureI18n, injectIntl, IntlProvider, mergeSiteConfig + configureI18n, injectIntl, IntlProvider, mergeAppConfig } from '@openedx/frontend-base'; import { fireEvent, render, screen, @@ -11,6 +11,7 @@ import configureStore from 'redux-mock-store'; import { INTERNAL_SERVER_ERROR, LOGIN_PAGE } from '../../data/constants'; import { PASSWORD_RESET } from '../../reset-password/data/constants'; +import { testAppId } from '../../setupTest'; import { setForgotPasswordFormData } from '../data/actions'; import ForgotPasswordPage from '../ForgotPasswordPage'; @@ -41,11 +42,9 @@ const initialState = { }; describe('ForgotPasswordPage', () => { - mergeSiteConfig({ - custom: { - LOGIN_ISSUE_SUPPORT_LINK: '', - INFO_EMAIL: '', - } + mergeAppConfig(testAppId, { + LOGIN_ISSUE_SUPPORT_LINK: '', + INFO_EMAIL: '', }); let props = {}; @@ -81,10 +80,8 @@ describe('ForgotPasswordPage', () => { }); it('should display need other help signing in button', () => { - mergeSiteConfig({ - custom: { - LOGIN_ISSUE_SUPPORT_LINK: '/support', - } + mergeAppConfig(testAppId, { + LOGIN_ISSUE_SUPPORT_LINK: '/support', }); render(reduxWrapper()); const forgotPasswordButton = screen.findByText('Need help signing in?'); diff --git a/src/register/RegistrationFields/CountryField/CountryField.test.jsx b/src/register/RegistrationFields/CountryField/CountryField.test.jsx index aa286fbe..b798af32 100644 --- a/src/register/RegistrationFields/CountryField/CountryField.test.jsx +++ b/src/register/RegistrationFields/CountryField/CountryField.test.jsx @@ -1,6 +1,6 @@ import { Provider } from 'react-redux'; -import { injectIntl, IntlProvider, mergeSiteConfig } from '@openedx/frontend-base'; +import { injectIntl, IntlProvider } from '@openedx/frontend-base'; import { fireEvent, render } from '@testing-library/react'; import { BrowserRouter as Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; @@ -71,12 +71,6 @@ describe('CountryField', () => { }); describe('Test Country Field', () => { - mergeSiteConfig({ - custom: { - SHOW_CONFIGURABLE_EDX_FIELDS: true, - } - }); - const emptyFieldValidation = { country: 'Select your country or region of residence', }; diff --git a/src/register/components/tests/RegistrationFailure.test.jsx b/src/register/components/tests/RegistrationFailure.test.jsx index 94a8c728..e38ca183 100644 --- a/src/register/components/tests/RegistrationFailure.test.jsx +++ b/src/register/components/tests/RegistrationFailure.test.jsx @@ -1,7 +1,7 @@ import { Provider } from 'react-redux'; import { - configureI18n, getLocale, injectIntl, IntlProvider, mergeSiteConfig + configureI18n, getLocale, injectIntl, IntlProvider, mergeAppConfig } from '@openedx/frontend-base'; import { render, screen } from '@testing-library/react'; import { BrowserRouter as Router } from 'react-router-dom'; @@ -10,6 +10,7 @@ import configureStore from 'redux-mock-store'; import { FORBIDDEN_REQUEST, INTERNAL_SERVER_ERROR, TPA_AUTHENTICATION_FAILURE, TPA_SESSION_EXPIRED, } from '../../data/constants'; +import { testAppId } from '../../../setupTest'; import RegistrationPage from '../../RegistrationPage'; import RegistrationFailureMessage from '../RegistrationFailure'; @@ -40,12 +41,10 @@ jest.mock('react-router-dom', () => { }); describe('RegistrationFailure', () => { - mergeSiteConfig({ - custom: { - PRIVACY_POLICY: 'https://privacy-policy.com', - TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com', - USER_RETENTION_COOKIE_NAME: 'authn-returning-user', - } + mergeAppConfig(testAppId, { + PRIVACY_POLICY: 'https://privacy-policy.com', + TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com', + USER_RETENTION_COOKIE_NAME: 'authn-returning-user', }); let props = {}; diff --git a/src/register/components/tests/ThirdPartyAuth.test.jsx b/src/register/components/tests/ThirdPartyAuth.test.jsx index 8fbf46dd..841feea4 100644 --- a/src/register/components/tests/ThirdPartyAuth.test.jsx +++ b/src/register/components/tests/ThirdPartyAuth.test.jsx @@ -1,7 +1,7 @@ import { Provider } from 'react-redux'; import { - configureI18n, getSiteConfig, getLocale, injectIntl, IntlProvider, mergeSiteConfig + configureI18n, getSiteConfig, getLocale, injectIntl, IntlProvider, mergeAppConfig } from '@openedx/frontend-base'; import { fireEvent, render } from '@testing-library/react'; import { BrowserRouter as Router } from 'react-router-dom'; @@ -10,6 +10,7 @@ import configureStore from 'redux-mock-store'; import { COMPLETE_STATE, LOGIN_PAGE, PENDING_STATE, REGISTER_PAGE, } from '../../../data/constants'; +import { testAppId } from '../../../setupTest'; import RegistrationPage from '../../RegistrationPage'; jest.mock('@openedx/frontend-base', () => ({ @@ -39,12 +40,10 @@ jest.mock('react-router-dom', () => { }); describe('ThirdPartyAuth', () => { - mergeSiteConfig({ - custom: { - PRIVACY_POLICY: 'https://privacy-policy.com', - TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com', - USER_RETENTION_COOKIE_NAME: 'authn-returning-user', - } + mergeAppConfig(testAppId, { + PRIVACY_POLICY: 'https://privacy-policy.com', + TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com', + USER_RETENTION_COOKIE_NAME: 'authn-returning-user', }); let props = {}; @@ -128,11 +127,6 @@ describe('ThirdPartyAuth', () => { }; describe('Test Third Party Auth', () => { - mergeSiteConfig({ - custom: { - SHOW_CONFIGURABLE_EDX_FIELDS: true, - } - }); getLocale.mockImplementation(() => ('en-us')); const secondaryProviders = { From 014a990c2277ca92f36cd4974851035e8f7753a3 Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Thu, 26 Jun 2025 19:27:40 -0300 Subject: [PATCH 02/10] docs: remove reference to devstack --- README.rst | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/README.rst b/README.rst index 6cf36b1d..0d1ba025 100644 --- a/README.rst +++ b/README.rst @@ -34,26 +34,6 @@ Installation .. _Tutor: https://github.com/overhangio/tutor .. _relevant tutor-mfe documentation: https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development -Devstack (Deprecated) instructions -================================== - -1. Install Devstack using the `Getting Started `_ instructions. - -2. Start up LMS, if it's not already started. - -4. Within this project (frontend-app-authn), install requirements and start the development server: - - .. code-block:: - - npm install - npm start # The server will run on port 1999 - -5. Once the dev server is up, visit http://localhost:1999 to access the MFE - - .. image:: ./docs/images/frontend-app-authn-localhost-preview.png - - **Note:** Follow `Enable social auth locally `_ for enabling Social Sign-on Buttons (SSO) locally - Environment Variables/Setup Notes ================================= From 3d778807f1268c5447ed20efbee6de9cc33f9e09 Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Thu, 26 Jun 2025 19:28:02 -0300 Subject: [PATCH 03/10] fix: update index.html The only purpose of the included index.html is to serve the dev environment, so modify it to make that clear. --- public/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index 96cf5255..e8c9ca09 100644 --- a/public/index.html +++ b/public/index.html @@ -1,10 +1,9 @@ - <%= (htmlWebpackPlugin.options.SITE_NAME && htmlWebpackPlugin.options.SITE_NAME != 'null') ? 'Authentication | ' + htmlWebpackPlugin.options.SITE_NAME : 'Authentication' %> + Authentication Development Site> -
From aea12a6a375a6e3c30d493d9f2a3a2aa71730e0a Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Thu, 26 Jun 2025 19:46:12 -0300 Subject: [PATCH 04/10] fix: remove catch-all route Apps should avoid having a catch-all route, instead relying on the shell to provide it. --- src/routes.jsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/routes.jsx b/src/routes.jsx index 6953151e..f5fabdf9 100644 --- a/src/routes.jsx +++ b/src/routes.jsx @@ -1,7 +1,7 @@ import { Navigate } from 'react-router'; import { EmbeddedRegistrationRoute, NotFoundPage, UnAuthOnlyRoute } from './common-components'; -import { LOGIN_PAGE, PAGE_NOT_FOUND } from './data/constants'; +import { LOGIN_PAGE } from './data/constants'; import { ForgotPasswordPage } from './forgot-password'; import Logistration from './logistration/Logistration'; import { ProgressiveProfiling } from './progressive-profiling'; @@ -57,12 +57,6 @@ const routes = [ ), }, - { - path: '*', - element: ( - - ), - } ] } ]; From 6acbf64a71e6fa8bc9f3e6d5959435210b1f1060 Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Thu, 26 Jun 2025 19:52:56 -0300 Subject: [PATCH 05/10] chore: prepare for publication Update package.json for publication as a "buildless" library. (Also upgrade openedx-atlas.) --- package-lock.json | 12 ++++++------ package.json | 9 ++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 96eaf07a..49c915d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { - "name": "@edx/frontend-app-authn", + "name": "@openedx/frontend-app-authn", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@edx/frontend-app-authn", + "name": "@openedx/frontend-app-authn", "version": "1.0.0", "license": "AGPL-3.0", "dependencies": { "@edx/brand": "npm:@openedx/brand-openedx@^1.2.3", - "@edx/openedx-atlas": "^0.6.0", + "@edx/openedx-atlas": "^0.7.0", "@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/free-solid-svg-icons": "^6.7.2", @@ -2048,9 +2048,9 @@ } }, "node_modules/@edx/openedx-atlas": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@edx/openedx-atlas/-/openedx-atlas-0.6.2.tgz", - "integrity": "sha512-28Q8vzJDMS4wUxdkbIUBQpzWJ3HTdMaGlaEhFjrVGfuZkh++1AG6Tn/7FMD88cegalYAkphu530VQCHEkMZQhw==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@edx/openedx-atlas/-/openedx-atlas-0.7.0.tgz", + "integrity": "sha512-jqv0IV1pHsSn9+RO8Rdsr8jm3SOd84CCzzmo2QC9yvh1MK1+p4YDURQLpmmgKJ0JzE5Cb6ImhnNL/ogpJ2wetQ==", "license": "AGPL-3.0", "bin": { "atlas": "atlas" diff --git a/package.json b/package.json index bfbd312f..98a554fa 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@edx/frontend-app-authn", + "name": "@openedx/frontend-app-authn", "version": "1.0.0", "description": "Frontend authentication", "repository": { @@ -7,6 +7,9 @@ "url": "git+https://github.com/openedx/frontend-app-authn.git" }, "main": "src/index.ts", + "files": [ + "/src" + ], "browserslist": [ "extends @edx/browserslist-config" ], @@ -22,7 +25,7 @@ "snapshot": "openedx test --updateSnapshot", "test": "openedx test --coverage --passWithNoTests" }, - "author": "edX", + "author": "Open edX", "license": "AGPL-3.0", "homepage": "https://github.com/openedx/frontend-app-authn#readme", "publishConfig": { @@ -33,7 +36,7 @@ }, "dependencies": { "@edx/brand": "npm:@openedx/brand-openedx@^1.2.3", - "@edx/openedx-atlas": "^0.6.0", + "@edx/openedx-atlas": "^0.7.0", "@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/free-solid-svg-icons": "^6.7.2", From 4dd5ddcc8b13ab1e08ed7907c162ed6ef67d4b2a Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Thu, 26 Jun 2025 21:13:06 -0300 Subject: [PATCH 06/10] refactor: use appId from constants --- site.config.test.tsx | 4 ++- src/Main.tsx | 2 +- src/app.ts | 3 +- .../tests/BaseContainer.test.jsx | 4 +-- src/constants.ts | 1 + .../tests/ForgotPasswordPage.test.jsx | 6 ++-- .../tests/AccountActivationMessage.test.jsx | 4 +-- src/login/tests/LoginFailure.test.jsx | 4 +-- src/login/tests/LoginPage.test.jsx | 25 ++++++++------- src/logistration/Logistration.test.jsx | 22 ++++++------- .../tests/ProgressiveProfiling.test.jsx | 12 +++---- .../HonorCodeField/HonorCode.test.jsx | 6 ++-- src/register/RegistrationPage.test.jsx | 31 ++++++++++--------- .../ConfigurableRegistrationForm.test.jsx | 10 +++--- .../tests/RegistrationFailure.test.jsx | 4 +-- .../components/tests/ThirdPartyAuth.test.jsx | 4 +-- .../tests/ResetPasswordPage.test.jsx | 5 +-- src/setupTest.js | 2 -- 18 files changed, 76 insertions(+), 73 deletions(-) create mode 100644 src/constants.ts diff --git a/site.config.test.tsx b/site.config.test.tsx index 2a1a3279..666226b5 100644 --- a/site.config.test.tsx +++ b/site.config.test.tsx @@ -1,5 +1,7 @@ import { EnvironmentTypes, SiteConfig } from '@openedx/frontend-base'; +import { appId } from './src/constants'; + const siteConfig: SiteConfig = { siteId: 'test-site', siteName: 'Test Site', @@ -10,7 +12,7 @@ const siteConfig: SiteConfig = { environment: EnvironmentTypes.TEST, apps: [{ - appId: 'test-app', + appId, config: { ACTIVATION_EMAIL_SUPPORT_LINK: null, ALLOW_PUBLIC_ACCOUNT_CREATION: false, diff --git a/src/Main.tsx b/src/Main.tsx index 070f5727..514dc44a 100755 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -2,7 +2,7 @@ import { Provider as ReduxProvider } from 'react-redux'; import { Outlet } from 'react-router-dom'; import { CurrentAppProvider } from '@openedx/frontend-base'; -import { appId } from './app'; +import { appId } from './constants'; import { registerIcons, } from './common-components'; diff --git a/src/app.ts b/src/app.ts index 767964fb..4f7c61f5 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,9 +1,8 @@ import { App } from '@openedx/frontend-base'; +import { appId } from './constants'; import routes from './routes'; import messages from './i18n'; -export const appId = 'org.openedx.frontend.app.authn'; - const app: App = { appId, routes, diff --git a/src/base-container/tests/BaseContainer.test.jsx b/src/base-container/tests/BaseContainer.test.jsx index aa530393..c2968e08 100644 --- a/src/base-container/tests/BaseContainer.test.jsx +++ b/src/base-container/tests/BaseContainer.test.jsx @@ -3,7 +3,7 @@ import { render } from '@testing-library/react'; import { Context as ResponsiveContext } from 'react-responsive'; import BaseContainer from '../index'; -import { testAppId } from '../../setupTest'; +import { appId } from '../../constants'; const LargeScreen = { wrappingComponent: ResponsiveContext.Provider, @@ -26,7 +26,7 @@ describe('Base component tests', () => { }); it('renders Image layout when ENABLE_IMAGE_LAYOUT configuration is enabled', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_IMAGE_LAYOUT: true, }); diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 00000000..40099391 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1 @@ +export const appId = 'org.openedx.frontend.app.authn'; diff --git a/src/forgot-password/tests/ForgotPasswordPage.test.jsx b/src/forgot-password/tests/ForgotPasswordPage.test.jsx index 3fdea9a8..4ecee3e3 100644 --- a/src/forgot-password/tests/ForgotPasswordPage.test.jsx +++ b/src/forgot-password/tests/ForgotPasswordPage.test.jsx @@ -11,7 +11,7 @@ import configureStore from 'redux-mock-store'; import { INTERNAL_SERVER_ERROR, LOGIN_PAGE } from '../../data/constants'; import { PASSWORD_RESET } from '../../reset-password/data/constants'; -import { testAppId } from '../../setupTest'; +import { appId } from '../../constants'; import { setForgotPasswordFormData } from '../data/actions'; import ForgotPasswordPage from '../ForgotPasswordPage'; @@ -42,7 +42,7 @@ const initialState = { }; describe('ForgotPasswordPage', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { LOGIN_ISSUE_SUPPORT_LINK: '', INFO_EMAIL: '', }); @@ -80,7 +80,7 @@ describe('ForgotPasswordPage', () => { }); it('should display need other help signing in button', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { LOGIN_ISSUE_SUPPORT_LINK: '/support', }); render(reduxWrapper()); diff --git a/src/login/tests/AccountActivationMessage.test.jsx b/src/login/tests/AccountActivationMessage.test.jsx index 868c533f..027061fb 100644 --- a/src/login/tests/AccountActivationMessage.test.jsx +++ b/src/login/tests/AccountActivationMessage.test.jsx @@ -4,14 +4,14 @@ import { } from '@testing-library/react'; -import { testAppId } from '../../setupTest'; +import { appId } from '../../constants'; import { ACCOUNT_ACTIVATION_MESSAGE } from '../data/constants'; import AccountActivationMessage from '../AccountActivationMessage'; const IntlAccountActivationMessage = injectIntl(AccountActivationMessage); const providerWrapper = children => ( - + {children} diff --git a/src/login/tests/LoginFailure.test.jsx b/src/login/tests/LoginFailure.test.jsx index 3125c6b0..88697ad6 100644 --- a/src/login/tests/LoginFailure.test.jsx +++ b/src/login/tests/LoginFailure.test.jsx @@ -4,7 +4,7 @@ import { } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; -import { testAppId, initializeMockServices } from '../../setupTest'; +import { appId } from '../../constants'; import { ACCOUNT_LOCKED_OUT, ALLOWED_DOMAIN_LOGIN_ERROR, @@ -29,7 +29,7 @@ jest.mock('@openedx/frontend-base', () => ({ const IntlLoginFailureMessage = injectIntl(LoginFailureMessage); const providerWrapper = children => ( - + {children} diff --git a/src/login/tests/LoginPage.test.jsx b/src/login/tests/LoginPage.test.jsx index 7770f00d..8506c51d 100644 --- a/src/login/tests/LoginPage.test.jsx +++ b/src/login/tests/LoginPage.test.jsx @@ -10,7 +10,8 @@ import { act } from 'react-dom/test-utils'; import { MemoryRouter } from 'react-router-dom'; import configureStore from 'redux-mock-store'; -import { initializeMockServices, testAppId } from '../../setupTest'; +import { appId } from '../../constants'; +import { initializeMockServices } from '../../setupTest'; import { COMPLETE_STATE, LOGIN_PAGE, PENDING_STATE } from '../../data/constants'; import { backupLoginFormBegin, dismissPasswordResetBanner, loginRequest } from '../data/actions'; import { INTERNAL_SERVER_ERROR } from '../data/constants'; @@ -30,7 +31,7 @@ describe('LoginPage', () => { const reduxWrapper = children => ( - + {children} @@ -85,7 +86,7 @@ describe('LoginPage', () => { it('should submit form for valid input', () => { store.dispatch = jest.fn(store.dispatch); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); @@ -272,7 +273,7 @@ describe('LoginPage', () => { { selector: `#${ssoProvider.id}` }, )).toBeDefined(); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); }); @@ -337,7 +338,7 @@ describe('LoginPage', () => { // ******** test enterprise login disabled scenarios ******** it('should show sign-in header for institution login if enterprise login is disabled', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: true, }); @@ -358,13 +359,13 @@ describe('LoginPage', () => { expect(queryByText('Company or school credentials')).toBeNull(); expect(queryByText('Institution/campus credentials')).toBeDefined(); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); }); it('should show sign-in header with secondary Providers and without Providers', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: true, }); @@ -385,7 +386,7 @@ describe('LoginPage', () => { expect(queryByText('Or sign in with:')).toBeDefined(); expect(queryByText('Institution/campus credentials')).toBeDefined(); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); }); @@ -424,7 +425,7 @@ describe('LoginPage', () => { expect(queryByText('Company or school credentials')).toBeNull(); expect(queryByText('Institution/campus credentials')).toBeDefined(); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); }); @@ -694,7 +695,7 @@ describe('LoginPage', () => { const { container } = render(reduxWrapper()); expect(container.querySelector(`#${ssoProvider.id}`).querySelector('#provider-name').textContent).toEqual(`${ssoProvider.name}`); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); }); @@ -712,7 +713,7 @@ describe('LoginPage', () => { }, }); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ALLOW_PUBLIC_ACCOUNT_CREATION: true, SHOW_REGISTRATION_LINKS: true, }); @@ -727,7 +728,7 @@ describe('LoginPage', () => { }); it('should render other ways to sign in button when public account creation is disabled', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ALLOW_PUBLIC_ACCOUNT_CREATION: false, }); diff --git a/src/logistration/Logistration.test.jsx b/src/logistration/Logistration.test.jsx index 7717fc68..e07106c0 100644 --- a/src/logistration/Logistration.test.jsx +++ b/src/logistration/Logistration.test.jsx @@ -7,7 +7,7 @@ import { fireEvent, render, screen } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import configureStore from 'redux-mock-store'; -import { testAppId } from '../setupTest'; +import { appId } from '../constants'; import { clearThirdPartyAuthContextErrorMessage } from '../common-components/data/actions'; import { COMPLETE_STATE, LOGIN_PAGE, REGISTER_PAGE, @@ -43,7 +43,7 @@ describe('Logistration', () => { const reduxWrapper = children => ( - + {children} @@ -91,7 +91,7 @@ describe('Logistration', () => { }); it('should render registration page', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ALLOW_PUBLIC_ACCOUNT_CREATION: true, }); @@ -108,7 +108,7 @@ describe('Logistration', () => { }); it('should render login/register headings when show registration links is disabled', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ALLOW_PUBLIC_ACCOUNT_CREATION: true, SHOW_REGISTRATION_LINKS: false, }); @@ -129,7 +129,7 @@ describe('Logistration', () => { }); it('should render only login page when public account creation is disabled', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ALLOW_PUBLIC_ACCOUNT_CREATION: false, DISABLE_ENTERPRISE_LOGIN: 'true', SHOW_REGISTRATION_LINKS: 'true', @@ -160,7 +160,7 @@ describe('Logistration', () => { }); it('should display institution login option when secondary providers are present', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: 'true', ALLOW_PUBLIC_ACCOUNT_CREATION: 'true', }); @@ -186,13 +186,13 @@ describe('Logistration', () => { fireEvent.click(screen.getByText('Institution/campus credentials')); expect(screen.getByText('Test University')).toBeDefined(); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); }); it('send tracking and page events when institutional login button is clicked', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: 'true', }); @@ -216,13 +216,13 @@ describe('Logistration', () => { expect(sendTrackEvent).toHaveBeenCalledWith('edx.bi.institution_login_form.toggled', { category: 'user-engagement' }); expect(sendPageEvent).toHaveBeenCalledWith('login_and_registration', 'institution_login'); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); }); it('should not display institution register button', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: 'true', }); @@ -246,7 +246,7 @@ describe('Logistration', () => { fireEvent.click(screen.getByText('Institution/campus credentials')); expect(screen.getByText('Test University')).toBeDefined(); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { DISABLE_ENTERPRISE_LOGIN: '', }); }); diff --git a/src/progressive-profiling/tests/ProgressiveProfiling.test.jsx b/src/progressive-profiling/tests/ProgressiveProfiling.test.jsx index 5fafdb16..2e655db0 100644 --- a/src/progressive-profiling/tests/ProgressiveProfiling.test.jsx +++ b/src/progressive-profiling/tests/ProgressiveProfiling.test.jsx @@ -17,7 +17,7 @@ import { import { MemoryRouter, mockNavigate, useLocation } from 'react-router-dom'; import configureStore from 'redux-mock-store'; -import { testAppId } from '../../setupTest'; +import { appId } from '../../constants'; import { AUTHN_PROGRESSIVE_PROFILING, COMPLETE_STATE, DEFAULT_REDIRECT_URL, @@ -87,7 +87,7 @@ describe('ProgressiveProfilingTests', () => { const reduxWrapper = children => ( - + {children} @@ -111,7 +111,7 @@ describe('ProgressiveProfilingTests', () => { // ******** test form links and modal ******** it('should not display button "Learn more about how we use this information."', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: '', }); const { queryByRole } = render(reduxWrapper()); @@ -121,7 +121,7 @@ describe('ProgressiveProfilingTests', () => { }); it('should display button "Learn more about how we use this information."', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: 'http://localhost:1999/support', }); @@ -157,7 +157,7 @@ describe('ProgressiveProfilingTests', () => { }); it('should send analytic event for support link click', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { AUTHN_PROGRESSIVE_PROFILING_SUPPORT_LINK: 'http://localhost:1999/support', }); render(reduxWrapper()); @@ -200,7 +200,7 @@ describe('ProgressiveProfilingTests', () => { }); describe('Embedded Form Workflow Test', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { SEARCH_CATALOG_URL: 'http://localhost/search', }); const host = 'http://example.com'; diff --git a/src/register/RegistrationFields/HonorCodeField/HonorCode.test.jsx b/src/register/RegistrationFields/HonorCodeField/HonorCode.test.jsx index 201c643a..d7896d94 100644 --- a/src/register/RegistrationFields/HonorCodeField/HonorCode.test.jsx +++ b/src/register/RegistrationFields/HonorCodeField/HonorCode.test.jsx @@ -3,21 +3,21 @@ import { } from '@openedx/frontend-base'; import { render } from '@testing-library/react'; -import { testAppId } from '../../../setupTest'; +import { appId } from '../../../constants'; import { HonorCode } from '../index'; const IntlHonorCode = injectIntl(HonorCode); const providerWrapper = children => ( - + {children} ); describe('HonorCodeTest', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { PRIVACY_POLICY: 'http://privacy-policy.com', TOS_AND_HONOR_CODE: 'http://tos-and-honot-code.com', }); diff --git a/src/register/RegistrationPage.test.jsx b/src/register/RegistrationPage.test.jsx index 9207d1ad..39667656 100644 --- a/src/register/RegistrationPage.test.jsx +++ b/src/register/RegistrationPage.test.jsx @@ -11,7 +11,8 @@ import configureStore from 'redux-mock-store'; import { AUTHN_PROGRESSIVE_PROFILING, COMPLETE_STATE, PENDING_STATE, REGISTER_PAGE, } from '../data/constants'; -import { initializeMockServices, testAppId } from '../setupTest'; +import { appId } from '../constants'; +import { initializeMockServices } from '../setupTest'; import { backupRegistrationFormBegin, clearRegistrationBackendError, @@ -51,7 +52,7 @@ jest.mock('react-router-dom', () => { jest.mock('universal-cookie'); describe('RegistrationPage', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { PRIVACY_POLICY: 'https://privacy-policy.com', TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com', USER_RETENTION_COOKIE_NAME: 'authn-returning-user', @@ -76,7 +77,7 @@ describe('RegistrationPage', () => { const reduxWrapper = children => ( - + {children} @@ -256,7 +257,7 @@ describe('RegistrationPage', () => { }); it('should submit form with marketing email opt in value', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { MARKETING_EMAILS_OPT_IN: 'true', }); @@ -278,13 +279,13 @@ describe('RegistrationPage', () => { fireEvent.click(button); expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload })); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { MARKETING_EMAILS_OPT_IN: '', }); }); it('should submit form without UsernameField when autoGeneratedUsernameEnabled is true', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_AUTO_GENERATED_USERNAME: true, }); jest.spyOn(global.Date, 'now').mockImplementation(() => 0); @@ -301,20 +302,20 @@ describe('RegistrationPage', () => { const button = container.querySelector('button.btn-brand'); fireEvent.click(button); expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload })); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_AUTO_GENERATED_USERNAME: false, }); }); it('should not display UsernameField when ENABLE_AUTO_GENERATED_USERNAME is true', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_AUTO_GENERATED_USERNAME: true, }); const { queryByLabelText } = render(routerWrapper(reduxWrapper())); expect(queryByLabelText('Username')).toBeNull(); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_AUTO_GENERATED_USERNAME: false, }); }); @@ -431,7 +432,7 @@ describe('RegistrationPage', () => { }); it('should display opt-in/opt-out checkbox', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { MARKETING_EMAILS_OPT_IN: 'true', }); @@ -439,7 +440,7 @@ describe('RegistrationPage', () => { const checkboxDivs = container.querySelectorAll('div.form-field--checkbox'); expect(checkboxDivs.length).toEqual(1); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { MARKETING_EMAILS_OPT_IN: '', }); }); @@ -468,7 +469,7 @@ describe('RegistrationPage', () => { }); render(routerWrapper(reduxWrapper())); - expect(Cookies.prototype.set).toHaveBeenCalledWith(getAppConfig(testAppId).USER_RETENTION_COOKIE_NAME, true, { domain: 'local.openedx.io', path: '/' }); + expect(Cookies.prototype.set).toHaveBeenCalledWith(getAppConfig(appId).USER_RETENTION_COOKIE_NAME, true, { domain: 'local.openedx.io', path: '/' }); }); it('should redirect to url returned in registration result after successful account creation', () => { @@ -490,7 +491,7 @@ describe('RegistrationPage', () => { }); it('should redirect to dashboard if features flags are configured but no optional fields are configured', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: true, }); const dashboardUrl = 'https://test.com/testing-dashboard/'; @@ -518,7 +519,7 @@ describe('RegistrationPage', () => { it('should redirect to progressive profiling page if optional fields are configured', () => { getLocale.mockImplementation(() => ('en-us')); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: true, }); @@ -679,7 +680,7 @@ describe('RegistrationPage', () => { it('should call the postMessage API when embedded variant is rendered', () => { getLocale.mockImplementation(() => ('en-us')); - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: true, }); diff --git a/src/register/components/tests/ConfigurableRegistrationForm.test.jsx b/src/register/components/tests/ConfigurableRegistrationForm.test.jsx index 5c38d2c5..6eeb7c05 100644 --- a/src/register/components/tests/ConfigurableRegistrationForm.test.jsx +++ b/src/register/components/tests/ConfigurableRegistrationForm.test.jsx @@ -7,7 +7,7 @@ import { fireEvent, render } from '@testing-library/react'; import { BrowserRouter as Router } from 'react-router-dom'; import configureStore from 'redux-mock-store'; -import { testAppId } from '../../../setupTest'; +import { appId } from '../../../constants'; import { registerNewUser } from '../../data/actions'; import { FIELDS } from '../../data/constants'; import RegistrationPage from '../../RegistrationPage'; @@ -30,7 +30,7 @@ const IntlRegistrationPage = injectIntl(RegistrationPage); const mockStore = configureStore(); describe('ConfigurableRegistrationForm', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { PRIVACY_POLICY: 'https://privacy-policy.com', TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com', }); @@ -54,7 +54,7 @@ describe('ConfigurableRegistrationForm', () => { const reduxWrapper = children => ( - + {children} @@ -126,7 +126,7 @@ describe('ConfigurableRegistrationForm', () => { }; describe('Test Configurable Fields', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_DYNAMIC_REGISTRATION_FIELDS: true, }); @@ -201,7 +201,7 @@ describe('ConfigurableRegistrationForm', () => { }); it('should submit form with fields returned by backend in payload', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { ENABLE_DYNAMIC_REGISTRATION_FIELDS: true, }); getLocale.mockImplementation(() => ('en-us')); diff --git a/src/register/components/tests/RegistrationFailure.test.jsx b/src/register/components/tests/RegistrationFailure.test.jsx index e38ca183..a2c842dd 100644 --- a/src/register/components/tests/RegistrationFailure.test.jsx +++ b/src/register/components/tests/RegistrationFailure.test.jsx @@ -10,7 +10,7 @@ import configureStore from 'redux-mock-store'; import { FORBIDDEN_REQUEST, INTERNAL_SERVER_ERROR, TPA_AUTHENTICATION_FAILURE, TPA_SESSION_EXPIRED, } from '../../data/constants'; -import { testAppId } from '../../../setupTest'; +import { appId } from '../../../constants'; import RegistrationPage from '../../RegistrationPage'; import RegistrationFailureMessage from '../RegistrationFailure'; @@ -41,7 +41,7 @@ jest.mock('react-router-dom', () => { }); describe('RegistrationFailure', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { PRIVACY_POLICY: 'https://privacy-policy.com', TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com', USER_RETENTION_COOKIE_NAME: 'authn-returning-user', diff --git a/src/register/components/tests/ThirdPartyAuth.test.jsx b/src/register/components/tests/ThirdPartyAuth.test.jsx index 841feea4..2127e7a4 100644 --- a/src/register/components/tests/ThirdPartyAuth.test.jsx +++ b/src/register/components/tests/ThirdPartyAuth.test.jsx @@ -10,7 +10,7 @@ import configureStore from 'redux-mock-store'; import { COMPLETE_STATE, LOGIN_PAGE, PENDING_STATE, REGISTER_PAGE, } from '../../../data/constants'; -import { testAppId } from '../../../setupTest'; +import { appId } from '../../../constants'; import RegistrationPage from '../../RegistrationPage'; jest.mock('@openedx/frontend-base', () => ({ @@ -40,7 +40,7 @@ jest.mock('react-router-dom', () => { }); describe('ThirdPartyAuth', () => { - mergeAppConfig(testAppId, { + mergeAppConfig(appId, { PRIVACY_POLICY: 'https://privacy-policy.com', TOS_AND_HONOR_CODE: 'https://tos-and-honot-code.com', USER_RETENTION_COOKIE_NAME: 'authn-returning-user', diff --git a/src/reset-password/tests/ResetPasswordPage.test.jsx b/src/reset-password/tests/ResetPasswordPage.test.jsx index 59a3775f..e96125d1 100644 --- a/src/reset-password/tests/ResetPasswordPage.test.jsx +++ b/src/reset-password/tests/ResetPasswordPage.test.jsx @@ -8,7 +8,8 @@ import { act } from 'react-dom/test-utils'; import { MemoryRouter, useParams } from 'react-router-dom'; import configureStore from 'redux-mock-store'; -import { testAppId, initializeMockServices } from '../../setupTest'; +import { appId } from '../../constants'; +import { initializeMockServices } from '../../setupTest'; import { LOGIN_PAGE, RESET_PAGE } from '../../data/constants'; import { resetPassword, validateToken } from '../data/actions'; import { @@ -36,7 +37,7 @@ describe('ResetPasswordPage', () => { const reduxWrapper = children => ( - + {children} diff --git a/src/setupTest.js b/src/setupTest.js index 7f0fd54a..0f3df8d3 100755 --- a/src/setupTest.js +++ b/src/setupTest.js @@ -5,8 +5,6 @@ import { addAppConfigs, configureAnalytics, configureAuth, configureLogging, get mergeSiteConfig(siteConfig); addAppConfigs(); -export const testAppId = getSiteConfig().apps[0].appId; - export function initializeMockServices() { const loggingService = configureLogging(MockLoggingService, { config: getSiteConfig(), From 18951cc4d0391a3ae51ab168d129f510d914a693 Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Thu, 26 Jun 2025 21:33:24 -0300 Subject: [PATCH 07/10] chore: clean up npmignore --- .npmignore | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.npmignore b/.npmignore index 045beed3..bb212e05 100755 --- a/.npmignore +++ b/.npmignore @@ -1,11 +1,6 @@ -.eslintignore -.eslintrc.json -.gitignore -docker-compose.yml -Dockerfile -Makefile -npm-debug.log - -coverage +__mocks__ node_modules -public +*.test.js +*.test.jsx +*.test.ts +*.test.tsx From 1ecdb0b6af3b9fa53e09a0c363dd52f76bb37a95 Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Thu, 26 Jun 2025 22:08:57 -0300 Subject: [PATCH 08/10] chore: gitignore npm pack artifacts --- .gitignore | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index e7260e99..a6ce6be5 100755 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,15 @@ -.DS_Store -.eslintcache -.idea node_modules npm-debug.log coverage module.config.js - dist/ +/*.tgz + +### i18n ### src/i18n/transifex_input.json -temp/babel-plugin-react-intl -### pyenv ### -.python-version - -### Emacs ### +### Editors ### +.DS_Store *~ /temp /.vscode -src/i18n/messages From 033e0fd7c5390527b463f73398cd18f72e1d3ee3 Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Sat, 28 Jun 2025 19:18:34 +0200 Subject: [PATCH 09/10] feat: handle authentication roles --- src/routes.jsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/routes.jsx b/src/routes.jsx index f5fabdf9..d7b05169 100644 --- a/src/routes.jsx +++ b/src/routes.jsx @@ -19,34 +19,49 @@ const routes = [ path: 'register-embedded', element: ( - ) + ), }, { path: 'login', + handle: { + role: 'org.openedx.frontend.role.login', + }, element: ( - ) + ), }, { path: 'register', + handle: { + role: 'org.openedx.frontend.role.register', + }, element: ( ), }, { path: 'reset', + handle: { + role: 'org.openedx.frontend.role.resetPassword', + }, element: ( ), }, { path: 'password_reset_confirm/:token', + handle: { + role: 'org.openedx.frontend.role.confirmPassword', + }, element: ( ), }, { path: 'welcome', + handle: { + role: 'org.openedx.frontend.role.welcome', + }, element: ( ), From 095b156b9516839e4803d36743ff68cb12a9de00 Mon Sep 17 00:00:00 2001 From: "Adolfo R. Brandes" Date: Sat, 28 Jun 2025 19:27:26 +0200 Subject: [PATCH 10/10] chore: bump frontend-base --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 49c915d0..b1263cc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,14 +41,14 @@ "react-test-renderer": "^18.3.1" }, "peerDependencies": { - "@openedx/frontend-base": "^1.0.0-alpha.0", + "@openedx/frontend-base": "^1.0.0-alpha.1", "@openedx/paragon": "^22", "react": "^18", "react-dom": "^18", - "react-redux": "^8.1.3", + "react-redux": "^8", "react-router": "^6", "react-router-dom": "^6", - "redux": "^4.2.1" + "redux": "^4" } }, "node_modules/@ampproject/remapping": { @@ -3666,9 +3666,9 @@ } }, "node_modules/@openedx/frontend-base": { - "version": "1.0.0-alpha.0", - "resolved": "https://registry.npmjs.org/@openedx/frontend-base/-/frontend-base-1.0.0-alpha.0.tgz", - "integrity": "sha512-7IgkQcQZ7AeLVPpc26KpTS4VI01s3+vXfDrYFRJNcmCN8kjx7OhCMauIAMDmpA36cjm37NNndxIuihscsUo/Bg==", + "version": "1.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/@openedx/frontend-base/-/frontend-base-1.0.0-alpha.1.tgz", + "integrity": "sha512-8NSHhC32FMlvFhXBggCyNE1uZ0bghtq3a0iY8W0/7S+9XZUUOQrvb0w+YUIkpf0CrzxS8jV0eRh4W5EF4IBVyQ==", "license": "AGPL-3.0", "peer": true, "dependencies": { diff --git a/package.json b/package.json index 98a554fa..01f88cec 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "react-test-renderer": "^18.3.1" }, "peerDependencies": { - "@openedx/frontend-base": "^1.0.0-alpha.0", + "@openedx/frontend-base": "^1.0.0-alpha.1", "@openedx/paragon": "^22", "react": "^18", "react-dom": "^18",