cops 0.2.0.6
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.
- data/LICENSE +20 -0
- data/README.rdoc +113 -0
- data/Rakefile +95 -0
- data/VERSION +1 -0
- data/app/controllers/blue_light_special/confirmations_controller.rb +76 -0
- data/app/controllers/blue_light_special/impersonations_controller.rb +44 -0
- data/app/controllers/blue_light_special/passwords_controller.rb +93 -0
- data/app/controllers/blue_light_special/sessions_controller.rb +76 -0
- data/app/controllers/blue_light_special/users_controller.rb +85 -0
- data/app/models/blue_light_special_mailer.rb +28 -0
- data/app/models/deliver_change_password_job.rb +19 -0
- data/app/models/deliver_welcome_job.rb +17 -0
- data/app/models/generic_mailer.rb +31 -0
- data/app/models/impersonation.rb +26 -0
- data/app/models/mimi_mailer.rb +30 -0
- data/app/views/generic_mailer/change_password.html.erb +9 -0
- data/app/views/generic_mailer/confirmation.html.erb +5 -0
- data/app/views/generic_mailer/welcome.html.erb +1 -0
- data/app/views/impersonations/index.html.erb +5 -0
- data/app/views/passwords/edit.html.erb +23 -0
- data/app/views/passwords/new.html.erb +15 -0
- data/app/views/sessions/new.html.erb +48 -0
- data/app/views/users/_form.html.erb +21 -0
- data/app/views/users/edit.html.erb +6 -0
- data/app/views/users/new.html.erb +6 -0
- data/app/views/users/show.html.erb +8 -0
- data/generators/blue_light_special/USAGE +1 -0
- data/generators/blue_light_special/blue_light_special_generator.rb +78 -0
- data/generators/blue_light_special/lib/insert_commands.rb +33 -0
- data/generators/blue_light_special/lib/rake_commands.rb +22 -0
- data/generators/blue_light_special/templates/README +20 -0
- data/generators/blue_light_special/templates/application.html.erb +50 -0
- data/generators/blue_light_special/templates/blue_light_special.rb +25 -0
- data/generators/blue_light_special/templates/blue_light_special.yml +45 -0
- data/generators/blue_light_special/templates/factories.rb +23 -0
- data/generators/blue_light_special/templates/migrations/create_users.rb +24 -0
- data/generators/blue_light_special/templates/migrations/update_users.rb +44 -0
- data/generators/blue_light_special/templates/style.css +31 -0
- data/generators/blue_light_special/templates/user.rb +3 -0
- data/generators/blue_light_special/templates/xd_receiver.html +10 -0
- data/generators/blue_light_special/templates/xd_receiver_ssl.html +10 -0
- data/generators/blue_light_special_admin/USAGE +1 -0
- data/generators/blue_light_special_admin/blue_light_special_admin_generator.rb +30 -0
- data/generators/blue_light_special_admin/lib/insert_commands.rb +33 -0
- data/generators/blue_light_special_admin/templates/README +16 -0
- data/generators/blue_light_special_admin/templates/app/controllers/admin/admin_controller.rb +14 -0
- data/generators/blue_light_special_admin/templates/app/controllers/admin/users_controller.rb +52 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/_form.html.erb +25 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/edit.html.erb +6 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/index.html.erb +7 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/new.html.erb +6 -0
- data/generators/blue_light_special_admin/templates/app/views/admin/users/show.html.erb +10 -0
- data/generators/blue_light_special_admin/templates/test/integration/admin/users_test.rb +201 -0
- data/generators/blue_light_special_tests/USAGE +1 -0
- data/generators/blue_light_special_tests/blue_light_special_tests_generator.rb +21 -0
- data/generators/blue_light_special_tests/templates/README +58 -0
- data/generators/blue_light_special_tests/templates/test/integration/edit_profile_test.rb +35 -0
- data/generators/blue_light_special_tests/templates/test/integration/facebook_test.rb +61 -0
- data/generators/blue_light_special_tests/templates/test/integration/impersonation_test.rb +39 -0
- data/generators/blue_light_special_tests/templates/test/integration/password_reset_test.rb +128 -0
- data/generators/blue_light_special_tests/templates/test/integration/sign_in_test.rb +66 -0
- data/generators/blue_light_special_tests/templates/test/integration/sign_out_test.rb +28 -0
- data/generators/blue_light_special_tests/templates/test/integration/sign_up_test.rb +47 -0
- data/lib/blue_light_special/authentication.rb +138 -0
- data/lib/blue_light_special/configuration.rb +34 -0
- data/lib/blue_light_special/extensions/errors.rb +6 -0
- data/lib/blue_light_special/extensions/rescue.rb +5 -0
- data/lib/blue_light_special/routes.rb +62 -0
- data/lib/blue_light_special/user.rb +279 -0
- data/lib/blue_light_special.rb +7 -0
- data/rails/init.rb +4 -0
- data/shoulda_macros/blue_light_special.rb +244 -0
- data/test/controllers/passwords_controller_test.rb +184 -0
- data/test/controllers/sessions_controller_test.rb +129 -0
- data/test/controllers/users_controller_test.rb +57 -0
- data/test/models/blue_light_special_mailer_test.rb +52 -0
- data/test/models/impersonation_test.rb +25 -0
- data/test/models/user_test.rb +213 -0
- data/test/rails_root/app/controllers/accounts_controller.rb +10 -0
- data/test/rails_root/app/controllers/application_controller.rb +6 -0
- data/test/rails_root/app/helpers/application_helper.rb +5 -0
- data/test/rails_root/app/helpers/confirmations_helper.rb +2 -0
- data/test/rails_root/app/helpers/passwords_helper.rb +2 -0
- data/test/rails_root/config/boot.rb +110 -0
- data/test/rails_root/config/environment.rb +22 -0
- data/test/rails_root/config/environments/development.rb +19 -0
- data/test/rails_root/config/environments/production.rb +1 -0
- data/test/rails_root/config/environments/test.rb +37 -0
- data/test/rails_root/config/initializers/inflections.rb +10 -0
- data/test/rails_root/config/initializers/mime_types.rb +5 -0
- data/test/rails_root/config/initializers/requires.rb +13 -0
- data/test/rails_root/config/initializers/time_formats.rb +4 -0
- data/test/rails_root/config/routes.rb +9 -0
- data/test/rails_root/public/dispatch.rb +10 -0
- data/test/rails_root/script/create_project.rb +52 -0
- data/test/rails_root/test/functional/accounts_controller_test.rb +23 -0
- data/test/test_helper.rb +21 -0
- metadata +212 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
require 'digest/sha1'
|
|
2
|
+
|
|
3
|
+
module BlueLightSpecial
|
|
4
|
+
module User
|
|
5
|
+
|
|
6
|
+
Admin = 'admin'
|
|
7
|
+
|
|
8
|
+
# Hook for all BlueLightSpecial::User modules.
|
|
9
|
+
#
|
|
10
|
+
# If you need to override parts of BlueLightSpecial::User,
|
|
11
|
+
# extend and include à la carte.
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# extend ClassMethods
|
|
15
|
+
# include InstanceMethods
|
|
16
|
+
# include AttrAccessor
|
|
17
|
+
# include Callbacks
|
|
18
|
+
#
|
|
19
|
+
# @see ClassMethods
|
|
20
|
+
# @see InstanceMethods
|
|
21
|
+
# @see AttrAccessible
|
|
22
|
+
# @see AttrAccessor
|
|
23
|
+
# @see Validations
|
|
24
|
+
# @see Callbacks
|
|
25
|
+
def self.included(model)
|
|
26
|
+
model.extend(ClassMethods)
|
|
27
|
+
|
|
28
|
+
model.send(:include, InstanceMethods)
|
|
29
|
+
model.send(:include, AttrAccessor)
|
|
30
|
+
model.send(:include, Validations)
|
|
31
|
+
model.send(:include, Callbacks)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
module AttrAccessor
|
|
35
|
+
# Hook for attr_accessor virtual attributes.
|
|
36
|
+
#
|
|
37
|
+
# :password, :password_confirmation
|
|
38
|
+
def self.included(model)
|
|
39
|
+
model.class_eval do
|
|
40
|
+
attr_accessor :password, :password_confirmation
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module Validations
|
|
46
|
+
# Hook for validations.
|
|
47
|
+
#
|
|
48
|
+
# :email must be present, unique, formatted
|
|
49
|
+
#
|
|
50
|
+
# If password is required,
|
|
51
|
+
# :password must be present, confirmed
|
|
52
|
+
def self.included(model)
|
|
53
|
+
model.class_eval do
|
|
54
|
+
validates_presence_of :email, :unless => :email_optional?
|
|
55
|
+
validates_uniqueness_of :email, :case_sensitive => false, :allow_blank => true
|
|
56
|
+
validates_format_of :email, :with => %r{.+@.+\..+}, :allow_blank => true
|
|
57
|
+
|
|
58
|
+
validates_presence_of :password, :unless => :password_optional?
|
|
59
|
+
validates_confirmation_of :password, :unless => :password_optional?
|
|
60
|
+
|
|
61
|
+
validates_presence_of :first_name, :last_name
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
module Callbacks
|
|
67
|
+
# Hook for callbacks.
|
|
68
|
+
#
|
|
69
|
+
# salt, token, password encryption are handled before_save.
|
|
70
|
+
def self.included(model)
|
|
71
|
+
model.class_eval do
|
|
72
|
+
before_save :initialize_salt,
|
|
73
|
+
:encrypt_password
|
|
74
|
+
before_create :generate_confirmation_token,
|
|
75
|
+
:generate_remember_token
|
|
76
|
+
after_create :send_welcome_email, :unless => :suppress_receive_welcome_email?
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
module InstanceMethods
|
|
82
|
+
# Am I authenticated with given password?
|
|
83
|
+
#
|
|
84
|
+
# @param [String] plain-text password
|
|
85
|
+
# @return [true, false]
|
|
86
|
+
# @example
|
|
87
|
+
# user.authenticated?('password')
|
|
88
|
+
def authenticated?(password)
|
|
89
|
+
encrypted_password == encrypt(password)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Don't send welcome email if email already confirmed, or
|
|
93
|
+
# use is a facebook connect user
|
|
94
|
+
def suppress_receive_welcome_email?
|
|
95
|
+
return true if email_confirmed?
|
|
96
|
+
if self.facebook_uid.present?
|
|
97
|
+
self.email_confirmed = true
|
|
98
|
+
self.confirmation_token = nil
|
|
99
|
+
self.save
|
|
100
|
+
return true
|
|
101
|
+
end
|
|
102
|
+
return false
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Set the remember token.
|
|
106
|
+
#
|
|
107
|
+
# @deprecated Use {#reset_remember_token!} instead
|
|
108
|
+
def remember_me!
|
|
109
|
+
warn "[DEPRECATION] remember_me!: use reset_remember_token! instead"
|
|
110
|
+
reset_remember_token!
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Reset the remember token.
|
|
114
|
+
#
|
|
115
|
+
# @example
|
|
116
|
+
# user.reset_remember_token!
|
|
117
|
+
def reset_remember_token!
|
|
118
|
+
generate_remember_token
|
|
119
|
+
save(false)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Confirm my email.
|
|
123
|
+
#
|
|
124
|
+
# @example
|
|
125
|
+
# user.confirm_email!
|
|
126
|
+
def confirm_email!
|
|
127
|
+
self.email_confirmed = true
|
|
128
|
+
self.confirmation_token = nil
|
|
129
|
+
save(false)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Mark my account as forgotten password.
|
|
133
|
+
#
|
|
134
|
+
# @example
|
|
135
|
+
# user.forgot_password!
|
|
136
|
+
def forgot_password!
|
|
137
|
+
generate_password_reset_token
|
|
138
|
+
save(false)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Update my password.
|
|
142
|
+
#
|
|
143
|
+
# @param [String, String] password and password confirmation
|
|
144
|
+
# @return [true, false] password was updated or not
|
|
145
|
+
# @example
|
|
146
|
+
# user.update_password('new-password', 'new-password')
|
|
147
|
+
def update_password(new_password, new_password_confirmation)
|
|
148
|
+
self.password = new_password
|
|
149
|
+
self.password_confirmation = new_password_confirmation
|
|
150
|
+
if valid?
|
|
151
|
+
self.password_reset_token = nil
|
|
152
|
+
end
|
|
153
|
+
save
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def facebook_user?
|
|
157
|
+
!self.facebook_uid.blank?
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
##
|
|
161
|
+
# Returns +true+ if the user is an admin.
|
|
162
|
+
#
|
|
163
|
+
def admin?
|
|
164
|
+
self.role == Admin
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
##
|
|
168
|
+
# Returns the user's full name.
|
|
169
|
+
#
|
|
170
|
+
def name
|
|
171
|
+
"#{self.first_name} #{self.last_name}"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
protected
|
|
175
|
+
|
|
176
|
+
def generate_hash(string)
|
|
177
|
+
Digest::SHA1.hexdigest(string)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def initialize_salt
|
|
181
|
+
if new_record?
|
|
182
|
+
self.salt = generate_hash("--#{Time.now.utc}--#{password}--#{rand}--")
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def encrypt_password
|
|
187
|
+
return if password.blank?
|
|
188
|
+
self.encrypted_password = encrypt(password)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def encrypt(string)
|
|
192
|
+
generate_hash("--#{salt}--#{string}--")
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def generate_confirmation_token
|
|
196
|
+
self.confirmation_token = encrypt("--#{Time.now.utc}--#{password}--#{rand}--")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def generate_password_reset_token
|
|
200
|
+
self.password_reset_token = encrypt("--#{Time.now.utc}--#{password}--#{rand}--")
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def generate_remember_token
|
|
204
|
+
self.remember_token = encrypt("--#{Time.now.utc}--#{encrypted_password}--#{id}--#{rand}--")
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Always false. Override to allow other forms of authentication
|
|
208
|
+
# (username, facebook, etc).
|
|
209
|
+
# @return [Boolean] true if the email field be left blank for this user
|
|
210
|
+
def email_optional?
|
|
211
|
+
false
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# True if the password has been set and the password is not being
|
|
215
|
+
# updated. Override to allow other forms of # authentication (username,
|
|
216
|
+
# facebook, etc).
|
|
217
|
+
# @return [Boolean] true if the password field can be left blank for this user
|
|
218
|
+
def password_optional?
|
|
219
|
+
facebook_user? || (encrypted_password.present? && password.blank?)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def password_required?
|
|
223
|
+
# warn "[DEPRECATION] password_required?: use !password_optional? instead"
|
|
224
|
+
!password_optional?
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def send_welcome_email
|
|
228
|
+
if BlueLightSpecial.configuration.use_delayed_job
|
|
229
|
+
Delayed::Job.enqueue DeliverWelcomeJob.new(self.id)
|
|
230
|
+
else
|
|
231
|
+
if user = ::User.find_by_id(self.id)
|
|
232
|
+
BlueLightSpecialMailer.deliver_welcome(user)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def send_confirmation_email
|
|
238
|
+
BlueLightSpecialMailer.deliver_confirmation self
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
module ClassMethods
|
|
244
|
+
# Authenticate with email and password.
|
|
245
|
+
#
|
|
246
|
+
# @param [String, String] email and password
|
|
247
|
+
# @return [User, nil] authenticated user or nil
|
|
248
|
+
# @example
|
|
249
|
+
# User.authenticate("email@example.com", "password")
|
|
250
|
+
def authenticate(email, password)
|
|
251
|
+
return nil unless user = find_by_email(email)
|
|
252
|
+
return user if user.authenticated?(password)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def find_facebook_user(facebook_session, facebook_uid)
|
|
256
|
+
return nil unless BlueLightSpecial.configuration.use_facebook_connect && facebook_session && facebook_uid
|
|
257
|
+
|
|
258
|
+
begin
|
|
259
|
+
facebook_user = MiniFB::Session.new(BlueLightSpecial.configuration.facebook_api_key,
|
|
260
|
+
BlueLightSpecial.configuration.facebook_secret_key,
|
|
261
|
+
facebook_session, facebook_uid).user
|
|
262
|
+
rescue MiniFB::FaceBookError
|
|
263
|
+
facebook_user = nil
|
|
264
|
+
end
|
|
265
|
+
return nil unless facebook_user
|
|
266
|
+
|
|
267
|
+
user = ::User.find_by_facebook_uid(facebook_uid) || ::User.find_by_email(facebook_user['email']) || ::User.new
|
|
268
|
+
user.tap do |user|
|
|
269
|
+
user.facebook_uid = facebook_uid
|
|
270
|
+
user.email = facebook_user['email']
|
|
271
|
+
user.first_name = facebook_user['first_name']
|
|
272
|
+
user.last_name = facebook_user['last_name']
|
|
273
|
+
user.save
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
end
|
|
279
|
+
end
|
data/rails/init.rb
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
module BlueLightSpecial
|
|
2
|
+
module Shoulda
|
|
3
|
+
|
|
4
|
+
# STATE OF AUTHENTICATION
|
|
5
|
+
|
|
6
|
+
def should_be_signed_in_as(&block)
|
|
7
|
+
warn "[DEPRECATION] should_be_signed_in_as cannot be used in functional tests anymore now that it depends on cookies, which are unavailable until the next request."
|
|
8
|
+
should "be signed in as #{block.bind(self).call}" do
|
|
9
|
+
user = block.bind(self).call
|
|
10
|
+
assert_not_nil user,
|
|
11
|
+
"please pass a User. try: should_be_signed_in_as { @user }"
|
|
12
|
+
assert_equal user, @controller.send(:current_user),
|
|
13
|
+
"#{user.inspect} is not the current_user, " <<
|
|
14
|
+
"which is #{@controller.send(:current_user).inspect}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def should_not_be_signed_in
|
|
19
|
+
warn "[DEPRECATION] should_not_be_signed_in is no longer a valid test since we now store a remember_token in cookies, not user_id in session"
|
|
20
|
+
should "not be signed in" do
|
|
21
|
+
assert_nil session[:user_id]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def should_deny_access_on(http_method, action, opts = {})
|
|
26
|
+
warn "[DEPRECATION] should_deny_access_on: use a setup & should_deny_access(:flash => ?)"
|
|
27
|
+
flash_message = opts.delete(:flash)
|
|
28
|
+
context "on #{http_method} to #{action}" do
|
|
29
|
+
setup do
|
|
30
|
+
send(http_method, action, opts)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
should_deny_access(:flash => flash_message)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def should_deny_access(opts = {})
|
|
38
|
+
if opts[:flash]
|
|
39
|
+
should_set_the_flash_to opts[:flash]
|
|
40
|
+
else
|
|
41
|
+
should_not_set_the_flash
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
should_redirect_to('sign in page') { sign_in_url }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# HTTP FLUENCY
|
|
48
|
+
|
|
49
|
+
def should_forbid(description, &block)
|
|
50
|
+
should "forbid #{description}" do
|
|
51
|
+
assert_raises ActionController::Forbidden do
|
|
52
|
+
instance_eval(&block)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# CONTEXTS
|
|
58
|
+
|
|
59
|
+
def signed_in_user_context(&blk)
|
|
60
|
+
warn "[DEPRECATION] signed_in_user_context: creates a Mystery Guest, causes Obscure Test"
|
|
61
|
+
context "A signed in user" do
|
|
62
|
+
setup do
|
|
63
|
+
@user = Factory(:user)
|
|
64
|
+
sign_in_as @user
|
|
65
|
+
end
|
|
66
|
+
merge_block(&blk)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def public_context(&blk)
|
|
71
|
+
warn "[DEPRECATION] public_context: common case is no-op. call sign_out otherwise"
|
|
72
|
+
context "The public" do
|
|
73
|
+
setup { sign_out }
|
|
74
|
+
merge_block(&blk)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# CREATING USERS
|
|
79
|
+
|
|
80
|
+
def should_create_user_successfully
|
|
81
|
+
warn "[DEPRECATION] should_create_user_successfully: not meant to be public, no longer used internally"
|
|
82
|
+
should_assign_to :user
|
|
83
|
+
should_change 'User.count', :by => 1
|
|
84
|
+
should_redirect_to_url_after_create
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# RENDERING
|
|
88
|
+
|
|
89
|
+
def should_render_nothing
|
|
90
|
+
should "render nothing" do
|
|
91
|
+
assert @response.body.blank?
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# REDIRECTS
|
|
96
|
+
|
|
97
|
+
def should_redirect_to_url_after_create
|
|
98
|
+
should_redirect_to("the post-create url") do
|
|
99
|
+
@controller.send(:url_after_create)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def should_redirect_to_url_after_update
|
|
104
|
+
should_redirect_to("the post-update url") do
|
|
105
|
+
@controller.send(:url_after_update)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def should_redirect_to_url_after_destroy
|
|
110
|
+
should_redirect_to("the post-destroy url") do
|
|
111
|
+
@controller.send(:url_after_destroy)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def should_redirect_to_url_already_confirmed
|
|
116
|
+
should_redirect_to("the already confirmed url") do
|
|
117
|
+
@controller.send(:url_already_confirmed)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# VALIDATIONS
|
|
122
|
+
|
|
123
|
+
def should_validate_confirmation_of(attribute, opts = {})
|
|
124
|
+
warn "[DEPRECATION] should_validate_confirmation_of: not meant to be public, no longer used internally"
|
|
125
|
+
raise ArgumentError if opts[:factory].nil?
|
|
126
|
+
|
|
127
|
+
context "on save" do
|
|
128
|
+
should_validate_confirmation_is_not_blank opts[:factory], attribute
|
|
129
|
+
should_validate_confirmation_is_not_bad opts[:factory], attribute
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def should_validate_confirmation_is_not_blank(factory, attribute, opts = {})
|
|
134
|
+
warn "[DEPRECATION] should_validate_confirmation_is_not_blank: not meant to be public, no longer used internally"
|
|
135
|
+
should "validate #{attribute}_confirmation is not blank" do
|
|
136
|
+
model = Factory.build(factory, blank_confirmation_options(attribute))
|
|
137
|
+
model.save
|
|
138
|
+
assert_confirmation_error(model, attribute,
|
|
139
|
+
"#{attribute}_confirmation cannot be blank")
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def should_validate_confirmation_is_not_bad(factory, attribute, opts = {})
|
|
144
|
+
warn "[DEPRECATION] should_validate_confirmation_is_not_bad: not meant to be public, no longer used internally"
|
|
145
|
+
should "validate #{attribute}_confirmation is different than #{attribute}" do
|
|
146
|
+
model = Factory.build(factory, bad_confirmation_options(attribute))
|
|
147
|
+
model.save
|
|
148
|
+
assert_confirmation_error(model, attribute,
|
|
149
|
+
"#{attribute}_confirmation cannot be different than #{attribute}")
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# FORMS
|
|
154
|
+
|
|
155
|
+
def should_display_a_password_update_form
|
|
156
|
+
warn "[DEPRECATION] should_display_a_password_update_form: not meant to be public, no longer used internally"
|
|
157
|
+
should "have a form for the user's token, password, and password confirm" do
|
|
158
|
+
update_path = ERB::Util.h(
|
|
159
|
+
user_password_path(@user, :token => @user.password_reset_token)
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
assert_select 'form[action=?]', update_path do
|
|
163
|
+
assert_select 'input[name=_method][value=?]', 'put'
|
|
164
|
+
assert_select 'input[name=?]', 'user[password]'
|
|
165
|
+
assert_select 'input[name=?]', 'user[password_confirmation]'
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def should_display_a_sign_up_form
|
|
171
|
+
warn "[DEPRECATION] should_display_a_sign_up_form: not meant to be public, no longer used internally"
|
|
172
|
+
should "display a form to sign up" do
|
|
173
|
+
assert_select "form[action=#{users_path}][method=post]",
|
|
174
|
+
true, "There must be a form to sign up" do
|
|
175
|
+
assert_select "input[type=text][name=?]",
|
|
176
|
+
"user[email]", true, "There must be an email field"
|
|
177
|
+
assert_select "input[type=password][name=?]",
|
|
178
|
+
"user[password]", true, "There must be a password field"
|
|
179
|
+
assert_select "input[type=password][name=?]",
|
|
180
|
+
"user[password_confirmation]", true, "There must be a password confirmation field"
|
|
181
|
+
assert_select "input[type=submit]", true,
|
|
182
|
+
"There must be a submit button"
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def should_display_a_sign_in_form
|
|
188
|
+
warn "[DEPRECATION] should_display_a_sign_in_form: not meant to be public, no longer used internally"
|
|
189
|
+
should 'display a "sign in" form' do
|
|
190
|
+
assert_select "form[action=#{session_path}][method=post]",
|
|
191
|
+
true, "There must be a form to sign in" do
|
|
192
|
+
assert_select "input[type=text][name=?]",
|
|
193
|
+
"session[email]", true, "There must be an email field"
|
|
194
|
+
assert_select "input[type=password][name=?]",
|
|
195
|
+
"session[password]", true, "There must be a password field"
|
|
196
|
+
assert_select "input[type=submit]", true,
|
|
197
|
+
"There must be a submit button"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
module BlueLightSpecial
|
|
205
|
+
module Shoulda
|
|
206
|
+
module Helpers
|
|
207
|
+
def sign_in_as(user)
|
|
208
|
+
@controller.current_user = user
|
|
209
|
+
return user
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def sign_in
|
|
213
|
+
sign_in_as Factory(:user)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def sign_out
|
|
217
|
+
@controller.current_user = nil
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def blank_confirmation_options(attribute)
|
|
221
|
+
warn "[DEPRECATION] blank_confirmation_options: not meant to be public, no longer used internally"
|
|
222
|
+
opts = { attribute => attribute.to_s }
|
|
223
|
+
opts.merge("#{attribute}_confirmation".to_sym => "")
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def bad_confirmation_options(attribute)
|
|
227
|
+
warn "[DEPRECATION] bad_confirmation_options: not meant to be public, no longer used internally"
|
|
228
|
+
opts = { attribute => attribute.to_s }
|
|
229
|
+
opts.merge("#{attribute}_confirmation".to_sym => "not_#{attribute}")
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def assert_confirmation_error(model, attribute, message = "confirmation error")
|
|
233
|
+
warn "[DEPRECATION] assert_confirmation_error: not meant to be public, no longer used internally"
|
|
234
|
+
assert model.errors.on(attribute).include?("doesn't match confirmation"),
|
|
235
|
+
message
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
class Test::Unit::TestCase
|
|
242
|
+
include BlueLightSpecial::Shoulda::Helpers
|
|
243
|
+
end
|
|
244
|
+
Test::Unit::TestCase.extend(BlueLightSpecial::Shoulda)
|