remarkable_devise 1.0.0.alpha3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. data/README.markdown +70 -7
  2. data/lib/remarkable/devise/matchers/base_matcher.rb +17 -0
  3. data/lib/remarkable/devise/matchers/be_a_confirmable_matcher.rb +7 -3
  4. data/lib/remarkable/devise/matchers/be_a_database_authenticatable_matcher.rb +11 -4
  5. data/lib/remarkable/devise/matchers/be_a_lockable_matcher.rb +34 -0
  6. data/lib/remarkable/devise/matchers/be_a_registerable_matcher.rb +19 -0
  7. data/lib/remarkable/devise/matchers/be_a_rememberable_matcher.rb +7 -3
  8. data/lib/remarkable/devise/matchers/be_a_timeoutable_matcher.rb +23 -0
  9. data/lib/remarkable/devise/matchers/be_a_token_authenticatable_matcher.rb +7 -3
  10. data/lib/remarkable/devise/matchers/be_a_validatable_matcher.rb +7 -3
  11. data/lib/remarkable/devise/matchers/be_an_authenticatable_matcher.rb +19 -0
  12. data/lib/remarkable/devise/version.rb +1 -1
  13. data/locale/en.yml +70 -0
  14. data/remarkable_devise.gemspec +1 -1
  15. data/spec/example_models.rb +10 -2
  16. data/spec/examples/user_spec.rb +24 -0
  17. data/spec/matchers/be_a_confirmable_spec.rb +32 -4
  18. data/spec/matchers/be_a_database_authenticatable_spec.rb +55 -5
  19. data/spec/matchers/be_a_lockable_spec.rb +274 -0
  20. data/spec/matchers/be_a_registerable_spec.rb +27 -0
  21. data/spec/matchers/be_a_rememberable_spec.rb +81 -1
  22. data/spec/matchers/be_a_timeoutable_spec.rb +59 -0
  23. data/spec/matchers/be_a_token_authenticatable_spec.rb +33 -1
  24. data/spec/matchers/be_a_validatable_spec.rb +58 -5
  25. data/spec/matchers_spec.rb +23 -5
  26. data/spec/shared_examples.rb +122 -0
  27. data/spec/spec_helper.rb +13 -4
  28. metadata +23 -12
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
  s.add_runtime_dependency(%q<rspec>, [">=2.1.0"])
22
22
  s.add_runtime_dependency(%q<rails>, [">=3.0.1"])
23
23
  s.add_runtime_dependency(%q<activerecord>, [">=3.0.1"])
24
- s.add_runtime_dependency(%q<remarkable_activerecord>, ["4.0.0.alpha4"])
24
+ s.add_runtime_dependency(%q<remarkable_activerecord>, [">=4.0.0.alpha4"])
25
25
  s.add_runtime_dependency(%q<devise>, [">=1.1.3"])
26
26
 
27
27
  s.add_development_dependency "mocha"
@@ -1,6 +1,14 @@
1
1
  class User < ActiveRecord::Base
2
- devise :database_authenticatable, :confirmable, :recoverable,
3
- :rememberable, :trackable, :validatable, :token_authenticatable
2
+ devise :database_authenticatable, :stretches => 15, :encryptor => :clearance_sha1, :authentication_keys => [:email, :login], :params_authenticatable => false
3
+ devise :confirmable, :confirm_within => 2.days
4
+ devise :recoverable
5
+ devise :rememberable, :remember_for => 2.weeks, :extend_remember_period => true, :cookie_domain => 'foo'
6
+ devise :trackable
7
+ devise :validatable, :password_length => 8..20, :email_regexp => /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
8
+ devise :token_authenticatable, :token_authentication_key => :auth_token
9
+ devise :timeoutable, :timeout_in => 15.minutes
10
+ devise :lockable, :maximum_attempts => 10, :lock_strategy => :none, :unlock_strategy => :time, :unlock_in => 5.hours
11
+ devise :registerable
4
12
  end
5
13
 
6
14
  class FooUser < ActiveRecord::Base
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe User do
4
+ before do
5
+ User.stubs(:column_names).returns(%w{email encrypted_password password_salt confirmation_token confirmed_at confirmation_sent_at remember_token remember_created_at locked_at authentication_token sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip reset_password_token failed_attempts unlock_token})
6
+ end
7
+
8
+ it { should be_a_confirmable(:confirm_within => 2.days) }
9
+ it { should be_a_rememberable(:remember_for => 2.weeks) }
10
+ it { should be_a_validatable(:password_length => 8..20) }
11
+ it { should be_a_timeoutable(:timeout_in => 15.minutes) }
12
+ it { should be_a_lockable(:lock_strategy => :failed_attempts, :unlock_strategy => :both) }
13
+ it { should be_a_token_authenticatable }
14
+ it { should be_a_trackable }
15
+ it { should be_a_registerable }
16
+ it { should be_a_recoverable }
17
+
18
+ should_be_a_database_authenticatable do |o|
19
+ o.stretches = 15
20
+ o.encryptor = :clearance_sha1
21
+ o.params_authenticatable = false
22
+ o.authentication_keys = [:email, :login]
23
+ end
24
+ end
@@ -17,6 +17,18 @@ describe Remarkable::Devise::Matchers::BeAConfirmableMatcher do
17
17
  end
18
18
  end
19
19
 
20
+ context "options validation" do
21
+ describe :confirm_within do
22
+ it "should validate that model has proper :confirm_within" do
23
+ subject.class.new(:confirm_within => 2.days).matches?(User).should be_true
24
+ end
25
+
26
+ it "should validate that model hasn't proper :confirm_within" do
27
+ subject.class.new(:confirm_within => 3.days).matches?(User).should be_false
28
+ end
29
+ end
30
+ end
31
+
20
32
  context "columns validation" do
21
33
  context "confirmation_token column" do
22
34
  before do
@@ -71,11 +83,18 @@ describe Remarkable::Devise::Matchers::BeAConfirmableMatcher do
71
83
  end
72
84
 
73
85
  describe "description" do
74
- before do
75
- @msg = subject.description
86
+ context "when matching without options" do
87
+ specify { subject.description.should eql('be a confirmable') }
88
+ end
89
+
90
+ context "when matching with :confirm_within" do
91
+ before do
92
+ @matcher = subject.class.new(:confirm_within => 5.days)
93
+ @matcher.matches?(User)
94
+ end
95
+
96
+ specify { @matcher.description.should eql("be a confirmable within 5 days") }
76
97
  end
77
-
78
- specify { @msg.should eql('be a confirmable') }
79
98
  end
80
99
 
81
100
  context "expectation message" do
@@ -121,5 +140,14 @@ describe Remarkable::Devise::Matchers::BeAConfirmableMatcher do
121
140
 
122
141
  specify { @msg.should match('to have confirmation_sent_at column') }
123
142
  end
143
+
144
+ context "when :confirm_within doesn't match" do
145
+ before do
146
+ @matcher = subject.class.new(:confirm_within => 3.days)
147
+ @matcher.matches?(User)
148
+ end
149
+
150
+ specify { @matcher.failure_message_for_should.should match("User to be a confirmable with options (.+), got (.+)")}
151
+ end
124
152
  end
125
153
  end
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Remarkable::Devise::Matchers::BeADatabaseAuthenticatableMatcher do
4
+ it_should_behave_like "any Devise authentication model"
5
+
4
6
  before do
5
7
  @valid_columns = ['email', 'encrypted_password', 'password_salt']
6
8
 
@@ -13,7 +15,29 @@ describe Remarkable::Devise::Matchers::BeADatabaseAuthenticatableMatcher do
13
15
  end
14
16
 
15
17
  it "should validate that model has no :database_authenticatable model" do
16
- subject.matches?(FooUser).should be_false
18
+ subject.matches?(FooUser).should be_false
19
+ end
20
+ end
21
+
22
+ context "options validation" do
23
+ describe :stretches do
24
+ it "should validate that a model has proper :stratches" do
25
+ subject.class.new(:stretches => 15).matches?(User).should be_true
26
+ end
27
+
28
+ it "should validate that a model hasn't proper :stratches" do
29
+ subject.class.new(:stretches => 10).matches?(User).should be_false
30
+ end
31
+ end
32
+
33
+ describe :encryptor do
34
+ it "should validate that a model has proper :encryptor" do
35
+ subject.class.new(:encryptor => :clearance_sha1).matches?(User).should be_true
36
+ end
37
+
38
+ it "should validate that a model hasn't proper :encryptor" do
39
+ subject.class.new(:encryptor => :bcrypt).matches?(User).should be_false
40
+ end
17
41
  end
18
42
  end
19
43
 
@@ -71,16 +95,33 @@ describe Remarkable::Devise::Matchers::BeADatabaseAuthenticatableMatcher do
71
95
  end
72
96
 
73
97
  describe "description" do
74
- before do
75
- @msg = subject.description
98
+ context "when matching without options" do
99
+ specify { subject.description.should eql('be a database authenticatable') }
100
+ end
101
+
102
+ context "when matching with :stretches option" do
103
+ before do
104
+ @matcher = subject.class.new(:stretches => 15)
105
+ @matcher.matches?(User)
106
+ end
107
+
108
+ specify { @matcher.description.should eql("be a database authenticatable with password stretches 15") }
109
+ end
110
+
111
+ context "when matching with :encryptor option" do
112
+ before do
113
+ @matcher = subject.class.new(:encryptor => :bcrypt)
114
+ @matcher.matches?(User)
115
+ end
116
+
117
+ specify { @matcher.description.should eql("be a database authenticatable with :bcrypt password encryptor") }
76
118
  end
77
-
78
- specify { @msg.should eql('be a database authenticatable') }
79
119
  end
80
120
 
81
121
  context "expectation message" do
82
122
  context "when Devise::Models::DatabaseAuthenticatable not included" do
83
123
  before do
124
+ subject.stubs(:has_authenticatable_module_included?).returns(true)
84
125
  subject.matches?(FooUser)
85
126
 
86
127
  @msg = subject.failure_message_for_should
@@ -121,5 +162,14 @@ describe Remarkable::Devise::Matchers::BeADatabaseAuthenticatableMatcher do
121
162
 
122
163
  specify { @msg.should match('to have password_salt column') }
123
164
  end
165
+
166
+ context "when options doesn't match" do
167
+ before do
168
+ @matcher = subject.class.new(:stretches => 10)
169
+ @matcher.matches?(User)
170
+ end
171
+
172
+ specify { @matcher.failure_message_for_should.should match('User to be a database authenticatable with options (.+), got (.+)') }
173
+ end
124
174
  end
125
175
  end
@@ -0,0 +1,274 @@
1
+ require 'spec_helper'
2
+
3
+ describe Remarkable::Devise::Matchers::BeALockableMatcher do
4
+ before do
5
+ @valid_columns = %w{failed_attempts unlock_token locked_at}
6
+
7
+ User.stubs(:column_names).returns(@valid_columns)
8
+ end
9
+
10
+ describe "validation of Devise::Models::Lockable module inclusion" do
11
+ before do
12
+ User.stubs(:lock_strategy).returns(:none)
13
+ User.stubs(:unlock_strategy).returns(:none)
14
+ User.stubs(:has_column?).returns(true)
15
+ end
16
+
17
+ it "should validate that a model has Devise::Models::Lockable module included" do
18
+ subject.matches?(User).should be_true
19
+ end
20
+
21
+ it "should validate that a model hasn't Devise::Models::Lockable module included" do
22
+ subject.matches?(FooUser).should be_false
23
+ end
24
+ end
25
+
26
+ describe "columns validation" do
27
+ before do
28
+ subject.stubs(:included?).returns(true)
29
+ end
30
+
31
+ context "when :lock_strategy is :failed_attempts" do
32
+ before do
33
+ User.stubs(:lock_strategy).returns(:failed_attempts)
34
+ end
35
+
36
+ it "should validate that a model has :failed_attempts column" do
37
+ subject.matches?(User).should be_true
38
+ end
39
+
40
+ it "should validate that a model hasn't :faild_attempts column" do
41
+ User.stubs(:column_names).returns(@valid_columns - ['failed_attempts'])
42
+
43
+ subject.matches?(User).should be_false
44
+ end
45
+ end
46
+
47
+ context "when :lock_strategy is :none" do
48
+ before do
49
+ User.stubs(:lock_strategy).returns(:none)
50
+ end
51
+
52
+ context "when a model has :failed_attempts column" do
53
+ it "should match" do
54
+ subject.matches?(User).should be_true
55
+ end
56
+ end
57
+
58
+ context "when a model hasn't :failed_attempts column" do
59
+ before do
60
+ User.stubs(:column_names).returns(@valid_columns - ['failed_attempts'])
61
+ end
62
+
63
+ it "should match" do
64
+ subject.matches?(User).should be_true
65
+ end
66
+ end
67
+ end
68
+
69
+ context "when :unlock_strategy is :time" do
70
+ before do
71
+ User.stubs(:unlock_strategy).returns(:time)
72
+ end
73
+
74
+ it_should_behave_like "lockable matcher for unlock_strategy without unlock_token column needed"
75
+ end
76
+
77
+ context "when :unlock_strategy is :email" do
78
+ before do
79
+ User.stubs(:unlock_strategy).returns(:email)
80
+ end
81
+
82
+ it_should_behave_like "lockable matcher for unlock_strategy with unlock_token column needed"
83
+ end
84
+
85
+ context "when :unlock_strategy is :both" do
86
+ before do
87
+ User.stubs(:unlock_strategy).returns(:both)
88
+ end
89
+
90
+ it_should_behave_like "lockable matcher for unlock_strategy with unlock_token column needed"
91
+ end
92
+
93
+ context "when :unlock_strategy is :none" do
94
+ before do
95
+ User.stubs(:unlock_strategy).returns(:none)
96
+ end
97
+
98
+ it_should_behave_like "lockable matcher for unlock_strategy without unlock_token column needed"
99
+ end
100
+
101
+ describe :locked_at do
102
+ context "when a model has locked_at column" do
103
+ it "should match" do
104
+ subject.matches?(User).should be_true
105
+ end
106
+ end
107
+
108
+ context "when a model has no locked_at column" do
109
+ before do
110
+ User.stubs(:column_names).returns(@valid_columns - ['locked_at'])
111
+ end
112
+
113
+ it "should not match" do
114
+ subject.matches?(User).should be_false
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "matching with options" do
121
+ describe :maximum_attempts do
122
+ context "when a model has expected :maximum_attepmts value" do
123
+ it "should match" do
124
+ subject.class.new(:maximum_attempts => 10).matches?(User).should be_true
125
+ end
126
+ end
127
+
128
+ context "when a model hasn't expected :maximum_attempts value" do
129
+ it "should not match" do
130
+ subject.class.new(:maximum_attempts => 25).matches?(User).should be_false
131
+ end
132
+ end
133
+ end
134
+
135
+ describe :lock_strategy do
136
+ context "when a model has expected :lock_strategy value" do
137
+ it "should match" do
138
+ subject.class.new(:lock_strategy => :none).matches?(User).should be_true
139
+ end
140
+ end
141
+
142
+ context "when a model hasn't expected :lock_strategy value" do
143
+ it "should not match" do
144
+ subject.class.new(:lock_strategy => :failed_attempts).matches?(User).should be_false
145
+ end
146
+ end
147
+ end
148
+
149
+ describe :unlock_strategy do
150
+ context "when a model has expected :unlock_strategy value" do
151
+ it "should match" do
152
+ subject.class.new(:unlock_strategy => :time).matches?(User).should be_true
153
+ end
154
+ end
155
+
156
+ context "when a model hasn't expected :unlock_strategy value" do
157
+ it "should not match" do
158
+ subject.class.new(:unlock_strategy => :both).matches?(User).should be_false
159
+ end
160
+ end
161
+ end
162
+
163
+ describe :unlock_in do
164
+ context "when a model has expected :unlock_in value" do
165
+ it "should match" do
166
+ subject.class.new(:unlock_in => 5.hours).matches?(User).should be_true
167
+ end
168
+
169
+ end
170
+
171
+ context "when a model hasn't expected :unlock_in value" do
172
+ it "should not match" do
173
+ subject.class.new(:unlock_in => 1.hour).matches?(User).should be_false
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ describe "description" do
180
+ context "when matching without options" do
181
+ specify { subject.description.should eql('be a lockable') }
182
+ end
183
+
184
+ context "when matching with :maximum_attempts option" do
185
+ before do
186
+ @matcher = subject.class.new(:maximum_attempts => 10)
187
+ @matcher.matches?(User)
188
+ end
189
+
190
+ specify { @matcher.description.should eql("be a lockable with 10 maximum attempts") }
191
+ end
192
+
193
+ context "when matching with :lock_strategy option" do
194
+ before do
195
+ @matcher = subject.class.new(:lock_strategy => :time)
196
+ @matcher.matches?(User)
197
+ end
198
+
199
+ specify { @matcher.description.should eql("be a lockable with :time lock strategy") }
200
+ end
201
+
202
+ context "when matching with :unlock_strategy option" do
203
+ before do
204
+ @matcher = subject.class.new(:unlock_strategy => :both)
205
+ @matcher.matches?(User)
206
+ end
207
+
208
+ specify { @matcher.description.should eql("be a lockable with :both unlock strategy") }
209
+ end
210
+
211
+ context "when matching with :unlock_in option" do
212
+ before do
213
+ @matcher = subject.class.new(:unlock_in => 5.minutes)
214
+ @matcher.matches?(User)
215
+ end
216
+
217
+ specify { @matcher.description.should eql("be a lockable with unlock in 300 seconds") }
218
+ end
219
+ end
220
+
221
+ describe "failure message" do
222
+ before do
223
+ User.lock_strategy = :failed_attempts
224
+ User.unlock_strategy = :both
225
+ end
226
+
227
+ context "when module Devise::Models::Lockable is not included" do
228
+ before do
229
+ subject.matches?(FooUser)
230
+ end
231
+
232
+ specify { subject.failure_message_for_should.should match("Foo user to have Devise :lockable model") }
233
+ end
234
+
235
+ context "when model doesn't have :failed_attempts column" do
236
+ before do
237
+ User.stubs(:column_names).returns(@valid_columns - ['failed_attempts'])
238
+
239
+ subject.matches?(User)
240
+ end
241
+
242
+ specify { subject.failure_message_for_should.should match("User to have failed_attempts column") }
243
+ end
244
+
245
+ context "when model doesn't have :unlock_token column" do
246
+ before do
247
+ User.stubs(:column_names).returns(@valid_columns - ['unlock_token'])
248
+
249
+ subject.matches?(User)
250
+ end
251
+
252
+ specify { subject.failure_message_for_should.should match("User to have unlock_token column") }
253
+ end
254
+
255
+ context "when model doesn't have :locked_at column" do
256
+ before do
257
+ User.stubs(:column_names).returns(@valid_columns - ['locked_at'])
258
+
259
+ subject.matches?(User)
260
+ end
261
+
262
+ specify { subject.failure_message_for_should.should match("User to have locked_at column") }
263
+ end
264
+
265
+ context "when options doesn't match" do
266
+ before do
267
+ @matcher = subject.class.new(:maximum_attempts => 15)
268
+ @matcher.matches?(User)
269
+ end
270
+
271
+ specify { @matcher.failure_message_for_should.should match("User to be a lockable with options (.+), got (.+)") }
272
+ end
273
+ end
274
+ end