Commit f1752bbd authored by Phil Hughes's avatar Phil Hughes

Merge branch 'feature/56787-realtime-validation-for-user-fullname-and-username' into 'master'

Feature/56787 realtime validation for user fullname and username

See merge request gitlab-org/gitlab-ce!25017
parents 10094950 7403d466
import { __ } from '~/locale';
import emojiRegex from 'emoji-regex';
const invalidInputClass = 'gl-field-error-outline';
export default class NoEmojiValidator {
constructor(opts = {}) {
const container = opts.container || '';
this.noEmojiEmelents = document.querySelectorAll(`${container} .js-block-emoji`);
this.noEmojiEmelents.forEach(element =>
element.addEventListener('input', this.eventHandler.bind(this)),
);
}
eventHandler(event) {
this.inputDomElement = event.target;
this.inputErrorMessage = this.inputDomElement.nextSibling;
const { value } = this.inputDomElement;
this.validatePattern(value);
this.setValidationStateAndMessage();
}
validatePattern(value) {
const pattern = emojiRegex();
this.hasEmojis = new RegExp(pattern).test(value);
if (this.hasEmojis) {
this.inputDomElement.setCustomValidity(__('Invalid input, please avoid emojis'));
} else {
this.inputDomElement.setCustomValidity('');
}
}
setValidationStateAndMessage() {
if (!this.inputDomElement.checkValidity()) {
this.setInvalidState();
} else {
this.clearFieldValidationState();
}
}
clearFieldValidationState() {
this.inputDomElement.classList.remove(invalidInputClass);
this.inputErrorMessage.classList.add('hide');
}
setInvalidState() {
this.inputDomElement.classList.add(invalidInputClass);
this.setErrorMessage();
}
setErrorMessage() {
if (this.hasEmojis) {
this.inputErrorMessage.innerHTML = this.inputDomElement.validationMessage;
} else {
this.inputErrorMessage.innerHTML = this.inputDomElement.title;
}
this.inputErrorMessage.classList.remove('hide');
}
}
import $ from 'jquery'; import $ from 'jquery';
import UsernameValidator from './username_validator'; import UsernameValidator from './username_validator';
import NoEmojiValidator from '../../../emoji/no_emoji_validator';
import SigninTabsMemoizer from './signin_tabs_memoizer'; import SigninTabsMemoizer from './signin_tabs_memoizer';
import OAuthRememberMe from './oauth_remember_me'; import OAuthRememberMe from './oauth_remember_me';
import preserveUrlFragment from './preserve_url_fragment'; import preserveUrlFragment from './preserve_url_fragment';
...@@ -7,6 +8,7 @@ import preserveUrlFragment from './preserve_url_fragment'; ...@@ -7,6 +8,7 @@ import preserveUrlFragment from './preserve_url_fragment';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
new UsernameValidator(); // eslint-disable-line no-new new UsernameValidator(); // eslint-disable-line no-new
new SigninTabsMemoizer(); // eslint-disable-line no-new new SigninTabsMemoizer(); // eslint-disable-line no-new
new NoEmojiValidator(); // eslint-disable-line no-new
new OAuthRememberMe({ new OAuthRememberMe({
container: $('.omniauth-container'), container: $('.omniauth-container'),
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
= form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f| = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f|
.devise-errors .devise-errors
= devise_error_messages! = devise_error_messages!
.form-group .name.form-group
= f.label :name, 'Full name', class: 'label-bold' = f.label :name, 'Full name', class: 'label-bold'
= f.text_field :name, class: "form-control top qa-new-user-name", required: true, title: "This field is required." = f.text_field :name, class: "form-control top qa-new-user-name js-block-emoji", required: true, title: _("This field is required.")
.username.form-group .username.form-group
= f.label :username, class: 'label-bold' = f.label :username, class: 'label-bold'
= f.text_field :username, class: "form-control middle qa-new-user-username", pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: 'Please create a username with only alphanumeric characters.' = f.text_field :username, class: "form-control middle qa-new-user-username js-block-emoji", pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
%p.validation-error.hide Username is already taken. %p.validation-error.hide Username is already taken.
%p.validation-success.hide Username is available. %p.validation-success.hide Username is available.
%p.validation-pending.hide Checking username availability... %p.validation-pending.hide Checking username availability...
......
---
title: Add realtime validation for user fullname and username on validation
merge_request: 25017
author: Ehsan Abdulqader @EhsanZ
type: added
...@@ -4058,6 +4058,9 @@ msgstr "" ...@@ -4058,6 +4058,9 @@ msgstr ""
msgid "Introducing Your Conversational Development Index" msgid "Introducing Your Conversational Development Index"
msgstr "" msgstr ""
msgid "Invalid input, please avoid emojis"
msgstr ""
msgid "Invitation" msgid "Invitation"
msgstr "" msgstr ""
...@@ -5470,6 +5473,9 @@ msgstr "" ...@@ -5470,6 +5473,9 @@ msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again." msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "" msgstr ""
msgid "Please create a username with only alphanumeric characters."
msgstr ""
msgid "Please fill in a descriptive name for your group." msgid "Please fill in a descriptive name for your group."
msgstr "" msgstr ""
...@@ -7387,6 +7393,9 @@ msgstr "" ...@@ -7387,6 +7393,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled." msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr "" msgstr ""
msgid "This field is required."
msgstr ""
msgid "This group" msgid "This group"
msgstr "" msgstr ""
......
...@@ -49,6 +49,34 @@ describe 'Signup' do ...@@ -49,6 +49,34 @@ describe 'Signup' do
expect(page).to have_content("Please create a username with only alphanumeric characters.") expect(page).to have_content("Please create a username with only alphanumeric characters.")
end end
it 'shows an error border if the username contains emojis' do
simulate_input('#new_user_username', 'ehsan😀')
expect(find('.username')).to have_css '.gl-field-error-outline'
end
it 'shows an error message if the username contains emojis' do
simulate_input('#new_user_username', 'ehsan😀')
expect(page).to have_content("Invalid input, please avoid emojis")
end
end
describe 'user\'s full name validation', :js do
before do
visit root_path
click_link 'Register'
simulate_input('#new_user_name', 'Ehsan 🦋')
end
it 'shows an error border if the user\'s fullname contains an emoji' do
expect(find('.name')).to have_css '.gl-field-error-outline'
end
it 'shows an error message if the username contains emojis' do
expect(page).to have_content("Invalid input, please avoid emojis")
end
end end
context 'with no errors' do context 'with no errors' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment