Commit d252e70eacdd4daebbd3aeead6e57f29c04cf0e4
Exists in
master
and in
22 other branches
Merge branch 'AI3009-username_suggestion' of https://gitlab.com/unb-gama/noosfer…
…o into AI3009-username_suggestion Conflicts: app/views/account/_signup_form.rhtml
Showing
7 changed files
with
99 additions
and
22 deletions
 
Show diff stats
app/controllers/public/account_controller.rb
| @@ -250,15 +250,19 @@ class AccountController < ApplicationController | @@ -250,15 +250,19 @@ class AccountController < ApplicationController | ||
| 250 | end | 250 | end | 
| 251 | end | 251 | end | 
| 252 | 252 | ||
| 253 | - def check_url | 253 | + def check_valid_name | 
| 254 | @identifier = params[:identifier] | 254 | @identifier = params[:identifier] | 
| 255 | valid = Person.is_available?(@identifier, environment) | 255 | valid = Person.is_available?(@identifier, environment) | 
| 256 | if valid | 256 | if valid | 
| 257 | @status = _('This login name is available') | 257 | @status = _('This login name is available') | 
| 258 | @status_class = 'validated' | 258 | @status_class = 'validated' | 
| 259 | - else | 259 | + elsif !@identifier.empty? | 
| 260 | + @suggested_usernames = suggestion_based_on_username(@identifier) | ||
| 260 | @status = _('This login name is unavailable') | 261 | @status = _('This login name is unavailable') | 
| 261 | @status_class = 'invalid' | 262 | @status_class = 'invalid' | 
| 263 | + else | ||
| 264 | + @status_class = 'invalid' | ||
| 265 | + @status = _('This field can\'t be blank') | ||
| 262 | end | 266 | end | 
| 263 | render :partial => 'identifier_status' | 267 | render :partial => 'identifier_status' | 
| 264 | end | 268 | end | 
app/helpers/account_helper.rb
| @@ -12,4 +12,17 @@ module AccountHelper | @@ -12,4 +12,17 @@ module AccountHelper | ||
| 12 | _('Checking if e-mail address is already taken...') | 12 | _('Checking if e-mail address is already taken...') | 
| 13 | end | 13 | end | 
| 14 | end | 14 | end | 
| 15 | + | ||
| 16 | + def suggestion_based_on_username(requested_username) | ||
| 17 | + return "" if requested_username.empty? | ||
| 18 | + usernames = [] | ||
| 19 | + 3.times do | ||
| 20 | + begin | ||
| 21 | + valid_name = requested_username + rand(1000).to_s | ||
| 22 | + end while (usernames.include?(valid_name) && Person.is_available?(valid_name, environment)) | ||
| 23 | + usernames += [valid_name] | ||
| 24 | + end | ||
| 25 | + usernames | ||
| 26 | + end | ||
| 27 | + | ||
| 15 | end | 28 | end | 
app/views/account/_identifier_status.rhtml
| 1 | <div class='status-identifier'> | 1 | <div class='status-identifier'> | 
| 2 | + <% if @suggested_usernames %> | ||
| 3 | + <% @status += '<br>' + _('Available: ') if not @suggested_usernames.empty? %> | ||
| 4 | + <% @suggested_usernames.each do |username| %> | ||
| 5 | + <% @status += "<a href='#' class='suggested_usernames'>" + username + '</a> ' %> | ||
| 6 | + <%end%> | ||
| 7 | + <% end %> | ||
| 8 | + | ||
| 9 | + | ||
| 2 | <p><span class='<%= @status_class %>'><%= @status %></span></p> | 10 | <p><span class='<%= @status_class %>'><%= @status %></span></p> | 
| 3 | <script type="text/javascript"> | 11 | <script type="text/javascript"> | 
| 4 | jQuery('#user_login').removeClass('<%= validation_classes %>'); | 12 | jQuery('#user_login').removeClass('<%= validation_classes %>'); | 
| 5 | jQuery('#user_login').addClass('<%= @status_class %>'); | 13 | jQuery('#user_login').addClass('<%= @status_class %>'); | 
| 14 | + jQuery('.suggested_usernames').click(function(e) { | ||
| 15 | + e.preventDefault(); | ||
| 16 | + | ||
| 17 | + fill_username(this.innerHTML); | ||
| 18 | + }); | ||
| 6 | </script> | 19 | </script> | 
| 7 | -</div> | 20 | -</div> | 
| 21 | +</div> | ||
| 8 | \ No newline at end of file | 22 | \ No newline at end of file | 
app/views/account/_signup_form.rhtml
| @@ -42,15 +42,7 @@ | @@ -42,15 +42,7 @@ | ||
| 42 | <br style="clear: both;" /> | 42 | <br style="clear: both;" /> | 
| 43 | </div> | 43 | </div> | 
| 44 | </div> | 44 | </div> | 
| 45 | - <%= observe_field 'user_login', | ||
| 46 | - :url => { :action => 'check_url' }, | ||
| 47 | - :with => 'identifier', | ||
| 48 | - :update => 'url-check', | ||
| 49 | - :loading => "jQuery('#user_login').removeClass('#{validation_classes}').addClass('checking'); | ||
| 50 | - jQuery('#url-check').html('<p><span class=\"checking\">#{checking_message(:url)}</span></p>');", | ||
| 51 | - :complete => "jQuery('#user_login').removeClass('checking')" | ||
| 52 | - %> | ||
| 53 | - | 45 | + <%= javascript_include_tag "signup_form" %> | 
| 54 | <div id='signup-password'> | 46 | <div id='signup-password'> | 
| 55 | <%= required f.password_field(:password, :id => 'user_pw') %> | 47 | <%= required f.password_field(:password, :id => 'user_pw') %> | 
| 56 | <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %> | 48 | <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %> | 
| @@ -198,4 +190,8 @@ jQuery(function($) { | @@ -198,4 +190,8 @@ jQuery(function($) { | ||
| 198 | }); | 190 | }); | 
| 199 | }); | 191 | }); | 
| 200 | 192 | ||
| 193 | +function fill_username(element){ | ||
| 194 | + jQuery('#url-check').html('<p><span class=\"checking\"><%= _('This login name is available') %></span></p>') | ||
| 195 | + jQuery('#user_login').val(element).addClass('validated').removeClass('invalid') | ||
| 196 | +} | ||
| 201 | </script> | 197 | </script> | 
features/signup.feature
| @@ -29,13 +29,32 @@ Feature: signup | @@ -29,13 +29,32 @@ Feature: signup | ||
| 29 | And I press "Log in" | 29 | And I press "Log in" | 
| 30 | Then I should be logged in as "josesilva" | 30 | Then I should be logged in as "josesilva" | 
| 31 | 31 | ||
| 32 | + @selenium | ||
| 33 | + Scenario: show error message if username is already used | ||
| 34 | + Given I am on the homepage | ||
| 35 | + When I follow "Login" | ||
| 36 | + And I follow "New user" | ||
| 37 | + And I fill in the following within ".no-boxes": | ||
| 38 | + | e-Mail | josesilva@example.com | | ||
| 39 | + | Username | josesilva | | ||
| 40 | + | Password | secret | | ||
| 41 | + | Password confirmation | secret | | ||
| 42 | + | Full name | José da Silva | | ||
| 43 | + And wait for the captcha signup time | ||
| 44 | + And I press "Create my account" | ||
| 45 | + Then I should receive an e-mail on josesilva@example.com | ||
| 46 | + And I go to signup page | ||
| 47 | + And I fill in "Username" with "josesilva" | ||
| 48 | + And I fill in "e-Mail" with "josesilva1" | ||
| 49 | + Then I should see "This login name is unavailable" | ||
| 50 | + | ||
| 32 | Scenario: be redirected if user goes to signup page and is logged | 51 | Scenario: be redirected if user goes to signup page and is logged | 
| 33 | Given the following users | 52 | Given the following users | 
| 34 | | login | name | | 53 | | login | name | | 
| 35 | - | joaosilva | Joao Silva | | ||
| 36 | - Given I am logged in as "joaosilva" | ||
| 37 | - And I go to signup page | ||
| 38 | - Then I should be on joaosilva's control panel | 54 | + | joaosilva | joao silva | | 
| 55 | + Given i am logged in as "joaosilva" | ||
| 56 | + And i go to signup page | ||
| 57 | + Then i should be on joaosilva's control panel | ||
| 39 | 58 | ||
| 40 | @selenium | 59 | @selenium | 
| 41 | Scenario: user cannot register without a name | 60 | Scenario: user cannot register without a name | 
| @@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
| 1 | +function verifyLoginLoad() { | ||
| 2 | + jQuery('#user_login').removeClass('available unavailable valid validated invalid checking').addClass('checking'); | ||
| 3 | + jQuery('#url-check').html('<p><span class="checking">Checking availability of login name...</span></p>'); | ||
| 4 | +} | ||
| 5 | + | ||
| 6 | +function verifyLoginAjax(value) { | ||
| 7 | + verifyLoginLoad(); | ||
| 8 | + | ||
| 9 | + jQuery.get( | ||
| 10 | + "/account/check_valid_name", | ||
| 11 | + {'identifier': encodeURIComponent(value)}, | ||
| 12 | + function(request){ | ||
| 13 | + jQuery('#user_login').removeClass('checking'); | ||
| 14 | + jQuery("#url-check").html(request); | ||
| 15 | + } | ||
| 16 | + ); | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +jQuery(document).ready(function(){ | ||
| 20 | + jQuery("#user_login").blur(function(){ | ||
| 21 | + verifyLoginAjax(this.value); | ||
| 22 | + }); | ||
| 23 | +}); | ||
| 0 | \ No newline at end of file | 24 | \ No newline at end of file | 
test/functional/account_controller_test.rb
| @@ -8,7 +8,6 @@ class AccountControllerTest < ActionController::TestCase | @@ -8,7 +8,6 @@ class AccountControllerTest < ActionController::TestCase | ||
| 8 | # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead | 8 | # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead | 
| 9 | # Then, you can remove it from this and the units test. | 9 | # Then, you can remove it from this and the units test. | 
| 10 | include AuthenticatedTestHelper | 10 | include AuthenticatedTestHelper | 
| 11 | - | ||
| 12 | all_fixtures | 11 | all_fixtures | 
| 13 | 12 | ||
| 14 | def teardown | 13 | def teardown | 
| @@ -17,8 +16,8 @@ class AccountControllerTest < ActionController::TestCase | @@ -17,8 +16,8 @@ class AccountControllerTest < ActionController::TestCase | ||
| 17 | 16 | ||
| 18 | def setup | 17 | def setup | 
| 19 | @controller = AccountController.new | 18 | @controller = AccountController.new | 
| 20 | - @request = ActionController::TestRequest.new | ||
| 21 | - @response = ActionController::TestResponse.new | 19 | + @request = ActionController::TestRequest.new | 
| 20 | + @response = ActionController::TestResponse.new | ||
| 22 | disable_signup_bot_check | 21 | disable_signup_bot_check | 
| 23 | end | 22 | end | 
| 24 | 23 | ||
| @@ -36,6 +35,16 @@ class AccountControllerTest < ActionController::TestCase | @@ -36,6 +35,16 @@ class AccountControllerTest < ActionController::TestCase | ||
| 36 | assert_response :redirect | 35 | assert_response :redirect | 
| 37 | end | 36 | end | 
| 38 | 37 | ||
| 38 | + should 'return empty string if suggest_based_on_username argument is empty' do | ||
| 39 | + result = @controller.suggestion_based_on_username("") | ||
| 40 | + assert_equal(result.empty?,true) | ||
| 41 | + end | ||
| 42 | + | ||
| 43 | + should 'return a list with three possible usernames suggestion' do | ||
| 44 | + result = @controller.suggestion_based_on_username("teste") | ||
| 45 | + assert_equal(result.uniq.size,3) | ||
| 46 | + end | ||
| 47 | + | ||
| 39 | should 'display notice message if the login fail' do | 48 | should 'display notice message if the login fail' do | 
| 40 | @controller.stubs(:logged_in?).returns(false) | 49 | @controller.stubs(:logged_in?).returns(false) | 
| 41 | post :login, :user => {:login => 'quire', :password => 'quire'} | 50 | post :login, :user => {:login => 'quire', :password => 'quire'} | 
| @@ -646,18 +655,18 @@ class AccountControllerTest < ActionController::TestCase | @@ -646,18 +655,18 @@ class AccountControllerTest < ActionController::TestCase | ||
| 646 | assert_redirected_to :controller => 'home', :action => 'index' | 655 | assert_redirected_to :controller => 'home', :action => 'index' | 
| 647 | end | 656 | end | 
| 648 | 657 | ||
| 649 | - should 'check_url is available on environment' do | 658 | + should 'check_valid_name is available on environment' do | 
| 650 | env = fast_create(Environment, :name => 'Environment test') | 659 | env = fast_create(Environment, :name => 'Environment test') | 
| 651 | @controller.expects(:environment).returns(env).at_least_once | 660 | @controller.expects(:environment).returns(env).at_least_once | 
| 652 | profile = create_user('mylogin').person | 661 | profile = create_user('mylogin').person | 
| 653 | - get :check_url, :identifier => 'mylogin' | 662 | + get :check_valid_name, :identifier => 'mylogin' | 
| 654 | assert_equal 'validated', assigns(:status_class) | 663 | assert_equal 'validated', assigns(:status_class) | 
| 655 | end | 664 | end | 
| 656 | 665 | ||
| 657 | should 'check if url is not available on environment' do | 666 | should 'check if url is not available on environment' do | 
| 658 | @controller.expects(:environment).returns(Environment.default).at_least_once | 667 | @controller.expects(:environment).returns(Environment.default).at_least_once | 
| 659 | profile = create_user('mylogin').person | 668 | profile = create_user('mylogin').person | 
| 660 | - get :check_url, :identifier => 'mylogin' | 669 | + get :check_valid_name, :identifier => 'mylogin' | 
| 661 | assert_equal 'invalid', assigns(:status_class) | 670 | assert_equal 'invalid', assigns(:status_class) | 
| 662 | end | 671 | end | 
| 663 | 672 |