Commit d252e70eacdd4daebbd3aeead6e57f29c04cf0e4
Exists in
master
and in
29 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 |