thoughtbot-clearance 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
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