Compare commits
146 Commits
remove-com
...
release/te
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e94124d74 | ||
|
|
af7edd8a3f | ||
|
|
9323f119c8 | ||
|
|
38a1924c6a | ||
|
|
2d7303009f | ||
|
|
dfcb94a831 | ||
|
|
520dd6ed6b | ||
|
|
1b32dbfa19 | ||
|
|
f7d9bdb5b5 | ||
|
|
063ec80cde | ||
|
|
3cbb134c3a | ||
|
|
059a60d1c8 | ||
|
|
c88d701271 | ||
|
|
33b98b356b | ||
|
|
1f81699af4 | ||
|
|
13aa77fc70 | ||
|
|
66531831b7 | ||
|
|
846d3f0662 | ||
|
|
f78e84ee0a | ||
|
|
2d27da2391 | ||
|
|
78413be34a | ||
|
|
88866a39c1 | ||
|
|
dc9699c033 | ||
|
|
00a0e27062 | ||
|
|
6839afcf3c | ||
|
|
1cd9c58c1a | ||
|
|
5d481a93c7 | ||
|
|
438d1fcfa7 | ||
|
|
bc912ce139 | ||
|
|
ab1c2d5379 | ||
|
|
c109f6e771 | ||
|
|
8976647190 | ||
|
|
cb051a83ad | ||
|
|
1b8aec5709 | ||
|
|
9a68e95fcc | ||
|
|
c90980afb0 | ||
|
|
abb8ae5085 | ||
|
|
8bb7462098 | ||
|
|
b4a5397ba1 | ||
|
|
a43c620dc4 | ||
|
|
93d11b8485 | ||
|
|
68e13d4daf | ||
|
|
f6617935e3 | ||
|
|
5f4591c046 | ||
|
|
ae52a8cb65 | ||
|
|
b8df66ad23 | ||
|
|
923776ab96 | ||
|
|
f170f5e3f0 | ||
|
|
730875ceb2 | ||
|
|
812350d24a | ||
|
|
6879bacb89 | ||
|
|
9b2b0f2019 | ||
|
|
87884f2d91 | ||
|
|
3e20fcae57 | ||
|
|
173896811d | ||
|
|
7af4a08bd9 | ||
|
|
6c12b3b034 | ||
|
|
5304085cd8 | ||
|
|
3cd9ae130c | ||
|
|
28ad2c2cf6 | ||
|
|
3e889df109 | ||
|
|
52c6efc34d | ||
|
|
584a84a99c | ||
|
|
7e4ab1c74c | ||
|
|
13d89cb3a0 | ||
|
|
5a1e2e6c97 | ||
|
|
6f1cf29a60 | ||
|
|
159f1ae30e | ||
|
|
e2e626552f | ||
|
|
308d7c62e4 | ||
|
|
0bc78da55d | ||
|
|
6527caea54 | ||
|
|
a52912e35b | ||
|
|
6479382b90 | ||
|
|
4ce36bb12c | ||
|
|
4cc7723984 | ||
|
|
3c3d359d4e | ||
|
|
cccbf3a9d1 | ||
|
|
4a3fd2ee8e | ||
|
|
48d7cb386a | ||
|
|
bdf9cab869 | ||
|
|
be02dabf40 | ||
|
|
c535fb9d24 | ||
|
|
8ab8d09b97 | ||
|
|
286c70d50f | ||
|
|
8939e5b91f | ||
|
|
bc9f7b3bce | ||
|
|
fd0bcb9e5f | ||
|
|
98e0167ef1 | ||
|
|
8091085f45 | ||
|
|
cd5abd1d9c | ||
|
|
2a88f435b9 | ||
|
|
fe1e9c5629 | ||
|
|
0e363ca724 | ||
|
|
c874638bd1 | ||
|
|
e5c3b1ed41 | ||
|
|
8a27b8cc37 | ||
|
|
046fbeab01 | ||
|
|
27ea509989 | ||
|
|
27f0508e6e | ||
|
|
c53fedf7a1 | ||
|
|
0f1a5e9aef | ||
|
|
6cb4b799b7 | ||
|
|
439b9161b5 | ||
|
|
6ffa45f0c1 | ||
|
|
a03ba3e3b3 | ||
|
|
e2a206caa5 | ||
|
|
3a963da819 | ||
|
|
4a65f0a84c | ||
|
|
9688bd3699 | ||
|
|
c123815a55 | ||
|
|
182e669593 | ||
|
|
65533b8d58 | ||
|
|
45185dba70 | ||
|
|
444c4b4434 | ||
|
|
d629d66bf2 | ||
|
|
9d46d68150 | ||
|
|
a4ed6a362e | ||
|
|
a1a0d3cd96 | ||
|
|
950c401e88 | ||
|
|
ce056c9ad2 | ||
|
|
3bd6e454d0 | ||
|
|
f52129a11e | ||
|
|
ea01050163 | ||
|
|
c1ec9b6e99 | ||
|
|
2c509b00ac | ||
|
|
ef358fe741 | ||
|
|
56e0520d9c | ||
|
|
1f7b7f5c41 | ||
|
|
471fa75155 | ||
|
|
c89d16e529 | ||
|
|
fc02ab820a | ||
|
|
ac23cdcc7a | ||
|
|
02c4c5be29 | ||
|
|
3bd7d61e3a | ||
|
|
32ebc69c0e | ||
|
|
c98c3b16c5 | ||
|
|
287fe3adfe | ||
|
|
d4e7b7b371 | ||
|
|
ad78f068e0 | ||
|
|
d156de2e66 | ||
|
|
99bca1bd9b | ||
|
|
8efb22595c | ||
|
|
73e8913f90 | ||
|
|
3ddaf795f2 | ||
|
|
a18df02d37 |
1
.env
1
.env
@@ -23,6 +23,7 @@ POST_REGISTRATION_REDIRECT_URL=''
|
|||||||
SEARCH_CATALOG_URL=''
|
SEARCH_CATALOG_URL=''
|
||||||
# ***** Features flags *****
|
# ***** Features flags *****
|
||||||
DISABLE_ENTERPRISE_LOGIN=''
|
DISABLE_ENTERPRISE_LOGIN=''
|
||||||
|
ENABLE_AUTO_GENERATED_USERNAME=''
|
||||||
ENABLE_DYNAMIC_REGISTRATION_FIELDS=''
|
ENABLE_DYNAMIC_REGISTRATION_FIELDS=''
|
||||||
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN=''
|
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN=''
|
||||||
ENABLE_POST_REGISTRATION_RECOMMENDATIONS=''
|
ENABLE_POST_REGISTRATION_RECOMMENDATIONS=''
|
||||||
|
|||||||
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* @openedx/2U-infinity
|
||||||
7
.github/dependabot.yml
vendored
Normal file
7
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# Adding new check for github-actions
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -25,5 +25,5 @@ Include a link to the sandbox for design changes or screenshot for before and af
|
|||||||
|
|
||||||
#### Post-merge Checklist
|
#### Post-merge Checklist
|
||||||
|
|
||||||
* [ ] Deploy the changes to prod after verifying on stage or ask **@openedx/2u-vanguards** to do it.
|
* [ ] Deploy the changes to prod after verifying on stage or ask **@openedx/2u-infinity** to do it.
|
||||||
* [ ] 🎉 🙌 Celebrate! Thanks for your contribution.
|
* [ ] 🎉 🙌 Celebrate! Thanks for your contribution.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
autoupdate:
|
autoupdate:
|
||||||
name: autoupdate
|
name: autoupdate
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: docker://chinthakagodawita/autoupdate-action:v1
|
- uses: docker://chinthakagodawita/autoupdate-action:v1
|
||||||
env:
|
env:
|
||||||
|
|||||||
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
@@ -10,17 +10,15 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Setup Nodejs Env
|
|
||||||
run: echo "NODE_VER=`cat .nvmrc`" >> $GITHUB_ENV
|
|
||||||
- name: Setup Nodejs
|
- name: Setup Nodejs
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VER }}
|
node-version-file: '.nvmrc'
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
@@ -41,4 +39,7 @@ jobs:
|
|||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
- name: Run Code Coverage
|
- name: Run Code Coverage
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v5
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
fail_ci_if_error: true
|
||||||
|
|||||||
2
.github/workflows/lockfileversion-check.yml
vendored
2
.github/workflows/lockfileversion-check.yml
vendored
@@ -10,4 +10,4 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
version-check:
|
version-check:
|
||||||
uses: openedx/.github/.github/workflows/lockfile-check.yml@master
|
uses: openedx/.github/.github/workflows/lockfileversion-check-v3.yml@master
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
# The following users are the owners of all frontend-app-authn files
|
# The following users are the owners of all frontend-app-authn files
|
||||||
* @openedx/2u-vanguards
|
* @openedx/2u-infinity
|
||||||
|
|||||||
16
README.rst
16
README.rst
@@ -29,7 +29,13 @@ Getting Started
|
|||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
This MFE is bundled with `Devstack <https://github.com/openedx/devstack>`_, see the `Getting Started <https://github.com/openedx/devstack#getting-started>`_ section for setup instructions.
|
`Tutor`_ is currently recommended as a development environment for your new MFE. Please refer to the `relevant tutor-mfe documentation`_ to get started using it.
|
||||||
|
|
||||||
|
.. _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 <https://github.com/openedx/devstack#getting-started>`_ instructions.
|
1. Install Devstack using the `Getting Started <https://github.com/openedx/devstack#getting-started>`_ instructions.
|
||||||
|
|
||||||
@@ -51,7 +57,7 @@ This MFE is bundled with `Devstack <https://github.com/openedx/devstack>`_, see
|
|||||||
Environment Variables/Setup Notes
|
Environment Variables/Setup Notes
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
This MFE is configured via environment variables supplied at build time. All micro-frontends have a shared set of required environment variables, as documented in the Open edX Developer Guide under `Required Environment Variables <https://edx.readthedocs.io/projects/edx-developer-docs/en/latest/developers_guide/micro_frontends_in_open_edx.html#required-environment-variables>`__.
|
This MFE is configured via environment variables supplied at build time. All micro-frontends have a shared set of required environment variables, as documented in the Open edX Developer Guide under `Required Environment Variables <https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development>`__.
|
||||||
|
|
||||||
The authentication micro-frontend also requires the following additional variable:
|
The authentication micro-frontend also requires the following additional variable:
|
||||||
|
|
||||||
@@ -142,13 +148,13 @@ Furthermore, there are several edX-specific environment variables that enable in
|
|||||||
- ``true`` | ``''`` (empty strings are falsy)
|
- ``true`` | ``''`` (empty strings are falsy)
|
||||||
|
|
||||||
For more information see the document: `Micro-frontend applications in Open
|
For more information see the document: `Micro-frontend applications in Open
|
||||||
edX <https://edx.readthedocs.io/projects/edx-developer-docs/en/latest/developers_guide/micro_frontends_in_open_edx.html#required-environment-variables>`__.
|
edX <https://github.com/overhangio/tutor-mfe?tab=readme-ov-file#mfe-development>`__.
|
||||||
|
|
||||||
How To Contribute
|
How To Contribute
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Contributions are very welcome, and strongly encouraged! We've
|
Contributions are very welcome, and strongly encouraged! We've
|
||||||
put together `some documentation that describes our contribution process <https://edx.readthedocs.org/projects/edx-developer-guide/en/latest/process/index.html>`_.
|
put together `some documentation that describes our contribution process <https://docs.openedx.org/en/latest/developers/references/developer_guide/process/index.html>`_.
|
||||||
|
|
||||||
Even though they were written with edx-platform in mind, the guidelines should be followed for Open edX code in general.
|
Even though they were written with edx-platform in mind, the guidelines should be followed for Open edX code in general.
|
||||||
|
|
||||||
@@ -187,7 +193,7 @@ All community members are expected to follow the `Open edX Code of Conduct <http
|
|||||||
People
|
People
|
||||||
======
|
======
|
||||||
The assigned maintainers for this component and other project details may be
|
The assigned maintainers for this component and other project details may be
|
||||||
found in `Backstage <https://backstage.openedx.org/catalog/default/group/2u-vanguards>`_. Backstage pulls this data from the ``catalog-info.yaml``
|
found in `Backstage <https://backstage.openedx.org/catalog/default/group/2u-infinity>`_. Backstage pulls this data from the ``catalog-info.yaml``
|
||||||
file in this repo.
|
file in this repo.
|
||||||
|
|
||||||
Reporting Security Issues
|
Reporting Security Issues
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ metadata:
|
|||||||
icon: 'Article'
|
icon: 'Article'
|
||||||
annotations:
|
annotations:
|
||||||
openedx.org/arch-interest-groups: ""
|
openedx.org/arch-interest-groups: ""
|
||||||
|
openedx.org/release: "master"
|
||||||
spec:
|
spec:
|
||||||
owner: group:2u-vanguards
|
owner: group:2u-infinity
|
||||||
type: 'service'
|
type: 'service'
|
||||||
lifecycle: 'production'
|
lifecycle: 'production'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Enable Social Auth Locally
|
|||||||
|
|
||||||
Please follow the steps below to enable social auth (SSO) locally.
|
Please follow the steps below to enable social auth (SSO) locally.
|
||||||
|
|
||||||
1. Follow `Enabling Third Party Authentication <https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/latest/configuration/tpa/index.html>`_ for backend configuration.
|
1. Follow `Enabling Third Party Authentication <https://docs.openedx.org/en/latest/site_ops/install_configure_run_guide/configuration/tpa/index.html>`_ for backend configuration.
|
||||||
|
|
||||||
2. Authn has a component for rendering Social Auth providers at frontend which goes through each provider.
|
2. Authn has a component for rendering Social Auth providers at frontend which goes through each provider.
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
# This file describes this Open edX repo, as described in OEP-2:
|
|
||||||
# http://open-edx-proposals.readthedocs.io/en/latest/oeps/oep-0002.html#specification
|
|
||||||
|
|
||||||
nick: Authn MFE
|
|
||||||
oeps: {}
|
|
||||||
owner: openedx/2u-vanguards
|
|
||||||
openedx-release:
|
|
||||||
ref: master
|
|
||||||
23086
package-lock.json
generated
23086
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
53
package.json
53
package.json
@@ -13,15 +13,12 @@
|
|||||||
"build": "fedx-scripts webpack",
|
"build": "fedx-scripts webpack",
|
||||||
"i18n_extract": "fedx-scripts formatjs extract",
|
"i18n_extract": "fedx-scripts formatjs extract",
|
||||||
"lint": "fedx-scripts eslint --ext .js --ext .jsx .",
|
"lint": "fedx-scripts eslint --ext .js --ext .jsx .",
|
||||||
|
"lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .",
|
||||||
"snapshot": "fedx-scripts jest --updateSnapshot",
|
"snapshot": "fedx-scripts jest --updateSnapshot",
|
||||||
"start": "fedx-scripts webpack-dev-server --progress",
|
"start": "fedx-scripts webpack-dev-server --progress",
|
||||||
|
"dev": "PUBLIC_PATH=/authn/ MFE_CONFIG_API_URL='http://localhost:8000/api/mfe_config/v1' fedx-scripts webpack-dev-server --progress --host apps.local.openedx.io",
|
||||||
"test": "fedx-scripts jest --coverage --passWithNoTests"
|
"test": "fedx-scripts jest --coverage --passWithNoTests"
|
||||||
},
|
},
|
||||||
"husky": {
|
|
||||||
"hooks": {
|
|
||||||
"pre-commit": "npm run lint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"author": "edX",
|
"author": "edX",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"homepage": "https://github.com/openedx/frontend-app-authn#readme",
|
"homepage": "https://github.com/openedx/frontend-app-authn#readme",
|
||||||
@@ -33,53 +30,51 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
|
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
|
||||||
"@edx/frontend-platform": "7.1.3",
|
"@edx/frontend-platform": "^8.3.1",
|
||||||
"@edx/openedx-atlas": "^0.6.0",
|
"@edx/openedx-atlas": "^0.6.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "6.5.2",
|
"@fortawesome/fontawesome-svg-core": "6.7.2",
|
||||||
"@fortawesome/free-brands-svg-icons": "6.5.2",
|
"@fortawesome/free-brands-svg-icons": "6.7.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "6.5.2",
|
"@fortawesome/free-solid-svg-icons": "6.7.2",
|
||||||
"@fortawesome/react-fontawesome": "0.2.0",
|
"@fortawesome/react-fontawesome": "0.2.2",
|
||||||
"@openedx/paragon": "^22.1.1",
|
"@openedx/paragon": "^22.16.0",
|
||||||
"@optimizely/react-sdk": "^2.9.1",
|
"@optimizely/react-sdk": "^2.9.1",
|
||||||
"@redux-devtools/extension": "3.3.0",
|
"@redux-devtools/extension": "3.3.0",
|
||||||
"@testing-library/react": "^12.1.5",
|
"@testing-library/react": "^16.2.0",
|
||||||
"@testing-library/react-hooks": "^8.0.1",
|
|
||||||
"algoliasearch": "^4.14.3",
|
"algoliasearch": "^4.14.3",
|
||||||
"algoliasearch-helper": "^3.14.0",
|
"algoliasearch-helper": "^3.14.0",
|
||||||
"classnames": "2.5.1",
|
"classnames": "2.5.1",
|
||||||
"core-js": "3.36.1",
|
"core-js": "3.41.0",
|
||||||
"fastest-levenshtein": "1.0.16",
|
"fastest-levenshtein": "1.0.16",
|
||||||
"form-urlencoded": "6.1.4",
|
"form-urlencoded": "6.1.5",
|
||||||
"prop-types": "15.8.1",
|
"prop-types": "15.8.1",
|
||||||
"query-string": "7.1.3",
|
"query-string": "7.1.3",
|
||||||
"react": "^17.0.2",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.3.1",
|
||||||
"react-helmet": "6.1.0",
|
"react-helmet": "6.1.0",
|
||||||
"react-loading-skeleton": "3.4.0",
|
"react-loading-skeleton": "3.5.0",
|
||||||
"react-redux": "7.2.9",
|
"react-redux": "7.2.9",
|
||||||
"react-responsive": "8.2.0",
|
"react-responsive": "8.2.0",
|
||||||
"react-router": "6.22.3",
|
"react-router": "6.30.0",
|
||||||
"react-router-dom": "6.22.3",
|
"react-router-dom": "6.30.0",
|
||||||
"react-zendesk": "^0.1.13",
|
"react-zendesk": "^0.1.13",
|
||||||
"redux": "4.2.0",
|
"redux": "4.2.1",
|
||||||
"redux-logger": "3.0.6",
|
"redux-logger": "3.0.6",
|
||||||
"redux-mock-store": "1.5.4",
|
"redux-mock-store": "1.5.5",
|
||||||
"redux-saga": "1.3.0",
|
"redux-saga": "1.3.0",
|
||||||
"redux-thunk": "2.4.2",
|
"redux-thunk": "2.4.2",
|
||||||
"regenerator-runtime": "0.14.1",
|
"regenerator-runtime": "0.14.1",
|
||||||
"reselect": "4.1.8",
|
"reselect": "5.1.1",
|
||||||
"universal-cookie": "4.0.4"
|
"universal-cookie": "7.2.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@edx/browserslist-config": "^1.1.1",
|
"@edx/browserslist-config": "^1.1.1",
|
||||||
"@edx/reactifex": "1.1.0",
|
"@edx/reactifex": "1.1.0",
|
||||||
"@openedx/frontend-build": "13.1.4",
|
"@openedx/frontend-build": "^14.4.2",
|
||||||
"babel-plugin-formatjs": "10.5.14",
|
"babel-plugin-formatjs": "10.5.37",
|
||||||
"eslint-plugin-import": "2.29.1",
|
"eslint-plugin-import": "2.31.0",
|
||||||
"glob": "7.2.3",
|
"glob": "7.2.3",
|
||||||
"history": "5.3.0",
|
"history": "5.3.0",
|
||||||
"husky": "7.0.4",
|
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"react-test-renderer": "^17.0.2"
|
"react-test-renderer": "^18.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="shortcut icon" href="<%=htmlWebpackPlugin.options.FAVICON_URL%>" type="image/x-icon"/>
|
<link rel="shortcut icon" href="<%=htmlWebpackPlugin.options.FAVICON_URL%>" type="image/x-icon"/>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.9/iframeResizer.contentWindow.min.js"
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.4.4/iframeResizer.contentWindow.min.js"
|
||||||
integrity="sha512-mdT/HQRzoRP4laVz49Mndx6rcCGA3IhuyhP3gaY0E9sZPkwbtDk9ttQIq9o8qGCf5VvJv1Xsy3k2yTjfUoczqw=="
|
integrity="sha512-IWwZFBvHzN41wNI6etRLLuLrDDj/6AwJcPt7cmKJAzluYTIHHQ1PF8wh0rSy05jxEvvjflVvH2MxeV6riyEEXg=="
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
referrerpolicy="no-referrer">
|
referrerpolicy="no-referrer">
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ const ThirdPartyAuth = (props) => {
|
|||||||
const isSocialAuthActive = !!providers.length && !currentProvider;
|
const isSocialAuthActive = !!providers.length && !currentProvider;
|
||||||
const isEnterpriseLoginDisabled = getConfig().DISABLE_ENTERPRISE_LOGIN;
|
const isEnterpriseLoginDisabled = getConfig().DISABLE_ENTERPRISE_LOGIN;
|
||||||
const enterpriseLoginURL = getConfig().LMS_BASE_URL + ENTERPRISE_LOGIN_URL;
|
const enterpriseLoginURL = getConfig().LMS_BASE_URL + ENTERPRISE_LOGIN_URL;
|
||||||
|
const isThirdPartyAuthActive = isSocialAuthActive || (isEnterpriseLoginDisabled && isInstitutionAuthActive);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -61,7 +62,7 @@ const ThirdPartyAuth = (props) => {
|
|||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{thirdPartyAuthApiStatus === PENDING_STATE ? (
|
{thirdPartyAuthApiStatus === PENDING_STATE && isThirdPartyAuthActive ? (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<Skeleton className="tpa-skeleton" height={36} count={2} />
|
<Skeleton className="tpa-skeleton" height={36} count={2} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,14 +5,13 @@ import React from 'react';
|
|||||||
import { getConfig } from '@edx/frontend-platform';
|
import { getConfig } from '@edx/frontend-platform';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
|
|
||||||
import { PAGE_NOT_FOUND, REGISTER_EMBEDDED_PAGE } from '../../data/constants';
|
|
||||||
import EmbeddedRegistrationRoute from '../EmbeddedRegistrationRoute';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MemoryRouter, Route, BrowserRouter as Router, Routes,
|
MemoryRouter, Route, BrowserRouter as Router, Routes,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
|
import { PAGE_NOT_FOUND, REGISTER_EMBEDDED_PAGE } from '../../data/constants';
|
||||||
|
import EmbeddedRegistrationRoute from '../EmbeddedRegistrationRoute';
|
||||||
|
|
||||||
const RRD = require('react-router-dom');
|
const RRD = require('react-router-dom');
|
||||||
// Just render plain div with its children
|
// Just render plain div with its children
|
||||||
// eslint-disable-next-line react/prop-types
|
// eslint-disable-next-line react/prop-types
|
||||||
|
|||||||
@@ -5,14 +5,13 @@ import React from 'react';
|
|||||||
import { fetchAuthenticatedUser, getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
import { fetchAuthenticatedUser, getAuthenticatedUser } from '@edx/frontend-platform/auth';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
|
|
||||||
import { UnAuthOnlyRoute } from '..';
|
|
||||||
import { REGISTER_PAGE } from '../../data/constants';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MemoryRouter, Route, BrowserRouter as Router, Routes,
|
MemoryRouter, Route, BrowserRouter as Router, Routes,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
|
import { UnAuthOnlyRoute } from '..';
|
||||||
|
import { REGISTER_PAGE } from '../../data/constants';
|
||||||
|
|
||||||
jest.mock('@edx/frontend-platform/auth', () => ({
|
jest.mock('@edx/frontend-platform/auth', () => ({
|
||||||
getAuthenticatedUser: jest.fn(),
|
getAuthenticatedUser: jest.fn(),
|
||||||
fetchAuthenticatedUser: jest.fn(),
|
fetchAuthenticatedUser: jest.fn(),
|
||||||
|
|||||||
@@ -66,14 +66,14 @@ exports[`SocialAuthProviders should match social auth provider with iconClass sn
|
|||||||
data-prefix="fab"
|
data-prefix="fab"
|
||||||
focusable="false"
|
focusable="false"
|
||||||
role="img"
|
role="img"
|
||||||
style={Object {}}
|
style={{}}
|
||||||
viewBox="0 0 488 512"
|
viewBox="0 0 488 512"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z"
|
d="M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
style={Object {}}
|
style={{}}
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,7 +93,7 @@ exports[`SocialAuthProviders should match social auth provider with iconClass sn
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`SocialAuthProviders should match social auth provider with iconImage snapshot 1`] = `
|
exports[`SocialAuthProviders should match social auth provider with iconImage snapshot 1`] = `
|
||||||
Array [
|
[
|
||||||
<button
|
<button
|
||||||
className="btn-social btn-oa2-apple-id mr-3"
|
className="btn-social btn-oa2-apple-id mr-3"
|
||||||
data-provider-url="/auth/login/apple-id/?auth_entry=login&next=/dashboard"
|
data-provider-url="/auth/login/apple-id/?auth_entry=login&next=/dashboard"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ exports[`ThirdPartyAuthAlert should match login page third party auth alert mess
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`ThirdPartyAuthAlert should match register page third party auth alert message snapshot 1`] = `
|
exports[`ThirdPartyAuthAlert should match register page third party auth alert message snapshot 1`] = `
|
||||||
Array [
|
[
|
||||||
<div
|
<div
|
||||||
className="fade alert-content alert-success mt-n2 mb-5 alert show"
|
className="fade alert-content alert-success mt-n2 mb-5 alert show"
|
||||||
id="tpa-alert"
|
id="tpa-alert"
|
||||||
|
|||||||
@@ -5,23 +5,23 @@ exports[`Zendesk Help should match login page third party auth alert message sna
|
|||||||
cookies={true}
|
cookies={true}
|
||||||
defer={true}
|
defer={true}
|
||||||
webWidget={
|
webWidget={
|
||||||
Object {
|
{
|
||||||
"answerBot": Object {
|
"answerBot": {
|
||||||
"avatar": Object {
|
"avatar": {
|
||||||
"name": Object {
|
"name": {
|
||||||
"*": "edX Support",
|
"*": "edX Support",
|
||||||
},
|
},
|
||||||
"url": undefined,
|
"url": undefined,
|
||||||
},
|
},
|
||||||
"contactOnlyAfterQuery": true,
|
"contactOnlyAfterQuery": true,
|
||||||
"suppress": false,
|
"suppress": false,
|
||||||
"title": Object {
|
"title": {
|
||||||
"*": "edX Support",
|
"*": "edX Support",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"chat": Object {
|
"chat": {
|
||||||
"departments": Object {
|
"departments": {
|
||||||
"enabled": Array [
|
"enabled": [
|
||||||
"account settings",
|
"account settings",
|
||||||
"billing and payments",
|
"billing and payments",
|
||||||
"certificates",
|
"certificates",
|
||||||
@@ -33,17 +33,17 @@ exports[`Zendesk Help should match login page third party auth alert message sna
|
|||||||
},
|
},
|
||||||
"suppress": false,
|
"suppress": false,
|
||||||
},
|
},
|
||||||
"contactForm": Object {
|
"contactForm": {
|
||||||
"attachments": true,
|
"attachments": true,
|
||||||
"selectTicketForm": Object {
|
"selectTicketForm": {
|
||||||
"*": "Please choose your request type:",
|
"*": "Please choose your request type:",
|
||||||
},
|
},
|
||||||
"ticketForms": Array [
|
"ticketForms": [
|
||||||
Object {
|
{
|
||||||
"fields": Array [
|
"fields": [
|
||||||
Object {
|
{
|
||||||
"id": "description",
|
"id": "description",
|
||||||
"prefill": Object {
|
"prefill": {
|
||||||
"*": "",
|
"*": "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -53,10 +53,10 @@ exports[`Zendesk Help should match login page third party auth alert message sna
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"contactOptions": Object {
|
"contactOptions": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
},
|
},
|
||||||
"helpCenter": Object {
|
"helpCenter": {
|
||||||
"originalArticleButton": true,
|
"originalArticleButton": true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const configuration = {
|
|||||||
USER_RETENTION_COOKIE_NAME: process.env.USER_RETENTION_COOKIE_NAME || '',
|
USER_RETENTION_COOKIE_NAME: process.env.USER_RETENTION_COOKIE_NAME || '',
|
||||||
// Features
|
// Features
|
||||||
DISABLE_ENTERPRISE_LOGIN: process.env.DISABLE_ENTERPRISE_LOGIN || '',
|
DISABLE_ENTERPRISE_LOGIN: process.env.DISABLE_ENTERPRISE_LOGIN || '',
|
||||||
|
ENABLE_AUTO_GENERATED_USERNAME: process.env.ENABLE_AUTO_GENERATED_USERNAME || false,
|
||||||
ENABLE_DYNAMIC_REGISTRATION_FIELDS: process.env.ENABLE_DYNAMIC_REGISTRATION_FIELDS || false,
|
ENABLE_DYNAMIC_REGISTRATION_FIELDS: process.env.ENABLE_DYNAMIC_REGISTRATION_FIELDS || false,
|
||||||
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: process.env.ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN || false,
|
ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN: process.env.ENABLE_PROGRESSIVE_PROFILING_ON_AUTHN || false,
|
||||||
ENABLE_POST_REGISTRATION_RECOMMENDATIONS: process.env.ENABLE_POST_REGISTRATION_RECOMMENDATIONS || false,
|
ENABLE_POST_REGISTRATION_RECOMMENDATIONS: process.env.ENABLE_POST_REGISTRATION_RECOMMENDATIONS || false,
|
||||||
|
|||||||
@@ -1,27 +1,36 @@
|
|||||||
import 'core-js/stable';
|
import 'core-js/stable';
|
||||||
import 'regenerator-runtime/runtime';
|
import 'regenerator-runtime/runtime';
|
||||||
|
|
||||||
import React from 'react';
|
import React, { StrictMode } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
APP_INIT_ERROR, APP_READY, initialize, mergeConfig, subscribe,
|
APP_INIT_ERROR, APP_READY, initialize, mergeConfig, subscribe,
|
||||||
} from '@edx/frontend-platform';
|
} from '@edx/frontend-platform';
|
||||||
import { ErrorPage } from '@edx/frontend-platform/react';
|
import { ErrorPage } from '@edx/frontend-platform/react';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
import configuration from './config';
|
import configuration from './config';
|
||||||
import messages from './i18n';
|
import messages from './i18n';
|
||||||
import MainApp from './MainApp';
|
import MainApp from './MainApp';
|
||||||
|
|
||||||
subscribe(APP_READY, () => {
|
subscribe(APP_READY, () => {
|
||||||
ReactDOM.render(
|
const root = createRoot(document.getElementById('root'));
|
||||||
<MainApp />,
|
|
||||||
document.getElementById('root'),
|
root.render(
|
||||||
|
<StrictMode>
|
||||||
|
<MainApp />
|
||||||
|
</StrictMode>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
subscribe(APP_INIT_ERROR, (error) => {
|
subscribe(APP_INIT_ERROR, (error) => {
|
||||||
ReactDOM.render(<ErrorPage message={error.message} />, document.getElementById('root'));
|
const root = createRoot(document.getElementById('root'));
|
||||||
|
|
||||||
|
root.render(
|
||||||
|
<StrictMode>
|
||||||
|
<ErrorPage message={error.message} />
|
||||||
|
</StrictMode>,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
initialize({
|
initialize({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { renderHook } from '@testing-library/react-hooks';
|
import { renderHook } from '@testing-library/react';
|
||||||
import algoliasearchHelper from 'algoliasearch-helper';
|
import algoliasearchHelper from 'algoliasearch-helper';
|
||||||
|
|
||||||
import mockedRecommendedProducts from './mockedData';
|
import mockedRecommendedProducts from './mockedData';
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ const CountryField = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getCountryList = () => countryList.map((country) => (
|
const getCountryList = () => countryList.map((country) => (
|
||||||
<FormAutosuggestOption key={country[COUNTRY_CODE_KEY]} id={country[COUNTRY_CODE_KEY]}>
|
<FormAutosuggestOption key={country[COUNTRY_DISPLAY_KEY]} id={country[COUNTRY_CODE_KEY]}>
|
||||||
{country[COUNTRY_DISPLAY_KEY]}
|
{country[COUNTRY_DISPLAY_KEY]}
|
||||||
</FormAutosuggestOption>
|
</FormAutosuggestOption>
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ const RegistrationPage = (props) => {
|
|||||||
showConfigurableEdxFields: getConfig().SHOW_CONFIGURABLE_EDX_FIELDS,
|
showConfigurableEdxFields: getConfig().SHOW_CONFIGURABLE_EDX_FIELDS,
|
||||||
showConfigurableRegistrationFields: getConfig().ENABLE_DYNAMIC_REGISTRATION_FIELDS,
|
showConfigurableRegistrationFields: getConfig().ENABLE_DYNAMIC_REGISTRATION_FIELDS,
|
||||||
showMarketingEmailOptInCheckbox: getConfig().MARKETING_EMAILS_OPT_IN,
|
showMarketingEmailOptInCheckbox: getConfig().MARKETING_EMAILS_OPT_IN,
|
||||||
|
autoGeneratedUsernameEnabled: getConfig().ENABLE_AUTO_GENERATED_USERNAME,
|
||||||
};
|
};
|
||||||
const {
|
const {
|
||||||
handleInstitutionLogin,
|
handleInstitutionLogin,
|
||||||
@@ -215,6 +216,9 @@ const RegistrationPage = (props) => {
|
|||||||
delete payload.password;
|
delete payload.password;
|
||||||
payload.social_auth_provider = currentProvider;
|
payload.social_auth_provider = currentProvider;
|
||||||
}
|
}
|
||||||
|
if (flags.autoGeneratedUsernameEnabled) {
|
||||||
|
delete payload.username;
|
||||||
|
}
|
||||||
|
|
||||||
// Validating form data before submitting
|
// Validating form data before submitting
|
||||||
const { isValid, fieldErrors, emailSuggestion } = isFormValid(
|
const { isValid, fieldErrors, emailSuggestion } = isFormValid(
|
||||||
@@ -324,16 +328,18 @@ const RegistrationPage = (props) => {
|
|||||||
helpText={[formatMessage(messages['help.text.email'])]}
|
helpText={[formatMessage(messages['help.text.email'])]}
|
||||||
floatingLabel={formatMessage(messages['registration.email.label'])}
|
floatingLabel={formatMessage(messages['registration.email.label'])}
|
||||||
/>
|
/>
|
||||||
<UsernameField
|
{!flags.autoGeneratedUsernameEnabled && (
|
||||||
name="username"
|
<UsernameField
|
||||||
spellCheck="false"
|
name="username"
|
||||||
value={formFields.username}
|
spellCheck="false"
|
||||||
handleChange={handleOnChange}
|
value={formFields.username}
|
||||||
handleErrorChange={handleErrorChange}
|
handleChange={handleOnChange}
|
||||||
errorMessage={errors.username}
|
handleErrorChange={handleErrorChange}
|
||||||
helpText={[formatMessage(messages['help.text.username.1']), formatMessage(messages['help.text.username.2'])]}
|
errorMessage={errors.username}
|
||||||
floatingLabel={formatMessage(messages['registration.username.label'])}
|
helpText={[formatMessage(messages['help.text.username.1']), formatMessage(messages['help.text.username.2'])]}
|
||||||
/>
|
floatingLabel={formatMessage(messages['registration.username.label'])}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{!currentProvider && (
|
{!currentProvider && (
|
||||||
<PasswordField
|
<PasswordField
|
||||||
name="password"
|
name="password"
|
||||||
|
|||||||
@@ -134,9 +134,16 @@ describe('RegistrationPage', () => {
|
|||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
const populateRequiredFields = (getByLabelText, payload, isThirdPartyAuth = false) => {
|
const populateRequiredFields = (
|
||||||
|
getByLabelText,
|
||||||
|
payload,
|
||||||
|
isThirdPartyAuth = false,
|
||||||
|
autoGeneratedUsernameEnabled = false,
|
||||||
|
) => {
|
||||||
fireEvent.change(getByLabelText('Full name'), { target: { value: payload.name, name: 'name' } });
|
fireEvent.change(getByLabelText('Full name'), { target: { value: payload.name, name: 'name' } });
|
||||||
fireEvent.change(getByLabelText('Public username'), { target: { value: payload.username, name: 'username' } });
|
if (!autoGeneratedUsernameEnabled) {
|
||||||
|
fireEvent.change(getByLabelText('Public username'), { target: { value: payload.username, name: 'username' } });
|
||||||
|
}
|
||||||
fireEvent.change(getByLabelText('Email'), { target: { value: payload.email, name: 'email' } });
|
fireEvent.change(getByLabelText('Email'), { target: { value: payload.email, name: 'email' } });
|
||||||
|
|
||||||
fireEvent.change(getByLabelText('Country/Region'), { target: { value: payload.country, name: 'country' } });
|
fireEvent.change(getByLabelText('Country/Region'), { target: { value: payload.country, name: 'country' } });
|
||||||
@@ -176,7 +183,7 @@ describe('RegistrationPage', () => {
|
|||||||
password: 'password1',
|
password: 'password1',
|
||||||
country: 'Pakistan',
|
country: 'Pakistan',
|
||||||
honor_code: true,
|
honor_code: true,
|
||||||
totalRegistrationTime: 0,
|
total_registration_time: 0,
|
||||||
next: '/course/demo-course-url',
|
next: '/course/demo-course-url',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -199,7 +206,7 @@ describe('RegistrationPage', () => {
|
|||||||
country: 'Pakistan',
|
country: 'Pakistan',
|
||||||
honor_code: true,
|
honor_code: true,
|
||||||
social_auth_provider: 'Apple',
|
social_auth_provider: 'Apple',
|
||||||
totalRegistrationTime: 0,
|
total_registration_time: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
store = mockStore({
|
store = mockStore({
|
||||||
@@ -232,7 +239,7 @@ describe('RegistrationPage', () => {
|
|||||||
password: 'password1',
|
password: 'password1',
|
||||||
country: 'Ukraine',
|
country: 'Ukraine',
|
||||||
honor_code: true,
|
honor_code: true,
|
||||||
totalRegistrationTime: 0,
|
total_registration_time: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
store.dispatch = jest.fn(store.dispatch);
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
@@ -257,7 +264,7 @@ describe('RegistrationPage', () => {
|
|||||||
password: 'password1',
|
password: 'password1',
|
||||||
country: 'Ukraine',
|
country: 'Ukraine',
|
||||||
honor_code: true,
|
honor_code: true,
|
||||||
totalRegistrationTime: 0,
|
total_registration_time: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
store.dispatch = jest.fn(store.dispatch);
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
@@ -283,7 +290,7 @@ describe('RegistrationPage', () => {
|
|||||||
password: 'password1',
|
password: 'password1',
|
||||||
country: 'Pakistan',
|
country: 'Pakistan',
|
||||||
honor_code: true,
|
honor_code: true,
|
||||||
totalRegistrationTime: 0,
|
total_registration_time: 0,
|
||||||
marketing_emails_opt_in: true,
|
marketing_emails_opt_in: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -299,6 +306,44 @@ describe('RegistrationPage', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should submit form without UsernameField when autoGeneratedUsernameEnabled is true', () => {
|
||||||
|
mergeConfig({
|
||||||
|
ENABLE_AUTO_GENERATED_USERNAME: true,
|
||||||
|
});
|
||||||
|
jest.spyOn(global.Date, 'now').mockImplementation(() => 0);
|
||||||
|
const payload = {
|
||||||
|
name: 'John Doe',
|
||||||
|
email: 'john.doe@gmail.com',
|
||||||
|
password: 'password1',
|
||||||
|
country: 'Pakistan',
|
||||||
|
honor_code: true,
|
||||||
|
total_registration_time: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
|
const { getByLabelText, container } = render(routerWrapper(reduxWrapper(<IntlRegistrationPage {...props} />)));
|
||||||
|
populateRequiredFields(getByLabelText, payload, false, true);
|
||||||
|
const button = container.querySelector('button.btn-brand');
|
||||||
|
fireEvent.click(button);
|
||||||
|
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...payload, country: 'PK' }));
|
||||||
|
mergeConfig({
|
||||||
|
ENABLE_AUTO_GENERATED_USERNAME: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display UsernameField when ENABLE_AUTO_GENERATED_USERNAME is true', () => {
|
||||||
|
mergeConfig({
|
||||||
|
ENABLE_AUTO_GENERATED_USERNAME: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryByLabelText } = render(routerWrapper(reduxWrapper(<IntlRegistrationPage {...props} />)));
|
||||||
|
expect(queryByLabelText('Username')).toBeNull();
|
||||||
|
|
||||||
|
mergeConfig({
|
||||||
|
ENABLE_AUTO_GENERATED_USERNAME: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should not dispatch registerNewUser on empty form Submission', () => {
|
it('should not dispatch registerNewUser on empty form Submission', () => {
|
||||||
store.dispatch = jest.fn(store.dispatch);
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
|
|
||||||
@@ -837,7 +882,7 @@ describe('RegistrationPage', () => {
|
|||||||
email: 'john.doe@example.com',
|
email: 'john.doe@example.com',
|
||||||
country: 'PK',
|
country: 'PK',
|
||||||
social_auth_provider: 'Apple',
|
social_auth_provider: 'Apple',
|
||||||
totalRegistrationTime: 0,
|
total_registration_time: 0,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ const ConfigurableRegistrationForm = (props) => {
|
|||||||
autoSubmitRegistrationForm,
|
autoSubmitRegistrationForm,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const countryList = useMemo(() => getCountryList(getLocale()), []);
|
/** The reason for adding the entry 'United States' is that Chrome browser aut-fill the form with the 'Unites
|
||||||
|
States' instead of 'United States of America' which does not exist in country dropdown list and gets the user
|
||||||
|
confused and unable to create an account. So we added the United States entry in the dropdown list.
|
||||||
|
*/
|
||||||
|
const countryList = useMemo(() => getCountryList(getLocale()).concat([{ code: 'US', name: 'United States' }]), []);
|
||||||
|
|
||||||
let showTermsOfServiceAndHonorCode = false;
|
let showTermsOfServiceAndHonorCode = false;
|
||||||
let showCountryField = false;
|
let showCountryField = false;
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ describe('ConfigurableRegistrationForm', () => {
|
|||||||
country: 'Pakistan',
|
country: 'Pakistan',
|
||||||
honor_code: true,
|
honor_code: true,
|
||||||
profession: 'Engineer',
|
profession: 'Engineer',
|
||||||
totalRegistrationTime: 0,
|
total_registration_time: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
store.dispatch = jest.fn(store.dispatch);
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
@@ -356,7 +356,7 @@ describe('ConfigurableRegistrationForm', () => {
|
|||||||
password: 'password1',
|
password: 'password1',
|
||||||
country: 'Ukraine',
|
country: 'Ukraine',
|
||||||
honor_code: true,
|
honor_code: true,
|
||||||
totalRegistrationTime: 0,
|
total_registration_time: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
store = mockStore({
|
store = mockStore({
|
||||||
|
|||||||
77
src/register/data/tests/utils.test.js
Normal file
77
src/register/data/tests/utils.test.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import { isFormValid } from '../utils';
|
||||||
|
|
||||||
|
describe('Payload validation', () => {
|
||||||
|
let formatMessage;
|
||||||
|
let configurableFormFields;
|
||||||
|
let fieldDescriptions;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
formatMessage = jest.fn(msg => msg);
|
||||||
|
configurableFormFields = {
|
||||||
|
confirm_email: true,
|
||||||
|
};
|
||||||
|
fieldDescriptions = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
test('validates name field correctly', () => {
|
||||||
|
const payload = { name: ' ' };
|
||||||
|
const errors = {};
|
||||||
|
const { isValid, fieldErrors } = isFormValid(
|
||||||
|
payload,
|
||||||
|
errors,
|
||||||
|
configurableFormFields,
|
||||||
|
fieldDescriptions,
|
||||||
|
formatMessage);
|
||||||
|
|
||||||
|
expect(fieldErrors.name).toBeDefined();
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('validates email field correctly', () => {
|
||||||
|
const payload = { email: 'invalid-email' };
|
||||||
|
const errors = {};
|
||||||
|
const { isValid, fieldErrors } = isFormValid(
|
||||||
|
payload, errors, configurableFormFields, fieldDescriptions, formatMessage);
|
||||||
|
|
||||||
|
expect(fieldErrors.email).toBeDefined();
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('validates username field correctly', () => {
|
||||||
|
const payload = { username: 'invalid username' };
|
||||||
|
const errors = {};
|
||||||
|
const { isValid, fieldErrors } = isFormValid(
|
||||||
|
payload, errors, configurableFormFields, fieldDescriptions, formatMessage);
|
||||||
|
|
||||||
|
expect(fieldErrors.username).toBeDefined();
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('validates password field correctly', () => {
|
||||||
|
const payload = { password: 'short' };
|
||||||
|
const errors = {};
|
||||||
|
const { isValid, fieldErrors } = isFormValid(
|
||||||
|
payload, errors, configurableFormFields, fieldDescriptions, formatMessage);
|
||||||
|
|
||||||
|
expect(fieldErrors.password).toBeDefined();
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('validates multiple fields correctly', () => {
|
||||||
|
const payload = {
|
||||||
|
name: 'InvalidName!',
|
||||||
|
email: 'invalid-email',
|
||||||
|
username: 'invalid username',
|
||||||
|
password: 'short',
|
||||||
|
};
|
||||||
|
const errors = {};
|
||||||
|
const { isValid, fieldErrors } = isFormValid(
|
||||||
|
payload, errors, configurableFormFields, fieldDescriptions, formatMessage);
|
||||||
|
|
||||||
|
expect(fieldErrors.name).toBeDefined();
|
||||||
|
expect(fieldErrors.email).toBeDefined();
|
||||||
|
expect(fieldErrors.username).toBeDefined();
|
||||||
|
expect(fieldErrors.password).toBeDefined();
|
||||||
|
expect(isValid).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -43,30 +43,39 @@ export const isFormValid = (
|
|||||||
Object.keys(payload).forEach(key => {
|
Object.keys(payload).forEach(key => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'name':
|
case 'name':
|
||||||
fieldErrors.name = validateName(payload.name, formatMessage);
|
if (!fieldErrors.name) {
|
||||||
|
fieldErrors.name = validateName(payload.name, formatMessage);
|
||||||
|
}
|
||||||
if (fieldErrors.name) { isValid = false; }
|
if (fieldErrors.name) { isValid = false; }
|
||||||
break;
|
break;
|
||||||
case 'email': {
|
case 'email': {
|
||||||
const {
|
if (!fieldErrors.email) {
|
||||||
fieldError, confirmEmailError, suggestion,
|
const {
|
||||||
} = validateEmail(payload.email, configurableFormFields?.confirm_email, formatMessage);
|
fieldError, confirmEmailError, suggestion,
|
||||||
if (fieldError) {
|
} = validateEmail(payload.email, configurableFormFields?.confirm_email, formatMessage);
|
||||||
fieldErrors.email = fieldError;
|
if (fieldError) {
|
||||||
isValid = false;
|
fieldErrors.email = fieldError;
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
if (confirmEmailError) {
|
||||||
|
fieldErrors.confirm_email = confirmEmailError;
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
emailSuggestion = suggestion;
|
||||||
}
|
}
|
||||||
if (confirmEmailError) {
|
if (fieldErrors.email) { isValid = false; }
|
||||||
fieldErrors.confirm_email = confirmEmailError;
|
|
||||||
isValid = false;
|
|
||||||
}
|
|
||||||
emailSuggestion = suggestion;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'username':
|
case 'username':
|
||||||
fieldErrors.username = validateUsername(payload.username, formatMessage);
|
if (!fieldErrors.username) {
|
||||||
|
fieldErrors.username = validateUsername(payload.username, formatMessage);
|
||||||
|
}
|
||||||
if (fieldErrors.username) { isValid = false; }
|
if (fieldErrors.username) { isValid = false; }
|
||||||
break;
|
break;
|
||||||
case 'password':
|
case 'password':
|
||||||
fieldErrors.password = validatePasswordField(payload.password, formatMessage);
|
if (!fieldErrors.password) {
|
||||||
|
fieldErrors.password = validatePasswordField(payload.password, formatMessage);
|
||||||
|
}
|
||||||
if (fieldErrors.password) { isValid = false; }
|
if (fieldErrors.password) { isValid = false; }
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -125,8 +134,8 @@ export const prepareRegistrationPayload = (
|
|||||||
delete payload.marketingEmailsOptIn;
|
delete payload.marketingEmailsOptIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
payload = snakeCaseObject(payload);
|
|
||||||
payload.totalRegistrationTime = totalRegistrationTime;
|
payload.totalRegistrationTime = totalRegistrationTime;
|
||||||
|
payload = snakeCaseObject(payload);
|
||||||
|
|
||||||
// add query params to the payload
|
// add query params to the payload
|
||||||
payload = { ...payload, ...queryParams };
|
payload = { ...payload, ...queryParams };
|
||||||
|
|||||||
Reference in New Issue
Block a user