Skip to content
This repository has been archived by the owner on Nov 21, 2024. It is now read-only.

Commit

Permalink
Merge pull request #4 from graasp/3/inputValidatin
Browse files Browse the repository at this point in the history
Input Validation
  • Loading branch information
pyphilia authored Jul 7, 2021
2 parents badfd98 + 016f57b commit cf86201
Show file tree
Hide file tree
Showing 18 changed files with 283 additions and 14,987 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ cypress/videos

# jetbrains
.idea

#yarn lock
yarn.lock
3 changes: 3 additions & 0 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"baseUrl": "http://localhost:3001"
}
25 changes: 25 additions & 0 deletions cypress/fixtures/members.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const MEMBERS = {
GRAASP: {
id: 'graasp-id',
name: 'graasp',
email: 'graasp@graasp.org',
nameValid: true,
emailValid: true,
},
WRONG_NAME: {
id: 'id1',
name: 'w',
email: 'graasp@graasp.org',
nameValid: false,
emailValid: true,
},
WRONG_EMAIL: {
id: 'id2',
name: 'graasp',
email: 'wrong',
nameValid: true,
emailValid: false,
},
};

export default MEMBERS;
13 changes: 13 additions & 0 deletions cypress/integration/SignInValidation.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { SIGN_IN_PATH } from '../../src/config/paths';
import { MEMBERS } from '../fixtures/members';

describe('Name and Email Validation', () => {
it('Sign In', () => {
const { GRAASP, WRONG_EMAIL } = MEMBERS;
cy.visit(SIGN_IN_PATH);
// Signing in with a wrong email format
cy.signInAndCheck(WRONG_EMAIL);
// Siging in with a valid email
cy.signInAndCheck(GRAASP);
});
});
15 changes: 15 additions & 0 deletions cypress/integration/SignUpValidation.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { SIGN_UP_PATH } from '../../src/config/paths';
import { MEMBERS } from '../fixtures/members';

describe('Name and Email Validation', () => {
it('Sign Up', () => {
const { GRAASP, WRONG_NAME, WRONG_EMAIL } = MEMBERS;
cy.visit(SIGN_UP_PATH);
// Signing up with a wrong name and right email
cy.signUpAndCheck(WRONG_NAME);
// Signing up with a wrong email and right name
cy.signUpAndCheck(WRONG_EMAIL);
// Signing up with right email and name
cy.signUpAndCheck(GRAASP);
});
});
24 changes: 24 additions & 0 deletions cypress/integration/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {
EMAIL_SIGN_IN_FIELD_ID,
EMAIL_SIGN_UP_FIELD_ID,
NAME_SIGN_UP_FIELD_ID,
SIGN_IN_BUTTON_ID,
SIGN_UP_BUTTON_ID,
} from '../../src/config/selectors';

export const fillSignUpLayout = ({ name, email }) => {
cy.get(`#${NAME_SIGN_UP_FIELD_ID}`).clear().type(name);
cy.get(`#${EMAIL_SIGN_UP_FIELD_ID}`).clear().type(email);
};

export const fillSignInLayout = ({ email }) => {
cy.get(`#${EMAIL_SIGN_IN_FIELD_ID}`).clear().type(email);
};

export const submitSignIn = () => {
cy.get(`#${SIGN_IN_BUTTON_ID}`).click();
};

export const submitSignUp = () => {
cy.get(`#${SIGN_UP_BUTTON_ID}`).click();
};
21 changes: 21 additions & 0 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

/**
* @type {Cypress.PluginConfig}
*/
module.exports = () => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
};
42 changes: 42 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
import {
EMAIL_SIGN_UP_FIELD_ID,
NAME_SIGN_UP_FIELD_ID,
} from '../../src/config/selectors';

const {
submitSignIn,
fillSignUpLayout,
fillSignInLayout,
submitSignUp,
} = require('../integration/util');

Cypress.Commands.add('checkErrorTextField', (id, flag) => {
const existence = flag ? 'not.exist' : 'exist';
cy.get(`#${id}-helper-text`).should(existence);
});

Cypress.Commands.add('signUpAndCheck', (user) => {
fillSignUpLayout(user);
submitSignUp();

cy.checkErrorTextField(NAME_SIGN_UP_FIELD_ID, user.nameValid);
cy.checkErrorTextField(EMAIL_SIGN_UP_FIELD_ID, user.emailValid);
});

Cypress.Commands.add('signInAndCheck', (user) => {
fillSignInLayout(user);
submitSignIn();
cy.checkErrorTextField(EMAIL_SIGN_UP_FIELD_ID, user.email);
});
20 changes: 20 additions & 0 deletions cypress/support/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands';

// Alternatively you can use CommonJS syntax:
// require('./commands')
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-scripts": "4.0.1",
"react-toastify": "7.0.3"
"react-toastify": "7.0.3",
"validator": "13.6.0"
},
"scripts": {
"start": "env-cmd -f ./.env.local react-scripts start",
Expand Down
44 changes: 30 additions & 14 deletions src/components/SignIn.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import { Link } from 'react-router-dom';
import FormControl from '@material-ui/core/FormControl';
import { SIGN_UP_PATH } from '../config/paths';
import { getCurrentMember, signIn } from '../actions/authentication';
import { GRAASP_COMPOSE_HOST } from '../config/constants';
import { FIELD_WIDTH, GRAASP_COMPOSE_HOST } from '../config/constants';
import { emailValidator } from '../utils/validation';
import { EMAIL_SIGN_IN_FIELD_ID, SIGN_IN_BUTTON_ID } from '../config/selectors';

const styles = (theme) => ({
fullScreen: {
Expand All @@ -21,10 +23,11 @@ const styles = (theme) => ({
},
input: {
margin: theme.spacing(1),
width: FIELD_WIDTH,
},
form: {
width: '50%',
minWidth: '200px',
minWidth: FIELD_WIDTH,
margin: 'auto',
},
divider: {
Expand All @@ -51,6 +54,8 @@ class SignIn extends Component {
state = {
email: '',
isAuthenticated: false,
emailError: '',
error: false,
};

async componentDidMount() {
Expand All @@ -75,24 +80,27 @@ class SignIn extends Component {
}
};

handleOnRegister = () => {
const {
history: { push },
} = this.props;
push(SIGN_UP_PATH);
};

signIn = async () => {
handleSignIn = async () => {
const { email } = this.state;
signIn({ email });
const checkingEmail = emailValidator(email);
if (checkingEmail) {
this.setState({ emailError: checkingEmail, error: true });
} else {
await signIn({ email });
}
};

handleOnChange = (e) => {
this.setState({ email: e.target.value });
const { error } = this.state;
const email = e.target.value;
this.setState({ email });
if (error) {
this.setState({ emailError: emailValidator(email) });
}
};

renderSignInForm = () => {
const { email } = this.state;
const { email, emailError } = this.state;
const { classes, t } = this.props;

return (
Expand All @@ -104,9 +112,17 @@ class SignIn extends Component {
label={t('Email')}
variant="outlined"
value={email}
error={emailError}
helperText={emailError}
onChange={this.handleOnChange}
id={EMAIL_SIGN_IN_FIELD_ID}
/>
<Button variant="contained" color="primary" onClick={this.signIn}>
<Button
variant="contained"
color="primary"
onClick={this.handleSignIn}
id={SIGN_IN_BUTTON_ID}
>
{t('Sign In')}
</Button>
</FormControl>
Expand Down
57 changes: 49 additions & 8 deletions src/components/SignUp.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import { Link } from 'react-router-dom';
import Grid from '@material-ui/core/Grid';
import { buildSignInPath } from '../config/paths';
import { getCurrentMember, signUp } from '../actions/authentication';
import { GRAASP_COMPOSE_HOST } from '../config/constants';
import { FIELD_WIDTH, GRAASP_COMPOSE_HOST } from '../config/constants';
import { emailValidator, nameValidator } from '../utils/validation';
import {
EMAIL_SIGN_UP_FIELD_ID,
NAME_SIGN_UP_FIELD_ID,
SIGN_UP_BUTTON_ID,
} from '../config/selectors';

const styles = (theme) => ({
fullScreen: {
Expand All @@ -20,10 +26,11 @@ const styles = (theme) => ({
},
input: {
margin: theme.spacing(1),
width: FIELD_WIDTH,
},
form: {
width: '50%',
minWidth: '200px',
minWidth: FIELD_WIDTH,
margin: 'auto',
},
});
Expand All @@ -48,6 +55,9 @@ class SignUp extends Component {
state = {
email: '',
name: '',
emailError: '',
nameError: '',
error: false,
};

async componentDidMount() {
Expand All @@ -73,21 +83,41 @@ class SignUp extends Component {
};

handleEmailOnChange = (e) => {
this.setState({ email: e.target.value });
const { error } = this.state;
const email = e.target.value;
this.setState({ email });
if (error) {
this.setState({ emailError: emailValidator(email) });
}
};

handleNameOnChange = (e) => {
this.setState({ name: e.target.value });
const { error } = this.state;
const name = e.target.value;
this.setState({ name });
if (error) {
this.setState({ nameError: nameValidator(name) });
}
};

register = async () => {
handleRegister = async () => {
const { email, name } = this.state;
signUp({ name, email });
const checkingEmail = emailValidator(email);
const checkingUsername = nameValidator(name);
if (checkingEmail || checkingUsername) {
this.setState({
emailError: checkingEmail,
nameError: checkingUsername,
error: true,
});
} else {
await signUp({ name, email });
}
};

renderForm = () => {
const { classes, t } = this.props;
const { email, name } = this.state;
const { email, name, emailError, nameError } = this.state;

return (
<>
Expand All @@ -98,7 +128,10 @@ class SignUp extends Component {
label={t('Name')}
variant="outlined"
value={name}
error={Boolean(nameError)}
helperText={nameError}
onChange={this.handleNameOnChange}
id={NAME_SIGN_UP_FIELD_ID}
/>
</Grid>
<Grid item xs={12}>
Expand All @@ -108,11 +141,19 @@ class SignUp extends Component {
label={t('Email')}
variant="outlined"
value={email}
error={Boolean(emailError)}
helperText={emailError}
onChange={this.handleEmailOnChange}
id={EMAIL_SIGN_UP_FIELD_ID}
/>
</Grid>
<Grid item xs={12}>
<Button variant="contained" color="primary" onClick={this.register}>
<Button
variant="contained"
color="primary"
onClick={this.handleRegister}
id={SIGN_UP_BUTTON_ID}
>
{t('Sign Up')}
</Button>
</Grid>
Expand Down
Loading

0 comments on commit cf86201

Please sign in to comment.