1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
require 'cases/helper'
require 'models/user'
require 'models/visitor'
class SecurePasswordTest < ActiveModel::TestCase
setup do
# Used only to speed up tests
@original_min_cost = ActiveModel::SecurePassword.min_cost
ActiveModel::SecurePassword.min_cost = true
@user = User.new
@visitor = Visitor.new
# Simulate loading an existing user from the DB
@existing_user = User.new
@existing_user.password_digest = BCrypt::Password.create('password', cost: BCrypt::Engine::MIN_COST)
end
teardown do
ActiveModel::SecurePassword.min_cost = @original_min_cost
end
test "automatically include ActiveModel::Validations when validations are enabled" do
assert_respond_to @user, :valid?
end
test "don't include ActiveModel::Validations when validations are disabled" do
assert_not_respond_to @visitor, :valid?
end
test "create a new user with validations and valid password/confirmation" do
@user.password = 'password'
@user.password_confirmation = 'password'
assert @user.valid?(:create), 'user should be valid'
@user.password = 'a' * 72
@user.password_confirmation = 'a' * 72
assert @user.valid?(:create), 'user should be valid'
end
test "create a new user with validation and a spaces only password" do
@user.password = ' ' * 72
assert @user.valid?(:create), 'user should be valid'
end
test "create a new user with validation and a blank password" do
@user.password = ''
assert !@user.valid?(:create), 'user should be invalid'
assert_equal 1, @user.errors.count
assert_equal ["can't be blank"], @user.errors[:password]
end
test "create a new user with validation and a nil password" do
@user.password = nil
assert !@user.valid?(:create), 'user should be invalid'
assert_equal 1, @user.errors.count
assert_equal ["can't be blank"], @user.errors[:password]
end
test 'create a new user with validation and password length greater than 72' do
@user.password = 'a' * 73
@user.password_confirmation = 'a' * 73
assert !@user.valid?(:create), 'user should be invalid'
assert_equal 1, @user.errors.count
assert_equal ["is too long (maximum is 72 characters)"], @user.errors[:password]
end
test "create a new user with validation and a blank password confirmation" do
@user.password = 'password'
@user.password_confirmation = ''
assert !@user.valid?(:create), 'user should be invalid'
assert_equal 1, @user.errors.count
assert_equal ["doesn't match Password"], @user.errors[:password_confirmation]
end
test "create a new user with validation and a nil password confirmation" do
@user.password = 'password'
@user.password_confirmation = nil
assert @user.valid?(:create), 'user should be valid'
end
test "create a new user with validation and an incorrect password confirmation" do
@user.password = 'password'
@user.password_confirmation = 'something else'
assert !@user.valid?(:create), 'user should be invalid'
assert_equal 1, @user.errors.count
assert_equal ["doesn't match Password"], @user.errors[:password_confirmation]
end
test "update an existing user with validation and no change in password" do
assert @existing_user.valid?(:update), 'user should be valid'
end
test "update an existing user with validations and valid password/confirmation" do
@existing_user.password = 'password'
@existing_user.password_confirmation = 'password'
assert @existing_user.valid?(:update), 'user should be valid'
@existing_user.password = 'a' * 72
@existing_user.password_confirmation = 'a' * 72
assert @existing_user.valid?(:update), 'user should be valid'
end
test "updating an existing user with validation and a blank password" do
@existing_user.password = ''
assert @existing_user.valid?(:update), 'user should be valid'
end
test "updating an existing user with validation and a spaces only password" do
@user.password = ' ' * 72
assert @user.valid?(:update), 'user should be valid'
end
test "updating an existing user with validation and a blank password and password_confirmation" do
@existing_user.password = ''
@existing_user.password_confirmation = ''
assert @existing_user.valid?(:update), 'user should be valid'
end
test "updating an existing user with validation and a nil password" do
@existing_user.password = nil
assert !@existing_user.valid?(:update), 'user should be invalid'
assert_equal 1, @existing_user.errors.count
assert_equal ["can't be blank"], @existing_user.errors[:password]
end
test 'updating an existing user with validation and password length greater than 72' do
@existing_user.password = 'a' * 73
@existing_user.password_confirmation = 'a' * 73
assert !@existing_user.valid?(:update), 'user should be invalid'
assert_equal 1, @existing_user.errors.count
assert_equal ["is too long (maximum is 72 characters)"], @existing_user.errors[:password]
end
test "updating an existing user with validation and a blank password confirmation" do
@existing_user.password = 'password'
@existing_user.password_confirmation = ''
assert !@existing_user.valid?(:update), 'user should be invalid'
assert_equal 1, @existing_user.errors.count
assert_equal ["doesn't match Password"], @existing_user.errors[:password_confirmation]
end
test "updating an existing user with validation and a nil password confirmation" do
@existing_user.password = 'password'
@existing_user.password_confirmation = nil
assert @existing_user.valid?(:update), 'user should be valid'
end
test "updating an existing user with validation and an incorrect password confirmation" do
@existing_user.password = 'password'
@existing_user.password_confirmation = 'something else'
assert !@existing_user.valid?(:update), 'user should be invalid'
assert_equal 1, @existing_user.errors.count
assert_equal ["doesn't match Password"], @existing_user.errors[:password_confirmation]
end
test "updating an existing user with validation and a blank password digest" do
@existing_user.password_digest = ''
assert !@existing_user.valid?(:update), 'user should be invalid'
assert_equal 1, @existing_user.errors.count
assert_equal ["can't be blank"], @existing_user.errors[:password]
end
test "updating an existing user with validation and a nil password digest" do
@existing_user.password_digest = nil
assert !@existing_user.valid?(:update), 'user should be invalid'
assert_equal 1, @existing_user.errors.count
assert_equal ["can't be blank"], @existing_user.errors[:password]
end
test "setting a blank password should not change an existing password" do
@existing_user.password = ''
assert @existing_user.password_digest == 'password'
end
test "setting a nil password should clear an existing password" do
@existing_user.password = nil
assert_equal nil, @existing_user.password_digest
end
test "authenticate" do
@user.password = "secret"
assert !@user.authenticate("wrong")
assert @user.authenticate("secret")
end
test "Password digest cost defaults to bcrypt default cost when min_cost is false" do
ActiveModel::SecurePassword.min_cost = false
@user.password = "secret"
assert_equal BCrypt::Engine::DEFAULT_COST, @user.password_digest.cost
end
test "Password digest cost honors bcrypt cost attribute when min_cost is false" do
begin
original_bcrypt_cost = BCrypt::Engine.cost
ActiveModel::SecurePassword.min_cost = false
BCrypt::Engine.cost = 5
@user.password = "secret"
assert_equal BCrypt::Engine.cost, @user.password_digest.cost
ensure
BCrypt::Engine.cost = original_bcrypt_cost
end
end
test "Password digest cost can be set to bcrypt min cost to speed up tests" do
ActiveModel::SecurePassword.min_cost = true
@user.password = "secret"
assert_equal BCrypt::Engine::MIN_COST, @user.password_digest.cost
end
end
|