thoughtbot-clearance 0.5.2 → 0.5.3
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/CHANGELOG.textile +12 -0
- data/README.textile +4 -4
- data/Rakefile +10 -9
- data/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb +2 -2
- data/lib/clearance/app/controllers/application_controller.rb +1 -1
- data/lib/clearance/app/controllers/confirmations_controller.rb +10 -10
- data/lib/clearance/app/controllers/sessions_controller.rb +2 -2
- data/lib/clearance/app/controllers/users_controller.rb +5 -5
- data/lib/clearance/app/models/clearance_mailer.rb +2 -2
- data/lib/clearance/test/functional/confirmations_controller_test.rb +7 -7
- data/lib/clearance/test/functional/passwords_controller_test.rb +31 -31
- data/lib/clearance/test/functional/sessions_controller_test.rb +141 -146
- data/lib/clearance/test/functional/users_controller_test.rb +9 -9
- data/lib/clearance/test/unit/clearance_mailer_test.rb +5 -5
- data/lib/clearance/test/unit/user_test.rb +8 -8
- data/shoulda_macros/clearance.rb +62 -56
- metadata +3 -2
data/CHANGELOG.textile
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
h1. 0.5.3 (3/5/2009)
|
2
|
+
|
3
|
+
* Clearance now works with (and requires) Shoulda 2.10.0. (Mark Cornick, Joe
|
4
|
+
Ferris, Dan Croak)
|
5
|
+
* Prefer flat over nested contexts in sessions_controller_test. (Joe Ferris,
|
6
|
+
Dan Croak)
|
7
|
+
|
8
|
+
h1. 0.5.2 (3/2/2009)
|
9
|
+
|
10
|
+
* Fixed last remaining errors in Rails 2.3 tests. Now fully compatible. (Joe
|
11
|
+
Ferris, Dan Croak)
|
12
|
+
|
1
13
|
h1. 0.5.1 (2/27/2009)
|
2
14
|
|
3
15
|
* [#46] A user with unconfirmed email who resets password now confirms email.
|
data/README.textile
CHANGED
@@ -19,18 +19,18 @@ In config/environment.rb:
|
|
19
19
|
config.gem "thoughtbot-clearance",
|
20
20
|
:lib => 'clearance',
|
21
21
|
:source => 'http://gems.github.com',
|
22
|
-
:version => '
|
22
|
+
:version => '0.5.3'
|
23
23
|
|
24
24
|
In config/environments/test.rb:
|
25
25
|
|
26
26
|
config.gem 'thoughtbot-shoulda',
|
27
27
|
:lib => 'shoulda',
|
28
28
|
:source => "http://gems.github.com",
|
29
|
-
:version => '
|
29
|
+
:version => '2.10.0'
|
30
30
|
config.gem 'thoughtbot-factory_girl',
|
31
31
|
:lib => 'factory_girl',
|
32
32
|
:source => "http://gems.github.com",
|
33
|
-
:version => '
|
33
|
+
:version => '1.2.0'
|
34
34
|
|
35
35
|
Then:
|
36
36
|
|
@@ -73,4 +73,4 @@ h2. Authors
|
|
73
73
|
|
74
74
|
Clearance was extracted out of "Hoptoad":http://hoptoadapp.com. We merged the authentication code from two of thoughtbot's client's Rails apps. The following people have made significant contributions, suggestions, and generally improved the library. Thank you!
|
75
75
|
|
76
|
-
Dan Croak, Mike Burns, Jason Morrison, Joe Ferris, Eugene Bolshakov, Josh Nichols, Mike Breen, Marcel Görner, Bence Nagy, Ben Mabey, Eloy Duran, Tim Pope, &
|
76
|
+
Dan Croak, Mike Burns, Jason Morrison, Joe Ferris, Eugene Bolshakov, Josh Nichols, Mike Breen, Marcel Görner, Bence Nagy, Ben Mabey, Eloy Duran, Tim Pope, Mihai Anca, & Mark Cornick.
|
data/Rakefile
CHANGED
@@ -5,17 +5,18 @@ require 'cucumber/rake/task'
|
|
5
5
|
test_files_pattern = 'test/rails_root/test/{unit,functional,other}/**/*_test.rb'
|
6
6
|
|
7
7
|
namespace :test do
|
8
|
-
Rake::TestTask.new(:all => ['generator:cleanup',
|
8
|
+
Rake::TestTask.new(:all => ['generator:cleanup',
|
9
|
+
'generator:generate']) do |task|
|
9
10
|
task.libs << 'lib'
|
10
11
|
task.libs << File.join(File.dirname(__FILE__), "test/rails_root/test")
|
11
12
|
task.pattern = test_files_pattern
|
12
13
|
task.verbose = false
|
13
14
|
end
|
14
|
-
|
15
|
+
|
15
16
|
Cucumber::Rake::Task.new(:features) do |t|
|
16
17
|
t.cucumber_opts = "--format pretty"
|
17
18
|
t.feature_pattern = 'test/rails_root/features/*.feature'
|
18
|
-
end
|
19
|
+
end
|
19
20
|
end
|
20
21
|
|
21
22
|
generators = %w(clearance clearance_features)
|
@@ -27,17 +28,17 @@ namespace :generator do
|
|
27
28
|
FileList["generators/#{generator}/templates/**/*.*"].each do |each|
|
28
29
|
file = "test/rails_root/#{each.gsub("generators/#{generator}/templates/",'')}"
|
29
30
|
File.delete(file) if File.exists?(file)
|
30
|
-
end
|
31
|
+
end
|
31
32
|
end
|
32
|
-
|
33
|
+
|
33
34
|
FileList["test/rails_root/db/**/*"].each do |each|
|
34
35
|
FileUtils.rm_rf(each)
|
35
36
|
end
|
36
37
|
FileUtils.rm_rf("test/rails_root/vendor/plugins/clearance")
|
37
38
|
system "mkdir -p test/rails_root/vendor/plugins/clearance"
|
38
|
-
system "cp -R generators test/rails_root/vendor/plugins/clearance"
|
39
|
+
system "cp -R generators test/rails_root/vendor/plugins/clearance"
|
39
40
|
end
|
40
|
-
|
41
|
+
|
41
42
|
desc "Run the generator on the tests"
|
42
43
|
task :generate do
|
43
44
|
generators.each do |generator|
|
@@ -51,7 +52,7 @@ task :default => ['test:all', 'test:features']
|
|
51
52
|
|
52
53
|
gem_spec = Gem::Specification.new do |gem_spec|
|
53
54
|
gem_spec.name = "clearance"
|
54
|
-
gem_spec.version = "0.5.
|
55
|
+
gem_spec.version = "0.5.3"
|
55
56
|
gem_spec.summary = "Rails authentication for developers who write tests."
|
56
57
|
gem_spec.email = "support@thoughtbot.com"
|
57
58
|
gem_spec.homepage = "http://github.com/thoughtbot/clearance"
|
@@ -60,7 +61,7 @@ gem_spec = Gem::Specification.new do |gem_spec|
|
|
60
61
|
"Jason Morrison", "Eugene Bolshakov", "Josh Nichols",
|
61
62
|
"Mike Breen", "Joe Ferris", "Bence Nagy",
|
62
63
|
"Marcel Görner", "Ben Mabey", "Tim Pope",
|
63
|
-
"Eloy Duran", "Mihai Anca"]
|
64
|
+
"Eloy Duran", "Mihai Anca", "Mark Cornick"]
|
64
65
|
gem_spec.files = FileList["[A-Z]*", "{generators,lib,shoulda_macros,rails}/**/*"]
|
65
66
|
end
|
66
67
|
|
@@ -89,7 +89,7 @@ When /^I sign in( with "remember me")? as "(.*)\/(.*)"$/ do |remember, email, pa
|
|
89
89
|
end
|
90
90
|
|
91
91
|
When /^I sign out$/ do
|
92
|
-
visit '/session', :delete
|
92
|
+
visit '/session', :delete
|
93
93
|
end
|
94
94
|
|
95
95
|
When /^I request password reset link to be sent to "(.*)"$/ do |email|
|
@@ -101,7 +101,7 @@ end
|
|
101
101
|
When /^I update my password with "(.*)\/(.*)"$/ do |password, confirmation|
|
102
102
|
And %{I fill in "Choose password" with "#{password}"}
|
103
103
|
And %{I fill in "Confirm password" with "#{confirmation}"}
|
104
|
-
And %{I press "Save this password"}
|
104
|
+
And %{I press "Save this password"}
|
105
105
|
end
|
106
106
|
|
107
107
|
When /^I return next time$/ do
|
@@ -74,7 +74,7 @@ module Clearance
|
|
74
74
|
def deny_access(flash_message = nil, opts = {})
|
75
75
|
store_location
|
76
76
|
flash[:failure] = flash_message if flash_message
|
77
|
-
render :template => "/sessions/new", :status => :unauthorized
|
77
|
+
render :template => "/sessions/new", :status => :unauthorized
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -2,19 +2,19 @@ module Clearance
|
|
2
2
|
module App
|
3
3
|
module Controllers
|
4
4
|
module ConfirmationsController
|
5
|
-
|
5
|
+
|
6
6
|
def self.included(controller)
|
7
7
|
controller.send(:include, Actions)
|
8
8
|
controller.send(:include, PrivateMethods)
|
9
|
-
|
9
|
+
|
10
10
|
controller.class_eval do
|
11
11
|
before_filter :forbid_confirmed_user, :only => :new
|
12
12
|
before_filter :forbid_missing_token, :only => :new
|
13
13
|
before_filter :forbid_non_existant_user, :only => :new
|
14
|
-
filter_parameter_logging :token
|
14
|
+
filter_parameter_logging :token
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
module Actions
|
19
19
|
def new
|
20
20
|
create
|
@@ -23,29 +23,29 @@ module Clearance
|
|
23
23
|
def create
|
24
24
|
@user = User.find_by_id_and_token(params[:user_id], params[:token])
|
25
25
|
@user.confirm_email!
|
26
|
-
|
26
|
+
|
27
27
|
sign_user_in(@user)
|
28
28
|
flash[:success] = "Confirmed email and signed in."
|
29
29
|
redirect_to url_after_create
|
30
30
|
end
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
module PrivateMethods
|
34
34
|
private
|
35
|
-
|
35
|
+
|
36
36
|
def forbid_confirmed_user
|
37
37
|
user = User.find_by_id(params[:user_id])
|
38
38
|
if user && user.email_confirmed?
|
39
39
|
raise ActionController::Forbidden, "confirmed user"
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def forbid_missing_token
|
44
44
|
if params[:token].blank?
|
45
45
|
raise ActionController::Forbidden, "missing token"
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def forbid_non_existant_user
|
50
50
|
unless User.find_by_id_and_token(params[:user_id], params[:token])
|
51
51
|
raise ActionController::Forbidden, "non-existant user"
|
@@ -56,7 +56,7 @@ module Clearance
|
|
56
56
|
root_url
|
57
57
|
end
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -15,7 +15,7 @@ module Clearance
|
|
15
15
|
|
16
16
|
module Actions
|
17
17
|
def create
|
18
|
-
@user = User.authenticate(params[:session][:email],
|
18
|
+
@user = User.authenticate(params[:session][:email],
|
19
19
|
params[:session][:password])
|
20
20
|
if @user.nil?
|
21
21
|
flash.now[:notice] = "Bad email or password."
|
@@ -50,7 +50,7 @@ module Clearance
|
|
50
50
|
|
51
51
|
def remember(user)
|
52
52
|
user.remember_me!
|
53
|
-
cookies[:remember_token] = { :value => user.token,
|
53
|
+
cookies[:remember_token] = { :value => user.token,
|
54
54
|
:expires => user.token_expires_at }
|
55
55
|
end
|
56
56
|
|
@@ -6,13 +6,13 @@ module Clearance
|
|
6
6
|
def self.included(controller)
|
7
7
|
controller.send(:include, Actions)
|
8
8
|
controller.send(:include, PrivateMethods)
|
9
|
-
|
9
|
+
|
10
10
|
controller.class_eval do
|
11
11
|
before_filter :redirect_to_root, :only => [:new, :create], :if => :signed_in?
|
12
|
-
filter_parameter_logging :password
|
12
|
+
filter_parameter_logging :password
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
module Actions
|
17
17
|
def new
|
18
18
|
@user = User.new(params[:user])
|
@@ -30,10 +30,10 @@ module Clearance
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
module PrivateMethods
|
35
35
|
private
|
36
|
-
|
36
|
+
|
37
37
|
def url_after_create
|
38
38
|
new_session_url
|
39
39
|
end
|
@@ -2,7 +2,7 @@ module Clearance
|
|
2
2
|
module App
|
3
3
|
module Models
|
4
4
|
module ClearanceMailer
|
5
|
-
|
5
|
+
|
6
6
|
def change_password(user)
|
7
7
|
from DO_NOT_REPLY
|
8
8
|
recipients user.email
|
@@ -16,7 +16,7 @@ module Clearance
|
|
16
16
|
subject "Account confirmation"
|
17
17
|
body :user => user
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -10,12 +10,12 @@ module Clearance
|
|
10
10
|
|
11
11
|
context "a user whose email has not been confirmed" do
|
12
12
|
setup { @user = Factory(:user) }
|
13
|
-
|
13
|
+
|
14
14
|
should "have a token" do
|
15
15
|
assert_not_nil @user.token
|
16
16
|
assert_not_equal "", @user.token
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
context "on GET to #new with correct id and token" do
|
20
20
|
setup do
|
21
21
|
get :new, :user_id => @user.to_param, :token => @user.token
|
@@ -28,20 +28,20 @@ module Clearance
|
|
28
28
|
end
|
29
29
|
|
30
30
|
context "with an incorrect token" do
|
31
|
-
setup do
|
31
|
+
setup do
|
32
32
|
@bad_token = "bad token"
|
33
33
|
assert_not_equal @bad_token, @user.token
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
should_forbid "on GET to #new with incorrect token" do
|
37
37
|
get :new, :user_id => @user.to_param, :token => @bad_token
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
should_forbid "on GET to #new with blank token" do
|
42
42
|
get :new, :user_id => @user.to_param, :token => ""
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
should_forbid "on GET to #new with no token" do
|
46
46
|
get :new, :user_id => @user.to_param
|
47
47
|
end
|
@@ -57,7 +57,7 @@ module Clearance
|
|
57
57
|
|
58
58
|
context "no users" do
|
59
59
|
setup { assert_equal 0, User.count }
|
60
|
-
|
60
|
+
|
61
61
|
should_forbid "on GET to #new with nonexistent id and token" do
|
62
62
|
get :new, :user_id => '123', :token => '123'
|
63
63
|
end
|
@@ -6,7 +6,7 @@ module Clearance
|
|
6
6
|
def self.included(controller_test)
|
7
7
|
controller_test.class_eval do
|
8
8
|
|
9
|
-
should_route :get, '/users/1/password/edit',
|
9
|
+
should_route :get, '/users/1/password/edit',
|
10
10
|
:action => 'edit', :user_id => '1'
|
11
11
|
|
12
12
|
context "a signed up user" do
|
@@ -27,9 +27,9 @@ module Clearance
|
|
27
27
|
ActionMailer::Base.deliveries.clear
|
28
28
|
post :create, :password => { :email => @user.email }
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
should "generate a token for the change your password email" do
|
32
|
-
assert_not_nil @user.reload.token
|
32
|
+
assert_not_nil @user.reload.token
|
33
33
|
end
|
34
34
|
|
35
35
|
should "send the change your password email" do
|
@@ -37,7 +37,7 @@ module Clearance
|
|
37
37
|
email.subject =~ /change your password/i
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
should_set_the_flash_to /password/i
|
42
42
|
should_redirect_to_url_after_create
|
43
43
|
end
|
@@ -51,15 +51,15 @@ module Clearance
|
|
51
51
|
|
52
52
|
post :create, :password => { :email => email }
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
should "not generate a token for the change your password email" do
|
56
|
-
assert_equal @user.token, @user.reload.token
|
57
|
-
end
|
56
|
+
assert_equal @user.token, @user.reload.token
|
57
|
+
end
|
58
58
|
|
59
59
|
should "not send a password reminder email" do
|
60
60
|
assert ActionMailer::Base.deliveries.empty?
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
should "set a :notice flash" do
|
64
64
|
assert_not_nil flash.now[:notice]
|
65
65
|
end
|
@@ -68,41 +68,41 @@ module Clearance
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
context "a signed up user and forgotten password" do
|
73
73
|
setup do
|
74
74
|
@user = Factory(:user)
|
75
75
|
@user.forgot_password!
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
context "on GET to #edit with correct id and token" do
|
79
79
|
setup do
|
80
80
|
get :edit, :user_id => @user.to_param, :token => @user.token
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
should "find the user" do
|
84
84
|
assert_equal @user, assigns(:user)
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
should_respond_with :success
|
88
88
|
should_render_template "edit"
|
89
89
|
should_display_a_password_update_form
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
should_forbid "on GET to #edit with correct id but blank token" do
|
93
93
|
get :edit, :user_id => @user.to_param, :token => ""
|
94
94
|
end
|
95
|
-
|
95
|
+
|
96
96
|
should_forbid "on GET to #edit with correct id but no token" do
|
97
97
|
get :edit, :user_id => @user.to_param
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
context "on PUT to #update with matching password and password confirmation" do
|
101
101
|
setup do
|
102
102
|
new_password = "new_password"
|
103
103
|
@encrypted_new_password = @user.encrypt(new_password)
|
104
104
|
assert_not_equal @encrypted_new_password, @user.encrypted_password
|
105
|
-
|
105
|
+
|
106
106
|
put(:update,
|
107
107
|
:user_id => @user,
|
108
108
|
:token => @user.token,
|
@@ -112,24 +112,24 @@ module Clearance
|
|
112
112
|
})
|
113
113
|
@user.reload
|
114
114
|
end
|
115
|
-
|
115
|
+
|
116
116
|
should "update password" do
|
117
117
|
assert_equal @encrypted_new_password, @user.encrypted_password
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
should "clear token" do
|
121
121
|
assert_nil @user.token
|
122
|
-
end
|
123
|
-
|
122
|
+
end
|
123
|
+
|
124
124
|
should_be_signed_in_as { @user }
|
125
125
|
should_redirect_to_url_after_update
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
context "on PUT to #update with password but blank password confirmation" do
|
129
129
|
setup do
|
130
130
|
new_password = "new_password"
|
131
131
|
@encrypted_new_password = @user.encrypt(new_password)
|
132
|
-
|
132
|
+
|
133
133
|
put(:update,
|
134
134
|
:user_id => @user.to_param,
|
135
135
|
:token => @user.token,
|
@@ -139,27 +139,27 @@ module Clearance
|
|
139
139
|
})
|
140
140
|
@user.reload
|
141
141
|
end
|
142
|
-
|
142
|
+
|
143
143
|
should "not update password" do
|
144
144
|
assert_not_equal @encrypted_new_password, @user.encrypted_password
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
should "not clear token" do
|
148
148
|
assert_not_nil @user.token
|
149
|
-
end
|
150
|
-
|
149
|
+
end
|
150
|
+
|
151
151
|
should_not_be_signed_in
|
152
152
|
should_respond_with :success
|
153
153
|
should_render_template :edit
|
154
|
-
|
155
|
-
should_display_a_password_update_form
|
154
|
+
|
155
|
+
should_display_a_password_update_form
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
should_forbid "on PUT to #update with id but no token" do
|
159
159
|
put :update, :user_id => @user.to_param, :token => ""
|
160
160
|
end
|
161
161
|
end
|
162
|
-
|
162
|
+
|
163
163
|
context "given two users and user one signs in" do
|
164
164
|
setup do
|
165
165
|
@user_one = Factory(:user)
|
@@ -170,7 +170,7 @@ module Clearance
|
|
170
170
|
should_forbid "when user one tries to change user two's password on GET with no token" do
|
171
171
|
get :edit, :user_id => @user_two.to_param
|
172
172
|
end
|
173
|
-
end
|
173
|
+
end
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
@@ -17,170 +17,165 @@ module Clearance
|
|
17
17
|
should_display_a_sign_in_form
|
18
18
|
end
|
19
19
|
|
20
|
-
context "
|
21
|
-
setup
|
20
|
+
context "a POST to #create with unconfirmed credentials" do
|
21
|
+
setup do
|
22
|
+
@user = Factory(:user)
|
23
|
+
ActionMailer::Base.deliveries.clear
|
24
|
+
post :create, :session => {
|
25
|
+
:email => @user.email,
|
26
|
+
:password => @user.password }
|
27
|
+
end
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
ActionMailer::Base.deliveries.clear
|
26
|
-
post :create, :session => {
|
27
|
-
:email => @user.email,
|
28
|
-
:password => @user.password }
|
29
|
-
end
|
29
|
+
should_deny_access(:flash => /User has not confirmed email. Confirmation email will be resent./i)
|
30
|
+
should_respond_with :unauthorized
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
should "send the confirmation email" do
|
33
|
+
assert_not_nil email = ActionMailer::Base.deliveries[0]
|
34
|
+
assert_match /account confirmation/i, email.subject
|
35
|
+
end
|
36
|
+
end
|
33
37
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
context "a POST to #create with good credentials" do
|
39
|
+
setup do
|
40
|
+
@user = Factory(:email_confirmed_user)
|
41
|
+
post :create, :session => {
|
42
|
+
:email => @user.email,
|
43
|
+
:password => @user.password }
|
38
44
|
end
|
45
|
+
|
46
|
+
should_set_the_flash_to /success/i
|
47
|
+
should_redirect_to_url_after_create
|
48
|
+
should_be_signed_in_as { @user }
|
39
49
|
end
|
40
50
|
|
41
|
-
context "
|
51
|
+
context "a POST to #create with good credentials and remember me" do
|
42
52
|
setup do
|
43
|
-
@user = Factory(:
|
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
|
-
end
|
110
|
-
|
111
|
-
should 'not set the remember me token in users table' do
|
112
|
-
assert_nil @user.reload.token
|
113
|
-
assert_nil @user.reload.token_expires_at
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context "a POST to #create with good credentials and A URL to return back" do
|
118
|
-
context "in the session" do
|
119
|
-
setup do
|
120
|
-
@request.session[:return_to] = '/url_in_the_session'
|
121
|
-
post :create, :session => {
|
122
|
-
:email => @user.email,
|
123
|
-
:password => @user.password }
|
124
|
-
end
|
125
|
-
|
126
|
-
should_redirect_to "'/url_in_the_session'"
|
127
|
-
end
|
128
|
-
|
129
|
-
context "in the request" do
|
130
|
-
setup do
|
131
|
-
post :create, :session => {
|
132
|
-
:email => @user.email,
|
133
|
-
:password => @user.password },
|
134
|
-
:return_to => '/url_in_the_request'
|
135
|
-
end
|
136
|
-
|
137
|
-
should_redirect_to "'/url_in_the_request'"
|
138
|
-
end
|
139
|
-
|
140
|
-
context "in the request and in the session" do
|
141
|
-
setup do
|
142
|
-
@request.session[:return_to] = '/url_in_the_session'
|
143
|
-
post :create, :session => {
|
144
|
-
:email => @user.email,
|
145
|
-
:password => @user.password },
|
146
|
-
:return_to => '/url_in_the_request'
|
147
|
-
end
|
148
|
-
|
149
|
-
should_redirect_to "'/url_in_the_session'"
|
150
|
-
end
|
53
|
+
@user = Factory(:email_confirmed_user)
|
54
|
+
post :create, :session => {
|
55
|
+
:email => @user.email,
|
56
|
+
:password => @user.password,
|
57
|
+
:remember_me => '1' }
|
58
|
+
end
|
59
|
+
|
60
|
+
should_set_the_flash_to /success/i
|
61
|
+
should_redirect_to_url_after_create
|
62
|
+
should_be_signed_in_as { @user }
|
63
|
+
|
64
|
+
should 'set the cookie' do
|
65
|
+
assert ! cookies['remember_token'].empty?
|
66
|
+
end
|
67
|
+
|
68
|
+
should 'set the token in users table' do
|
69
|
+
assert_not_nil @user.reload.token
|
70
|
+
assert_not_nil @user.reload.token_expires_at
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "a POST to #create with good credentials and a session return url" do
|
75
|
+
setup do
|
76
|
+
@user = Factory(:email_confirmed_user)
|
77
|
+
@return_url = '/url_in_the_session'
|
78
|
+
@request.session[:return_to] = @return_url
|
79
|
+
post :create, :session => {
|
80
|
+
:email => @user.email,
|
81
|
+
:password => @user.password }
|
82
|
+
end
|
83
|
+
|
84
|
+
should_redirect_to("the return URL") { @return_url }
|
85
|
+
end
|
86
|
+
|
87
|
+
context "a POST to #create with good credentials and a request return url" do
|
88
|
+
setup do
|
89
|
+
@user = Factory(:email_confirmed_user)
|
90
|
+
@return_url = '/url_in_the_request'
|
91
|
+
post :create, :session => {
|
92
|
+
:email => @user.email,
|
93
|
+
:password => @user.password },
|
94
|
+
:return_to => @return_url
|
95
|
+
end
|
96
|
+
|
97
|
+
should_redirect_to("the return URL") { @return_url }
|
98
|
+
end
|
99
|
+
|
100
|
+
context "a POST to #create with good credentials and a session return url and request return url" do
|
101
|
+
setup do
|
102
|
+
@user = Factory(:email_confirmed_user)
|
103
|
+
@return_url = '/url_in_the_session'
|
104
|
+
@request.session[:return_to] = @return_url
|
105
|
+
post :create, :session => {
|
106
|
+
:email => @user.email,
|
107
|
+
:password => @user.password },
|
108
|
+
:return_to => '/url_in_the_request'
|
109
|
+
end
|
110
|
+
|
111
|
+
should_redirect_to("the return URL") { @return_url }
|
112
|
+
end
|
113
|
+
|
114
|
+
context "a POST to #create with bad credentials" do
|
115
|
+
setup do
|
116
|
+
post :create, :session => {
|
117
|
+
:email => 'bad.email@example.com',
|
118
|
+
:password => "bad value" }
|
151
119
|
end
|
120
|
+
|
121
|
+
should_set_the_flash_to /bad/i
|
122
|
+
should_respond_with :unauthorized
|
123
|
+
should_render_template :new
|
124
|
+
should_not_be_signed_in
|
152
125
|
end
|
153
126
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
127
|
+
context "a POST to #create with bad credentials and remember me" do
|
128
|
+
setup do
|
129
|
+
post :create, :session => {
|
130
|
+
:email => 'bad.email@example.com',
|
131
|
+
:password => "bad value",
|
132
|
+
:remember_me => '1' }
|
133
|
+
end
|
134
|
+
|
135
|
+
should_set_the_flash_to /bad/i
|
136
|
+
should_respond_with :unauthorized
|
137
|
+
should_render_template :new
|
138
|
+
should_not_be_signed_in
|
139
|
+
|
140
|
+
should 'not create the cookie' do
|
141
|
+
assert_nil cookies['remember_token']
|
158
142
|
end
|
159
143
|
end
|
160
144
|
|
161
|
-
|
162
|
-
|
163
|
-
|
145
|
+
context "signing out given a signed out user" do
|
146
|
+
setup do
|
147
|
+
sign_out
|
148
|
+
delete :destroy
|
149
|
+
end
|
150
|
+
should_redirect_to_url_after_destroy
|
151
|
+
end
|
164
152
|
|
165
|
-
|
166
|
-
|
153
|
+
context "a DELETE to #destroy without a cookie" do
|
154
|
+
setup do
|
155
|
+
sign_in_as
|
156
|
+
delete :destroy
|
167
157
|
end
|
168
158
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
159
|
+
should_set_the_flash_to(/signed out/i)
|
160
|
+
should_redirect_to_url_after_destroy
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'a DELETE to #destroy with a cookie' do
|
164
|
+
setup do
|
165
|
+
@user = Factory(:email_confirmed_user)
|
166
|
+
cookies['remember_token'] = CGI::Cookie.new('token', 'value')
|
167
|
+
sign_in_as @user
|
168
|
+
delete :destroy
|
169
|
+
end
|
174
170
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
171
|
+
should 'delete the cookie' do
|
172
|
+
assert cookies['remember_token'].nil? || # Rails >= 2.3
|
173
|
+
cookies['remember_token'].empty? # Rails < 2.3
|
174
|
+
end
|
179
175
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end
|
176
|
+
should 'delete the remember me token in users table' do
|
177
|
+
assert_nil @user.reload.token
|
178
|
+
assert_nil @user.reload.token_expires_at
|
184
179
|
end
|
185
180
|
end
|
186
181
|
|
@@ -5,20 +5,20 @@ module Clearance
|
|
5
5
|
|
6
6
|
def self.included(controller_test)
|
7
7
|
controller_test.class_eval do
|
8
|
-
|
8
|
+
|
9
9
|
should_filter_params :password
|
10
|
-
|
10
|
+
|
11
11
|
public_context do
|
12
12
|
context "When getting new User view" do
|
13
13
|
setup { get :new }
|
14
|
-
|
14
|
+
|
15
15
|
should_respond_with :success
|
16
16
|
should_render_template :new
|
17
17
|
should_not_set_the_flash
|
18
|
-
|
18
|
+
|
19
19
|
should_display_a_sign_up_form
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
context "Given email parameter when getting new User view" do
|
23
23
|
setup do
|
24
24
|
@email = "a@example.com"
|
@@ -35,7 +35,7 @@ module Clearance
|
|
35
35
|
user_attributes = Factory.attributes_for(:user)
|
36
36
|
post :create, :user => user_attributes
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
should_create_user_successfully
|
40
40
|
end
|
41
41
|
end
|
@@ -43,15 +43,15 @@ module Clearance
|
|
43
43
|
signed_in_user_context do
|
44
44
|
context "GET to new" do
|
45
45
|
setup { get :new }
|
46
|
-
should_redirect_to "root_url
|
46
|
+
should_redirect_to("the home page") { root_url }
|
47
47
|
end
|
48
48
|
|
49
49
|
context "POST to create" do
|
50
50
|
setup { post :create, :user => {} }
|
51
|
-
should_redirect_to "root_url
|
51
|
+
should_redirect_to("the home page") { root_url }
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -2,10 +2,10 @@ module Clearance
|
|
2
2
|
module Test
|
3
3
|
module Unit
|
4
4
|
module ClearanceMailerTest
|
5
|
-
|
5
|
+
|
6
6
|
def self.included(mailer_test)
|
7
7
|
mailer_test.class_eval do
|
8
|
-
|
8
|
+
|
9
9
|
context "A change password email" do
|
10
10
|
setup do
|
11
11
|
@user = Factory(:user)
|
@@ -30,7 +30,7 @@ module Clearance
|
|
30
30
|
assert_match /Change your password/, @email.subject
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
context "A confirmation email" do
|
35
35
|
setup do
|
36
36
|
@user = Factory(:user)
|
@@ -55,11 +55,11 @@ module Clearance
|
|
55
55
|
assert_match regexp, @email.body
|
56
56
|
end
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
62
|
end
|
63
|
-
end
|
63
|
+
end
|
64
64
|
end
|
65
65
|
end
|
@@ -6,8 +6,8 @@ module Clearance
|
|
6
6
|
def self.included(unit_test)
|
7
7
|
unit_test.class_eval do
|
8
8
|
|
9
|
-
should_not_allow_mass_assignment_of :email_confirmed,
|
10
|
-
:salt, :encrypted_password,
|
9
|
+
should_not_allow_mass_assignment_of :email_confirmed,
|
10
|
+
:salt, :encrypted_password,
|
11
11
|
:token, :token_expires_at
|
12
12
|
|
13
13
|
# signing up
|
@@ -19,9 +19,9 @@ module Clearance
|
|
19
19
|
should_not_allow_values_for :email, "example.com"
|
20
20
|
|
21
21
|
should "require password confirmation on create" do
|
22
|
-
user = Factory.build(:user, :password => 'blah',
|
22
|
+
user = Factory.build(:user, :password => 'blah',
|
23
23
|
:password_confirmation => 'boogidy')
|
24
|
-
assert !user.save
|
24
|
+
assert ! user.save
|
25
25
|
assert user.errors.on(:password)
|
26
26
|
end
|
27
27
|
|
@@ -121,13 +121,13 @@ module Clearance
|
|
121
121
|
end
|
122
122
|
|
123
123
|
should "remember user when token expires in the future" do
|
124
|
-
@user.update_attribute :token_expires_at,
|
124
|
+
@user.update_attribute :token_expires_at,
|
125
125
|
2.weeks.from_now.utc
|
126
126
|
assert @user.remember?
|
127
127
|
end
|
128
128
|
|
129
129
|
should "not remember user when token has already expired" do
|
130
|
-
@user.update_attribute :token_expires_at,
|
130
|
+
@user.update_attribute :token_expires_at,
|
131
131
|
2.weeks.ago.utc
|
132
132
|
assert ! @user.remember?
|
133
133
|
end
|
@@ -167,7 +167,7 @@ module Clearance
|
|
167
167
|
end
|
168
168
|
|
169
169
|
should "change encrypted password" do
|
170
|
-
assert_not_equal @user.encrypted_password,
|
170
|
+
assert_not_equal @user.encrypted_password,
|
171
171
|
@old_encrypted_password
|
172
172
|
end
|
173
173
|
end
|
@@ -199,7 +199,7 @@ module Clearance
|
|
199
199
|
end
|
200
200
|
|
201
201
|
should "change encrypted password" do
|
202
|
-
assert_not_equal @user.encrypted_password,
|
202
|
+
assert_not_equal @user.encrypted_password,
|
203
203
|
@old_encrypted_password
|
204
204
|
end
|
205
205
|
|
data/shoulda_macros/clearance.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module Clearance
|
1
|
+
module Clearance
|
2
2
|
module Shoulda
|
3
3
|
|
4
4
|
# STATE OF AUTHENTICATION
|
@@ -6,25 +6,25 @@ module Clearance
|
|
6
6
|
def should_be_signed_in_as(&block)
|
7
7
|
should "be signed in as #{block.bind(self).call}" do
|
8
8
|
user = block.bind(self).call
|
9
|
-
assert_not_nil user,
|
9
|
+
assert_not_nil user,
|
10
10
|
"please pass a User. try: should_be_signed_in_as { @user }"
|
11
|
-
assert_equal user.id, session[:user_id],
|
11
|
+
assert_equal user.id, session[:user_id],
|
12
12
|
"session[:user_id] is not set to User's id"
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
def should_be_signed_in_and_email_confirmed_as(&block)
|
17
17
|
should_be_signed_in_as &block
|
18
|
-
|
18
|
+
|
19
19
|
should "have confirmed email" do
|
20
20
|
user = block.bind(self).call
|
21
|
-
|
21
|
+
|
22
22
|
assert_not_nil user
|
23
23
|
assert_equal user, assigns(:user)
|
24
24
|
assert assigns(:user).email_confirmed?
|
25
25
|
end
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def should_not_be_signed_in
|
29
29
|
should "not be signed in" do
|
30
30
|
assert_nil session[:user_id]
|
@@ -44,17 +44,17 @@ module Clearance
|
|
44
44
|
else
|
45
45
|
should_not_set_the_flash
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
should "respond with 401 Unauthorized and render sign_in template" do
|
49
|
-
assert_response :unauthorized,
|
49
|
+
assert_response :unauthorized,
|
50
50
|
"access was expected to be denied (401 unauthorized)"
|
51
51
|
assert_template "sessions/new",
|
52
52
|
"template was expected to be sign in (sessions/new)"
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
# HTTP FLUENCY
|
57
|
-
|
57
|
+
|
58
58
|
def should_forbid(description, &block)
|
59
59
|
should "forbid #{description}" do
|
60
60
|
assert_raises ActionController::Forbidden do
|
@@ -62,7 +62,7 @@ module Clearance
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
# CONTEXTS
|
67
67
|
|
68
68
|
def signed_in_user_context(&blk)
|
@@ -82,65 +82,71 @@ module Clearance
|
|
82
82
|
merge_block(&blk)
|
83
83
|
end
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
# CREATING USERS
|
87
|
-
|
87
|
+
|
88
88
|
def should_create_user_successfully
|
89
89
|
should_assign_to :user
|
90
90
|
should_change 'User.count', :by => 1
|
91
|
-
|
91
|
+
|
92
92
|
should "send the confirmation email" do
|
93
93
|
assert_sent_email do |email|
|
94
94
|
email.subject =~ /account confirmation/i
|
95
95
|
end
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
should_set_the_flash_to /confirm/i
|
99
99
|
should_redirect_to_url_after_create
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
# RENDERING
|
103
|
-
|
103
|
+
|
104
104
|
def should_render_nothing
|
105
105
|
should "render nothing" do
|
106
106
|
assert @response.body.blank?
|
107
107
|
end
|
108
108
|
end
|
109
|
-
|
109
|
+
|
110
110
|
# REDIRECTS
|
111
|
-
|
111
|
+
|
112
112
|
def should_redirect_to_url_after_create
|
113
|
-
should_redirect_to "
|
113
|
+
should_redirect_to("the post-create url") do
|
114
|
+
@controller.send(:url_after_create)
|
115
|
+
end
|
114
116
|
end
|
115
|
-
|
117
|
+
|
116
118
|
def should_redirect_to_url_after_update
|
117
|
-
should_redirect_to "
|
119
|
+
should_redirect_to("the post-update url") do
|
120
|
+
@controller.send(:url_after_update)
|
121
|
+
end
|
118
122
|
end
|
119
|
-
|
123
|
+
|
120
124
|
def should_redirect_to_url_after_destroy
|
121
|
-
should_redirect_to "
|
125
|
+
should_redirect_to("the post-destroy url") do
|
126
|
+
@controller.send(:url_after_destroy)
|
127
|
+
end
|
122
128
|
end
|
123
|
-
|
129
|
+
|
124
130
|
# VALIDATIONS
|
125
|
-
|
131
|
+
|
126
132
|
def should_validate_confirmation_of(attribute, opts = {})
|
127
133
|
raise ArgumentError if opts[:factory].nil?
|
128
|
-
|
129
|
-
context "on save" do
|
134
|
+
|
135
|
+
context "on save" do
|
130
136
|
should_validate_confirmation_is_not_blank opts[:factory], attribute
|
131
137
|
should_validate_confirmation_is_not_bad opts[:factory], attribute
|
132
138
|
end
|
133
139
|
end
|
134
|
-
|
140
|
+
|
135
141
|
def should_validate_confirmation_is_not_blank(factory, attribute, opts = {})
|
136
142
|
should "validate #{attribute}_confirmation is not blank" do
|
137
143
|
model = Factory.build(factory, blank_confirmation_options(attribute))
|
138
144
|
model.save
|
139
|
-
assert_confirmation_error(model, attribute,
|
145
|
+
assert_confirmation_error(model, attribute,
|
140
146
|
"#{attribute}_confirmation cannot be blank")
|
141
147
|
end
|
142
148
|
end
|
143
|
-
|
149
|
+
|
144
150
|
def should_validate_confirmation_is_not_bad(factory, attribute, opts = {})
|
145
151
|
should "validate #{attribute}_confirmation is different than #{attribute}" do
|
146
152
|
model = Factory.build(factory, bad_confirmation_options(attribute))
|
@@ -149,9 +155,9 @@ module Clearance
|
|
149
155
|
"#{attribute}_confirmation cannot be different than #{attribute}")
|
150
156
|
end
|
151
157
|
end
|
152
|
-
|
158
|
+
|
153
159
|
# FORMS
|
154
|
-
|
160
|
+
|
155
161
|
def should_display_a_password_update_form
|
156
162
|
should "have a form for the user's token, password, and password confirm" do
|
157
163
|
update_path = ERB::Util.h(
|
@@ -163,39 +169,39 @@ module Clearance
|
|
163
169
|
assert_select 'input[name=?]', 'user[password]'
|
164
170
|
assert_select 'input[name=?]', 'user[password_confirmation]'
|
165
171
|
end
|
166
|
-
end
|
172
|
+
end
|
167
173
|
end
|
168
|
-
|
174
|
+
|
169
175
|
def should_display_a_sign_up_form
|
170
176
|
should "display a form to sign up" do
|
171
|
-
assert_select "form[action=#{users_path}][method=post]",
|
177
|
+
assert_select "form[action=#{users_path}][method=post]",
|
172
178
|
true, "There must be a form to sign up" do
|
173
|
-
assert_select "input[type=text][name=?]",
|
179
|
+
assert_select "input[type=text][name=?]",
|
174
180
|
"user[email]", true, "There must be an email field"
|
175
|
-
assert_select "input[type=password][name=?]",
|
181
|
+
assert_select "input[type=password][name=?]",
|
176
182
|
"user[password]", true, "There must be a password field"
|
177
|
-
assert_select "input[type=password][name=?]",
|
178
|
-
"user[password_confirmation]", true, "There must be a password confirmation field"
|
179
|
-
assert_select "input[type=submit]", true,
|
183
|
+
assert_select "input[type=password][name=?]",
|
184
|
+
"user[password_confirmation]", true, "There must be a password confirmation field"
|
185
|
+
assert_select "input[type=submit]", true,
|
180
186
|
"There must be a submit button"
|
181
187
|
end
|
182
|
-
end
|
188
|
+
end
|
183
189
|
end
|
184
|
-
|
185
|
-
def should_display_a_sign_in_form
|
190
|
+
|
191
|
+
def should_display_a_sign_in_form
|
186
192
|
should 'display a "sign in" form' do
|
187
|
-
assert_select "form[action=#{session_path}][method=post]",
|
193
|
+
assert_select "form[action=#{session_path}][method=post]",
|
188
194
|
true, "There must be a form to sign in" do
|
189
|
-
assert_select "input[type=text][name=?]",
|
195
|
+
assert_select "input[type=text][name=?]",
|
190
196
|
"session[email]", true, "There must be an email field"
|
191
|
-
assert_select "input[type=password][name=?]",
|
197
|
+
assert_select "input[type=password][name=?]",
|
192
198
|
"session[password]", true, "There must be a password field"
|
193
|
-
assert_select "input[type=checkbox][name=?]",
|
199
|
+
assert_select "input[type=checkbox][name=?]",
|
194
200
|
"session[remember_me]", true, "There must be a 'remember me' check box"
|
195
|
-
assert_select "input[type=submit]", true,
|
201
|
+
assert_select "input[type=submit]", true,
|
196
202
|
"There must be a submit button"
|
197
|
-
end
|
198
|
-
end
|
203
|
+
end
|
204
|
+
end
|
199
205
|
end
|
200
206
|
end
|
201
207
|
end
|
@@ -212,22 +218,22 @@ module Clearance
|
|
212
218
|
return user
|
213
219
|
end
|
214
220
|
|
215
|
-
def sign_out
|
221
|
+
def sign_out
|
216
222
|
@request.session[:user_id] = nil
|
217
223
|
end
|
218
|
-
|
224
|
+
|
219
225
|
def blank_confirmation_options(attribute)
|
220
226
|
opts = { attribute => attribute.to_s }
|
221
227
|
opts.merge("#{attribute}_confirmation".to_sym => "")
|
222
228
|
end
|
223
|
-
|
229
|
+
|
224
230
|
def bad_confirmation_options(attribute)
|
225
231
|
opts = { attribute => attribute.to_s }
|
226
232
|
opts.merge("#{attribute}_confirmation".to_sym => "not_#{attribute}")
|
227
233
|
end
|
228
|
-
|
234
|
+
|
229
235
|
def assert_confirmation_error(model, attribute, message = "confirmation error")
|
230
|
-
assert model.errors.on(attribute).include?("doesn't match confirmation"),
|
236
|
+
assert model.errors.on(attribute).include?("doesn't match confirmation"),
|
231
237
|
message
|
232
238
|
end
|
233
239
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thoughtbot-clearance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thoughtbot, inc.
|
@@ -18,11 +18,12 @@ authors:
|
|
18
18
|
- Tim Pope
|
19
19
|
- Eloy Duran
|
20
20
|
- Mihai Anca
|
21
|
+
- Mark Cornick
|
21
22
|
autorequire:
|
22
23
|
bindir: bin
|
23
24
|
cert_chain: []
|
24
25
|
|
25
|
-
date: 2009-03-
|
26
|
+
date: 2009-03-04 21:00:00 -08:00
|
26
27
|
default_executable:
|
27
28
|
dependencies: []
|
28
29
|
|