remarkable_devise 1.0.0.alpha3 → 1.0.0

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 (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