Adds realtime validations to register form.
This patch adds realtime/ validations for; *) name *) fullname *) password *) email VAN-30
This commit is contained in:
@@ -13,7 +13,12 @@ import {
|
||||
} from '@edx/frontend-platform/i18n';
|
||||
|
||||
import camelCase from 'lodash.camelcase';
|
||||
import { getThirdPartyAuthContext, registerNewUser, fetchRegistrationForm } from './data/actions';
|
||||
import {
|
||||
getThirdPartyAuthContext,
|
||||
registerNewUser,
|
||||
fetchRegistrationForm,
|
||||
fetchRealtimeValidations,
|
||||
} from './data/actions';
|
||||
import { registrationRequestSelector, thirdPartyAuthContextSelector } from './data/selectors';
|
||||
import { RedirectLogistration } from '../common-components';
|
||||
import RegistrationFailure from './RegistrationFailure';
|
||||
@@ -36,6 +41,8 @@ class RegistrationPage extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.intl = props.intl;
|
||||
|
||||
this.state = {
|
||||
email: '',
|
||||
name: '',
|
||||
@@ -52,6 +59,7 @@ class RegistrationPage extends React.Component {
|
||||
levelOfEducation: '',
|
||||
confirmEmail: '',
|
||||
enableOptionalField: false,
|
||||
validationFieldName: '',
|
||||
errors: {
|
||||
email: '',
|
||||
name: '',
|
||||
@@ -82,6 +90,19 @@ class RegistrationPage extends React.Component {
|
||||
this.props.fetchRegistrationForm();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (this.props.validations !== nextProps.validations) {
|
||||
const { errors } = this.state;
|
||||
const errorMsg = nextProps.validations.validation_decisions[this.state.validationFieldName];
|
||||
errors[this.state.validationFieldName] = errorMsg;
|
||||
this.setState({
|
||||
errors,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
handleInstitutionLogin = () => {
|
||||
this.setState(prevState => ({ institutionLogin: !prevState.institutionLogin }));
|
||||
}
|
||||
@@ -115,7 +136,7 @@ class RegistrationPage extends React.Component {
|
||||
|
||||
if (!this.state.formValid) {
|
||||
// Special case where honor code and tos is a single field, true by default. We don't need
|
||||
// to validate this field.
|
||||
// to validate this field
|
||||
Object.entries(payload).filter(([key]) => (key !== 'honor_code' || !('terms_of_service' in REGISTRATION_EXTRA_FIELDS)))
|
||||
.forEach(([key, value]) => {
|
||||
this.validateInput(key, value);
|
||||
@@ -125,6 +146,22 @@ class RegistrationPage extends React.Component {
|
||||
this.props.registerNewUser(payload);
|
||||
}
|
||||
|
||||
handleOnBlur(e) {
|
||||
this.setState({
|
||||
validationFieldName: e.target.name,
|
||||
});
|
||||
|
||||
const payload = {
|
||||
email: this.state.email,
|
||||
username: this.state.username,
|
||||
password: this.state.password,
|
||||
name: this.state.name,
|
||||
honor_code: this.state.honorCode,
|
||||
country: this.state.country,
|
||||
};
|
||||
this.props.fetchRealtimeValidations(payload);
|
||||
}
|
||||
|
||||
handleOnChange(e) {
|
||||
const targetValue = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
|
||||
this.setState({
|
||||
@@ -156,23 +193,23 @@ class RegistrationPage extends React.Component {
|
||||
switch (inputName) {
|
||||
case 'email':
|
||||
emailValid = value.match(/^([\w.%+-]+)@([\w-]+\.)+([\w]{2,})$/i);
|
||||
errors.email = emailValid ? '' : null;
|
||||
errors.email = emailValid ? '' : this.intl.formatMessage(messages['logistration.email.validation.message']);
|
||||
break;
|
||||
case 'name':
|
||||
nameValid = value.length >= 1;
|
||||
errors.name = nameValid ? '' : null;
|
||||
errors.name = nameValid ? '' : this.intl.formatMessage(messages['logistration.fullname.validation.message']);
|
||||
break;
|
||||
case 'username':
|
||||
usernameValid = value.length >= 2 && value.length <= 30;
|
||||
errors.username = usernameValid ? '' : null;
|
||||
errors.username = usernameValid ? '' : this.intl.formatMessage(messages['logistration.username.validation.message']);
|
||||
break;
|
||||
case 'password':
|
||||
passwordValid = !!(value.length >= 8 && value.match(/\d+/g));
|
||||
errors.password = passwordValid ? '' : null;
|
||||
errors.password = passwordValid ? '' : this.intl.formatMessage(messages['logistration.register.page.password.validation.message']);
|
||||
break;
|
||||
case 'country':
|
||||
countryValid = value !== '';
|
||||
errors.country = countryValid ? '' : null;
|
||||
errors.country = countryValid ? '' : this.intl.formatMessage(messages['logistration.country.validation.message']);
|
||||
break;
|
||||
case 'honor_code':
|
||||
honorCodeValid = value !== false;
|
||||
@@ -411,7 +448,7 @@ class RegistrationPage extends React.Component {
|
||||
<ValidationFormGroup
|
||||
for="name"
|
||||
invalid={this.state.errors.name !== ''}
|
||||
invalidMessage={intl.formatMessage(messages['logistration.fullname.validation.message'])}
|
||||
invalidMessage={this.state.errors.name}
|
||||
>
|
||||
<label htmlFor="name" className="h6 pt-3">
|
||||
{intl.formatMessage(messages['logistration.fullname.label'])}
|
||||
@@ -423,13 +460,14 @@ class RegistrationPage extends React.Component {
|
||||
placeholder=""
|
||||
value={this.state.name}
|
||||
onChange={e => this.handleOnChange(e)}
|
||||
onBlur={e => this.handleOnBlur(e)}
|
||||
required
|
||||
/>
|
||||
</ValidationFormGroup>
|
||||
<ValidationFormGroup
|
||||
for="username"
|
||||
invalid={this.state.errors.username !== ''}
|
||||
invalidMessage={intl.formatMessage(messages['logistration.username.validation.message'])}
|
||||
invalidMessage={this.state.errors.username}
|
||||
>
|
||||
<label htmlFor="username" className="h6 pt-3">
|
||||
{intl.formatMessage(messages['logistration.username.label'])}
|
||||
@@ -441,13 +479,14 @@ class RegistrationPage extends React.Component {
|
||||
placeholder=""
|
||||
value={this.state.username}
|
||||
onChange={e => this.handleOnChange(e)}
|
||||
onBlur={e => this.handleOnBlur(e)}
|
||||
required
|
||||
/>
|
||||
</ValidationFormGroup>
|
||||
<ValidationFormGroup
|
||||
for="email"
|
||||
invalid={this.state.errors.email !== ''}
|
||||
invalidMessage={intl.formatMessage(messages['logistration.email.validation.message'])}
|
||||
invalidMessage={this.state.errors.email}
|
||||
>
|
||||
<label htmlFor="email" className="h6 pt-3">
|
||||
{intl.formatMessage(messages['logistration.register.page.email.label'])}
|
||||
@@ -459,13 +498,14 @@ class RegistrationPage extends React.Component {
|
||||
placeholder=""
|
||||
value={this.state.email}
|
||||
onChange={e => this.handleOnChange(e)}
|
||||
onBlur={e => this.handleOnBlur(e)}
|
||||
required
|
||||
/>
|
||||
</ValidationFormGroup>
|
||||
<ValidationFormGroup
|
||||
for="password"
|
||||
invalid={this.state.errors.password !== ''}
|
||||
invalidMessage={intl.formatMessage(messages['logistration.register.page.password.validation.message'])}
|
||||
invalidMessage={this.state.errors.password}
|
||||
>
|
||||
<label htmlFor="password" className="h6 pt-3">
|
||||
{intl.formatMessage(messages['logistration.password.label'])}
|
||||
@@ -477,6 +517,7 @@ class RegistrationPage extends React.Component {
|
||||
placeholder=""
|
||||
value={this.state.password}
|
||||
onChange={e => this.handleOnChange(e)}
|
||||
onBlur={e => this.handleOnBlur(e)}
|
||||
required
|
||||
/>
|
||||
</ValidationFormGroup>
|
||||
@@ -527,6 +568,7 @@ RegistrationPage.defaultProps = {
|
||||
secondaryProviders: [],
|
||||
},
|
||||
formData: null,
|
||||
validations: null,
|
||||
};
|
||||
|
||||
RegistrationPage.propTypes = {
|
||||
@@ -561,6 +603,16 @@ RegistrationPage.propTypes = {
|
||||
formData: PropTypes.shape({
|
||||
fields: PropTypes.array,
|
||||
}),
|
||||
fetchRealtimeValidations: PropTypes.func.isRequired,
|
||||
validations: PropTypes.shape({
|
||||
validation_decisions: PropTypes.shape({
|
||||
country: PropTypes.string,
|
||||
email: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
password: PropTypes.string,
|
||||
username: PropTypes.string,
|
||||
}),
|
||||
}),
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
@@ -572,6 +624,7 @@ const mapStateToProps = state => {
|
||||
registrationResult,
|
||||
thirdPartyAuthContext,
|
||||
formData: state.logistration.formData,
|
||||
validations: state.logistration.validations,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -580,6 +633,7 @@ export default connect(
|
||||
{
|
||||
getThirdPartyAuthContext,
|
||||
fetchRegistrationForm,
|
||||
fetchRealtimeValidations,
|
||||
registerNewUser,
|
||||
},
|
||||
)(injectIntl(RegistrationPage));
|
||||
|
||||
@@ -4,6 +4,7 @@ export const REGISTER_NEW_USER = new AsyncActionType('REGISTRATION', 'REGISTER_N
|
||||
export const LOGIN_REQUEST = new AsyncActionType('LOGIN', 'REQUEST');
|
||||
export const THIRD_PARTY_AUTH_CONTEXT = new AsyncActionType('THIRD_PARTY_AUTH', 'GET_THIRD_PARTY_AUTH_CONTEXT');
|
||||
export const REGISTER_FORM = new AsyncActionType('REGISTRATION', 'GET_FORM_FIELDS');
|
||||
export const REGISTER_FORM_VALIDATIONS = new AsyncActionType('REGISTRATION', 'GET_FORM_VALIDATIONS');
|
||||
|
||||
// Register
|
||||
|
||||
@@ -83,3 +84,22 @@ export const fetchRegistrationFormSuccess = (formData) => ({
|
||||
export const fetchRegistrationFormFailure = () => ({
|
||||
type: REGISTER_FORM.FAILURE,
|
||||
});
|
||||
|
||||
// Realtime Field validations
|
||||
export const fetchRealtimeValidations = (formPayload) => ({
|
||||
type: REGISTER_FORM_VALIDATIONS.BASE,
|
||||
payload: { formPayload },
|
||||
});
|
||||
|
||||
export const fetchRealtimeValidationsBegin = () => ({
|
||||
type: REGISTER_FORM_VALIDATIONS.BEGIN,
|
||||
});
|
||||
|
||||
export const fetchRealtimeValidationsSuccess = (validations) => ({
|
||||
type: REGISTER_FORM_VALIDATIONS.SUCCESS,
|
||||
payload: { validations },
|
||||
});
|
||||
|
||||
export const fetchRealtimeValidationsFailure = () => ({
|
||||
type: REGISTER_FORM_VALIDATIONS.FAILURE,
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
LOGIN_REQUEST,
|
||||
THIRD_PARTY_AUTH_CONTEXT,
|
||||
REGISTER_FORM,
|
||||
REGISTER_FORM_VALIDATIONS,
|
||||
} from './actions';
|
||||
|
||||
import { DEFAULT_STATE, PENDING_STATE } from '../../data/constants';
|
||||
@@ -13,6 +14,7 @@ export const defaultState = {
|
||||
registrationError: null,
|
||||
registrationResult: {},
|
||||
formData: null,
|
||||
validations: null,
|
||||
};
|
||||
|
||||
const reducer = (state = defaultState, action) => {
|
||||
@@ -75,6 +77,19 @@ const reducer = (state = defaultState, action) => {
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
case REGISTER_FORM_VALIDATIONS.BEGIN:
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
case REGISTER_FORM_VALIDATIONS.SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
validations: action.payload.validations,
|
||||
};
|
||||
case REGISTER_FORM_VALIDATIONS.FAILURE:
|
||||
return {
|
||||
...state,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ import {
|
||||
loginRequestBegin,
|
||||
loginRequestFailure,
|
||||
loginRequestSuccess,
|
||||
REGISTER_FORM_VALIDATIONS,
|
||||
fetchRealtimeValidationsBegin,
|
||||
fetchRealtimeValidationsSuccess,
|
||||
fetchRealtimeValidationsFailure,
|
||||
THIRD_PARTY_AUTH_CONTEXT,
|
||||
getThirdPartyAuthContextBegin,
|
||||
getThirdPartyAuthContextSuccess,
|
||||
@@ -24,6 +28,7 @@ import {
|
||||
|
||||
// Services
|
||||
import {
|
||||
getFieldsValidations,
|
||||
getRegistrationForm,
|
||||
getThirdPartyAuthContext,
|
||||
postNewUser,
|
||||
@@ -94,9 +99,24 @@ export function* fetchRegistrationForm() {
|
||||
}
|
||||
}
|
||||
|
||||
export function* fetchRealtimeValidations(action) {
|
||||
try {
|
||||
yield put(fetchRealtimeValidationsBegin());
|
||||
const { fieldValidations } = yield call(getFieldsValidations, action.payload.formPayload);
|
||||
|
||||
yield put(fetchRealtimeValidationsSuccess(
|
||||
fieldValidations,
|
||||
));
|
||||
} catch (e) {
|
||||
yield put(fetchRealtimeValidationsFailure());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export default function* saga() {
|
||||
yield takeEvery(REGISTER_NEW_USER.BASE, handleNewUserRegistration);
|
||||
yield takeEvery(LOGIN_REQUEST.BASE, handleLoginRequest);
|
||||
yield takeEvery(THIRD_PARTY_AUTH_CONTEXT.BASE, fetchThirdPartyAuthContext);
|
||||
yield takeEvery(REGISTER_FORM.BASE, fetchRegistrationForm);
|
||||
yield takeEvery(REGISTER_FORM_VALIDATIONS.BASE, fetchRealtimeValidations);
|
||||
}
|
||||
|
||||
@@ -85,3 +85,24 @@ export async function getRegistrationForm() {
|
||||
registrationForm: data,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getFieldsValidations(formPayload) {
|
||||
const requestConfig = {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
isPublic: true,
|
||||
};
|
||||
|
||||
const { data } = await getAuthenticatedHttpClient()
|
||||
.post(
|
||||
`${getConfig().LMS_BASE_URL}/api/user/v1/validation/registration`,
|
||||
querystring.stringify(formPayload),
|
||||
requestConfig,
|
||||
)
|
||||
.catch((e) => {
|
||||
throw (e);
|
||||
});
|
||||
|
||||
return {
|
||||
fieldValidations: data,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { runSaga } from 'redux-saga';
|
||||
|
||||
import {
|
||||
fetchRealtimeValidationsBegin,
|
||||
fetchRealtimeValidationsSuccess,
|
||||
fetchRealtimeValidationsFailure,
|
||||
getThirdPartyAuthContextBegin,
|
||||
getThirdPartyAuthContextSuccess,
|
||||
getThirdPartyAuthContextFailure,
|
||||
@@ -8,7 +11,7 @@ import {
|
||||
fetchRegistrationFormSuccess,
|
||||
fetchRegistrationFormFailure,
|
||||
} from '../actions';
|
||||
import { fetchThirdPartyAuthContext, fetchRegistrationForm } from '../sagas';
|
||||
import { fetchRealtimeValidations, fetchThirdPartyAuthContext, fetchRegistrationForm } from '../sagas';
|
||||
import * as api from '../service';
|
||||
|
||||
describe('fetchThirdPartyAuthContext', () => {
|
||||
@@ -109,3 +112,56 @@ describe('fetchRegistrationForm', () => {
|
||||
getRegistrationForm.mockClear();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchRealtimeValidations', () => {
|
||||
const params = {
|
||||
payload: {
|
||||
formData: {
|
||||
email: 'test@test.com',
|
||||
username: '',
|
||||
password: 'test-password',
|
||||
name: 'test-name',
|
||||
honor_code: true,
|
||||
country: 'test-country',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const data = {
|
||||
validation_decisions: {
|
||||
username: 'Username must be between 2 and 30 characters long.',
|
||||
},
|
||||
};
|
||||
|
||||
it('should call service and dispatch success action', async () => {
|
||||
const getFieldsValidations = jest.spyOn(api, 'getFieldsValidations')
|
||||
.mockImplementation(() => Promise.resolve({ fieldValidations: data }));
|
||||
|
||||
const dispatched = [];
|
||||
await runSaga(
|
||||
{ dispatch: (action) => dispatched.push(action) },
|
||||
fetchRealtimeValidations,
|
||||
params,
|
||||
);
|
||||
|
||||
expect(getFieldsValidations).toHaveBeenCalledTimes(1);
|
||||
expect(dispatched).toEqual([fetchRealtimeValidationsBegin(), fetchRealtimeValidationsSuccess(data)]);
|
||||
getFieldsValidations.mockClear();
|
||||
});
|
||||
|
||||
it('should call service and dispatch error action', async () => {
|
||||
const getFieldsValidations = jest.spyOn(api, 'getFieldsValidations')
|
||||
.mockImplementation(() => Promise.reject());
|
||||
|
||||
const dispatched = [];
|
||||
await runSaga(
|
||||
{ dispatch: (action) => dispatched.push(action) },
|
||||
fetchRealtimeValidations,
|
||||
params,
|
||||
);
|
||||
|
||||
expect(getFieldsValidations).toHaveBeenCalledTimes(1);
|
||||
expect(dispatched).toEqual([fetchRealtimeValidationsBegin(), fetchRealtimeValidationsFailure()]);
|
||||
getFieldsValidations.mockClear();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -176,6 +176,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Username must be between 2 and 30 characters long.',
|
||||
description: 'Validation message that appears when username is invalid',
|
||||
},
|
||||
'logistration.country.validation.message': {
|
||||
id: 'logistration.country.validation.message',
|
||||
defaultMessage: 'Select your country or region of residence.',
|
||||
description: 'Validation message that appears when country is not selected',
|
||||
},
|
||||
'logistration.support.education.research': {
|
||||
id: 'logistration.support.education.research',
|
||||
defaultMessage: 'Support education research by providing additional information',
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IntlProvider, injectIntl, configure } from '@edx/frontend-platform/i18n
|
||||
import RegistrationPage from '../RegistrationPage';
|
||||
import { RenderInstitutionButton } from '../InstitutionLogistration';
|
||||
import { PENDING_STATE } from '../../data/constants';
|
||||
import { fetchRegistrationForm } from '../data/actions';
|
||||
import { fetchRegistrationForm, fetchRealtimeValidations, registerNewUser } from '../data/actions';
|
||||
|
||||
const IntlRegistrationPage = injectIntl(RegistrationPage);
|
||||
const mockStore = configureStore();
|
||||
@@ -237,6 +237,62 @@ describe('./RegistrationPage.js', () => {
|
||||
expect(store.dispatch).toHaveBeenCalledWith(fetchRegistrationForm());
|
||||
});
|
||||
|
||||
it('should dispatch fetchRealtimeValidations on Blur', () => {
|
||||
store = mockStore({
|
||||
...initialState,
|
||||
logistration: {
|
||||
...initialState.logistration,
|
||||
},
|
||||
});
|
||||
|
||||
const formPayload = {
|
||||
email: '',
|
||||
username: '',
|
||||
password: '',
|
||||
name: '',
|
||||
honor_code: true,
|
||||
country: '',
|
||||
};
|
||||
store.dispatch = jest.fn(store.dispatch);
|
||||
|
||||
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
|
||||
|
||||
registrationPage.find('input#username').simulate('blur', { target: { value: '', name: 'username' } });
|
||||
expect(store.dispatch).toHaveBeenCalledWith(fetchRealtimeValidations(formPayload));
|
||||
|
||||
registrationPage.find('input#name').simulate('blur', { target: { value: '', name: 'name' } });
|
||||
expect(store.dispatch).toHaveBeenCalledWith(fetchRealtimeValidations(formPayload));
|
||||
|
||||
registrationPage.find('input#email').simulate('blur', { target: { value: '', name: 'email' } });
|
||||
expect(store.dispatch).toHaveBeenCalledWith(fetchRealtimeValidations(formPayload));
|
||||
|
||||
registrationPage.find('input#password').simulate('blur', { target: { value: '', name: 'password' } });
|
||||
expect(store.dispatch).toHaveBeenCalledWith(fetchRealtimeValidations(formPayload));
|
||||
});
|
||||
|
||||
it('should not dispatch registerNewUser on Submit', () => {
|
||||
store = mockStore({
|
||||
...initialState,
|
||||
logistration: {
|
||||
...initialState.logistration,
|
||||
},
|
||||
});
|
||||
|
||||
const formPayload = {
|
||||
email: '',
|
||||
username: '',
|
||||
password: '',
|
||||
name: '',
|
||||
honor_code: true,
|
||||
country: '',
|
||||
};
|
||||
store.dispatch = jest.fn(store.dispatch);
|
||||
|
||||
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
|
||||
registrationPage.find('button.submit').simulate('click');
|
||||
expect(store.dispatch).not.toHaveBeenCalledWith(registerNewUser(formPayload));
|
||||
});
|
||||
|
||||
it('should match default section snapshot', () => {
|
||||
const tree = renderer.create(reduxWrapper(<IntlRegistrationPage {...props} />));
|
||||
expect(tree.toJSON()).toMatchSnapshot();
|
||||
|
||||
@@ -73,18 +73,13 @@ exports[`./RegistrationPage.js should match TPA provider snapshot 1`] = `
|
||||
className="form-control"
|
||||
id="name"
|
||||
name="name"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="name-invalid-feedback"
|
||||
>
|
||||
Enter your full name.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -100,18 +95,13 @@ exports[`./RegistrationPage.js should match TPA provider snapshot 1`] = `
|
||||
className="form-control"
|
||||
id="username"
|
||||
name="username"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="username-invalid-feedback"
|
||||
>
|
||||
Username must be between 2 and 30 characters long.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -127,18 +117,13 @@ exports[`./RegistrationPage.js should match TPA provider snapshot 1`] = `
|
||||
className="form-control"
|
||||
id="email"
|
||||
name="email"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="email"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="email-invalid-feedback"
|
||||
>
|
||||
Enter a valid email address that contains at least 3 characters.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -154,18 +139,13 @@ exports[`./RegistrationPage.js should match TPA provider snapshot 1`] = `
|
||||
className="form-control"
|
||||
id="password"
|
||||
name="password"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="password-invalid-feedback"
|
||||
>
|
||||
This password is too short. It must contain at least 8 characters. This password must contain at least 1 number.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group custom-control"
|
||||
@@ -270,18 +250,13 @@ exports[`./RegistrationPage.js should match default section snapshot 1`] = `
|
||||
className="form-control"
|
||||
id="name"
|
||||
name="name"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="name-invalid-feedback"
|
||||
>
|
||||
Enter your full name.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -297,18 +272,13 @@ exports[`./RegistrationPage.js should match default section snapshot 1`] = `
|
||||
className="form-control"
|
||||
id="username"
|
||||
name="username"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="username-invalid-feedback"
|
||||
>
|
||||
Username must be between 2 and 30 characters long.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -324,18 +294,13 @@ exports[`./RegistrationPage.js should match default section snapshot 1`] = `
|
||||
className="form-control"
|
||||
id="email"
|
||||
name="email"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="email"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="email-invalid-feedback"
|
||||
>
|
||||
Enter a valid email address that contains at least 3 characters.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -351,18 +316,13 @@ exports[`./RegistrationPage.js should match default section snapshot 1`] = `
|
||||
className="form-control"
|
||||
id="password"
|
||||
name="password"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="password-invalid-feedback"
|
||||
>
|
||||
This password is too short. It must contain at least 8 characters. This password must contain at least 1 number.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group custom-control"
|
||||
@@ -467,18 +427,13 @@ exports[`./RegistrationPage.js should match pending button state snapshot 1`] =
|
||||
className="form-control"
|
||||
id="name"
|
||||
name="name"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="name-invalid-feedback"
|
||||
>
|
||||
Enter your full name.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -494,18 +449,13 @@ exports[`./RegistrationPage.js should match pending button state snapshot 1`] =
|
||||
className="form-control"
|
||||
id="username"
|
||||
name="username"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="username-invalid-feedback"
|
||||
>
|
||||
Username must be between 2 and 30 characters long.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -521,18 +471,13 @@ exports[`./RegistrationPage.js should match pending button state snapshot 1`] =
|
||||
className="form-control"
|
||||
id="email"
|
||||
name="email"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="email"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="email-invalid-feedback"
|
||||
>
|
||||
Enter a valid email address that contains at least 3 characters.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -548,18 +493,13 @@ exports[`./RegistrationPage.js should match pending button state snapshot 1`] =
|
||||
className="form-control"
|
||||
id="password"
|
||||
name="password"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="password-invalid-feedback"
|
||||
>
|
||||
This password is too short. It must contain at least 8 characters. This password must contain at least 1 number.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group custom-control"
|
||||
@@ -711,18 +651,13 @@ exports[`./RegistrationPage.js should show error message on 409 1`] = `
|
||||
className="form-control"
|
||||
id="name"
|
||||
name="name"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="name-invalid-feedback"
|
||||
>
|
||||
Enter your full name.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -738,18 +673,13 @@ exports[`./RegistrationPage.js should show error message on 409 1`] = `
|
||||
className="form-control"
|
||||
id="username"
|
||||
name="username"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="username-invalid-feedback"
|
||||
>
|
||||
Username must be between 2 and 30 characters long.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -765,18 +695,13 @@ exports[`./RegistrationPage.js should show error message on 409 1`] = `
|
||||
className="form-control"
|
||||
id="email"
|
||||
name="email"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="email"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="email-invalid-feedback"
|
||||
>
|
||||
Enter a valid email address that contains at least 3 characters.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group"
|
||||
@@ -792,18 +717,13 @@ exports[`./RegistrationPage.js should show error message on 409 1`] = `
|
||||
className="form-control"
|
||||
id="password"
|
||||
name="password"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
placeholder=""
|
||||
required={true}
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<strong
|
||||
className="invalid-feedback"
|
||||
id="password-invalid-feedback"
|
||||
>
|
||||
This password is too short. It must contain at least 8 characters. This password must contain at least 1 number.
|
||||
</strong>
|
||||
</div>
|
||||
<div
|
||||
className="form-group custom-control"
|
||||
|
||||
Reference in New Issue
Block a user