devise_g5_authenticatable 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +25 -0
  6. data/Gemfile +23 -0
  7. data/LICENSE +20 -0
  8. data/README.md +243 -0
  9. data/Rakefile +20 -0
  10. data/app/controllers/devise_g5_authenticatable/registrations_controller.rb +5 -0
  11. data/app/controllers/devise_g5_authenticatable/sessions_controller.rb +58 -0
  12. data/circle.yml +4 -0
  13. data/config/initializers/devise_g5_authenticatable.rb +3 -0
  14. data/config/locales/en.yml +6 -0
  15. data/devise_g5_authenticatable.gemspec +24 -0
  16. data/lib/devise_g5_authenticatable.rb +16 -0
  17. data/lib/devise_g5_authenticatable/controllers/helpers.rb +37 -0
  18. data/lib/devise_g5_authenticatable/controllers/url_helpers.rb +13 -0
  19. data/lib/devise_g5_authenticatable/engine.rb +11 -0
  20. data/lib/devise_g5_authenticatable/g5.rb +4 -0
  21. data/lib/devise_g5_authenticatable/g5/auth_password_validator.rb +30 -0
  22. data/lib/devise_g5_authenticatable/g5/auth_user_creator.rb +48 -0
  23. data/lib/devise_g5_authenticatable/g5/auth_user_updater.rb +43 -0
  24. data/lib/devise_g5_authenticatable/g5/user_exporter.rb +61 -0
  25. data/lib/devise_g5_authenticatable/models/g5_authenticatable.rb +99 -0
  26. data/lib/devise_g5_authenticatable/models/protected_attributes.rb +16 -0
  27. data/lib/devise_g5_authenticatable/omniauth.rb +9 -0
  28. data/lib/devise_g5_authenticatable/routes.rb +58 -0
  29. data/lib/devise_g5_authenticatable/version.rb +3 -0
  30. data/lib/tasks/g5/export_users.rake +13 -0
  31. data/spec/controllers/helpers_spec.rb +295 -0
  32. data/spec/controllers/sessions_controller_spec.rb +256 -0
  33. data/spec/controllers/url_helpers_spec.rb +332 -0
  34. data/spec/dummy/.gitignore +15 -0
  35. data/spec/dummy/README.rdoc +261 -0
  36. data/spec/dummy/Rakefile +7 -0
  37. data/spec/dummy/app/assets/images/rails.png +0 -0
  38. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  39. data/spec/dummy/app/assets/javascripts/custom_sessions.js +2 -0
  40. data/spec/dummy/app/assets/javascripts/home.js +2 -0
  41. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  42. data/spec/dummy/app/assets/stylesheets/custom_sessions.css +4 -0
  43. data/spec/dummy/app/assets/stylesheets/home.css +4 -0
  44. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  45. data/spec/dummy/app/controllers/custom_registrations_controllers.rb +2 -0
  46. data/spec/dummy/app/controllers/custom_sessions_controller.rb +2 -0
  47. data/spec/dummy/app/controllers/home_controller.rb +4 -0
  48. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  49. data/spec/dummy/app/helpers/custom_sessions_helper.rb +2 -0
  50. data/spec/dummy/app/helpers/home_helper.rb +2 -0
  51. data/spec/dummy/app/mailers/.gitkeep +0 -0
  52. data/spec/dummy/app/models/admin.rb +3 -0
  53. data/spec/dummy/app/models/user.rb +10 -0
  54. data/spec/dummy/app/views/anonymous/new.html.erb +0 -0
  55. data/spec/dummy/app/views/home/index.html.erb +1 -0
  56. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  57. data/spec/dummy/config.ru +4 -0
  58. data/spec/dummy/config/application.rb +64 -0
  59. data/spec/dummy/config/boot.rb +10 -0
  60. data/spec/dummy/config/database.yml.ci +6 -0
  61. data/spec/dummy/config/database.yml.sample +13 -0
  62. data/spec/dummy/config/environment.rb +5 -0
  63. data/spec/dummy/config/environments/development.rb +39 -0
  64. data/spec/dummy/config/environments/production.rb +67 -0
  65. data/spec/dummy/config/environments/test.rb +37 -0
  66. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  67. data/spec/dummy/config/initializers/devise.rb +259 -0
  68. data/spec/dummy/config/initializers/inflections.rb +15 -0
  69. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  70. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  71. data/spec/dummy/config/initializers/session_store.rb +8 -0
  72. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  73. data/spec/dummy/config/locales/devise.en.yml +60 -0
  74. data/spec/dummy/config/locales/en.yml +5 -0
  75. data/spec/dummy/config/routes.rb +70 -0
  76. data/spec/dummy/db/migrate/20131230235849_devise_create_users.rb +42 -0
  77. data/spec/dummy/db/migrate/20140102213131_drop_database_authenticatable.rb +16 -0
  78. data/spec/dummy/db/migrate/20140103032308_drop_recoverable.rb +16 -0
  79. data/spec/dummy/db/migrate/20140103042329_drop_rememberable.rb +13 -0
  80. data/spec/dummy/db/migrate/20140103174810_add_omniauth_columns_to_users.rb +18 -0
  81. data/spec/dummy/db/migrate/20140103191601_add_email_back_to_user.rb +8 -0
  82. data/spec/dummy/db/migrate/20140113202948_devise_create_admins.rb +42 -0
  83. data/spec/dummy/db/migrate/20140113233821_add_provider_and_uid_to_admins.rb +8 -0
  84. data/spec/dummy/db/schema.rb +50 -0
  85. data/spec/dummy/db/seeds.rb +7 -0
  86. data/spec/dummy/lib/assets/.gitkeep +0 -0
  87. data/spec/dummy/lib/tasks/.gitkeep +0 -0
  88. data/spec/dummy/log/.gitkeep +0 -0
  89. data/spec/dummy/public/404.html +26 -0
  90. data/spec/dummy/public/422.html +26 -0
  91. data/spec/dummy/public/500.html +25 -0
  92. data/spec/dummy/public/favicon.ico +0 -0
  93. data/spec/dummy/public/robots.txt +5 -0
  94. data/spec/dummy/script/rails +6 -0
  95. data/spec/dummy/vendor/assets/javascripts/.gitkeep +0 -0
  96. data/spec/dummy/vendor/assets/stylesheets/.gitkeep +0 -0
  97. data/spec/dummy/vendor/plugins/.gitkeep +0 -0
  98. data/spec/factories/admin.rb +10 -0
  99. data/spec/factories/user.rb +10 -0
  100. data/spec/features/edit_registration_spec.rb +109 -0
  101. data/spec/features/registration_spec.rb +99 -0
  102. data/spec/features/sign_in_spec.rb +91 -0
  103. data/spec/features/sign_out_spec.rb +7 -0
  104. data/spec/g5/auth_password_validator_spec.rb +81 -0
  105. data/spec/g5/auth_user_creator_spec.rb +100 -0
  106. data/spec/g5/auth_user_updater_spec.rb +113 -0
  107. data/spec/g5/user_exporter_spec.rb +105 -0
  108. data/spec/models/g5_authenticatable_spec.rb +540 -0
  109. data/spec/models/protected_attributes_spec.rb +17 -0
  110. data/spec/routing/registrations_routing_spec.rb +107 -0
  111. data/spec/routing/sessions_routing_spec.rb +111 -0
  112. data/spec/spec_helper.rb +44 -0
  113. data/spec/support/devise.rb +3 -0
  114. data/spec/support/omniauth.rb +3 -0
  115. data/spec/support/shared_contexts/oauth_error.rb +9 -0
  116. data/spec/support/shared_contexts/rake.rb +21 -0
  117. data/spec/support/shared_examples/registration_error.rb +15 -0
  118. data/spec/support/user_feature_methods.rb +26 -0
  119. data/spec/tasks/export_users_spec.rb +90 -0
  120. metadata +293 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ </div>
24
+ </body>
25
+ </html>
File without changes
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
File without changes
File without changes
File without changes
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ factory :admin do
3
+ sequence(:email) { |n| "admin.#{n}@test.host" }
4
+ password 'my_new_secret'
5
+ password_confirmation 'my_new_secret'
6
+ provider 'g5'
7
+ sequence(:uid) { |n| "remote-admin-#{n}" }
8
+ sequence(:g5_access_token) { |n| "token-abc123-#{n}" }
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ FactoryGirl.define do
2
+ factory :user do
3
+ sequence(:email) { |n| "user.#{n}@test.host" }
4
+ password 'my_new_secret'
5
+ password_confirmation 'my_new_secret'
6
+ provider 'g5'
7
+ sequence(:uid) { |n| "remote-user-#{n}" }
8
+ sequence(:g5_access_token) { |n| "token-abc123-#{n}" }
9
+ end
10
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Editing a user registration' do
4
+ subject(:update_registration) { click_button 'Update' }
5
+
6
+ let(:user) { create(:user) }
7
+
8
+ let(:auth_client) { double(:auth_client, update_user: auth_user, me: auth_user) }
9
+
10
+ let(:auth_user) { double(:auth_user, id: user.uid, email: user.email) }
11
+ before do
12
+ allow(G5AuthenticationClient::Client).to receive(:new).and_return(auth_client)
13
+ end
14
+
15
+ before do
16
+ visit_path_and_login_with(edit_user_registration_path, user)
17
+ fill_in 'Email', with: email
18
+ fill_in 'Password', with: password
19
+ fill_in 'Password confirmation', with: password_confirmation
20
+ fill_in 'Current password', with: current_password
21
+ end
22
+
23
+ let(:email) { 'new.email@test.host' }
24
+ let(:password) { '' }
25
+ let(:password_confirmation) { password }
26
+ let(:current_password) { user.password }
27
+
28
+ context 'when current password is valid' do
29
+ context 'when password is blank' do
30
+ it 'should update the email locally' do
31
+ update_registration
32
+ user.reload
33
+ expect(user.email).to eq(email)
34
+ end
35
+
36
+ it 'should update the email on the auth server' do
37
+ expect(auth_client).to receive(:update_user).with({id: user.uid,
38
+ email: email,
39
+ password: nil,
40
+ password_confirmation: nil})
41
+ update_registration
42
+ end
43
+ end
44
+
45
+ context 'when password is updated' do
46
+ let(:password) { 'a brand new password' }
47
+
48
+ it 'should update the password on the auth server' do
49
+ expect(auth_client).to receive(:update_user).with({id: user.uid,
50
+ email: email,
51
+ password: password,
52
+ password_confirmation: password_confirmation})
53
+ update_registration
54
+ end
55
+ end
56
+
57
+ context 'when email is blank' do
58
+ let(:email) { '' }
59
+
60
+ it 'should display an error message' do
61
+ update_registration
62
+ expect(page).to have_content("Email can't be blank")
63
+ end
64
+
65
+ it 'should not update the credentials on the auth server' do
66
+ expect(auth_client).to_not receive(:update_user)
67
+ update_registration
68
+ end
69
+ end
70
+
71
+ context 'when the auth server returns an error' do
72
+ include_context 'OAuth2::Error'
73
+ before { allow(auth_client).to receive(:update_user).and_raise(oauth_error) }
74
+
75
+ it 'should display an error message' do
76
+ update_registration
77
+ expect(page).to have_content(error_message)
78
+ end
79
+
80
+ it 'should not update the email locally' do
81
+ update_registration
82
+ user.reload
83
+ expect(user.email).to_not eq(email)
84
+ end
85
+ end
86
+ end
87
+
88
+ context 'when current password is invalid' do
89
+ include_context 'OAuth2::Error'
90
+ let(:error_message) { 'invalid_resource_owner' }
91
+ before { allow(auth_client).to receive(:me).and_raise(oauth_error) }
92
+
93
+ it 'should display an error message' do
94
+ update_registration
95
+ expect(page).to have_content('Current password is invalid')
96
+ end
97
+
98
+ it 'should not update the credentials on the auth server' do
99
+ expect(auth_client).to_not receive(:update_user)
100
+ update_registration
101
+ end
102
+
103
+ it 'should not update the email locally' do
104
+ update_registration
105
+ user.reload
106
+ expect(user.email).to_not eq(email)
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'User registration' do
4
+ subject(:register_user) { click_button 'Sign up' }
5
+
6
+ let(:auth_client) { double(:auth_client, create_user: auth_user) }
7
+ let(:auth_user) { double(:auth_user, id: uid, email: email) }
8
+ before do
9
+ allow(G5AuthenticationClient::Client).to receive(:new).and_return(auth_client)
10
+ end
11
+
12
+ before do
13
+ visit new_user_registration_path
14
+ fill_in 'Email', with: email
15
+ fill_in 'Password', with: password
16
+ fill_in 'Password confirmation', with: password_confirmation
17
+ end
18
+
19
+ let(:email) { 'fred.rogers@theneighborhood.net' }
20
+ let(:password) { 'wontyoubemyneighbor' }
21
+ let(:password_confirmation) { password }
22
+ let(:uid) { '42-remote-uid' }
23
+
24
+ context 'when registration is valid' do
25
+ it 'should create a user' do
26
+ expect { register_user }.to change { User.count }.by(1)
27
+ end
28
+
29
+ it 'should redirect to the root path' do
30
+ register_user
31
+ expect(current_path).to eq(root_path)
32
+ end
33
+
34
+ it 'should create the user on the auth server' do
35
+ expect(auth_client).to receive(:create_user).
36
+ with({email: email,
37
+ password: password,
38
+ password_confirmation: password_confirmation}).
39
+ and_return(auth_user)
40
+ register_user
41
+ end
42
+
43
+ it 'needs a token from somewhere - figure it out'
44
+
45
+ it 'should assign the provider and uid to the user' do
46
+ register_user
47
+ user = User.find_by_email(email)
48
+ expect(user.provider).to eq('g5')
49
+ expect(user.uid).to eq(uid)
50
+ end
51
+ end
52
+
53
+ context 'when there is an error on the auth server' do
54
+ include_context 'OAuth2::Error'
55
+ before { allow(auth_client).to receive(:create_user).and_raise(oauth_error) }
56
+
57
+ it 'should display an error message' do
58
+ register_user
59
+ expect(page).to have_content(error_message)
60
+ end
61
+
62
+ it 'should not create the user locally' do
63
+ expect { register_user }.to_not change { User.count }
64
+ end
65
+ end
66
+
67
+ context 'when password is blank' do
68
+ let(:password) { ' ' }
69
+
70
+ it_should_behave_like 'a registration validation error' do
71
+ let(:error_message) { "Password can't be blank" }
72
+ end
73
+ end
74
+
75
+ context 'when password does not match confirmation' do
76
+ let(:password_confirmation) { 'something else entirely' }
77
+
78
+ it_should_behave_like 'a registration validation error' do
79
+ let(:error_message) { "Password doesn't match confirmation" }
80
+ end
81
+ end
82
+
83
+ context 'when email is blank' do
84
+ let(:email) { '' }
85
+
86
+ it_should_behave_like 'a registration validation error' do
87
+ let(:error_message) { "Email can't be blank" }
88
+ end
89
+ end
90
+
91
+ context 'when email is not unique' do
92
+ let(:user) { create(:user) }
93
+ let(:email) { user.email }
94
+
95
+ it_should_behave_like 'a registration validation error' do
96
+ let(:error_message) { 'Email has already been taken' }
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Signing in' do
4
+ context 'when visiting a protected page' do
5
+ let(:protected_path) { edit_user_registration_path }
6
+
7
+ context 'with valid credentials' do
8
+ before do
9
+ stub_g5_omniauth(user)
10
+ visit protected_path
11
+ end
12
+
13
+ context 'when user exists locally' do
14
+ let(:user) { create(:user) }
15
+
16
+ it 'should sign in the user successfully' do
17
+ expect(page).to have_content('Signed in successfully.')
18
+ end
19
+
20
+ it 'should redirect the user to the requested path' do
21
+ expect(current_path).to eq(protected_path)
22
+ end
23
+ end
24
+
25
+ context 'when user does not exist locally' do
26
+ let(:user) { build(:user, uid: 42) }
27
+
28
+ it 'should display an informative message' do
29
+ expect(page).to have_content('You must sign up before continuing.')
30
+ end
31
+
32
+ it 'should redirect the user to the registration page' do
33
+ expect(current_path).to eq(new_user_registration_path)
34
+ end
35
+
36
+ it 'should prefill the Email field' do
37
+ expect(find_field('Email').value).to eq(user.email)
38
+ end
39
+ end
40
+ end
41
+
42
+ context 'with invalid credentials' do
43
+ before do
44
+ stub_g5_invalid_credentials
45
+ visit protected_path
46
+ end
47
+
48
+ let(:user) { create(:user) }
49
+
50
+ it 'should display an error' do
51
+ expect(page).to have_content('Invalid credentials')
52
+ end
53
+ end
54
+ end
55
+
56
+ context 'when clicking a login link' do
57
+ before do
58
+ visit root_path
59
+ stub_g5_omniauth(user)
60
+ click_link 'Login'
61
+ end
62
+
63
+ let(:user) { create(:user) }
64
+
65
+ it 'should sign in the user successfully' do
66
+ expect(page).to have_content('Signed in successfully.')
67
+ end
68
+
69
+ it 'should redirect the user to the root path' do
70
+ expect(current_path).to eq(root_path)
71
+ end
72
+ end
73
+
74
+ context 'when clicking a login link after signing in' do
75
+ before do
76
+ visit_path_and_login_with(edit_user_registration_path, user)
77
+ visit root_path
78
+ click_link 'Login'
79
+ end
80
+
81
+ let(:user) { create(:user) }
82
+
83
+ it 'should warn the user that they are currently signed in' do
84
+ expect(page).to have_content('You are already signed in.')
85
+ end
86
+
87
+ it 'should redirect the user to the root path' do
88
+ expect(current_path).to eq(root_path)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Signing out' do
4
+ it 'should redirect to the auth server'
5
+ it 'should pass the root url as a param to the redirect'
6
+ it 'should not allow the user to access protected pages'
7
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe Devise::G5::AuthPasswordValidator do
4
+ let(:validator) { described_class.new(model) }
5
+
6
+ let(:model) { build_stubbed(:user) }
7
+
8
+ describe '#valid_password?' do
9
+ subject(:valid_password?) { validator.valid_password?(password) }
10
+
11
+ let(:password) { 'password to check' }
12
+
13
+ let(:auth_client) { double(:g5_authentication_client, me: auth_user) }
14
+ let(:auth_user) { double(:auth_user, uid: model.uid, email: model.email) }
15
+
16
+ let(:oauth_error) { OAuth2::Error.new(response) }
17
+ let(:response) { double(:oauth_response, parsed: oauth_error_hash).as_null_object }
18
+
19
+ before do
20
+ allow(G5AuthenticationClient::Client).to receive(:new).
21
+ and_return(auth_client)
22
+ end
23
+
24
+ context 'with valid password' do
25
+ before { valid_password? }
26
+
27
+ it 'should initialize auth client with the username' do
28
+ expect(G5AuthenticationClient::Client).to have_received(:new).
29
+ with(hash_including(username: model.email))
30
+ end
31
+
32
+ it 'should initialize auth client with the password' do
33
+ expect(G5AuthenticationClient::Client).to have_received(:new).
34
+ with(hash_including(password: password))
35
+ end
36
+
37
+ it 'should retrieve the auth user associated with these credentials' do
38
+ expect(auth_client).to have_received(:me)
39
+ end
40
+
41
+ it 'should return true' do
42
+ expect(valid_password?).to be_true
43
+ end
44
+ end
45
+
46
+ context 'with invalid password' do
47
+ before { allow(auth_client).to receive(:me).and_raise(oauth_error) }
48
+
49
+ let(:oauth_error_hash) do
50
+ {'error' => 'invalid_resource_owner',
51
+ 'error_description' => 'The provided resource owner credentials are not valid, or resource owner cannot be found.'}
52
+ end
53
+
54
+ it 'should return false' do
55
+ expect(valid_password?).to be_false
56
+ end
57
+ end
58
+
59
+ context 'with blank password' do
60
+ before { allow(auth_client).to receive(:me).and_raise(runtime_error) }
61
+ let(:runtime_error) { RuntimeError.new('Insufficient credentials for access token. Supply a username/password or authentication code.') }
62
+
63
+ it 'should return false' do
64
+ expect(valid_password?).to be_false
65
+ end
66
+ end
67
+
68
+ context 'when an unrelated server error occurs' do
69
+ before { allow(auth_client).to receive(:me).and_raise(oauth_error) }
70
+
71
+ let(:oauth_error_hash) do
72
+ {'error' => 'unauthorized_client',
73
+ 'error_description' => 'The client is not authorized to perform this request using this method.'}
74
+ end
75
+
76
+ it 'should re-raise the error' do
77
+ expect { valid_password? }.to raise_error(oauth_error)
78
+ end
79
+ end
80
+ end
81
+ end