Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Client side validation of Signup form #1251

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions app/assets/javascripts/modules/users/components/signup-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import BaseComponent from '~/base/component';

const PASSWORD_FIELD = '#user_password';
const USERNAME_FIELD = '#user_username';
const EMAIL_FIELD = '#user_email';
const CONFIRMATION_PASSWORD_FIELD = '#user_password_confirmation';
const SUBMIT_BUTTON = '#submit_btn';

// UsersPasswordForm component that handles user password form
// interactions.
class UsersSignUpForm extends BaseComponent {
elements() {
this.$password = this.$el.find(PASSWORD_FIELD);
this.$passwordConfirmation = this.$el.find(CONFIRMATION_PASSWORD_FIELD);
this.$username = this.$el.find(USERNAME_FIELD);
this.$userEmail = this.$el.find(EMAIL_FIELD);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are not gonna use the $element, you don't need to cache it here. So, I think you can remove both username and email elements, constants and event listeners.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. My bad! Forgot the disabled button. 😅

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah ..they are used in emailInvalid , usernameInvalid and for disabling the submit button. So no need to remove them right ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need. I just woke up. Wasn't thinking really straight yet. KKKK.

this.$submit = this.$el.find(SUBMIT_BUTTON);
}

events() {
this.$el.on('focusout', PASSWORD_FIELD, e => this.onFocusout(e));
this.$el.on('focusout', CONFIRMATION_PASSWORD_FIELD, e => this.onFocusout(e));
this.$el.on('focusout', USERNAME_FIELD, e => this.onFocusout(e));
this.$el.on('focusout', EMAIL_FIELD, e => this.onFocusout(e));
}

onFocusout() {
const usernameInvalid = !this.$username[0].validity.valid;
const emailInvalid = !this.$userEmail[0].validity.valid;
const passwordInvalid = !this.$password.val() || this.$password.val().length < 8;
const passwordConfirmationInvalid = !this.$passwordConfirmation.val() ||
this.$password.val() !== this.$passwordConfirmation.val();

if (passwordConfirmationInvalid) {
this.$passwordConfirmation[0].setCustomValidity('Please enter same password as above');
} else {
this.$passwordConfirmation[0].setCustomValidity('');
}

if (passwordInvalid) {
this.$password[0].setCustomValidity('Password should be of at least 8 characters minimum.');
} else {
this.$password[0].setCustomValidity('');
this.$passwordConfirmation.attr('pattern', this.$password.val());
}

if (passwordInvalid || passwordConfirmationInvalid || emailInvalid || usernameInvalid) {
this.$submit.attr('disabled', true);
} else {
this.$submit.removeAttr('disabled');
}
}
}

export default UsersSignUpForm;
8 changes: 8 additions & 0 deletions app/assets/javascripts/modules/users/pages/sign-up.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import BaseComponent from '~/base/component';

import { fadeIn } from '~/utils/effects';
import SignUpForm from '../components/signup-form';

const SIGN_UP_FORM = 'form.new_user';

// UsersSignUpPage component responsible to instantiate
// the user's sign up page components and handle interactions.
class UsersSignUpPage extends BaseComponent {
elements() {
this.$signupForm = this.$el.find(SIGN_UP_FORM);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking: add an empty line to separate the elements and the mount functions 😄

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah Sure 😃


mount() {
fadeIn(this.$el);
this.signupForm = new SignUpForm(this.$signupForm);
}
}

Expand Down
6 changes: 3 additions & 3 deletions app/views/devise/registrations/new.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ section.sign-up class=(@have_users ? '' : 'first-user')
= image_tag 'layout/portus-logo-login-page.png', class: 'login-picture'
= form_for(resource, as: resource_name, url: { action: 'create' }, :html => {:autocomplete => "off"}) do |f|
= f.text_field :username, class: 'form-control input-lg', placeholder: 'Username', required: true, autofocus: true
= f.email_field :email, class: 'form-control input-lg first', placeholder: 'Email', required: true
= f.password_field :password, class: 'form-control input-lg', placeholder: 'Password (8 characters min.)', required: true
= f.email_field :email, class: 'form-control input-lg first', placeholder: 'Email', required: true
= f.password_field :password, class: 'form-control input-lg', placeholder: 'Password (8 characters min.)', required: true, pattern: '^.{8,}$'
= f.password_field :password_confirmation, class: 'form-control input-lg last', placeholder: 'Password again', required: true

- if !@admin && @first_user_admin
= f.hidden_field :admin, value: true

button.btn.btn-primary.btn-block.btn-lg type="submit"
button.btn.btn-primary.btn-block.btn-lg#submit_btn type="submit"
i.fa.fa-check
- if @admin || !@first_user_admin
| Create account
Expand Down
24 changes: 24 additions & 0 deletions spec/features/auth/signup_feature_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,30 @@
text: 'Password confirmation doesn\'t match Password')
end

scenario "Submit Button gets disabled when any field is filled wrong", js: true do
visit "/users/sign_up"
wait_for_effect_on("#new_user")
fill_in "Username", with: user.username
fill_in "user_email", with: "gibberish"
fill_in "user_password", with: "12341234"
fill_in "user_password_confirmation", with: "532"
page.execute_script "$('#user_username').trigger('focusout')"
wait_for_effect_on("#submit_btn")
expect(page).to have_button("submit_btn", disabled: true)
end

scenario "Submit Button should be enabled when all fields are filled right", js: true do
visit "/users/sign_up"
wait_for_effect_on("#new_user")
fill_in "Username", with: user.username
fill_in "user_email", with: user.email
fill_in "user_password", with: user.password
fill_in "user_password_confirmation", with: user.password
page.execute_script "$('#user_username').trigger('focusout')"
wait_for_effect_on("#submit_btn")
expect(page).to have_button("submit_btn", disabled: false)
end

scenario "If there are users on the system, and can move through sign_in and sign_up" do
click_link("Login")
expect(current_path).to eql(new_user_session_path)
Expand Down