goma 0.0.1.gamma → 0.0.1.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -1
  3. data/Gemfile.lock +13 -9
  4. data/Rakefile +14 -0
  5. data/goma.gemspec +6 -0
  6. data/lib/generators/goma/erb/templates/confirmation/new.html.erb +2 -2
  7. data/lib/generators/goma/erb/templates/password/edit.html.erb +6 -6
  8. data/lib/generators/goma/erb/templates/unlock/new.html.erb +1 -1
  9. data/lib/generators/goma/erb/templates/user/_form.html.erb +1 -1
  10. data/lib/generators/goma/erb/templates/user/new.html.erb +4 -0
  11. data/lib/generators/goma/mailer/erb/templates/activation_needed_email.text.erb +1 -1
  12. data/lib/generators/goma/model/active_record_generator.rb +1 -0
  13. data/lib/generators/goma/model/oauth/active_record_generator.rb +3 -3
  14. data/lib/generators/goma/resource_route/resource_route_generator.rb +13 -9
  15. data/lib/generators/goma/scaffold_controller/templates/confirmation_controller.rb +8 -4
  16. data/lib/generators/goma/scaffold_controller/templates/oauth_controller.rb +5 -0
  17. data/lib/generators/goma/scaffold_controller/templates/password_controller.rb +9 -4
  18. data/lib/generators/goma/scaffold_controller/templates/unlock_controller.rb +1 -0
  19. data/lib/generators/goma/scaffold_controller/templates/user_controller.rb +41 -1
  20. data/lib/goma/config.rb +4 -4
  21. data/lib/goma/models/authenticatable.rb +20 -9
  22. data/lib/goma/models/confirmable.rb +15 -9
  23. data/lib/goma/models/password_authenticatable.rb +2 -1
  24. data/lib/goma/models/recoverable.rb +1 -1
  25. data/lib/goma/models/validatable.rb +4 -4
  26. data/lib/goma/railtie.rb +1 -0
  27. data/lib/goma/version.rb +1 -1
  28. data/test/integration/confirmable_integration_test.rb +185 -0
  29. data/test/integration/lockable_integration_test.rb +49 -0
  30. data/test/integration/omniauthable_integration_test.rb +64 -12
  31. data/test/integration/password_authenticatable_integration_test.rb +40 -0
  32. data/test/integration/recoverable_integration_test.rb +96 -0
  33. data/test/integration/rememberable_integration_test.rb +14 -0
  34. data/test/models/confirmable_test.rb +6 -6
  35. data/test/models/omniauthable_test.rb +2 -2
  36. data/test/rails_app/app/controllers/authentications_controller.rb +5 -0
  37. data/test/rails_app/app/controllers/confirmations_controller.rb +8 -4
  38. data/test/rails_app/app/controllers/passwords_controller.rb +9 -4
  39. data/test/rails_app/app/controllers/unlocks_controller.rb +1 -0
  40. data/test/rails_app/app/controllers/users_controller.rb +25 -2
  41. data/test/rails_app/app/views/confirmations/new.html.erb +2 -2
  42. data/test/rails_app/app/views/layouts/application.html.erb +3 -1
  43. data/test/rails_app/app/views/passwords/edit.html.erb +6 -6
  44. data/test/rails_app/app/views/unlocks/new.html.erb +1 -1
  45. data/test/rails_app/app/views/user_mailer/activation_needed_email.text.erb +1 -1
  46. data/test/rails_app/app/views/users/_form.html.erb +1 -1
  47. data/test/rails_app/app/views/users/new.html.erb +1 -0
  48. data/test/rails_app/config/initializers/omniauth.rb +0 -1
  49. data/test/rails_app/config/routes.rb +6 -10
  50. data/test/rails_app/db/migrate/{20140512081308_create_users.rb → 20140515111009_create_users.rb} +0 -0
  51. data/test/rails_app/db/migrate/{20140512081309_create_authentications.rb → 20140515111010_create_authentications.rb} +0 -0
  52. data/test/rails_app/db/schema.rb +1 -1
  53. data/test/test_helper.rb +43 -0
  54. metadata +33 -13
  55. data/test/controllers/confirmations_controller_test.rb +0 -14
  56. data/test/controllers/users_controller_test.rb +0 -12
  57. data/test/integration/authenticatable_integration_test.rb +0 -26
data/lib/goma/config.rb CHANGED
@@ -134,6 +134,10 @@ module Goma
134
134
  config_accessor(:oauth_uid_attribute_name) { :uid }
135
135
 
136
136
 
137
+ def password_confirmation_attribute_name
138
+ @password_confirmation_attribute_name ||= "#{password_attribute_name}_confirmation".to_sym
139
+ end
140
+
137
141
  self.instance_methods(false).grep(/attribute_name$/).each do |conf_name|
138
142
  name = conf_name.to_s[0...-15]
139
143
 
@@ -153,10 +157,6 @@ module Goma
153
157
  RUBY
154
158
  end
155
159
 
156
- def password_confirmation_attribute_name
157
- @password_confirmation_attribute_name ||= "#{password_attribute_name}_confirmation".to_sym
158
- end
159
-
160
160
  def oauth_association_name
161
161
  @oauth_association_name ||=
162
162
  oauth_authentication_class_name ? oauth_authentication_class_name.underscore.pluralize.to_sym : ''
@@ -34,10 +34,10 @@ module Goma
34
34
  # You don't have to call this method directly.
35
35
  # This method is called from the modules defined under {Goma::Models}
36
36
  # @return [Object, Symbol] Object load from the token and nil or, if it failed, nil and a symbol which indicates reason
37
- def load_from_token_with_error(raw_token, token_attr, token_sent_at_attr, valid_period)
37
+ def load_from_token_with_error(raw_token, token_attr, token_sent_at_attr, valid_period=nil)
38
38
  token = Goma.token_generator.digest(token_attr, raw_token)
39
39
  if record = self.find_by(token_attr => token)
40
- if Time.new.utc - record.send(token_sent_at_attr) <= valid_period
40
+ if valid_period.nil? || (Time.new.utc - record.send(token_sent_at_attr) <= valid_period)
41
41
  [record, nil]
42
42
  else
43
43
  [nil, :token_expired]
@@ -77,14 +77,25 @@ module Goma
77
77
  class << self
78
78
  # class methods
79
79
 
80
- def define_load_from_token_with_error_method_for(target, purpose)
81
- target.module_eval <<-METHOD, __FILE__, __LINE__ + 1
82
- def load_from_#{purpose}_token_with_error(raw_token, valid_period)
83
- token_attr = goma_config.#{purpose}_token_attribute_name
84
- token_sent_at_attr = goma_config.#{purpose}_token_sent_at_attribute_name
85
- load_from_token_with_error(raw_token, token_attr, token_sent_at_attr, valid_period)
80
+ def define_load_from_token_with_error_method_for(target, name, valid_period_config=nil, purpose=name)
81
+ if valid_period_config
82
+ target.module_eval <<-METHOD, __FILE__, __LINE__ + 1
83
+ def load_from_#{purpose}_token_with_error(raw_token)
84
+ token_attr = goma_config.#{name}_token_attribute_name
85
+ token_sent_at_attr = goma_config.#{name}_token_sent_at_attribute_name
86
+ valid_period = goma_config.#{valid_period_config}
87
+ load_from_token_with_error(raw_token, token_attr, token_sent_at_attr, valid_period)
88
+ end
89
+ METHOD
90
+ else
91
+ target.module_eval <<-METHOD, __FILE__, __LINE__ + 1
92
+ def load_from_#{purpose}_token_with_error(raw_token)
93
+ token_attr = goma_config.#{name}_token_attribute_name
94
+ token_sent_at_attr = goma_config.#{name}_token_sent_at_attribute_name
95
+ load_from_token_with_error(raw_token, token_attr, token_sent_at_attr)
96
+ end
97
+ METHOD
86
98
  end
87
- METHOD
88
99
  end
89
100
 
90
101
  def define_load_from_token_methods_for(target, purpose)
@@ -14,17 +14,11 @@ module Goma
14
14
 
15
15
  # @!parse extend ClassMethods
16
16
  module ClassMethods
17
- DefinitionHelper.define_load_from_token_with_error_method_for(self, :confirmation)
18
-
19
- def load_from_activation_token_with_error(raw_token)
20
- load_from_confirmation_token_with_error(raw_token, goma_config.activate_within)
21
- end
17
+ DefinitionHelper.define_load_from_token_with_error_method_for(self, :confirmation, :activate_within, :activation)
18
+ DefinitionHelper.define_load_from_token_methods_for(self, :activation)
22
19
 
23
- def load_from_email_confirmation_token_with_error(raw_token)
24
- load_from_confirmation_token_with_error(raw_token, goma_config.confirm_email_within)
25
- end
20
+ DefinitionHelper.define_load_from_token_with_error_method_for(self, :confirmation, :confirm_email_within, :email_confirmation)
26
21
 
27
- DefinitionHelper.define_load_from_token_methods_for(self, :activation)
28
22
  DefinitionHelper.define_load_from_token_methods_for(self, :email_confirmation)
29
23
  end
30
24
 
@@ -97,6 +91,18 @@ module Goma
97
91
  goma_config.email_confirmation_success_email_method_name && !@skip_email_confirmation_success_email
98
92
  end
99
93
 
94
+ def resend_activation_needed_email(to: nil)
95
+ if to
96
+ @skip_email_confirmation = true
97
+ self.send(goma_config.email_setter, to)
98
+ return false unless self.save
99
+ @skip_email_confirmation = false
100
+ end
101
+ setup_activation
102
+ save(validate: false)
103
+ send_activation_needed_email
104
+ end
105
+
100
106
  DefinitionHelper.define_token_generator_method_for(self, :confirmation)
101
107
 
102
108
  protected
@@ -5,10 +5,11 @@ module Goma
5
5
 
6
6
  included do
7
7
  password_attr = goma_config.password_attribute_name
8
- attr_reader password_attr, "current_#{password_attr}"
8
+ attr_reader password_attr
9
9
 
10
10
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
11
11
  def #{password_attr}=(new_#{password_attr})
12
+ return if new_#{password_attr}.blank?
12
13
  @#{password_attr} = new_#{password_attr}
13
14
  self.#{Goma.config.encrypted_password_attribute_name} = encrypt_password(new_#{password_attr})
14
15
  end
@@ -8,7 +8,7 @@ module Goma
8
8
  end
9
9
 
10
10
  module ClassMethods
11
- DefinitionHelper.define_load_from_token_with_error_method_for(self, :reset_password)
11
+ DefinitionHelper.define_load_from_token_with_error_method_for(self, :reset_password, :reset_password_within)
12
12
  DefinitionHelper.define_load_from_token_methods_for(self, :reset_password)
13
13
  end
14
14
 
@@ -41,16 +41,16 @@ module Goma
41
41
  def password_required?
42
42
  !@creating_with_omniauth && #{goma_config.oauth_association_name}.empty? && (
43
43
  !persisted? ||
44
- !#{goma_config.password_attribute_name}.nil? ||
45
- !#{goma_config.password_confirmation_attribute_name}.nil?)
44
+ #{goma_config.password_attribute_name}.present? ||
45
+ #{goma_config.password_confirmation_attribute_name}.present?)
46
46
  end
47
47
  RUBY
48
48
  else
49
49
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
50
50
  def password_required?
51
51
  !persisted? ||
52
- !#{goma_config.password_attribute_name}.nil? ||
53
- !#{goma_config.password_confirmation_attribute_name}.nil?
52
+ #{goma_config.password_attribute_name}.present? ||
53
+ #{goma_config.password_confirmation_attribute_name}.present?
54
54
  end
55
55
  RUBY
56
56
  end
data/lib/goma/railtie.rb CHANGED
@@ -6,6 +6,7 @@ module Goma
6
6
  class Railtie < ::Rails::Railtie
7
7
  config.app_middleware.use Warden::Manager do |config|
8
8
  if Goma.config && Goma.config.modules.include?(:rememberable)
9
+ require 'goma/strategies/rememberable'
9
10
  config.default_strategies :rememberable
10
11
  end
11
12
  end
data/lib/goma/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Goma
2
- VERSION = "0.0.1.gamma"
2
+ VERSION = "0.0.1.rc1"
3
3
  end
@@ -0,0 +1,185 @@
1
+ require 'test_helper'
2
+
3
+ class ConfirmableIntegrationTest < ActionDispatch::IntegrationTest
4
+ test 'should work activation proccess' do
5
+ Goma.token_generator.stubs(:friendly_token).returns('sesame')
6
+
7
+ visit new_user_url
8
+ fill_in :user_username, with: 'user'
9
+ fill_in :user_email, with: 'user@example.com'
10
+ fill_in :user_password, with: 'password'
11
+ fill_in :user_password_confirmation, with: 'password'
12
+
13
+ assert_difference ['User.count', 'ActionMailer::Base.deliveries.size'], 1 do
14
+ click_button 'Sign up'
15
+ end
16
+ user = User.order(created_at: :desc).first
17
+ refute user.activated?
18
+
19
+ email = ActionMailer::Base.deliveries.last
20
+ assert_match %r{/confirmations/sesame}, email.body.encoded
21
+
22
+ visit confirmation_url('sesame')
23
+ assert_equal 'Your account was successfully activated.', _flash[:notice]
24
+ assert_equal new_session_url, current_url
25
+ user.reload
26
+ assert user.activated?
27
+ end
28
+
29
+ test 'should be able to change email and resend activation token before activation with username and password which is entered in registration' do
30
+ Goma.token_generator.expects(:friendly_token).twice.returns('sesame', 'simsim')
31
+
32
+ visit new_user_url
33
+ fill_in :user_username, with: 'user'
34
+ fill_in :user_email, with: 'wrong@example.com'
35
+ fill_in :user_password, with: 'password'
36
+ fill_in :user_password_confirmation, with: 'password'
37
+ click_button 'Sign up'
38
+
39
+ user = User.order(created_at: :desc).first
40
+ refute user.activated?
41
+
42
+
43
+ visit new_user_url
44
+ assert_match /If you signed up with wrong email address/, page.body
45
+ fill_in :user_username, with: 'user'
46
+ fill_in :user_email, with: 'correct@example.com'
47
+ fill_in :user_password, with: 'password'
48
+ fill_in :user_password_confirmation, with: 'password'
49
+
50
+ assert_no_difference 'User.count' do
51
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
52
+ click_button 'Sign up'
53
+ end
54
+ end
55
+
56
+ email = ActionMailer::Base.deliveries.last
57
+ assert_match %r{/confirmations/simsim}, email.body.encoded
58
+ assert_equal 'correct@example.com', email.to.first
59
+
60
+ visit confirmation_url('simsim')
61
+ assert_equal 'Your account was successfully activated.', _flash[:notice]
62
+ assert_equal new_session_url, current_url
63
+ user.reload
64
+ assert user.activated?
65
+ end
66
+
67
+ test 'should not activate user with wrong token' do
68
+ Goma.token_generator.stubs(:friendly_token).returns('sesame')
69
+
70
+ visit new_user_url
71
+ fill_in :user_username, with: 'user'
72
+ fill_in :user_email, with: 'user@example.com'
73
+ fill_in :user_password, with: 'password'
74
+ fill_in :user_password_confirmation, with: 'password'
75
+ click_button 'Sign up'
76
+
77
+ user = User.order(created_at: :desc).first
78
+ refute user.activated?
79
+
80
+ visit confirmation_url('beans')
81
+ assert_equal confirmation_url('beans'), current_url
82
+ assert_match /Not found any account by this URL/, _flash[:alert]
83
+ user.reload
84
+ refute user.activated?
85
+ end
86
+
87
+ test 'should resend activation token by username' do
88
+ Goma.token_generator.expects(:friendly_token).twice.returns('sesame', 'simsim')
89
+
90
+ visit new_user_url
91
+ fill_in :user_username, with: 'user'
92
+ fill_in :user_email, with: 'user@example.com'
93
+ fill_in :user_password, with: 'password'
94
+ fill_in :user_password_confirmation, with: 'password'
95
+ click_button 'Sign up'
96
+
97
+ user = User.order(created_at: :desc).first
98
+ refute user.activated?
99
+
100
+ visit new_confirmation_url
101
+ fill_in :username_or_email, with: 'user'
102
+
103
+ assert_no_difference 'User.count' do
104
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
105
+ click_button 'Resend activation instructions'
106
+ end
107
+ end
108
+ email = ActionMailer::Base.deliveries.last
109
+ assert_match %r{/confirmations/simsim}, email.body.encoded
110
+
111
+ visit confirmation_url('simsim')
112
+ assert_equal 'Your account was successfully activated.', _flash[:notice]
113
+ assert_equal new_session_url, current_url
114
+ user.reload
115
+ assert user.activated?
116
+ end
117
+
118
+ test 'should resend activation token by email' do
119
+ Goma.token_generator.expects(:friendly_token).twice.returns('sesame', 'simsim')
120
+
121
+ visit new_user_url
122
+ fill_in :user_username, with: 'user'
123
+ fill_in :user_email, with: 'user@example.com'
124
+ fill_in :user_password, with: 'password'
125
+ fill_in :user_password_confirmation, with: 'password'
126
+ click_button 'Sign up'
127
+
128
+ user = User.order(created_at: :desc).first
129
+ refute user.activated?
130
+
131
+ visit new_confirmation_url
132
+ fill_in :username_or_email, with: 'user@example.com'
133
+
134
+ assert_no_difference 'User.count' do
135
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
136
+ click_button 'Resend activation instructions'
137
+ end
138
+ end
139
+ email = ActionMailer::Base.deliveries.last
140
+ assert_match %r{/confirmations/simsim}, email.body.encoded
141
+
142
+ visit confirmation_url('simsim')
143
+ assert_equal 'Your account was successfully activated.', _flash[:notice]
144
+ assert_equal new_session_url, current_url
145
+ user.reload
146
+ assert user.activated?
147
+ end
148
+
149
+ test 'should work email confirmation process' do
150
+ user = Fabricate(:user, email: 'old@example.com')
151
+
152
+ Goma.token_generator.stubs(:friendly_token).returns('sesame')
153
+
154
+ visit new_session_url
155
+ fill_in :username_or_email, with: 'old@example.com'
156
+ fill_in :password, with: 'password'
157
+ click_button 'Login'
158
+
159
+ visit edit_user_url(user)
160
+ fill_in :user_email, with: 'new@example.com'
161
+
162
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
163
+ click_button 'Update'
164
+ end
165
+ assert_match /but we need to verify your new email address/, _flash[:notice]
166
+
167
+ email = ActionMailer::Base.deliveries.last
168
+ assert_match %r{/confirmations/sesame/email}, email.body.encoded
169
+
170
+ user.reload
171
+ assert_equal 'old@example.com', user.email
172
+ assert_equal 'new@example.com', user.unconfirmed_email
173
+
174
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
175
+ visit email_confirmation_url('sesame')
176
+ end
177
+ email = ActionMailer::Base.deliveries.last
178
+ assert_match /You have successfully changed your account email/, email.body.encoded
179
+
180
+ user.reload
181
+ assert_equal root_url, current_url
182
+ assert_equal 'new@example.com', user.email
183
+ assert_nil user.unconfirmed_email
184
+ end
185
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ class LockableIntegrationTest < ActionDispatch::IntegrationTest
4
+ def setup
5
+ @user = Fabricate(:user)
6
+ end
7
+
8
+
9
+ test 'should work unlock process' do
10
+ Goma.token_generator.stubs(:friendly_token).returns('sesame')
11
+ @user.lock_access!
12
+ assert @user.access_locked?
13
+
14
+ email = ActionMailer::Base.deliveries.last
15
+ assert_match %r{/unlocks/sesame}, email.body.encoded
16
+
17
+ visit unlock_url('sesame')
18
+
19
+ @user.reload
20
+ assert_equal new_session_url, current_url
21
+ refute @user.access_locked?
22
+ end
23
+
24
+ test 'should work resending unlock token process' do
25
+ @user.lock_access!
26
+ assert @user.access_locked?
27
+ old_token = @user.unlock_token
28
+
29
+ Goma.token_generator.stubs(:friendly_token).returns('sesame')
30
+
31
+ visit new_unlock_url
32
+ fill_in :username_or_email, with: @user.email
33
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
34
+ click_button 'Resend unlock instructions'
35
+ end
36
+ email = ActionMailer::Base.deliveries.last
37
+ assert_match %r{/unlocks/sesame}, email.body.encoded
38
+
39
+ @user.reload
40
+ refute_equal old_token, @user.unlock_token
41
+ assert_equal new_session_url, current_url
42
+
43
+ visit unlock_url('sesame')
44
+
45
+ @user.reload
46
+ assert_equal new_session_url, current_url
47
+ refute @user.access_locked?
48
+ end
49
+ end
@@ -2,25 +2,77 @@ require 'test_helper'
2
2
 
3
3
  class OmniauthableIntegrationTest < ActionDispatch::IntegrationTest
4
4
  def setup
5
- OmniAuth.config.mock_auth[:twitter] = OmniAuth::AuthHash.new({
6
- provider: 'twitter',
5
+ OmniAuth.config.mock_auth[:developer] = OmniAuth::AuthHash.new({
6
+ provider: 'developer',
7
7
  uid: '1234567'
8
8
  })
9
9
  end
10
10
 
11
11
  test 'should create user with omniauth' do
12
- get '/auth/twitter'
13
- assert_redirected_to '/auth/twitter/callback'
12
+ visit new_session_url
14
13
 
15
- assert_no_difference 'ActionMailer::Base.deliveries.count' do
16
- assert_difference ['User.count', 'Authentication.count'], 1 do
17
- follow_redirect!
18
- end
14
+ assert_difference ['User.count', 'Authentication.count'], 1 do
15
+ click_link 'Sign in with Developer'
16
+ end
17
+
18
+ assert_equal root_url, current_url, 'should be redirected to root_url'
19
+ assert_equal 'Successfully authenticated from developer account.', _flash[:notice]
20
+
21
+ assert _current_user
22
+ assert_equal 'developer', _current_user.authentications.first.provider
23
+ assert_equal '1234567', _current_user.authentications.first.uid
24
+ end
25
+
26
+ test 'should redirect back after creating user with omniauth ' do
27
+ visit secret_url
28
+ assert_equal root_url, current_url, 'should be redirect to root_url'
29
+
30
+ visit new_session_url
31
+ click_link 'Sign in with Developer'
32
+
33
+ assert_equal secret_url, current_url, 'should redirect back'
34
+ assert_equal 'Successfully authenticated from developer account.', _flash[:notice]
35
+ end
36
+
37
+ test 'should authenticate but not create user if already created' do
38
+ visit new_session_url
39
+ click_link 'Sign in with Developer'
40
+ _warden.logout(:user)
41
+
42
+
43
+ visit new_session_url
44
+
45
+ assert_no_difference ['User.count', 'Authentication.count'] do
46
+ click_link 'Sign in with Developer'
19
47
  end
20
- assert_redirected_to root_url
21
48
 
22
- assert current_user
23
- assert_equal 'twitter', current_user.authentications.first.provider
24
- assert_equal '1234567', current_user.authentications.first.uid
49
+ assert_equal root_url, current_url, 'should be redirected to root_url'
50
+ assert_equal 'Successfully authenticated from developer account.', _flash[:notice]
51
+
52
+ assert _current_user
53
+ assert_equal 'developer', _current_user.authentications.first.provider
54
+ assert_equal '1234567', _current_user.authentications.first.uid
55
+ end
56
+
57
+
58
+ test 'should handle errors' do
59
+ OmniAuth.config.mock_auth[:developer] = :access_denied
60
+
61
+ visit new_session_url
62
+
63
+ assert_no_difference ['User.count', 'Authentication.count'] do
64
+ click_link 'Sign in with Developer'
65
+ end
66
+
67
+ assert_match /Could not authenticate you from Developer because "Access denied"/, _flash[:alert]
68
+ assert_equal new_session_url, current_url
69
+ end
70
+
71
+ test 'should not accept unknown provider' do
72
+ assert_no_difference ['User.count', 'Authentication.count'] do
73
+ assert_raise ActionController::RoutingError do
74
+ visit 'auth/unknown'
75
+ end
76
+ end
25
77
  end
26
78
  end