goma 0.0.1.rc2 → 0.0.1.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/Rakefile +11 -6
  4. data/lib/generators/goma/helpers/helpers.rb +39 -0
  5. data/lib/generators/goma/install/templates/goma.rb +1 -2
  6. data/lib/generators/goma/mailer/templates/mailer.rb +1 -1
  7. data/lib/generators/goma/model/active_record_generator.rb +3 -1
  8. data/lib/generators/goma/scaffold/user_generator.rb +2 -0
  9. data/lib/generators/goma/scaffold_controller/scaffold_controller_generator.rb +2 -0
  10. data/lib/generators/goma/scaffold_controller/templates/confirmation_controller.rb +4 -4
  11. data/lib/generators/goma/scaffold_controller/templates/user_controller.rb +3 -3
  12. data/lib/generators/test_unit/goma/model/model_generator.rb +13 -0
  13. data/lib/generators/test_unit/goma/model/templates/fixtures.yml +30 -0
  14. data/lib/generators/test_unit/goma/model/templates/unit_test.rb +9 -0
  15. data/lib/generators/test_unit/goma/scaffold/scaffold_generator.rb +36 -0
  16. data/lib/generators/test_unit/goma/scaffold/templates/confirmation_functional_test.rb +137 -0
  17. data/lib/generators/test_unit/goma/scaffold/templates/functional_test.rb +51 -0
  18. data/lib/generators/test_unit/goma/scaffold/templates/oauth_functional_test.rb +6 -0
  19. data/lib/generators/test_unit/goma/scaffold/templates/password_functional_test.rb +67 -0
  20. data/lib/generators/test_unit/goma/scaffold/templates/session_functional_test.rb +122 -0
  21. data/lib/generators/test_unit/goma/scaffold/templates/unlock_functional_test.rb +47 -0
  22. data/lib/generators/test_unit/goma/scaffold/templates/user_functional_test.rb +118 -0
  23. data/lib/goma.rb +1 -1
  24. data/lib/goma/config.rb +0 -1
  25. data/lib/goma/controller_test_helpers.rb +65 -0
  26. data/lib/goma/controllers.rb +1 -1
  27. data/lib/goma/models/authenticatable.rb +20 -11
  28. data/lib/goma/models/confirmable.rb +1 -1
  29. data/lib/goma/models/lockable.rb +1 -2
  30. data/lib/goma/version.rb +1 -1
  31. data/test/models/lockable_test.rb +0 -2
  32. data/test/rails_app/app/controllers/confirmations_controller.rb +4 -4
  33. data/test/rails_app/app/controllers/users_controller.rb +3 -3
  34. data/test/rails_app/app/mailers/user_mailer.rb +1 -1
  35. data/test/rails_app/config/initializers/goma.rb +1 -2
  36. data/test/rails_app/db/migrate/{20140515111009_create_users.rb → 20140524062919_create_users.rb} +0 -1
  37. data/test/rails_app/db/migrate/{20140515111010_create_authentications.rb → 20140524062920_create_authentications.rb} +0 -0
  38. data/test/rails_app/db/schema.rb +1 -2
  39. data/test/rails_app/test/controllers/authentications_controller_test.rb +4 -0
  40. data/test/rails_app/test/controllers/confirmations_controller_test.rb +127 -0
  41. data/test/rails_app/test/controllers/passwords_controller_test.rb +65 -0
  42. data/test/rails_app/test/controllers/sessions_controller_test.rb +70 -0
  43. data/test/rails_app/test/controllers/unlocks_controller_test.rb +43 -0
  44. data/test/rails_app/test/controllers/users_controller_test.rb +109 -0
  45. data/test/rails_app/test/fixtures/authentications.yml +11 -0
  46. data/test/rails_app/test/fixtures/users.yml +17 -0
  47. data/test/rails_app/test/helpers/authentications_helper_test.rb +4 -0
  48. data/test/rails_app/test/helpers/confirmations_helper_test.rb +4 -0
  49. data/test/rails_app/test/helpers/passwords_helper_test.rb +4 -0
  50. data/test/rails_app/test/helpers/sessions_helper_test.rb +4 -0
  51. data/test/rails_app/test/helpers/unlocks_helper_test.rb +4 -0
  52. data/test/rails_app/test/helpers/users_helper_test.rb +4 -0
  53. data/test/rails_app/test/mailers/user_mailer_test.rb +7 -0
  54. data/test/rails_app/test/models/authentication_test.rb +7 -0
  55. data/test/rails_app/test/models/user_test.rb +7 -0
  56. data/test/rails_app/test/test_helper.rb +16 -0
  57. data/test/test_helper.rb +1 -1
  58. metadata +54 -7
  59. data/lib/goma/test_helpers.rb +0 -67
@@ -113,7 +113,7 @@ module Goma
113
113
  end
114
114
 
115
115
  def not_authenticated
116
- redirect_to root_path
116
+ redirect_to root_path, alert: 'Login required'
117
117
  end
118
118
 
119
119
  end
@@ -34,7 +34,7 @@ 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=nil)
37
+ def load_from_token_with_error(raw_token, token_attr, token_sent_at_attr=nil, 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
40
  if valid_period.nil? || (Time.new.utc - record.send(token_sent_at_attr) <= valid_period)
@@ -91,8 +91,7 @@ module Goma
91
91
  target.module_eval <<-METHOD, __FILE__, __LINE__ + 1
92
92
  def load_from_#{purpose}_token_with_error(raw_token)
93
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)
94
+ load_from_token_with_error(raw_token, token_attr)
96
95
  end
97
96
  METHOD
98
97
  end
@@ -121,15 +120,25 @@ module Goma
121
120
 
122
121
  # instance methods
123
122
 
124
- def define_token_generator_method_for(target, purpose)
125
- target.module_eval <<-METHOD, __FILE__, __LINE__ + 1
126
- def generate_#{purpose}_token
127
- raw, enc = Goma.token_generator.generate(self.class, goma_config.#{purpose}_token_attribute_name)
128
- self.send(goma_config.#{purpose}_token_to_send_setter, raw)
129
- self.send(goma_config.#{purpose}_token_setter, enc)
130
- self.send(goma_config.#{purpose}_token_sent_at_setter, Time.now.utc)
123
+ def define_token_generator_method_for(target, purpose, has_period: true)
124
+ if has_period
125
+ target.module_eval <<-METHOD, __FILE__, __LINE__ + 1
126
+ def generate_#{purpose}_token
127
+ raw, enc = Goma.token_generator.generate(self.class, goma_config.#{purpose}_token_attribute_name)
128
+ self.send(goma_config.#{purpose}_token_to_send_setter, raw)
129
+ self.send(goma_config.#{purpose}_token_setter, enc)
130
+ self.send(goma_config.#{purpose}_token_sent_at_setter, Time.now.utc)
131
+ end
132
+ METHOD
133
+ else
134
+ target.module_eval <<-METHOD, __FILE__, __LINE__ + 1
135
+ def generate_#{purpose}_token
136
+ raw, enc = Goma.token_generator.generate(self.class, goma_config.#{purpose}_token_attribute_name)
137
+ self.send(goma_config.#{purpose}_token_to_send_setter, raw)
138
+ self.send(goma_config.#{purpose}_token_setter, enc)
139
+ end
140
+ METHOD
131
141
  end
132
- METHOD
133
142
  end
134
143
 
135
144
  def define_send_email_method_for(target, mailer_name, name)
@@ -64,7 +64,7 @@ module Goma
64
64
  end
65
65
 
66
66
  def unactivated_access_allowed_period?
67
- period = goma_config.allow_unconfirmed_access_for
67
+ period = goma_config.allow_unactivated_access_for
68
68
  return false if period == 0
69
69
 
70
70
  Time.now - created_at < period ? true : false
@@ -21,7 +21,7 @@ module Goma
21
21
  send_unlock_token_email
22
22
  end
23
23
 
24
- DefinitionHelper.define_token_generator_method_for(self, :unlock)
24
+ DefinitionHelper.define_token_generator_method_for(self, :unlock, has_period: false)
25
25
  DefinitionHelper.define_send_email_method_for(self, :unlock_token, :unlock_token_email)
26
26
 
27
27
  def valid_password?(password)
@@ -53,7 +53,6 @@ module Goma
53
53
  self.send(goma_config.locked_at_setter, nil)
54
54
  self.send(goma_config.failed_attempts_setter, 0)
55
55
  self.send(goma_config.unlock_token_setter, nil)
56
- self.send(goma_config.unlock_token_sent_at_setter, nil)
57
56
  save(validate: false)
58
57
  end
59
58
 
@@ -1,3 +1,3 @@
1
1
  module Goma
2
- VERSION = "0.0.1.rc2"
2
+ VERSION = "0.0.1.rc3"
3
3
  end
@@ -7,7 +7,6 @@ class LockableTest < ActiveSupport::TestCase
7
7
  user.reload
8
8
  assert user.access_locked?
9
9
  assert user.unlock_token
10
- assert user.unlock_token_sent_at
11
10
  assert user.locked_at
12
11
  end
13
12
 
@@ -87,7 +86,6 @@ class LockableTest < ActiveSupport::TestCase
87
86
  user.reload
88
87
  refute user.access_locked?
89
88
  assert_nil user.unlock_token
90
- assert_nil user.unlock_token_sent_at
91
89
  assert_nil user.locked_at
92
90
  end
93
91
 
@@ -41,15 +41,15 @@ class ConfirmationsController < ApplicationController
41
41
  redirect_to root_url, notice: 'Your new email was successfully confirmed.'
42
42
  else
43
43
  if err == :token_expired
44
- flash.now[:alert] = "Your email confirmation URL has expired, please change your email again."
44
+ flash[:alert] = "Your email confirmation URL has expired, please change your email again."
45
45
  else
46
- flash.now[:alert] = "Email confirmation failed. Please make sure you used the full URL provided."
46
+ flash[:alert] = "Email confirmation failed. Please make sure you used the full URL provided."
47
47
  end
48
48
 
49
49
  if current_user
50
- render edit_user_url(current_user)
50
+ redirect_to edit_user_url(current_user)
51
51
  else
52
- render root_url
52
+ redirect_to root_url
53
53
  end
54
54
  end
55
55
  end
@@ -18,7 +18,7 @@ class UsersController < ApplicationController
18
18
 
19
19
  # GET /users/1/edit
20
20
  def edit
21
- not_authenticated unless current_user = @user
21
+ not_authenticated unless current_user == @user
22
22
  end
23
23
 
24
24
  # POST /users
@@ -34,7 +34,7 @@ class UsersController < ApplicationController
34
34
 
35
35
  # PATCH/PUT /users/1
36
36
  def update
37
- not_authenticated unless current_user = @user
37
+ not_authenticated unless current_user == @user
38
38
  if @user.update(user_params)
39
39
  flash[:notice] = @user.raw_confirmation_token ?
40
40
  'You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirmation link to finalize confirming your new email address.' :
@@ -47,7 +47,7 @@ class UsersController < ApplicationController
47
47
 
48
48
  # DELETE /users/1
49
49
  def destroy
50
- not_authenticated unless current_user = @user
50
+ not_authenticated unless current_user == @user
51
51
  @user.destroy
52
52
  redirect_to users_url, notice: 'User was successfully destroyed.'
53
53
  end
@@ -1,5 +1,5 @@
1
1
  class UserMailer < ActionMailer::Base
2
- default from: "please-change-me-at-config-initializers-goma@example.com"
2
+ default from: Goma.config(:user).mailer_sender
3
3
 
4
4
  # Subject can be set in your I18n file at config/locales/en.yml
5
5
  # with the following lookup:
@@ -35,7 +35,7 @@ Goma.configure do |config|
35
35
  # config.activation_mailer_name = nil
36
36
  # config.email_confirmation_mailer_name = nil
37
37
  # config.confirmation_keys = [ :email ]
38
- # config.allow_unconfirmed_access_for = 0
38
+ # config.allow_unactivated_access_for = 0
39
39
  # config.activate_within = 3.days
40
40
  # config.activation_needed_email_method_name = :activation_needed_email
41
41
  # config.activation_success_email_method_name = :activation_success_email
@@ -78,7 +78,6 @@ Goma.configure do |config|
78
78
  # config.unlock_in = 1.hour
79
79
  # config.last_attempt_warning = false # TODO not yet implemented
80
80
  # config.unlock_token_attribute_name = :unlock_token
81
- # config.unlock_token_sent_at_attribute_name = :unlock_token_sent_at
82
81
  # config.unlock_token_to_send_attribute_name = :raw_unlock_token
83
82
 
84
83
  ####################################################
@@ -21,7 +21,6 @@ class CreateUsers < ActiveRecord::Migration
21
21
  t.integer :failed_attempts, default: 0, null: false
22
22
  t.datetime :locked_at
23
23
  t.string :unlock_token
24
- t.datetime :unlock_token_sent_at
25
24
 
26
25
  # Recoverable
27
26
  t.string :reset_password_token
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(version: 20140515111010) do
14
+ ActiveRecord::Schema.define(version: 20140524062920) do
15
15
 
16
16
  create_table "authentications", force: true do |t|
17
17
  t.string "provider"
@@ -37,7 +37,6 @@ ActiveRecord::Schema.define(version: 20140515111010) do
37
37
  t.integer "failed_attempts", default: 0, null: false
38
38
  t.datetime "locked_at"
39
39
  t.string "unlock_token"
40
- t.datetime "unlock_token_sent_at"
41
40
  t.string "reset_password_token"
42
41
  t.datetime "reset_password_token_sent_at"
43
42
  t.integer "login_count", default: 0, null: false
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class AuthenticationsControllerTest < ActionController::TestCase
4
+ end
@@ -0,0 +1,127 @@
1
+ require 'test_helper'
2
+
3
+ class ConfirmationsControllerTest < ActionController::TestCase
4
+ setup do
5
+ @user = users(:unactivated_user)
6
+ end
7
+
8
+ test "should get new" do
9
+ get :new
10
+ assert_response :success
11
+ end
12
+
13
+ test "should create confirmation" do
14
+ user = User.create({ username: "username1", email: "user1@example.com", password: "password", password_confirmation: "password" })
15
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
16
+ post :create, username_or_email: user.email
17
+ end
18
+ assert_redirected_to new_session_url
19
+ assert_match /You will receive new activation email/, flash[:notice]
20
+ end
21
+
22
+ test "should activate user" do
23
+ user = User.create({ username: "username2", email: "user2@example.com", password: "password", password_confirmation: "password" })
24
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
25
+ get :show, id: user.raw_confirmation_token
26
+ end
27
+ assert_redirected_to new_session_url
28
+ assert_match /Your account was successfully activated/, flash[:notice]
29
+ user.reload
30
+ assert user.activated?
31
+ end
32
+
33
+ test "should not activate user with wrong token" do
34
+ user = User.create({ username: "username3", email: "user3@example.com", password: "password", password_confirmation: "password" })
35
+ assert_no_difference 'ActionMailer::Base.deliveries.size' do
36
+ get :show, id: 'oops'
37
+ end
38
+ assert_response :success
39
+ assert_template :new
40
+ assert_match /Not found any account by this URL/, flash[:alert]
41
+ user.reload
42
+ refute user.activated?
43
+ end
44
+
45
+ test "should not activate user with expired token" do
46
+ user = User.create({ username: "username4", email: "user4@example.com", password: "password", password_confirmation: "password" })
47
+ user.update_column(:confirmation_token_sent_at, 4.days.ago)
48
+ assert_no_difference 'ActionMailer::Base.deliveries.size' do
49
+ get :show, id: user.raw_confirmation_token
50
+ end
51
+ assert_response :success
52
+ assert_template :new
53
+ assert_match /Your activation URL has expired/, flash[:alert]
54
+ user.reload
55
+ refute user.activated?
56
+ end
57
+
58
+ test "should confirm email" do
59
+ user = users(:one)
60
+ email = user.email
61
+ user.update(email: 'new@example.com')
62
+ assert_equal 'new@example.com', user.unconfirmed_email
63
+ assert_equal email, user.email
64
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
65
+ get :email, id: user.raw_confirmation_token
66
+ end
67
+ assert_redirected_to root_path
68
+ assert_match /Your new email was successfully confirmed/, flash[:notice]
69
+ user.reload
70
+ assert_equal 'new@example.com', user.email
71
+ assert_nil user.unconfirmed_email
72
+ end
73
+
74
+ test "should not confirm email with wrong token" do
75
+ user = users(:one)
76
+ email = user.email
77
+ user.update(email: 'new@example.com')
78
+ assert_equal 'new@example.com', user.unconfirmed_email
79
+ assert_equal email, user.email
80
+ assert_no_difference 'ActionMailer::Base.deliveries.size' do
81
+ get :email, id: 'oops'
82
+ end
83
+ assert_redirected_to root_path
84
+ assert_match /Please make sure you used the full URL provided/, flash[:alert]
85
+ user.reload
86
+ assert_equal email, user.email
87
+ assert_equal 'new@example.com', user.unconfirmed_email
88
+ end
89
+
90
+ test "should not confirm email with expired token" do
91
+ user = users(:one)
92
+ email = user.email
93
+ user.update(email: 'new@example.com')
94
+ user.update_column(:confirmation_token_sent_at, 4.days.ago)
95
+ assert_equal 'new@example.com', user.unconfirmed_email
96
+ assert_equal email, user.email
97
+ assert_no_difference 'ActionMailer::Base.deliveries.size' do
98
+ get :email, id: user.raw_confirmation_token
99
+ end
100
+ assert_redirected_to root_path
101
+ assert_match /Your email confirmation URL has expired/, flash[:alert]
102
+ user.reload
103
+ assert_equal email, user.email
104
+ assert_equal 'new@example.com', user.unconfirmed_email
105
+ end
106
+
107
+ test "should be redirected to edit_user_url when failed to confirm email with wrong token if logged in" do
108
+ user = users(:one)
109
+ force_login(user)
110
+ user.update(email: 'new@example.com')
111
+ get :email, id: 'oops'
112
+ assert_redirected_to edit_user_url(user)
113
+ assert_match /Please make sure you used the full URL provided/, flash[:alert]
114
+ user.reload
115
+ end
116
+
117
+ test "should be redirected to edit_user_url when failed to confirm email with expired token if logged in" do
118
+ user = users(:one)
119
+ force_login(user)
120
+ user.update(email: 'new@example.com')
121
+ user.update_column(:confirmation_token_sent_at, 4.days.ago)
122
+ get :email, id: user.raw_confirmation_token
123
+ assert_redirected_to edit_user_url(user)
124
+ assert_match /Your email confirmation URL has expired/, flash[:alert]
125
+ end
126
+
127
+ end
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+
3
+ class PasswordsControllerTest < ActionController::TestCase
4
+ setup do
5
+ @user = users(:one)
6
+ end
7
+
8
+ test "should get new" do
9
+ get :new
10
+ assert_response :success
11
+ end
12
+
13
+ test "should resend reset password token with email" do
14
+ @user.send_reset_password_instructions!
15
+ reset_password_token = @user.unlock_token
16
+ assert_difference 'ActionMailer::Base.deliveries.size', 1 do
17
+ post :create, username_or_email: @user.email
18
+ end
19
+ assert_redirected_to new_session_url
20
+ @user.reload
21
+ assert_not_equal reset_password_token, @user.reset_password_token
22
+ end
23
+
24
+
25
+ test "should get edit" do
26
+ @user.send_reset_password_instructions!
27
+ raw_reset_password_token = @user.raw_reset_password_token
28
+ get :edit, id: raw_reset_password_token
29
+ assert_response :success
30
+ assert_match /<input[^>]*type="hidden"[^>]*value="#{raw_reset_password_token}"/, response.body
31
+ end
32
+
33
+ test "should update password" do
34
+ @user.send_reset_password_instructions!
35
+ raw_reset_password_token = @user.raw_reset_password_token
36
+ patch :update, id: raw_reset_password_token, user: { raw_reset_password_token: raw_reset_password_token, password: 'newpassword', password_confirmation: 'newpassword' }
37
+ assert_redirected_to root_path
38
+ @user.reload
39
+ assert @user.valid_password? 'newpassword'
40
+ refute @user.valid_password? 'password'
41
+ end
42
+
43
+ test "should not update password with wrong token" do
44
+ @user.send_reset_password_instructions!
45
+ raw_reset_password_token = @user.raw_reset_password_token
46
+ patch :update, id: raw_reset_password_token, user: { raw_reset_password_token: 'oops', password: 'newpassword', password_confirmation: 'newpassword' }
47
+ assert_template :edit
48
+ assert_match /make sure you used the full URL provided/, flash[:alert]
49
+ @user.reload
50
+ refute @user.valid_password? 'newpassword'
51
+ assert @user.valid_password? 'password'
52
+ end
53
+
54
+ test "should not update password with expired token" do
55
+ @user.send_reset_password_instructions!
56
+ raw_reset_password_token = @user.raw_reset_password_token
57
+ @user.update_column(:reset_password_token_sent_at, 21601.seconds.ago)
58
+ patch :update, id: raw_reset_password_token, user: { raw_reset_password_token: raw_reset_password_token, password: 'newpassword', password_confirmation: 'newpassword' }
59
+ assert_template :new
60
+ assert_match /The password reset URL you visited has expired/, flash[:alert]
61
+ @user.reload
62
+ refute @user.valid_password? 'newpassword'
63
+ assert @user.valid_password? 'password'
64
+ end
65
+ end
@@ -0,0 +1,70 @@
1
+ require 'test_helper'
2
+
3
+ class SessionsControllerTest < ActionController::TestCase
4
+ setup do
5
+ @user = users(:one)
6
+ end
7
+
8
+ test "should get new" do
9
+ get :new
10
+ assert_response :success
11
+ end
12
+
13
+ test "should login with username" do
14
+ refute logged_in?
15
+ post :create, username_or_email: @user.username, password: 'password'
16
+ assert logged_in?
17
+ assert_redirected_to root_path
18
+ assert_match /Login successful/, flash[:notice]
19
+ end
20
+
21
+ test "should not login with username with wrong password" do
22
+ refute logged_in?
23
+ post :create, username_or_email: @user.username, password: 'wrongpass'
24
+ refute logged_in?
25
+ assert_template :new
26
+ assert_match /Login failed/, flash[:alert]
27
+ end
28
+
29
+ test "should not login unactivated user with username" do
30
+ unactivated_user = users(:unactivated_user)
31
+ refute logged_in?
32
+ post :create, username_or_email: unactivated_user.username, password: 'password'
33
+ refute logged_in?
34
+ assert_template :new
35
+ assert_match /Not activated/, flash[:alert]
36
+ end
37
+ test "should login with email" do
38
+ refute logged_in?
39
+ post :create, username_or_email: @user.email, password: 'password'
40
+ assert logged_in?
41
+ assert_redirected_to root_path
42
+ assert_match /Login successful/, flash[:notice]
43
+ end
44
+
45
+ test "should not login with email with wrong password" do
46
+ refute logged_in?
47
+ post :create, username_or_email: @user.email, password: 'wrongpass'
48
+ refute logged_in?
49
+ assert_template :new
50
+ assert_match /Login failed/, flash[:alert]
51
+ end
52
+
53
+ test "should not login unactivated user with email" do
54
+ unactivated_user = users(:unactivated_user)
55
+ refute logged_in?
56
+ post :create, username_or_email: unactivated_user.email, password: 'password'
57
+ refute logged_in?
58
+ assert_template :new
59
+ assert_match /Not activated/, flash[:alert]
60
+ end
61
+
62
+ test "should logout user" do
63
+ force_login(@user)
64
+ assert logged_in?
65
+ delete :destroy, id: @user
66
+ assert_redirected_to root_path
67
+ assert_match /Logged out/, flash[:notice]
68
+ refute logged_in?
69
+ end
70
+ end