cops 0.2.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +113 -0
  3. data/Rakefile +95 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/blue_light_special/confirmations_controller.rb +76 -0
  6. data/app/controllers/blue_light_special/impersonations_controller.rb +44 -0
  7. data/app/controllers/blue_light_special/passwords_controller.rb +93 -0
  8. data/app/controllers/blue_light_special/sessions_controller.rb +76 -0
  9. data/app/controllers/blue_light_special/users_controller.rb +85 -0
  10. data/app/models/blue_light_special_mailer.rb +28 -0
  11. data/app/models/deliver_change_password_job.rb +19 -0
  12. data/app/models/deliver_welcome_job.rb +17 -0
  13. data/app/models/generic_mailer.rb +31 -0
  14. data/app/models/impersonation.rb +26 -0
  15. data/app/models/mimi_mailer.rb +30 -0
  16. data/app/views/generic_mailer/change_password.html.erb +9 -0
  17. data/app/views/generic_mailer/confirmation.html.erb +5 -0
  18. data/app/views/generic_mailer/welcome.html.erb +1 -0
  19. data/app/views/impersonations/index.html.erb +5 -0
  20. data/app/views/passwords/edit.html.erb +23 -0
  21. data/app/views/passwords/new.html.erb +15 -0
  22. data/app/views/sessions/new.html.erb +48 -0
  23. data/app/views/users/_form.html.erb +21 -0
  24. data/app/views/users/edit.html.erb +6 -0
  25. data/app/views/users/new.html.erb +6 -0
  26. data/app/views/users/show.html.erb +8 -0
  27. data/generators/blue_light_special/USAGE +1 -0
  28. data/generators/blue_light_special/blue_light_special_generator.rb +78 -0
  29. data/generators/blue_light_special/lib/insert_commands.rb +33 -0
  30. data/generators/blue_light_special/lib/rake_commands.rb +22 -0
  31. data/generators/blue_light_special/templates/README +20 -0
  32. data/generators/blue_light_special/templates/application.html.erb +50 -0
  33. data/generators/blue_light_special/templates/blue_light_special.rb +25 -0
  34. data/generators/blue_light_special/templates/blue_light_special.yml +45 -0
  35. data/generators/blue_light_special/templates/factories.rb +23 -0
  36. data/generators/blue_light_special/templates/migrations/create_users.rb +24 -0
  37. data/generators/blue_light_special/templates/migrations/update_users.rb +44 -0
  38. data/generators/blue_light_special/templates/style.css +31 -0
  39. data/generators/blue_light_special/templates/user.rb +3 -0
  40. data/generators/blue_light_special/templates/xd_receiver.html +10 -0
  41. data/generators/blue_light_special/templates/xd_receiver_ssl.html +10 -0
  42. data/generators/blue_light_special_admin/USAGE +1 -0
  43. data/generators/blue_light_special_admin/blue_light_special_admin_generator.rb +30 -0
  44. data/generators/blue_light_special_admin/lib/insert_commands.rb +33 -0
  45. data/generators/blue_light_special_admin/templates/README +16 -0
  46. data/generators/blue_light_special_admin/templates/app/controllers/admin/admin_controller.rb +14 -0
  47. data/generators/blue_light_special_admin/templates/app/controllers/admin/users_controller.rb +52 -0
  48. data/generators/blue_light_special_admin/templates/app/views/admin/users/_form.html.erb +25 -0
  49. data/generators/blue_light_special_admin/templates/app/views/admin/users/edit.html.erb +6 -0
  50. data/generators/blue_light_special_admin/templates/app/views/admin/users/index.html.erb +7 -0
  51. data/generators/blue_light_special_admin/templates/app/views/admin/users/new.html.erb +6 -0
  52. data/generators/blue_light_special_admin/templates/app/views/admin/users/show.html.erb +10 -0
  53. data/generators/blue_light_special_admin/templates/test/integration/admin/users_test.rb +201 -0
  54. data/generators/blue_light_special_tests/USAGE +1 -0
  55. data/generators/blue_light_special_tests/blue_light_special_tests_generator.rb +21 -0
  56. data/generators/blue_light_special_tests/templates/README +58 -0
  57. data/generators/blue_light_special_tests/templates/test/integration/edit_profile_test.rb +35 -0
  58. data/generators/blue_light_special_tests/templates/test/integration/facebook_test.rb +61 -0
  59. data/generators/blue_light_special_tests/templates/test/integration/impersonation_test.rb +39 -0
  60. data/generators/blue_light_special_tests/templates/test/integration/password_reset_test.rb +128 -0
  61. data/generators/blue_light_special_tests/templates/test/integration/sign_in_test.rb +66 -0
  62. data/generators/blue_light_special_tests/templates/test/integration/sign_out_test.rb +28 -0
  63. data/generators/blue_light_special_tests/templates/test/integration/sign_up_test.rb +47 -0
  64. data/lib/blue_light_special/authentication.rb +138 -0
  65. data/lib/blue_light_special/configuration.rb +34 -0
  66. data/lib/blue_light_special/extensions/errors.rb +6 -0
  67. data/lib/blue_light_special/extensions/rescue.rb +5 -0
  68. data/lib/blue_light_special/routes.rb +62 -0
  69. data/lib/blue_light_special/user.rb +279 -0
  70. data/lib/blue_light_special.rb +7 -0
  71. data/rails/init.rb +4 -0
  72. data/shoulda_macros/blue_light_special.rb +244 -0
  73. data/test/controllers/passwords_controller_test.rb +184 -0
  74. data/test/controllers/sessions_controller_test.rb +129 -0
  75. data/test/controllers/users_controller_test.rb +57 -0
  76. data/test/models/blue_light_special_mailer_test.rb +52 -0
  77. data/test/models/impersonation_test.rb +25 -0
  78. data/test/models/user_test.rb +213 -0
  79. data/test/rails_root/app/controllers/accounts_controller.rb +10 -0
  80. data/test/rails_root/app/controllers/application_controller.rb +6 -0
  81. data/test/rails_root/app/helpers/application_helper.rb +5 -0
  82. data/test/rails_root/app/helpers/confirmations_helper.rb +2 -0
  83. data/test/rails_root/app/helpers/passwords_helper.rb +2 -0
  84. data/test/rails_root/config/boot.rb +110 -0
  85. data/test/rails_root/config/environment.rb +22 -0
  86. data/test/rails_root/config/environments/development.rb +19 -0
  87. data/test/rails_root/config/environments/production.rb +1 -0
  88. data/test/rails_root/config/environments/test.rb +37 -0
  89. data/test/rails_root/config/initializers/inflections.rb +10 -0
  90. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  91. data/test/rails_root/config/initializers/requires.rb +13 -0
  92. data/test/rails_root/config/initializers/time_formats.rb +4 -0
  93. data/test/rails_root/config/routes.rb +9 -0
  94. data/test/rails_root/public/dispatch.rb +10 -0
  95. data/test/rails_root/script/create_project.rb +52 -0
  96. data/test/rails_root/test/functional/accounts_controller_test.rb +23 -0
  97. data/test/test_helper.rb +21 -0
  98. 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
@@ -0,0 +1,7 @@
1
+ require 'blue_light_special/extensions/errors'
2
+ require 'blue_light_special/extensions/rescue'
3
+
4
+ require 'blue_light_special/configuration'
5
+ require 'blue_light_special/routes'
6
+ require 'blue_light_special/authentication'
7
+ require 'blue_light_special/user'
data/rails/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'delayed_job'
2
+ require 'mini_fb'
3
+ require 'mad_mimi_mailer'
4
+ require 'blue_light_special'
@@ -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)