Compare commits
33 Commits
split-full
...
test-sandb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e29a461a34 | ||
|
|
9276f25200 | ||
|
|
dc90cf9ce5 | ||
|
|
36354761cc | ||
|
|
f53add81f3 | ||
|
|
bca59ebd40 | ||
|
|
dcb5da42b0 | ||
|
|
b346c22b57 | ||
|
|
8be350e35f | ||
|
|
6695fb6f61 | ||
|
|
be5b0bb461 | ||
|
|
5f93278326 | ||
|
|
488644f50d | ||
|
|
56bab26018 | ||
|
|
ca42f3851d | ||
|
|
e4bddc2db0 | ||
|
|
8aeacaa001 | ||
|
|
80435d3e5b | ||
|
|
d6c5415c9a | ||
|
|
0306763eeb | ||
|
|
e4ac1288a9 | ||
|
|
e1f489838c | ||
|
|
9b046146a0 | ||
|
|
e0d605582e | ||
|
|
21b5a01cab | ||
|
|
955ea6485f | ||
|
|
9f8a1af7e3 | ||
|
|
e617a3ba40 | ||
|
|
fb3f962039 | ||
|
|
64da54f17c | ||
|
|
74741a1be6 | ||
|
|
e9aaf7024a | ||
|
|
e3d96385ee |
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=''
|
||||||
|
|||||||
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/vanguards** to do it.
|
* [ ] Deploy the changes to prod after verifying on stage or ask **@openedx/2u-vanguards** to do it.
|
||||||
* [ ] 🎉 🙌 Celebrate! Thanks for your contribution.
|
* [ ] 🎉 🙌 Celebrate! Thanks for your contribution.
|
||||||
|
|||||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -41,4 +41,4 @@ 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@v4
|
||||||
|
|||||||
@@ -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/vanguards
|
* @openedx/2u-vanguards
|
||||||
|
|||||||
@@ -187,7 +187,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/vanguards>`_. Backstage pulls this data from the ``catalog-info.yaml``
|
found in `Backstage <https://backstage.openedx.org/catalog/default/group/2u-vanguards>`_. Backstage pulls this data from the ``catalog-info.yaml``
|
||||||
file in this repo.
|
file in this repo.
|
||||||
|
|
||||||
Reporting Security Issues
|
Reporting Security Issues
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ metadata:
|
|||||||
annotations:
|
annotations:
|
||||||
openedx.org/arch-interest-groups: ""
|
openedx.org/arch-interest-groups: ""
|
||||||
spec:
|
spec:
|
||||||
owner: group:vanguards
|
owner: group:2u-vanguards
|
||||||
type: 'service'
|
type: 'service'
|
||||||
lifecycle: 'production'
|
lifecycle: 'production'
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
nick: Authn MFE
|
nick: Authn MFE
|
||||||
oeps: {}
|
oeps: {}
|
||||||
owner: openedx/vanguards
|
owner: openedx/2u-vanguards
|
||||||
openedx-release:
|
openedx-release:
|
||||||
ref: master
|
ref: master
|
||||||
|
|||||||
66
package-lock.json
generated
66
package-lock.json
generated
@@ -10,7 +10,7 @@
|
|||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
|
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
|
||||||
"@edx/frontend-platform": "7.0.1",
|
"@edx/frontend-platform": "7.1.1",
|
||||||
"@edx/openedx-atlas": "^0.6.0",
|
"@edx/openedx-atlas": "^0.6.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "6.5.1",
|
"@fortawesome/fontawesome-svg-core": "6.5.1",
|
||||||
"@fortawesome/free-brands-svg-icons": "6.5.1",
|
"@fortawesome/free-brands-svg-icons": "6.5.1",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"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.35.1",
|
"core-js": "3.36.0",
|
||||||
"fastest-levenshtein": "1.0.16",
|
"fastest-levenshtein": "1.0.16",
|
||||||
"form-urlencoded": "6.1.4",
|
"form-urlencoded": "6.1.4",
|
||||||
"prop-types": "15.8.1",
|
"prop-types": "15.8.1",
|
||||||
@@ -32,11 +32,11 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-helmet": "6.1.0",
|
"react-helmet": "6.1.0",
|
||||||
"react-loading-skeleton": "3.3.1",
|
"react-loading-skeleton": "3.4.0",
|
||||||
"react-redux": "7.2.9",
|
"react-redux": "7.2.9",
|
||||||
"react-responsive": "8.2.0",
|
"react-responsive": "8.2.0",
|
||||||
"react-router": "6.21.3",
|
"react-router": "6.22.3",
|
||||||
"react-router-dom": "6.21.3",
|
"react-router-dom": "6.22.3",
|
||||||
"react-zendesk": "^0.1.13",
|
"react-zendesk": "^0.1.13",
|
||||||
"redux": "4.2.0",
|
"redux": "4.2.0",
|
||||||
"redux-logger": "3.0.6",
|
"redux-logger": "3.0.6",
|
||||||
@@ -2159,9 +2159,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cospired/i18n-iso-languages": {
|
"node_modules/@cospired/i18n-iso-languages": {
|
||||||
"version": "4.1.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@cospired/i18n-iso-languages/-/i18n-iso-languages-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@cospired/i18n-iso-languages/-/i18n-iso-languages-4.2.0.tgz",
|
||||||
"integrity": "sha512-5+JK7YiO9r/FmwtlEPL1tQNt04/9AuN1t9GO/0C2yitqhKwFRa1r7VohNNUnFgB84MW5v4Lwq8ZAUZexuJh1nQ==",
|
"integrity": "sha512-vy8cq1176MTxVwB1X9niQjcIYOH29F8Huxtx8hLmT5Uz3l1ztGDGri8KN/4zE7LV2mCT7JrcAoNV/I9yb+lNUw==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
@@ -2283,11 +2283,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@edx/frontend-platform": {
|
"node_modules/@edx/frontend-platform": {
|
||||||
"version": "7.0.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@edx/frontend-platform/-/frontend-platform-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@edx/frontend-platform/-/frontend-platform-7.1.1.tgz",
|
||||||
"integrity": "sha512-q5/S8V+hsX6ENYtTgMw0IfhMNshlBZ6pPfMft/ciVgCuTgW1XNZtgL98HhAEcBwmPshWgTRWVEQ83dniFrxwew==",
|
"integrity": "sha512-sr4ExW/ZxyTLp0ielhJnH9fzDIj7Bg7uuYL96ebYamMIHv4WeFQ92gad023vlaoVg60JdMp9XVoDhsf7dHFPLA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cospired/i18n-iso-languages": "4.1.0",
|
"@cospired/i18n-iso-languages": "4.2.0",
|
||||||
"@formatjs/intl-pluralrules": "4.3.3",
|
"@formatjs/intl-pluralrules": "4.3.3",
|
||||||
"@formatjs/intl-relativetimeformat": "10.0.1",
|
"@formatjs/intl-relativetimeformat": "10.0.1",
|
||||||
"axios": "0.27.2",
|
"axios": "0.27.2",
|
||||||
@@ -5505,9 +5505,9 @@
|
|||||||
"integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA=="
|
"integrity": "sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA=="
|
||||||
},
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.14.2",
|
"version": "1.15.3",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz",
|
||||||
"integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==",
|
"integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
@@ -6647,9 +6647,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/algoliasearch-helper": {
|
"node_modules/algoliasearch-helper": {
|
||||||
"version": "3.16.2",
|
"version": "3.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.16.3.tgz",
|
||||||
"integrity": "sha512-Yl/Gu5Cq4Z5s/AJ0jR37OPI1H3+z7PHz657ibyaXgMOaWvPlZ3OACN13N+7HCLPUlB0BN+8BtmrG/CqTilowBA==",
|
"integrity": "sha512-1OuJT6sONAa9PxcOmWo5WCAT3jQSpCR9/m5Azujja7nhUQwAUDvaaAYrcmUySsrvHh74usZHbE3jFfGnWtZj8w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/events": "^4.0.1"
|
"@algolia/events": "^4.0.1"
|
||||||
},
|
},
|
||||||
@@ -8257,9 +8257,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js": {
|
"node_modules/core-js": {
|
||||||
"version": "3.35.1",
|
"version": "3.36.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.1.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.36.0.tgz",
|
||||||
"integrity": "sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw==",
|
"integrity": "sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -18381,9 +18381,9 @@
|
|||||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
},
|
},
|
||||||
"node_modules/react-loading-skeleton": {
|
"node_modules/react-loading-skeleton": {
|
||||||
"version": "3.3.1",
|
"version": "3.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.4.0.tgz",
|
||||||
"integrity": "sha512-NilqqwMh2v9omN7LteiDloEVpFyMIa0VGqF+ukqp0ncVlYu1sKYbYGX9JEl+GtOT9TKsh04zCHAbavnQ2USldA==",
|
"integrity": "sha512-1oJEBc9+wn7BbkQQk7YodlYEIjgeR+GrRjD+QXkVjwZN7LGIcAFHrx4NhT7UHGBxNY1+zax3c+Fo6XQM4R7CgA==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=16.8.0"
|
"react": ">=16.8.0"
|
||||||
}
|
}
|
||||||
@@ -18526,11 +18526,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.21.3",
|
"version": "6.22.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz",
|
||||||
"integrity": "sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==",
|
"integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.14.2"
|
"@remix-run/router": "1.15.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@@ -18540,12 +18540,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "6.21.3",
|
"version": "6.22.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz",
|
||||||
"integrity": "sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==",
|
"integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.14.2",
|
"@remix-run/router": "1.15.3",
|
||||||
"react-router": "6.21.3"
|
"react-router": "6.22.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
|
"@edx/brand": "npm:@openedx/brand-openedx@^1.2.2",
|
||||||
"@edx/frontend-platform": "7.0.1",
|
"@edx/frontend-platform": "7.1.1",
|
||||||
"@edx/openedx-atlas": "^0.6.0",
|
"@edx/openedx-atlas": "^0.6.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "6.5.1",
|
"@fortawesome/fontawesome-svg-core": "6.5.1",
|
||||||
"@fortawesome/free-brands-svg-icons": "6.5.1",
|
"@fortawesome/free-brands-svg-icons": "6.5.1",
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
"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.35.1",
|
"core-js": "3.36.0",
|
||||||
"fastest-levenshtein": "1.0.16",
|
"fastest-levenshtein": "1.0.16",
|
||||||
"form-urlencoded": "6.1.4",
|
"form-urlencoded": "6.1.4",
|
||||||
"prop-types": "15.8.1",
|
"prop-types": "15.8.1",
|
||||||
@@ -55,11 +55,11 @@
|
|||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-helmet": "6.1.0",
|
"react-helmet": "6.1.0",
|
||||||
"react-loading-skeleton": "3.3.1",
|
"react-loading-skeleton": "3.4.0",
|
||||||
"react-redux": "7.2.9",
|
"react-redux": "7.2.9",
|
||||||
"react-responsive": "8.2.0",
|
"react-responsive": "8.2.0",
|
||||||
"react-router": "6.21.3",
|
"react-router": "6.22.3",
|
||||||
"react-router-dom": "6.21.3",
|
"react-router-dom": "6.22.3",
|
||||||
"react-zendesk": "^0.1.13",
|
"react-zendesk": "^0.1.13",
|
||||||
"redux": "4.2.0",
|
"redux": "4.2.0",
|
||||||
"redux-logger": "3.0.6",
|
"redux-logger": "3.0.6",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en-us">
|
<html lang="en-us">
|
||||||
<head>
|
<head>
|
||||||
<title>Authn | <%= process.env.SITE_NAME %></title>
|
<title><%= (process.env.SITE_NAME && process.env.SITE_NAME != 'null') ? 'Authentication | ' + process.env.SITE_NAME : 'Authentication' %></title>
|
||||||
<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"/>
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
const IMAGE_LAYOUT = 'image-layout';
|
|
||||||
const DEFAULT_LAYOUT = 'default-layout';
|
|
||||||
|
|
||||||
export { DEFAULT_LAYOUT, IMAGE_LAYOUT };
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { getConfig } from '@edx/frontend-platform';
|
import { getConfig } from '@edx/frontend-platform';
|
||||||
import { breakpoints } from '@openedx/paragon';
|
import { breakpoints } from '@openedx/paragon';
|
||||||
@@ -11,28 +11,11 @@ import {
|
|||||||
ImageExtraSmallLayout, ImageLargeLayout, ImageMediumLayout, ImageSmallLayout,
|
ImageExtraSmallLayout, ImageLargeLayout, ImageMediumLayout, ImageSmallLayout,
|
||||||
} from './components/image-layout';
|
} from './components/image-layout';
|
||||||
import { AuthLargeLayout, AuthMediumLayout, AuthSmallLayout } from './components/welcome-page-layout';
|
import { AuthLargeLayout, AuthMediumLayout, AuthSmallLayout } from './components/welcome-page-layout';
|
||||||
import { DEFAULT_LAYOUT, IMAGE_LAYOUT } from './data/constants';
|
|
||||||
|
|
||||||
const BaseContainer = ({ children, showWelcomeBanner, fullName }) => {
|
const BaseContainer = ({ children, showWelcomeBanner, fullName }) => {
|
||||||
const [baseContainerVersion, setBaseContainerVersion] = useState(DEFAULT_LAYOUT);
|
|
||||||
const enableImageLayout = getConfig().ENABLE_IMAGE_LAYOUT;
|
const enableImageLayout = getConfig().ENABLE_IMAGE_LAYOUT;
|
||||||
|
|
||||||
useEffect(() => {
|
if (enableImageLayout) {
|
||||||
const initRebrandExperiment = () => {
|
|
||||||
if (window.experiments?.rebrandExperiment) {
|
|
||||||
setBaseContainerVersion(window.experiments?.rebrandExperiment?.variation);
|
|
||||||
} else {
|
|
||||||
window.experiments = window.experiments || {};
|
|
||||||
window.experiments.rebrandExperiment = {};
|
|
||||||
window.experiments.rebrandExperiment.handleLoaded = () => {
|
|
||||||
setBaseContainerVersion(window.experiments?.rebrandExperiment?.variation);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
initRebrandExperiment();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (baseContainerVersion === IMAGE_LAYOUT || enableImageLayout) {
|
|
||||||
return (
|
return (
|
||||||
<div className="layout">
|
<div className="layout">
|
||||||
<MediaQuery maxWidth={breakpoints.extraSmall.maxWidth - 1}>
|
<MediaQuery maxWidth={breakpoints.extraSmall.maxWidth - 1}>
|
||||||
|
|||||||
@@ -25,23 +25,6 @@ describe('Base component tests', () => {
|
|||||||
expect(container.querySelector('.large-screen-svg-primary')).toBeDefined();
|
expect(container.querySelector('.large-screen-svg-primary')).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[experiment] should show image layout for treatment group', () => {
|
|
||||||
window.experiments = {
|
|
||||||
rebrandExperiment: {
|
|
||||||
variation: 'image-layout',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const { container } = render(
|
|
||||||
<IntlProvider locale="en">
|
|
||||||
<BaseContainer />
|
|
||||||
</IntlProvider>,
|
|
||||||
LargeScreen,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(container.querySelector('.banner__image')).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders Image layout when ENABLE_IMAGE_LAYOUT configuration is enabled', () => {
|
it('renders Image layout when ENABLE_IMAGE_LAYOUT configuration is enabled', () => {
|
||||||
mergeConfig({
|
mergeConfig({
|
||||||
ENABLE_IMAGE_LAYOUT: true,
|
ENABLE_IMAGE_LAYOUT: true,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
Hyperlink, Icon,
|
Hyperlink, Icon,
|
||||||
} from '@openedx/paragon';
|
} from '@openedx/paragon';
|
||||||
import { Institution } from '@openedx/paragon/icons';
|
import { Institution } from '@openedx/paragon/icons';
|
||||||
|
import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Skeleton from 'react-loading-skeleton';
|
import Skeleton from 'react-loading-skeleton';
|
||||||
|
|
||||||
@@ -47,14 +48,23 @@ const ThirdPartyAuth = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{(isLoginPage && !isEnterpriseLoginDisabled && isSocialAuthActive) && (
|
{(isLoginPage && !isEnterpriseLoginDisabled && isSocialAuthActive) && (
|
||||||
<Hyperlink className="btn btn-link btn-sm text-body p-0 mb-4" destination={enterpriseLoginURL}>
|
<Hyperlink
|
||||||
|
className={classNames(
|
||||||
|
'btn btn-link btn-sm text-body p-0',
|
||||||
|
{ 'mb-0': thirdPartyAuthApiStatus === PENDING_STATE },
|
||||||
|
{ 'mb-4': thirdPartyAuthApiStatus !== PENDING_STATE },
|
||||||
|
)}
|
||||||
|
destination={enterpriseLoginURL}
|
||||||
|
>
|
||||||
<Icon src={Institution} className="institute-icon" />
|
<Icon src={Institution} className="institute-icon" />
|
||||||
{formatMessage(messages['enterprise.login.btn.text'])}
|
{formatMessage(messages['enterprise.login.btn.text'])}
|
||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{thirdPartyAuthApiStatus === PENDING_STATE ? (
|
{thirdPartyAuthApiStatus === PENDING_STATE ? (
|
||||||
<Skeleton className="tpa-skeleton" height={36} count={2} />
|
<div className="mt-4">
|
||||||
|
<Skeleton className="tpa-skeleton" height={36} count={2} />
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{(isEnterpriseLoginDisabled && isInstitutionAuthActive) && (
|
{(isEnterpriseLoginDisabled && isInstitutionAuthActive) && (
|
||||||
|
|||||||
@@ -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 || true,
|
||||||
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,
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "كلمة مرورك الحالية لا تستسجيب لمتطلبات الأمان الجديدة. لقد أرسلنا للتو رسالة لإعادة ضبط كلمة المرور إلى عنوان البريد الإلكتروني المرتبط بهذا الحساب. شكرًا لك على مساعدتنا في الحفاظ على سلامة بياناتك.",
|
"non.compliant.password.message": "كلمة مرورك الحالية لا تستسجيب لمتطلبات الأمان الجديدة. لقد أرسلنا للتو رسالة لإعادة ضبط كلمة المرور إلى عنوان البريد الإلكتروني المرتبط بهذا الحساب. شكرًا لك على مساعدتنا في الحفاظ على سلامة بياناتك.",
|
||||||
"account.locked.out.message.1": "لحماية حسابك، تم إقفاله مؤقتًا. حاول مرة أخرى بعد 30 دقيقة.",
|
"account.locked.out.message.1": "لحماية حسابك، تم إقفاله مؤقتًا. حاول مرة أخرى بعد 30 دقيقة.",
|
||||||
"enterprise.login.btn.text": "بيانات الشركة أو المدرسة",
|
"enterprise.login.btn.text": "بيانات الشركة أو المدرسة",
|
||||||
"username.or.email.format.validation.less.chars.message": "يجب أن يحتوي اسم المستخدم أو البريد الإلكتروني على 3 أحرف على الأقل.",
|
"username.or.email.format.validation.less.chars.message": "يجب أن يحتوي اسم المستخدم أو البريد الإلكتروني على 2 أحرف على الأقل.",
|
||||||
"email.validation.message": "أدخل اسم المستخدم أو البريد الإلكتروني الخاص بك",
|
"email.validation.message": "أدخل اسم المستخدم أو البريد الإلكتروني الخاص بك",
|
||||||
"password.validation.message": "لم يتم استيفاء معايير كلمة المرور",
|
"password.validation.message": "لم يتم استيفاء معايير كلمة المرور",
|
||||||
"account.activation.success.message.title": "نجح الأمر! لقد قمت بتفعيل حسابك.",
|
"account.activation.success.message.title": "نجح الأمر! لقد قمت بتفعيل حسابك.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
||||||
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
||||||
"enterprise.login.btn.text": "Company or school credentials",
|
"enterprise.login.btn.text": "Company or school credentials",
|
||||||
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 3 characters.",
|
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 2 characters.",
|
||||||
"email.validation.message": "Enter your username or email",
|
"email.validation.message": "Enter your username or email",
|
||||||
"password.validation.message": "Password criteria has not been met",
|
"password.validation.message": "Password criteria has not been met",
|
||||||
"account.activation.success.message.title": "Success! You have activated your account.",
|
"account.activation.success.message.title": "Success! You have activated your account.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Ihr aktuelles Passwort entspricht nicht den neuen Sicherheitsanforderungen. Wir haben gerade eine Nachricht zum Zurücksetzen des Passworts an die mit diesem Konto verknüpfte E-Mail-Adresse gesendet. Vielen Dank, dass Sie uns helfen, Ihre Daten zu schützen.",
|
"non.compliant.password.message": "Ihr aktuelles Passwort entspricht nicht den neuen Sicherheitsanforderungen. Wir haben gerade eine Nachricht zum Zurücksetzen des Passworts an die mit diesem Konto verknüpfte E-Mail-Adresse gesendet. Vielen Dank, dass Sie uns helfen, Ihre Daten zu schützen.",
|
||||||
"account.locked.out.message.1": "Um Ihr Konto zu schützen, wurde es vorübergehend gesperrt. Versuchen Sie es in 30 Minuten erneut.",
|
"account.locked.out.message.1": "Um Ihr Konto zu schützen, wurde es vorübergehend gesperrt. Versuchen Sie es in 30 Minuten erneut.",
|
||||||
"enterprise.login.btn.text": "Arbeits- oder Schulzeugnisse",
|
"enterprise.login.btn.text": "Arbeits- oder Schulzeugnisse",
|
||||||
"username.or.email.format.validation.less.chars.message": "Benutzername oder E-Mail müssen mindestens 3 Zeichen lang sein.",
|
"username.or.email.format.validation.less.chars.message": "Benutzername oder E-Mail müssen mindestens 2 Zeichen lang sein.",
|
||||||
"email.validation.message": "Geben Sie Ihren Benutzernamen oder Ihre E-Mail-Adresse ein",
|
"email.validation.message": "Geben Sie Ihren Benutzernamen oder Ihre E-Mail-Adresse ein",
|
||||||
"password.validation.message": "Die Passwortkriterien wurden nicht erfüllt",
|
"password.validation.message": "Die Passwortkriterien wurden nicht erfüllt",
|
||||||
"account.activation.success.message.title": "Super! Sie haben Ihr Konto aktiviert.",
|
"account.activation.success.message.title": "Super! Sie haben Ihr Konto aktiviert.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Tu contraseña actual no cumple con los nuevos requisitos de seguridad. Acabamos de enviar un mensaje de restablecimiento de contraseña a la dirección de correo electrónico asociada a esta cuenta. Gracias por ayudarnos a mantener tus datos seguros.",
|
"non.compliant.password.message": "Tu contraseña actual no cumple con los nuevos requisitos de seguridad. Acabamos de enviar un mensaje de restablecimiento de contraseña a la dirección de correo electrónico asociada a esta cuenta. Gracias por ayudarnos a mantener tus datos seguros.",
|
||||||
"account.locked.out.message.1": "Para proteger tu cuenta, se ha bloqueado temporalmente. Inténtalo de nuevo en 30 minutos.",
|
"account.locked.out.message.1": "Para proteger tu cuenta, se ha bloqueado temporalmente. Inténtalo de nuevo en 30 minutos.",
|
||||||
"enterprise.login.btn.text": "Credenciales de la empresa o de la institución ",
|
"enterprise.login.btn.text": "Credenciales de la empresa o de la institución ",
|
||||||
"username.or.email.format.validation.less.chars.message": "El nombre de usuario o el correo electrónico deben tener al menos 3 caracteres.",
|
"username.or.email.format.validation.less.chars.message": "El nombre de usuario o el correo electrónico deben tener al menos 2 caracteres.",
|
||||||
"email.validation.message": "Introduce tu nombre de usuario o correo electrónico",
|
"email.validation.message": "Introduce tu nombre de usuario o correo electrónico",
|
||||||
"password.validation.message": "No se han cumplido los criterios de la contraseña",
|
"password.validation.message": "No se han cumplido los criterios de la contraseña",
|
||||||
"account.activation.success.message.title": "Ha sido un éxito. Has activado tu cuenta.",
|
"account.activation.success.message.title": "Ha sido un éxito. Has activado tu cuenta.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "Al crear una cuenta, acepta {tosAndHonorCode} y reconoce que {platformName} y cada miembro procesan sus datos personales de acuerdo con {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "Al crear una cuenta, acepta {tosAndHonorCode} y reconoce que {platformName} y cada miembro procesan sus datos personales de acuerdo con {privacyPolicy}.",
|
||||||
"register.page.honor.code": "Acepto las {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "Acepto las {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "Acepto las {platformName} {termsOfService}"
|
"register.page.terms.of.service": "Acepto las {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "گذرواژه فعلی شما الزامات امنیتی جدید را برآورده نمیکند. ما فقط یک پیام بازتنظیم گذرواژه به نشانی رایانامه مرتبط با این حساب کاربری ارسال کردیم. از اینکه به ما کمک میکنید تا دادههای شما را ایمن نگه دارید متشکریم.",
|
"non.compliant.password.message": "گذرواژه فعلی شما الزامات امنیتی جدید را برآورده نمیکند. ما فقط یک پیام بازتنظیم گذرواژه به نشانی رایانامه مرتبط با این حساب کاربری ارسال کردیم. از اینکه به ما کمک میکنید تا دادههای شما را ایمن نگه دارید متشکریم.",
|
||||||
"account.locked.out.message.1": "حساب کاربری شما، به دلیل حفاظت، بهطور موقت قفل شده است. 30 دقیقه دیگر دوباره امتحان کنید.",
|
"account.locked.out.message.1": "حساب کاربری شما، به دلیل حفاظت، بهطور موقت قفل شده است. 30 دقیقه دیگر دوباره امتحان کنید.",
|
||||||
"enterprise.login.btn.text": "اعتبار دانشکده یا شرکت",
|
"enterprise.login.btn.text": "اعتبار دانشکده یا شرکت",
|
||||||
"username.or.email.format.validation.less.chars.message": "نام کاربری یا نشانی رایانامه حداقل باید 3 نویسه داشته باشد",
|
"username.or.email.format.validation.less.chars.message": "نام کاربری یا نشانی رایانامه حداقل باید 2 نویسه داشته باشد",
|
||||||
"email.validation.message": "نام کاربری یا رایانامه خود را وارد کنید",
|
"email.validation.message": "نام کاربری یا رایانامه خود را وارد کنید",
|
||||||
"password.validation.message": "معیارهای گذرواژه رعایت نشده است",
|
"password.validation.message": "معیارهای گذرواژه رعایت نشده است",
|
||||||
"account.activation.success.message.title": "موفق شدید! شما حساب کاربری خود را فعال کردید.",
|
"account.activation.success.message.title": "موفق شدید! شما حساب کاربری خود را فعال کردید.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Votre mot de passe actuel ne répond pas aux nouvelles exigences de sécurité. Nous venons d'envoyer un message de réinitialisation de mot de passe à l'adresse courriel associée à ce compte. Merci de nous aider à protéger vos données.",
|
"non.compliant.password.message": "Votre mot de passe actuel ne répond pas aux nouvelles exigences de sécurité. Nous venons d'envoyer un message de réinitialisation de mot de passe à l'adresse courriel associée à ce compte. Merci de nous aider à protéger vos données.",
|
||||||
"account.locked.out.message.1": "Pour protéger votre compte, il a été temporairement verrouillé. Réessayez dans 30 minutes.",
|
"account.locked.out.message.1": "Pour protéger votre compte, il a été temporairement verrouillé. Réessayez dans 30 minutes.",
|
||||||
"enterprise.login.btn.text": "Identifiants de la compagnie ou de l'école",
|
"enterprise.login.btn.text": "Identifiants de la compagnie ou de l'école",
|
||||||
"username.or.email.format.validation.less.chars.message": "Le nom d'utilisateur ou l'adresse courriel doit comporter au moins 3 caractères.",
|
"username.or.email.format.validation.less.chars.message": "Le nom d'utilisateur ou l'adresse courriel doit comporter au moins 2 caractères.",
|
||||||
"email.validation.message": "Entrez votre nom d'utilisateur ou votre adresse courriel",
|
"email.validation.message": "Entrez votre nom d'utilisateur ou votre adresse courriel",
|
||||||
"password.validation.message": "Les critères de mot de passe n'ont pas été remplis",
|
"password.validation.message": "Les critères de mot de passe n'ont pas été remplis",
|
||||||
"account.activation.success.message.title": "Succès! Vous avez activé votre compte.",
|
"account.activation.success.message.title": "Succès! Vous avez activé votre compte.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Votre mot de passe actuel ne répond pas aux nouvelles exigences de sécurité. Nous venons d'envoyer un message de réinitialisation de mot de passe à l'adresse courriel associée à ce compte. Merci de nous aider à protéger vos données.",
|
"non.compliant.password.message": "Votre mot de passe actuel ne répond pas aux nouvelles exigences de sécurité. Nous venons d'envoyer un message de réinitialisation de mot de passe à l'adresse courriel associée à ce compte. Merci de nous aider à protéger vos données.",
|
||||||
"account.locked.out.message.1": "Pour protéger votre compte, il a été temporairement verrouillé. Réessayez dans 30 minutes.",
|
"account.locked.out.message.1": "Pour protéger votre compte, il a été temporairement verrouillé. Réessayez dans 30 minutes.",
|
||||||
"enterprise.login.btn.text": "Informations d'identification de la compagnie ou de l'école",
|
"enterprise.login.btn.text": "Informations d'identification de la compagnie ou de l'école",
|
||||||
"username.or.email.format.validation.less.chars.message": "Le nom d'utilisateur ou l'adresse courriel doit comporter au moins 3 caractères.",
|
"username.or.email.format.validation.less.chars.message": "Le nom d'utilisateur ou l'adresse courriel doit comporter au moins 2 caractères.",
|
||||||
"email.validation.message": "Entrez votre nom d'utilisateur ou votre adresse courriel",
|
"email.validation.message": "Entrez votre nom d'utilisateur ou votre adresse courriel",
|
||||||
"password.validation.message": "Les critères de mot de passe n'ont pas été remplis",
|
"password.validation.message": "Les critères de mot de passe n'ont pas été remplis",
|
||||||
"account.activation.success.message.title": "Succès! Vous avez activé votre compte.",
|
"account.activation.success.message.title": "Succès! Vous avez activé votre compte.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "En créant un compte, vous acceptez le {tosAndHonorCode} et vous reconnaissez que {platformName} et chaque membre traitent vos données personnelles conformément au {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "En créant un compte, vous acceptez le {tosAndHonorCode} et vous reconnaissez que {platformName} et chaque membre traitent vos données personnelles conformément au {privacyPolicy}.",
|
||||||
"register.page.honor.code": "J'accepte le {tosAndHonorCode} {platformName}",
|
"register.page.honor.code": "J'accepte le {tosAndHonorCode} {platformName}",
|
||||||
"register.page.terms.of.service": "J'accepte les {termsOfService} {platformName}"
|
"register.page.terms.of.service": "J'accepte les {termsOfService} {platformName}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
||||||
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
||||||
"enterprise.login.btn.text": "Company or school credentials",
|
"enterprise.login.btn.text": "Company or school credentials",
|
||||||
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 3 characters.",
|
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 2 characters.",
|
||||||
"email.validation.message": "Enter your username or email",
|
"email.validation.message": "Enter your username or email",
|
||||||
"password.validation.message": "Password criteria has not been met",
|
"password.validation.message": "Password criteria has not been met",
|
||||||
"account.activation.success.message.title": "Success! You have activated your account.",
|
"account.activation.success.message.title": "Success! You have activated your account.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
||||||
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
||||||
"enterprise.login.btn.text": "Company or school credentials",
|
"enterprise.login.btn.text": "Company or school credentials",
|
||||||
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 3 characters.",
|
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 2 characters.",
|
||||||
"email.validation.message": "Enter your username or email",
|
"email.validation.message": "Enter your username or email",
|
||||||
"password.validation.message": "Password criteria has not been met",
|
"password.validation.message": "Password criteria has not been met",
|
||||||
"account.activation.success.message.title": "Success! You have activated your account.",
|
"account.activation.success.message.title": "Success! You have activated your account.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "La tua password attuale non soddisfa i nuovi requisiti di sicurezza. Abbiamo appena inviato un messaggio di reimpostazione della password all'indirizzo e-mail associato a questo account. Grazie per averci aiutato a mantenere i tuoi dati al sicuro.",
|
"non.compliant.password.message": "La tua password attuale non soddisfa i nuovi requisiti di sicurezza. Abbiamo appena inviato un messaggio di reimpostazione della password all'indirizzo e-mail associato a questo account. Grazie per averci aiutato a mantenere i tuoi dati al sicuro.",
|
||||||
"account.locked.out.message.1": "Per proteggere il tuo account, è stato temporaneamente bloccato. Riprova tra 30 minuti.",
|
"account.locked.out.message.1": "Per proteggere il tuo account, è stato temporaneamente bloccato. Riprova tra 30 minuti.",
|
||||||
"enterprise.login.btn.text": "Credenziali aziendali o scolastiche",
|
"enterprise.login.btn.text": "Credenziali aziendali o scolastiche",
|
||||||
"username.or.email.format.validation.less.chars.message": "Il nome utente o l'e-mail deve contenere almeno 3 caratteri.",
|
"username.or.email.format.validation.less.chars.message": "Il nome utente o l'e-mail deve contenere almeno 2 caratteri.",
|
||||||
"email.validation.message": "Inserisci il tuo nome utente o e-mail",
|
"email.validation.message": "Inserisci il tuo nome utente o e-mail",
|
||||||
"password.validation.message": "I criteri della password non sono stati soddisfatti",
|
"password.validation.message": "I criteri della password non sono stati soddisfatti",
|
||||||
"account.activation.success.message.title": "Completato correttamente! Hai attivato il tuo account. ",
|
"account.activation.success.message.title": "Completato correttamente! Hai attivato il tuo account. ",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
||||||
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
||||||
"enterprise.login.btn.text": "Company or school credentials",
|
"enterprise.login.btn.text": "Company or school credentials",
|
||||||
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 3 characters.",
|
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 2 characters.",
|
||||||
"email.validation.message": "Enter your username or email",
|
"email.validation.message": "Enter your username or email",
|
||||||
"password.validation.message": "Password criteria has not been met",
|
"password.validation.message": "Password criteria has not been met",
|
||||||
"account.activation.success.message.title": "Success! You have activated your account.",
|
"account.activation.success.message.title": "Success! You have activated your account.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "A sua palavra-passe atual não satisfaz os novos requisitos de segurança. Acabámos de enviar uma mensagem de redefinição da palavra-passe para o endereço de email associado a esta conta. Obrigado por nos ajudar a manter os seus dados em segurança.",
|
"non.compliant.password.message": "A sua palavra-passe atual não satisfaz os novos requisitos de segurança. Acabámos de enviar uma mensagem de redefinição da palavra-passe para o endereço de email associado a esta conta. Obrigado por nos ajudar a manter os seus dados em segurança.",
|
||||||
"account.locked.out.message.1": "Para proteger sua conta, esta foi temporariamente bloqueada. Tente novamente dentro de 30 minutos.",
|
"account.locked.out.message.1": "Para proteger sua conta, esta foi temporariamente bloqueada. Tente novamente dentro de 30 minutos.",
|
||||||
"enterprise.login.btn.text": "Credenciais da empresa ou escola",
|
"enterprise.login.btn.text": "Credenciais da empresa ou escola",
|
||||||
"username.or.email.format.validation.less.chars.message": "O nome de utilizador ou email deve ter pelo menos 3 carateres.",
|
"username.or.email.format.validation.less.chars.message": "O nome de utilizador ou email deve ter pelo menos 2 carateres.",
|
||||||
"email.validation.message": "Insira o seu nome de utilizador ou email",
|
"email.validation.message": "Insira o seu nome de utilizador ou email",
|
||||||
"password.validation.message": "Os critérios de palavra-passe não foram cumpridos",
|
"password.validation.message": "Os critérios de palavra-passe não foram cumpridos",
|
||||||
"account.activation.success.message.title": "Sucesso! Você ativou a sua conta.",
|
"account.activation.success.message.title": "Sucesso! Você ativou a sua conta.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
||||||
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
||||||
"enterprise.login.btn.text": "Company or school credentials",
|
"enterprise.login.btn.text": "Company or school credentials",
|
||||||
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 3 characters.",
|
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 2 characters.",
|
||||||
"email.validation.message": "Enter your username or email",
|
"email.validation.message": "Enter your username or email",
|
||||||
"password.validation.message": "Password criteria has not been met",
|
"password.validation.message": "Password criteria has not been met",
|
||||||
"account.activation.success.message.title": "Success! You have activated your account.",
|
"account.activation.success.message.title": "Success! You have activated your account.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
"non.compliant.password.message": "Your current password does not meet the new security requirements. We just sent a password-reset message to the email address associated with this account. Thank you for helping us keep your data safe.",
|
||||||
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
"account.locked.out.message.1": "To protect your account, it's been temporarily locked. Try again in 30 minutes.",
|
||||||
"enterprise.login.btn.text": "Company or school credentials",
|
"enterprise.login.btn.text": "Company or school credentials",
|
||||||
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 3 characters.",
|
"username.or.email.format.validation.less.chars.message": "Username or email must have at least 2 characters.",
|
||||||
"email.validation.message": "Enter your username or email",
|
"email.validation.message": "Enter your username or email",
|
||||||
"password.validation.message": "Password criteria has not been met",
|
"password.validation.message": "Password criteria has not been met",
|
||||||
"account.activation.success.message.title": "Success! You have activated your account.",
|
"account.activation.success.message.title": "Success! You have activated your account.",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"non.compliant.password.message": "您当前的密码不符合新的安全要求。我们刚刚向与此帐户关联的电子邮件地址发送了密码重置邮件。感谢您帮助我们保护您的数据安全。",
|
"non.compliant.password.message": "您当前的密码不符合新的安全要求。我们刚刚向与此帐户关联的电子邮件地址发送了密码重置邮件。感谢您帮助我们保护您的数据安全。",
|
||||||
"account.locked.out.message.1": "为了保护您的帐户,它已被暂时锁定。请在 30 分钟后重试。",
|
"account.locked.out.message.1": "为了保护您的帐户,它已被暂时锁定。请在 30 分钟后重试。",
|
||||||
"enterprise.login.btn.text": "单位或学校证书",
|
"enterprise.login.btn.text": "单位或学校证书",
|
||||||
"username.or.email.format.validation.less.chars.message": "用户名或电子邮件必须至少包含 3 个字符。",
|
"username.or.email.format.validation.less.chars.message": "用户名或电子邮件必须至少包含 2 个字符。",
|
||||||
"email.validation.message": "输入您的用户名或电子邮件",
|
"email.validation.message": "输入您的用户名或电子邮件",
|
||||||
"password.validation.message": "未满足密码条件",
|
"password.validation.message": "未满足密码条件",
|
||||||
"account.activation.success.message.title": "成功!您已激活您的帐户。",
|
"account.activation.success.message.title": "成功!您已激活您的帐户。",
|
||||||
@@ -178,4 +178,4 @@
|
|||||||
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
"register.page.terms.of.service.and.honor.code": "By creating an account, you agree to the {tosAndHonorCode} and you acknowledge that {platformName} and each Member process your personal data in accordance with the {privacyPolicy}.",
|
||||||
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
"register.page.honor.code": "I agree to the {platformName} {tosAndHonorCode}",
|
||||||
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
"register.page.terms.of.service": "I agree to the {platformName} {termsOfService}"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ const LoginPage = (props) => {
|
|||||||
|
|
||||||
if (emailOrUsername === '') {
|
if (emailOrUsername === '') {
|
||||||
fieldErrors.emailOrUsername = formatMessage(messages['email.validation.message']);
|
fieldErrors.emailOrUsername = formatMessage(messages['email.validation.message']);
|
||||||
} else if (emailOrUsername.length < 3) {
|
} else if (emailOrUsername.length < 2) {
|
||||||
fieldErrors.emailOrUsername = formatMessage(messages['username.or.email.format.validation.less.chars.message']);
|
fieldErrors.emailOrUsername = formatMessage(messages['username.or.email.format.validation.less.chars.message']);
|
||||||
}
|
}
|
||||||
if (password === '') {
|
if (password === '') {
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ const messages = defineMessages({
|
|||||||
},
|
},
|
||||||
'username.or.email.format.validation.less.chars.message': {
|
'username.or.email.format.validation.less.chars.message': {
|
||||||
id: 'username.or.email.format.validation.less.chars.message',
|
id: 'username.or.email.format.validation.less.chars.message',
|
||||||
defaultMessage: 'Username or email must have at least 3 characters.',
|
defaultMessage: 'Username or email must have at least 2 characters.',
|
||||||
description: 'Validation message that appears when username or email address is less than 3 characters',
|
description: 'Validation message that appears when username or email address is less than 2 characters',
|
||||||
},
|
},
|
||||||
'email.validation.message': {
|
'email.validation.message': {
|
||||||
id: 'email.validation.message',
|
id: 'email.validation.message',
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ describe('LoginPage', () => {
|
|||||||
|
|
||||||
// ******** test login form validations ********
|
// ******** test login form validations ********
|
||||||
|
|
||||||
it('should match state for invalid email (less than 3 characters), on form submission', () => {
|
it('should match state for invalid email (less than 2 characters), on form submission', () => {
|
||||||
store.dispatch = jest.fn(store.dispatch);
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
|
|
||||||
render(reduxWrapper(<IntlLoginPage {...props} />));
|
render(reduxWrapper(<IntlLoginPage {...props} />));
|
||||||
@@ -151,14 +151,14 @@ describe('LoginPage', () => {
|
|||||||
fireEvent.change(screen.getByText(
|
fireEvent.change(screen.getByText(
|
||||||
'',
|
'',
|
||||||
{ selector: '#emailOrUsername' },
|
{ selector: '#emailOrUsername' },
|
||||||
), { target: { value: 'te' } });
|
), { target: { value: 't' } });
|
||||||
|
|
||||||
fireEvent.click(screen.getByText(
|
fireEvent.click(screen.getByText(
|
||||||
'',
|
'',
|
||||||
{ selector: '.btn-brand' },
|
{ selector: '.btn-brand' },
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(screen.getByText('Username or email must have at least 3 characters.')).toBeDefined();
|
expect(screen.getByText('Username or email must have at least 2 characters.')).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show error messages for required fields on empty form submission', () => {
|
it('should show error messages for required fields on empty form submission', () => {
|
||||||
@@ -181,14 +181,14 @@ describe('LoginPage', () => {
|
|||||||
fireEvent.change(screen.getByText(
|
fireEvent.change(screen.getByText(
|
||||||
'',
|
'',
|
||||||
{ selector: '#emailOrUsername' },
|
{ selector: '#emailOrUsername' },
|
||||||
), { target: { value: 'te', name: 'emailOrUsername' } });
|
), { target: { value: 't', name: 'emailOrUsername' } });
|
||||||
|
|
||||||
fireEvent.click(screen.getByText(
|
fireEvent.click(screen.getByText(
|
||||||
'',
|
'',
|
||||||
{ selector: '.btn-brand' },
|
{ selector: '.btn-brand' },
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(container.querySelector('div[feedback-for="emailOrUsername"]').textContent).toEqual('Username or email must have at least 3 characters.');
|
expect(container.querySelector('div[feedback-for="emailOrUsername"]').textContent).toEqual('Username or email must have at least 2 characters.');
|
||||||
});
|
});
|
||||||
|
|
||||||
// ******** test field focus in functionality ********
|
// ******** test field focus in functionality ********
|
||||||
|
|||||||
@@ -66,7 +66,10 @@ const Logistration = (props) => {
|
|||||||
setInstitutionLogin(!institutionLogin);
|
setInstitutionLogin(!institutionLogin);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnSelect = (tabKey) => {
|
const handleOnSelect = (tabKey, currentTab) => {
|
||||||
|
if (tabKey === currentTab) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
sendTrackEvent(`edx.bi.${tabKey.replace('/', '')}_form.toggled`, { category: 'user-engagement' });
|
sendTrackEvent(`edx.bi.${tabKey.replace('/', '')}_form.toggled`, { category: 'user-engagement' });
|
||||||
props.clearThirdPartyAuthContextErrorMessage();
|
props.clearThirdPartyAuthContextErrorMessage();
|
||||||
if (tabKey === LOGIN_PAGE) {
|
if (tabKey === LOGIN_PAGE) {
|
||||||
@@ -121,7 +124,7 @@ const Logistration = (props) => {
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
)
|
)
|
||||||
: (!isValidTpaHint() && !hideRegistrationLink && (
|
: (!isValidTpaHint() && !hideRegistrationLink && (
|
||||||
<Tabs defaultActiveKey={selectedPage} id="controlled-tab" onSelect={handleOnSelect}>
|
<Tabs defaultActiveKey={selectedPage} id="controlled-tab" onSelect={(tabKey) => handleOnSelect(tabKey, selectedPage)}>
|
||||||
<Tab title={formatMessage(messages['logistration.register'])} eventKey={REGISTER_PAGE} />
|
<Tab title={formatMessage(messages['logistration.register'])} eventKey={REGISTER_PAGE} />
|
||||||
<Tab title={formatMessage(messages['logistration.sign.in'])} eventKey={LOGIN_PAGE} />
|
<Tab title={formatMessage(messages['logistration.sign.in'])} eventKey={LOGIN_PAGE} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -94,6 +94,14 @@ describe('Logistration', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should do nothing when user clicks on the same tab (login/register) again', () => {
|
||||||
|
const { container } = render(reduxWrapper(<IntlLogistration />));
|
||||||
|
// While staying on the registration form, clicking the register tab again
|
||||||
|
fireEvent.click(container.querySelector('a[data-rb-event-key="/register"]'));
|
||||||
|
|
||||||
|
expect(sendTrackEvent).not.toHaveBeenCalledWith('edx.bi.register_form.toggled', { category: 'user-engagement' });
|
||||||
|
});
|
||||||
|
|
||||||
it('should render registration page', () => {
|
it('should render registration page', () => {
|
||||||
mergeConfig({
|
mergeConfig({
|
||||||
ALLOW_PUBLIC_ACCOUNT_CREATION: true,
|
ALLOW_PUBLIC_ACCOUNT_CREATION: true,
|
||||||
@@ -260,9 +268,11 @@ describe('Logistration', () => {
|
|||||||
fireEvent.click(container.querySelector('a[data-rb-event-key="/login"]'));
|
fireEvent.click(container.querySelector('a[data-rb-event-key="/login"]'));
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(backupRegistrationForm());
|
expect(store.dispatch).toHaveBeenCalledWith(backupRegistrationForm());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fire action to backup login form on tab click', () => {
|
it('should fire action to backup login form on tab click', () => {
|
||||||
store.dispatch = jest.fn(store.dispatch);
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
const { container } = render(reduxWrapper(<IntlLogistration />));
|
const props = { selectedPage: LOGIN_PAGE };
|
||||||
|
const { container } = render(reduxWrapper(<IntlLogistration {...props} />));
|
||||||
fireEvent.click(container.querySelector('a[data-rb-event-key="/register"]'));
|
fireEvent.click(container.querySelector('a[data-rb-event-key="/register"]'));
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(backupLoginForm());
|
expect(store.dispatch).toHaveBeenCalledWith(backupLoginForm());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ const ProgressiveProfiling = (props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseContainer showWelcomeBanner fullName={authenticatedUser?.fullName || authenticatedUser?.username}>
|
<BaseContainer showWelcomeBanner fullName={authenticatedUser?.fullName || authenticatedUser?.name}>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{formatMessage(messages['progressive.profiling.page.title'],
|
<title>{formatMessage(messages['progressive.profiling.page.title'],
|
||||||
{ siteName: getConfig().SITE_NAME })}
|
{ siteName: getConfig().SITE_NAME })}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const BaseCard = ({
|
|||||||
<div className="recommendation-card" key={`container-${uuid}`}>
|
<div className="recommendation-card" key={`container-${uuid}`}>
|
||||||
<Hyperlink
|
<Hyperlink
|
||||||
target="_blank"
|
target="_blank"
|
||||||
className="card-box"
|
className="card-box d-inline"
|
||||||
showLaunchIcon={false}
|
showLaunchIcon={false}
|
||||||
onClick={handleOnClick}
|
onClick={handleOnClick}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||||
@@ -9,9 +9,9 @@ import PropTypes from 'prop-types';
|
|||||||
import validateEmail from './validator';
|
import validateEmail from './validator';
|
||||||
import { FormGroup } from '../../../common-components';
|
import { FormGroup } from '../../../common-components';
|
||||||
import {
|
import {
|
||||||
backupRegistrationFormBegin,
|
|
||||||
clearRegistrationBackendError,
|
clearRegistrationBackendError,
|
||||||
fetchRealtimeValidations,
|
fetchRealtimeValidations,
|
||||||
|
setEmailSuggestionInStore,
|
||||||
} from '../../data/actions';
|
} from '../../data/actions';
|
||||||
import messages from '../../messages';
|
import messages from '../../messages';
|
||||||
|
|
||||||
@@ -44,6 +44,10 @@ const EmailField = (props) => {
|
|||||||
|
|
||||||
const [emailSuggestion, setEmailSuggestion] = useState({ ...backedUpFormData?.emailSuggestion });
|
const [emailSuggestion, setEmailSuggestion] = useState({ ...backedUpFormData?.emailSuggestion });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setEmailSuggestion(backedUpFormData.emailSuggestion);
|
||||||
|
}, [backedUpFormData.emailSuggestion]);
|
||||||
|
|
||||||
const handleOnBlur = (e) => {
|
const handleOnBlur = (e) => {
|
||||||
const { value } = e.target;
|
const { value } = e.target;
|
||||||
const { fieldError, confirmEmailError, suggestion } = validateEmail(value, confirmEmailValue, formatMessage);
|
const { fieldError, confirmEmailError, suggestion } = validateEmail(value, confirmEmailValue, formatMessage);
|
||||||
@@ -52,10 +56,7 @@ const EmailField = (props) => {
|
|||||||
handleErrorChange('confirm_email', confirmEmailError);
|
handleErrorChange('confirm_email', confirmEmailError);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(backupRegistrationFormBegin({
|
dispatch(setEmailSuggestionInStore(suggestion));
|
||||||
...backedUpFormData,
|
|
||||||
emailSuggestion: { ...suggestion },
|
|
||||||
}));
|
|
||||||
setEmailSuggestion(suggestion);
|
setEmailSuggestion(suggestion);
|
||||||
|
|
||||||
if (fieldError) {
|
if (fieldError) {
|
||||||
|
|||||||
@@ -46,7 +46,14 @@ describe('EmailField', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
register: {},
|
register: {
|
||||||
|
registrationFormData: {
|
||||||
|
emailSuggestion: {
|
||||||
|
suggestion: 'example@gmail.com',
|
||||||
|
type: 'warning',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export const validateEmailAddress = (value, username, domainName) => {
|
|||||||
const validateEmail = (value, confirmEmailValue, formatMessage) => {
|
const validateEmail = (value, confirmEmailValue, formatMessage) => {
|
||||||
let fieldError = '';
|
let fieldError = '';
|
||||||
let confirmEmailError = '';
|
let confirmEmailError = '';
|
||||||
let emailSuggestion = {};
|
let emailSuggestion = { suggestion: '', type: '' };
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
fieldError = formatMessage(messages['empty.email.field.error']);
|
fieldError = formatMessage(messages['empty.email.field.error']);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const HTML_REGEX = /<|>/u;
|
|||||||
export const INVALID_NAME_REGEX = /https?:\/\/(?:[-\w.]|(?:%[\da-fA-F]{2}))*/g;
|
export const INVALID_NAME_REGEX = /https?:\/\/(?:[-\w.]|(?:%[\da-fA-F]{2}))*/g;
|
||||||
|
|
||||||
const validateName = (value, formatMessage) => {
|
const validateName = (value, formatMessage) => {
|
||||||
let fieldError;
|
let fieldError = '';
|
||||||
if (!value.trim()) {
|
if (!value.trim()) {
|
||||||
fieldError = formatMessage(messages['empty.name.field.error']);
|
fieldError = formatMessage(messages['empty.name.field.error']);
|
||||||
} else if (URL_REGEX.test(value) || HTML_REGEX.test(value) || INVALID_NAME_REGEX.test(value)) {
|
} else if (URL_REGEX.test(value) || HTML_REGEX.test(value) || INVALID_NAME_REGEX.test(value)) {
|
||||||
|
|||||||
@@ -18,13 +18,16 @@ import {
|
|||||||
backupRegistrationFormBegin,
|
backupRegistrationFormBegin,
|
||||||
clearRegistrationBackendError,
|
clearRegistrationBackendError,
|
||||||
registerNewUser,
|
registerNewUser,
|
||||||
|
setEmailSuggestionInStore,
|
||||||
setUserPipelineDataLoaded,
|
setUserPipelineDataLoaded,
|
||||||
} from './data/actions';
|
} from './data/actions';
|
||||||
import {
|
import {
|
||||||
FORM_SUBMISSION_ERROR,
|
FORM_SUBMISSION_ERROR,
|
||||||
TPA_AUTHENTICATION_FAILURE,
|
TPA_AUTHENTICATION_FAILURE,
|
||||||
} from './data/constants';
|
} from './data/constants';
|
||||||
import { getBackendValidations, isFormValid, prepareRegistrationPayload } from './data/utils';
|
import {
|
||||||
|
getBackendValidations, isFormValid, prepareRegistrationPayload,
|
||||||
|
} from './data/utils';
|
||||||
import messages from './messages';
|
import messages from './messages';
|
||||||
import { EmailField, NameField, UsernameField } from './RegistrationFields';
|
import { EmailField, NameField, UsernameField } from './RegistrationFields';
|
||||||
import {
|
import {
|
||||||
@@ -56,6 +59,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,
|
||||||
@@ -188,8 +192,8 @@ const RegistrationPage = (props) => {
|
|||||||
const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
|
const value = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
|
||||||
if (registrationError[name]) {
|
if (registrationError[name]) {
|
||||||
dispatch(clearRegistrationBackendError(name));
|
dispatch(clearRegistrationBackendError(name));
|
||||||
setErrors(prevErrors => ({ ...prevErrors, [name]: '' }));
|
|
||||||
}
|
}
|
||||||
|
setErrors(prevErrors => ({ ...prevErrors, [name]: '' }));
|
||||||
setFormFields(prevState => ({ ...prevState, [name]: value }));
|
setFormFields(prevState => ({ ...prevState, [name]: value }));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -221,9 +225,12 @@ 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 } = isFormValid(
|
const { isValid, fieldErrors, emailSuggestion } = isFormValid(
|
||||||
payload,
|
payload,
|
||||||
registrationEmbedded ? temporaryErrors : errors,
|
registrationEmbedded ? temporaryErrors : errors,
|
||||||
configurableFormFields,
|
configurableFormFields,
|
||||||
@@ -231,6 +238,7 @@ const RegistrationPage = (props) => {
|
|||||||
formatMessage,
|
formatMessage,
|
||||||
);
|
);
|
||||||
setErrors({ ...fieldErrors });
|
setErrors({ ...fieldErrors });
|
||||||
|
dispatch(setEmailSuggestionInStore(emailSuggestion));
|
||||||
|
|
||||||
// returning if not valid
|
// returning if not valid
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
@@ -329,16 +337,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"
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ describe('RegistrationPage', () => {
|
|||||||
registrationError: {},
|
registrationError: {},
|
||||||
registrationFormData,
|
registrationFormData,
|
||||||
usernameSuggestions: [],
|
usernameSuggestions: [],
|
||||||
|
|
||||||
},
|
},
|
||||||
commonComponents: {
|
commonComponents: {
|
||||||
thirdPartyAuthApiStatus: null,
|
thirdPartyAuthApiStatus: null,
|
||||||
@@ -133,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' } });
|
||||||
@@ -220,6 +228,54 @@ describe('RegistrationPage', () => {
|
|||||||
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...formPayload, country: 'PK' }));
|
expect(store.dispatch).toHaveBeenCalledWith(registerNewUser({ ...formPayload, country: 'PK' }));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should display an error when form is submitted with an invalid email', () => {
|
||||||
|
jest.spyOn(global.Date, 'now').mockImplementation(() => 0);
|
||||||
|
const emailError = "We couldn't create your account.Please check your responses and try again.";
|
||||||
|
|
||||||
|
const formPayload = {
|
||||||
|
name: 'Petro',
|
||||||
|
username: 'petro_qa',
|
||||||
|
email: 'petro @example.com',
|
||||||
|
password: 'password1',
|
||||||
|
country: 'Ukraine',
|
||||||
|
honor_code: true,
|
||||||
|
totalRegistrationTime: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
|
const { getByLabelText, container } = render(routerWrapper(reduxWrapper(<IntlRegistrationPage {...props} />)));
|
||||||
|
populateRequiredFields(getByLabelText, formPayload, true);
|
||||||
|
|
||||||
|
const button = container.querySelector('button.btn-brand');
|
||||||
|
fireEvent.click(button);
|
||||||
|
|
||||||
|
const validationErrors = container.querySelector('#validation-errors');
|
||||||
|
expect(validationErrors.textContent).toContain(emailError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display an error when form is submitted with an invalid username', () => {
|
||||||
|
jest.spyOn(global.Date, 'now').mockImplementation(() => 0);
|
||||||
|
const usernameError = "We couldn't create your account.Please check your responses and try again.";
|
||||||
|
|
||||||
|
const formPayload = {
|
||||||
|
name: 'Petro',
|
||||||
|
username: 'petro qa',
|
||||||
|
email: 'petro@example.com',
|
||||||
|
password: 'password1',
|
||||||
|
country: 'Ukraine',
|
||||||
|
honor_code: true,
|
||||||
|
totalRegistrationTime: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
store.dispatch = jest.fn(store.dispatch);
|
||||||
|
const { getByLabelText, container } = render(routerWrapper(reduxWrapper(<IntlRegistrationPage {...props} />)));
|
||||||
|
populateRequiredFields(getByLabelText, formPayload, true);
|
||||||
|
const button = container.querySelector('button.btn-brand');
|
||||||
|
fireEvent.click(button);
|
||||||
|
const validationErrors = container.querySelector('#validation-errors');
|
||||||
|
expect(validationErrors.textContent).toContain(usernameError);
|
||||||
|
});
|
||||||
|
|
||||||
it('should submit form with marketing email opt in value', () => {
|
it('should submit form with marketing email opt in value', () => {
|
||||||
mergeConfig({
|
mergeConfig({
|
||||||
MARKETING_EMAILS_OPT_IN: 'true',
|
MARKETING_EMAILS_OPT_IN: 'true',
|
||||||
@@ -250,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,
|
||||||
|
totalRegistrationTime: 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);
|
||||||
|
|
||||||
|
|||||||
@@ -348,6 +348,49 @@ describe('ConfigurableRegistrationForm', () => {
|
|||||||
expect(confirmEmailErrorElement.textContent).toEqual('The email addresses do not match.');
|
expect(confirmEmailErrorElement.textContent).toEqual('The email addresses do not match.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should show error if email and confirm email fields do not match on submit click', () => {
|
||||||
|
const formPayload = {
|
||||||
|
name: 'Petro',
|
||||||
|
username: 'petro_qa',
|
||||||
|
email: 'petro@example.com',
|
||||||
|
password: 'password1',
|
||||||
|
country: 'Ukraine',
|
||||||
|
honor_code: true,
|
||||||
|
totalRegistrationTime: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
store = mockStore({
|
||||||
|
...initialState,
|
||||||
|
commonComponents: {
|
||||||
|
...initialState.commonComponents,
|
||||||
|
fieldDescriptions: {
|
||||||
|
confirm_email: {
|
||||||
|
name: 'confirm_email', type: 'text', label: 'Confirm Email',
|
||||||
|
},
|
||||||
|
country: { name: 'country' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { getByLabelText, container } = render(routerWrapper(reduxWrapper(<IntlRegistrationPage {...props} />)));
|
||||||
|
|
||||||
|
populateRequiredFields(getByLabelText, formPayload, true);
|
||||||
|
fireEvent.change(
|
||||||
|
getByLabelText('Confirm Email'),
|
||||||
|
{ target: { value: 'test2@gmail.com', name: 'confirm_email' } },
|
||||||
|
);
|
||||||
|
|
||||||
|
const button = container.querySelector('button.btn-brand');
|
||||||
|
fireEvent.click(button);
|
||||||
|
|
||||||
|
const confirmEmailErrorElement = container.querySelector('div#confirm_email-error');
|
||||||
|
expect(confirmEmailErrorElement.textContent).toEqual('The email addresses do not match.');
|
||||||
|
|
||||||
|
const validationErrors = container.querySelector('#validation-errors');
|
||||||
|
expect(validationErrors.textContent).toContain(
|
||||||
|
"We couldn't create your account.Please check your responses and try again.",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should run validations for configurable focused field on form submission', () => {
|
it('should run validations for configurable focused field on form submission', () => {
|
||||||
const professionError = 'Enter your profession';
|
const professionError = 'Enter your profession';
|
||||||
store = mockStore({
|
store = mockStore({
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export const REGISTER_CLEAR_USERNAME_SUGGESTIONS = 'REGISTRATION_CLEAR_USERNAME_
|
|||||||
export const REGISTRATION_CLEAR_BACKEND_ERROR = 'REGISTRATION_CLEAR_BACKEND_ERROR';
|
export const REGISTRATION_CLEAR_BACKEND_ERROR = 'REGISTRATION_CLEAR_BACKEND_ERROR';
|
||||||
export const REGISTER_SET_COUNTRY_CODE = 'REGISTER_SET_COUNTRY_CODE';
|
export const REGISTER_SET_COUNTRY_CODE = 'REGISTER_SET_COUNTRY_CODE';
|
||||||
export const REGISTER_SET_USER_PIPELINE_DATA_LOADED = 'REGISTER_SET_USER_PIPELINE_DATA_LOADED';
|
export const REGISTER_SET_USER_PIPELINE_DATA_LOADED = 'REGISTER_SET_USER_PIPELINE_DATA_LOADED';
|
||||||
|
export const REGISTER_SET_EMAIL_SUGGESTIONS = 'REGISTER_SET_EMAIL_SUGGESTIONS';
|
||||||
|
|
||||||
// Backup registration form
|
// Backup registration form
|
||||||
export const backupRegistrationForm = () => ({
|
export const backupRegistrationForm = () => ({
|
||||||
@@ -37,6 +38,12 @@ export const fetchRealtimeValidationsFailure = () => ({
|
|||||||
type: REGISTER_FORM_VALIDATIONS.FAILURE,
|
type: REGISTER_FORM_VALIDATIONS.FAILURE,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set email field frontend validations
|
||||||
|
export const setEmailSuggestionInStore = (emailSuggestion) => ({
|
||||||
|
type: REGISTER_SET_EMAIL_SUGGESTIONS,
|
||||||
|
payload: { emailSuggestion },
|
||||||
|
});
|
||||||
|
|
||||||
// Register
|
// Register
|
||||||
export const registerNewUser = registrationInfo => ({
|
export const registerNewUser = registrationInfo => ({
|
||||||
type: REGISTER_NEW_USER.BASE,
|
type: REGISTER_NEW_USER.BASE,
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import {
|
|||||||
REGISTER_CLEAR_USERNAME_SUGGESTIONS,
|
REGISTER_CLEAR_USERNAME_SUGGESTIONS,
|
||||||
REGISTER_FORM_VALIDATIONS,
|
REGISTER_FORM_VALIDATIONS,
|
||||||
REGISTER_NEW_USER,
|
REGISTER_NEW_USER,
|
||||||
REGISTER_SET_COUNTRY_CODE, REGISTER_SET_USER_PIPELINE_DATA_LOADED,
|
REGISTER_SET_COUNTRY_CODE,
|
||||||
|
REGISTER_SET_EMAIL_SUGGESTIONS,
|
||||||
|
REGISTER_SET_USER_PIPELINE_DATA_LOADED,
|
||||||
REGISTRATION_CLEAR_BACKEND_ERROR,
|
REGISTRATION_CLEAR_BACKEND_ERROR,
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import {
|
import {
|
||||||
@@ -48,7 +50,7 @@ const reducer = (state = defaultState, action = {}) => {
|
|||||||
};
|
};
|
||||||
case BACKUP_REGISTRATION_DATA.BEGIN:
|
case BACKUP_REGISTRATION_DATA.BEGIN:
|
||||||
return {
|
return {
|
||||||
...defaultState,
|
...state,
|
||||||
usernameSuggestions: state.usernameSuggestions,
|
usernameSuggestions: state.usernameSuggestions,
|
||||||
registrationFormData: { ...action.payload },
|
registrationFormData: { ...action.payload },
|
||||||
userPipelineDataLoaded: state.userPipelineDataLoaded,
|
userPipelineDataLoaded: state.userPipelineDataLoaded,
|
||||||
@@ -119,6 +121,14 @@ const reducer = (state = defaultState, action = {}) => {
|
|||||||
userPipelineDataLoaded: value,
|
userPipelineDataLoaded: value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case REGISTER_SET_EMAIL_SUGGESTIONS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
registrationFormData: {
|
||||||
|
...state.registrationFormData,
|
||||||
|
emailSuggestion: action.payload.emailSuggestion,
|
||||||
|
},
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
REGISTER_FORM_VALIDATIONS,
|
REGISTER_FORM_VALIDATIONS,
|
||||||
REGISTER_NEW_USER,
|
REGISTER_NEW_USER,
|
||||||
REGISTER_SET_COUNTRY_CODE,
|
REGISTER_SET_COUNTRY_CODE,
|
||||||
|
REGISTER_SET_EMAIL_SUGGESTIONS,
|
||||||
REGISTER_SET_USER_PIPELINE_DATA_LOADED,
|
REGISTER_SET_USER_PIPELINE_DATA_LOADED,
|
||||||
REGISTRATION_CLEAR_BACKEND_ERROR,
|
REGISTRATION_CLEAR_BACKEND_ERROR,
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
@@ -65,6 +66,28 @@ describe('Registration Reducer Tests', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set email suggestions', () => {
|
||||||
|
const emailSuggestion = {
|
||||||
|
type: 'test type',
|
||||||
|
suggestion: 'test suggestion',
|
||||||
|
};
|
||||||
|
const action = {
|
||||||
|
type: REGISTER_SET_EMAIL_SUGGESTIONS,
|
||||||
|
payload: { emailSuggestion },
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(defaultState, action)).toEqual(
|
||||||
|
{
|
||||||
|
...defaultState,
|
||||||
|
registrationFormData: {
|
||||||
|
...defaultState.registrationFormData,
|
||||||
|
emailSuggestion: {
|
||||||
|
type: 'test type', suggestion: 'test suggestion',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should set redirect url dashboard on registration success action', () => {
|
it('should set redirect url dashboard on registration success action', () => {
|
||||||
const payload = {
|
const payload = {
|
||||||
redirectUrl: `${getConfig().BASE_URL}${DEFAULT_REDIRECT_URL}`,
|
redirectUrl: `${getConfig().BASE_URL}${DEFAULT_REDIRECT_URL}`,
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import { snakeCaseObject } from '@edx/frontend-platform';
|
|||||||
|
|
||||||
import { LETTER_REGEX, NUMBER_REGEX } from '../../data/constants';
|
import { LETTER_REGEX, NUMBER_REGEX } from '../../data/constants';
|
||||||
import messages from '../messages';
|
import messages from '../messages';
|
||||||
|
import validateEmail from '../RegistrationFields/EmailField/validator';
|
||||||
|
import validateName from '../RegistrationFields/NameField/validator';
|
||||||
|
import validateUsername from '../RegistrationFields/UsernameField/validator';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It validates the password field value
|
* It validates the password field value
|
||||||
@@ -35,12 +38,39 @@ export const isFormValid = (
|
|||||||
) => {
|
) => {
|
||||||
const fieldErrors = { ...errors };
|
const fieldErrors = { ...errors };
|
||||||
let isValid = true;
|
let isValid = true;
|
||||||
|
let emailSuggestion = { suggestion: '', type: '' };
|
||||||
|
|
||||||
Object.keys(payload).forEach(key => {
|
Object.keys(payload).forEach(key => {
|
||||||
if (!payload[key]) {
|
switch (key) {
|
||||||
fieldErrors[key] = formatMessage(messages[`empty.${key}.field.error`]);
|
case 'name':
|
||||||
|
fieldErrors.name = validateName(payload.name, formatMessage);
|
||||||
|
if (fieldErrors.name) { isValid = false; }
|
||||||
|
break;
|
||||||
|
case 'email': {
|
||||||
|
const {
|
||||||
|
fieldError, confirmEmailError, suggestion,
|
||||||
|
} = validateEmail(payload.email, configurableFormFields?.confirm_email, formatMessage);
|
||||||
|
if (fieldError) {
|
||||||
|
fieldErrors.email = fieldError;
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
if (confirmEmailError) {
|
||||||
|
fieldErrors.confirm_email = confirmEmailError;
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
emailSuggestion = suggestion;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (fieldErrors[key]) {
|
case 'username':
|
||||||
isValid = false;
|
fieldErrors.username = validateUsername(payload.username, formatMessage);
|
||||||
|
if (fieldErrors.username) { isValid = false; }
|
||||||
|
break;
|
||||||
|
case 'password':
|
||||||
|
fieldErrors.password = validatePasswordField(payload.password, formatMessage);
|
||||||
|
if (fieldErrors.password) { isValid = false; }
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -54,17 +84,15 @@ export const isFormValid = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(fieldDescriptions).forEach(key => {
|
Object.keys(fieldDescriptions).forEach(key => {
|
||||||
if (key === 'country' && !configurableFormFields.country.displayValue) {
|
if (key === 'country' && !configurableFormFields?.country?.displayValue) {
|
||||||
fieldErrors[key] = formatMessage(messages['empty.country.field.error']);
|
fieldErrors[key] = formatMessage(messages['empty.country.field.error']);
|
||||||
} else if (!configurableFormFields[key]) {
|
} else if (!configurableFormFields[key]) {
|
||||||
fieldErrors[key] = fieldDescriptions[key].error_message;
|
fieldErrors[key] = fieldDescriptions[key].error_message;
|
||||||
}
|
}
|
||||||
if (fieldErrors[key]) {
|
if (fieldErrors[key]) { isValid = false; }
|
||||||
isValid = false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return { isValid, fieldErrors };
|
return { isValid, fieldErrors, emailSuggestion };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
// ----------------------------
|
// ----------------------------
|
||||||
// #COLORS
|
// #COLORS
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
$font-blue: #126f9a;
|
|
||||||
$white: #FFFFFF;
|
$white: #FFFFFF;
|
||||||
|
|
||||||
// social platforms
|
// social platforms
|
||||||
@@ -105,10 +104,10 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
border: 1px solid $font-blue;
|
border: 1px solid $primary;
|
||||||
width: 224px;
|
width: 224px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
color: $font-blue;
|
color: $primary;
|
||||||
|
|
||||||
.btn-tpa__image-icon{
|
.btn-tpa__image-icon{
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@@ -133,7 +132,7 @@ $elevation-level-2-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.15);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-tpa__font-container {
|
.btn-tpa__font-container {
|
||||||
background-color: $font-blue;
|
background-color: $primary;
|
||||||
color: $white;
|
color: $white;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user