thoughtbot-clearance 0.3.7 → 0.3.8

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.
Files changed (32) hide show
  1. data/README.textile +147 -60
  2. data/Rakefile +29 -21
  3. data/TODO.textile +1 -15
  4. data/generators/clearance/clearance_generator.rb +31 -9
  5. data/generators/clearance/lib/insert_commands.rb +103 -0
  6. data/generators/clearance/lib/rake_commands.rb +22 -0
  7. data/generators/clearance/templates/README +37 -0
  8. data/generators/clearance/templates/app/views/clearance_mailer/change_password.html.erb +3 -1
  9. data/generators/clearance/templates/app/views/passwords/edit.html.erb +4 -4
  10. data/generators/clearance/templates/db/migrate/create_users_with_clearance_columns.rb +21 -0
  11. data/generators/clearance/templates/db/migrate/update_users_with_clearance_columns.rb +41 -0
  12. data/generators/clearance/templates/test/{factories.rb → factories/clearance_user.rb} +1 -1
  13. data/lib/clearance.rb +3 -4
  14. data/lib/clearance/app/controllers/application_controller.rb +47 -61
  15. data/lib/clearance/app/controllers/confirmations_controller.rb +25 -33
  16. data/lib/clearance/app/controllers/passwords_controller.rb +41 -46
  17. data/lib/clearance/app/controllers/sessions_controller.rb +49 -56
  18. data/lib/clearance/app/controllers/users_controller.rb +21 -29
  19. data/lib/clearance/app/models/clearance_mailer.rb +15 -19
  20. data/lib/clearance/app/models/user.rb +53 -56
  21. data/lib/clearance/test/functional/confirmations_controller_test.rb +4 -35
  22. data/lib/clearance/test/functional/passwords_controller_test.rb +9 -5
  23. data/lib/clearance/test/functional/sessions_controller_test.rb +67 -17
  24. data/lib/clearance/test/functional/users_controller_test.rb +15 -7
  25. data/lib/clearance/test/test_helper.rb +10 -81
  26. data/lib/clearance/test/unit/clearance_mailer_test.rb +5 -5
  27. data/lib/clearance/test/unit/user_test.rb +42 -59
  28. data/rails/init.rb +1 -0
  29. data/shoulda_macros/clearance.rb +45 -0
  30. metadata +14 -6
  31. data/generators/clearance/templates/app/views/confirmations/new.html.erb +0 -6
  32. data/lib/clearance/version.rb +0 -7
@@ -13,24 +13,32 @@ module Clearance
13
13
  should_respond_with :success
14
14
  should_render_template :new
15
15
  should_not_set_the_flash
16
- should_have_form :action => "session_path",
17
- :fields => { "session[email]" => :text,
18
- "session[password]" => :password,
19
- "session[remember_me]" => :checkbox }
16
+ should 'display a "sign in" form' do
17
+ assert_select "form[action=#{session_path}][method=post]",
18
+ true, "There must be a form to log in" do
19
+ assert_select "input[type=text][name=?]",
20
+ "session[email]", true, "There must be an email field"
21
+ assert_select "input[type=password][name=?]",
22
+ "session[password]", true, "There must be a password field"
23
+ assert_select "input[type=checkbox][name=?]",
24
+ "session[remember_me]", true, "There must be a 'remember me' check box"
25
+ assert_select "input[type=submit]", true,
26
+ "There must be a submit button"
27
+ end
28
+ end
20
29
  end
21
30
 
22
31
  context "Given an unconfirmed user" do
23
32
  setup do
24
- @user = Factory(:user, :confirmed => false)
33
+ @user = Factory(:clearance_user, :confirmed => false)
25
34
  end
26
35
 
27
36
  context "a POST to #create with good credentials" do
28
37
  setup do
29
38
  ActionMailer::Base.deliveries.clear
30
39
  post :create, :session => {
31
- :email => @user.email,
32
- :password => @user.password
33
- }
40
+ :email => @user.email,
41
+ :password => @user.password }
34
42
  end
35
43
 
36
44
  should_deny_access(:flash => /confirm/i)
@@ -43,12 +51,13 @@ module Clearance
43
51
  end
44
52
 
45
53
  context "Given a confirmed user" do
46
- setup { @user = Factory(:user, :confirmed => true) }
54
+ setup { @user = Factory(:clearance_user, :confirmed => true) }
47
55
 
48
56
  context "a POST to #create with good credentials" do
49
57
  setup do
50
- post :create, :session => { :email => @user.email,
51
- :password => @user.password }
58
+ post :create, :session => {
59
+ :email => @user.email,
60
+ :password => @user.password }
52
61
  end
53
62
 
54
63
  should_set_the_flash_to /success/i
@@ -58,8 +67,9 @@ module Clearance
58
67
 
59
68
  context "a POST to #create with bad credentials" do
60
69
  setup do
61
- post :create, :session => { :email => @user.email,
62
- :password => "bad value" }
70
+ post :create, :session => {
71
+ :email => @user.email,
72
+ :password => "bad value" }
63
73
  end
64
74
 
65
75
  should_set_the_flash_to /bad/i
@@ -69,8 +79,10 @@ module Clearance
69
79
 
70
80
  context "a POST to #create with good credentials and remember me" do
71
81
  setup do
72
- post :create, :session => { :email => @user.email,
73
- :password => @user.password, :remember_me => '1' }
82
+ post :create, :session => {
83
+ :email => @user.email,
84
+ :password => @user.password,
85
+ :remember_me => '1' }
74
86
  end
75
87
 
76
88
  should_set_the_flash_to /success/i
@@ -89,8 +101,10 @@ module Clearance
89
101
 
90
102
  context "a POST to #create with bad credentials and remember me" do
91
103
  setup do
92
- post :create, :session => { :email => @user.email,
93
- :password => "bad value", :remember_me => '1' }
104
+ post :create, :session => {
105
+ :email => @user.email,
106
+ :password => "bad value",
107
+ :remember_me => '1' }
94
108
  end
95
109
 
96
110
  should_set_the_flash_to /bad/i
@@ -106,6 +120,42 @@ module Clearance
106
120
  assert_nil @user.reload.remember_token_expires_at
107
121
  end
108
122
  end
123
+
124
+ context "a POST to #create with good credentials and A URL to return back" do
125
+ context "in the session" do
126
+ setup do
127
+ @request.session[:return_to] = '/url_in_the_session'
128
+ post :create, :session => {
129
+ :email => @user.email,
130
+ :password => @user.password }
131
+ end
132
+
133
+ should_redirect_to "'/url_in_the_session'"
134
+ end
135
+
136
+ context "in the request" do
137
+ setup do
138
+ post :create, :session => {
139
+ :email => @user.email,
140
+ :password => @user.password },
141
+ :return_to => '/url_in_the_request'
142
+ end
143
+
144
+ should_redirect_to "'/url_in_the_request'"
145
+ end
146
+
147
+ context "in the request and in the session" do
148
+ setup do
149
+ @request.session[:return_to] = '/url_in_the_session'
150
+ post :create, :session => {
151
+ :email => @user.email,
152
+ :password => @user.password },
153
+ :return_to => '/url_in_the_request'
154
+ end
155
+
156
+ should_redirect_to "'/url_in_the_session'"
157
+ end
158
+ end
109
159
  end
110
160
 
111
161
  public_context do
@@ -12,12 +12,20 @@ module Clearance
12
12
  should_respond_with :success
13
13
  should_render_template :new
14
14
  should_not_set_the_flash
15
- should_have_form :action => "users_path",
16
- :method => :post,
17
- :fields => { :email => :text,
18
- :password => :password,
19
- :password_confirmation => :password }
20
-
15
+ should "display a form to register" do
16
+ assert_select "form[action=#{users_path}][method=post]",
17
+ true, "There must be a form to register" do
18
+ assert_select "input[type=text][name=?]",
19
+ "user[email]", true, "There must be an email field"
20
+ assert_select "input[type=password][name=?]",
21
+ "user[password]", true, "There must be a password field"
22
+ assert_select "input[type=password][name=?]",
23
+ "user[password_confirmation]", true, "There must be a password confirmation field"
24
+ assert_select "input[type=submit]", true,
25
+ "There must be a submit button"
26
+ end
27
+ end
28
+
21
29
  context "with params" do
22
30
  setup do
23
31
  @email = 'a@example.com'
@@ -33,7 +41,7 @@ module Clearance
33
41
 
34
42
  context "on POST to /users" do
35
43
  setup do
36
- post :create, :user => Factory.build(:user).attributes.merge(
44
+ post :create, :user => Factory.build(:clearance_user).attributes.merge(
37
45
  {:password => 'skerit',
38
46
  :password_confirmation => 'skerit'})
39
47
  end
@@ -2,90 +2,19 @@ module Clearance
2
2
  module Test
3
3
  module TestHelper
4
4
 
5
- def self.included(base)
6
- base.class_eval do
7
- include InstanceMethods
8
- extend ClassMethods
9
- end
10
- end
11
-
12
- module InstanceMethods
13
- def login_as(user = nil)
14
- user ||= Factory(:user)
15
- @request.session[:user_id] = user.id
16
- return user
17
- end
18
-
19
- def logout
20
- @request.session[:user_id] = nil
21
- end
22
- end
23
-
24
- module ClassMethods
25
- def should_deny_access_on(command, opts = {})
26
-
27
- context "on #{command}" do
28
- setup { eval command }
29
- should_deny_access(opts)
5
+ def self.included(test_helper)
6
+ test_helper.class_eval do
7
+
8
+ def login_as(user = nil)
9
+ user ||= Factory(:clearance_user)
10
+ @request.session[:user_id] = user.id
11
+ return user
30
12
  end
31
- end
32
13
 
33
- def should_deny_access(opts = {})
34
- opts[:redirect] ||= "new_session_path"
35
- should_redirect_to opts[:redirect]
36
- if opts[:flash]
37
- should_set_the_flash_to opts[:flash]
38
- else
39
- should_not_set_the_flash
40
- end
41
- end
42
-
43
- # should_have_form :action => 'admin_users_path',
44
- # :method => :get,
45
- # :fields => { 'email' => :text }
46
- # TODO: http_method should be pulled out
47
- def should_have_form(opts)
48
- model = self.name.gsub(/ControllerTest$/, '').singularize.downcase
49
- model = model[model.rindex('::')+2..model.size] if model.include?('::')
50
- http_method, hidden_http_method = form_http_method opts[:method]
51
- should "have a #{model} form" do
52
- assert_select "form[action=?][method=#{http_method}]", eval(opts[:action]) do
53
- if hidden_http_method
54
- assert_select "input[type=hidden][name=_method][value=#{hidden_http_method}]"
55
- end
56
- opts[:fields].each do |attribute, type|
57
- attribute = attribute.is_a?(Symbol) ? "#{model}[#{attribute.to_s}]" : attribute
58
- assert_select "input[type=#{type.to_s}][name=?]", attribute
59
- end
60
- assert_select "input[type=submit]"
61
- end
62
- end
63
- end
64
-
65
- def form_http_method(http_method)
66
- http_method = http_method.nil? ? 'post' : http_method.to_s
67
- if http_method == "post" || http_method == "get"
68
- return http_method, nil
69
- else
70
- return "post", http_method
71
- end
72
- end
73
-
74
- def logged_in_user_context(&blk)
75
- context "A logged in user" do
76
- setup do
77
- @user = Factory :user
78
- login_as @user
79
- end
80
- merge_block(&blk)
81
- end
82
- end
83
-
84
- def public_context(&blk)
85
- context "The public" do
86
- setup { logout }
87
- merge_block(&blk)
14
+ def logout
15
+ @request.session[:user_id] = nil
88
16
  end
17
+
89
18
  end
90
19
  end
91
20
 
@@ -7,7 +7,7 @@ module Clearance
7
7
  base.class_eval do
8
8
  context "A change password email" do
9
9
  setup do
10
- @user = Factory :user
10
+ @user = Factory :clearance_user
11
11
  @email = ClearanceMailer.create_change_password @user
12
12
  end
13
13
 
@@ -25,14 +25,14 @@ module Clearance
25
25
  assert_equal [@user.email], @email.to
26
26
  end
27
27
 
28
- should "have a subject of '[PROJECT_NAME] Change your password'" do
29
- assert_equal @email.subject, "[#{PROJECT_NAME.humanize}] Change your password"
28
+ should "set its subject" do
29
+ assert_match /Change your password/, @email.subject
30
30
  end
31
31
  end
32
32
 
33
33
  context "A confirmation email" do
34
34
  setup do
35
- @user = Factory :user
35
+ @user = Factory :clearance_user
36
36
  @email = ClearanceMailer.create_confirmation @user
37
37
  end
38
38
 
@@ -41,7 +41,7 @@ module Clearance
41
41
  end
42
42
 
43
43
  should 'set its subject' do
44
- assert_equal "[#{PROJECT_NAME.humanize}] Account confirmation", @email.subject
44
+ assert_match /Account confirmation/, @email.subject
45
45
  end
46
46
 
47
47
  should 'set its from address to DO_NOT_REPLY' do
@@ -5,24 +5,24 @@ module Clearance
5
5
 
6
6
  def self.included(base)
7
7
  base.class_eval do
8
- should_require_attributes :email, :password
9
- should_allow_values_for :email, 'foo@example.com'
8
+ should_require_attributes :email, :password
9
+ should_allow_values_for :email, 'foo@example.com'
10
10
  should_not_allow_values_for :email, 'foo'
11
11
  should_not_allow_values_for :email, 'example.com'
12
12
 
13
13
  should "require password validation on create" do
14
- user = Factory.build(:user, :password => 'blah', :password_confirmation => 'boogidy')
14
+ user = Factory.build(:clearance_user, :password => 'blah', :password_confirmation => 'boogidy')
15
15
  assert !user.save
16
16
  assert_match(/confirmation/i, user.errors.on(:password))
17
17
  end
18
18
 
19
19
  should "create a crypted_password on save" do
20
- assert_not_nil Factory(:user, :crypted_password => nil).crypted_password
20
+ assert_not_nil Factory(:clearance_user, :crypted_password => nil).crypted_password
21
21
  end
22
22
 
23
23
  context 'updating a password' do
24
24
  setup do
25
- @user = Factory(:user)
25
+ @user = Factory(:clearance_user)
26
26
  assert_not_nil @user.crypted_password
27
27
  @crypt = @user.crypted_password
28
28
  assert_not_nil @user.salt
@@ -42,69 +42,52 @@ module Clearance
42
42
  setup do
43
43
  @salt = 'salt'
44
44
  User.any_instance.stubs(:initialize_salt)
45
- @user = Factory :user, :salt => @salt
45
+
46
+ @user = Factory(:clearance_user, :salt => @salt)
46
47
  @password = @user.password
47
48
  end
48
49
 
49
50
  should "require password validation on update" do
50
- @user.update_attributes(:password => "blah", :password_confirmation => "boogidy")
51
+ @user.update_attributes :password => "blah",
52
+ :password_confirmation => "boogidy"
51
53
  assert !@user.save
52
54
  assert_match(/confirmation/i, @user.errors.on(:password))
53
55
  end
54
56
 
55
57
  should_require_unique_attributes :email
56
-
57
- context 'authenticating a user' do
58
- context 'with good credentials' do
59
- setup do
60
- @result = User.authenticate @user.email, @password
61
- end
62
-
63
- should 'return true' do
64
- assert @result
65
- end
66
- end
67
-
68
- context 'with bad credentials' do
69
- setup do
70
- @result = User.authenticate @user.email, 'horribly_wrong_password'
71
- end
72
-
73
- should 'return false' do
74
- assert !@result
75
- end
76
- end
58
+
59
+ should 'store email in lower case' do
60
+ @user.update_attributes(:email => 'John.Doe@example.com')
61
+ assert_equal 'john.doe@example.com', @user.email
77
62
  end
78
-
79
- context 'authenticated?' do
80
- context 'with good credentials' do
81
- setup do
82
- @result = @user.authenticated? @password
83
- end
84
-
85
- should 'return true' do
86
- assert @result
87
- end
88
- end
89
-
90
- context 'with bad credentials' do
91
- setup do
92
- @result = @user.authenticated? 'horribly_wrong_password'
93
- end
94
-
95
- should 'return false' do
96
- assert !@result
97
- end
98
- end
63
+
64
+ should "authenticate with good credentials" do
65
+ assert User.authenticate(@user.email, @password)
66
+ end
67
+
68
+ should "authenticate with good credentials, email in uppercase" do
69
+ assert User.authenticate(@user.email.upcase, @password)
70
+ end
71
+
72
+ should "not authenticate with bad credentials" do
73
+ assert ! User.authenticate(@user.email, 'horribly_wrong_password')
74
+ end
75
+
76
+ should "be authenticated with a good password" do
77
+ assert @user.authenticated?(@password)
78
+ end
79
+
80
+ should "not be authenticated with a bad password" do
81
+ assert ! @user.authenticated?('horribly_wrong_password')
99
82
  end
100
83
 
101
84
  context 'encrypt' do
102
85
  setup do
103
86
  @crypted = @user.encrypt(@password)
104
- @expected = Digest::SHA1.hexdigest("--#{@salt}--#{@password}--")
87
+ @expected = Digest::SHA512.hexdigest("--#{@salt}--#{@password}--")
105
88
  end
106
89
 
107
- should 'create a Hash using SHA1 encryption' do
90
+ should 'create a Hash using SHA512 encryption' do
108
91
  assert_equal @expected, @crypted
109
92
  assert_not_equal @password, @crypted
110
93
  end
@@ -127,9 +110,7 @@ module Clearance
127
110
  end
128
111
 
129
112
  context 'forget_me!' do
130
- setup do
131
- @user.forget_me!
132
- end
113
+ setup { @user.forget_me! }
133
114
 
134
115
  should 'unset the remember token and expiration date' do
135
116
  assert_nil @user.remember_token
@@ -145,7 +126,8 @@ module Clearance
145
126
  context 'remember_token?' do
146
127
  context 'when token expires in the future' do
147
128
  setup do
148
- @user.update_attribute :remember_token_expires_at, 2.weeks.from_now.utc
129
+ @user.update_attribute :remember_token_expires_at,
130
+ 2.weeks.from_now.utc
149
131
  end
150
132
 
151
133
  should 'be true' do
@@ -155,7 +137,8 @@ module Clearance
155
137
 
156
138
  context 'when token expired' do
157
139
  setup do
158
- @user.update_attribute :remember_token_expires_at, 2.weeks.ago.utc
140
+ @user.update_attribute :remember_token_expires_at,
141
+ 2.weeks.ago.utc
159
142
  end
160
143
 
161
144
  should 'be false' do
@@ -166,7 +149,7 @@ module Clearance
166
149
 
167
150
  context "User.authenticate with a valid email and password" do
168
151
  setup do
169
- @found_user = User.authenticate @user.email, @user.password
152
+ @found_user = User.authenticate(@user.email, @user.password)
170
153
  end
171
154
 
172
155
  should "find that user" do
@@ -176,7 +159,7 @@ module Clearance
176
159
 
177
160
  context "When sent authenticate with an invalid email and password" do
178
161
  setup do
179
- @found_user = User.authenticate "not", "valid"
162
+ @found_user = User.authenticate("not", "valid")
180
163
  end
181
164
 
182
165
  should "find nothing" do
@@ -187,7 +170,7 @@ module Clearance
187
170
 
188
171
  context "A user" do
189
172
  setup do
190
- @user = Factory :user
173
+ @user = Factory(:clearance_user)
191
174
  end
192
175
 
193
176
  context 'when sent #confirm!' do