Skip to content

Commit 8f0e894

Browse files
authored
Merge pull request #390 from willnet/use-real-model-instead-of-mock
Stop mocking models in controller specs and switch to using ActiveRecord directly
2 parents a5e2035 + 75e734c commit 8f0e894

14 files changed

+83
-159
lines changed

lib/sorcery/controller/submodules/activity_logging.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ def self.included(base)
1616
base.send(:include, InstanceMethods)
1717
Config.module_eval do
1818
class << self
19-
attr_accessor :register_login_time
20-
attr_accessor :register_logout_time
21-
attr_accessor :register_last_activity_time
22-
attr_accessor :register_last_ip_address
19+
attr_accessor :register_login_time, :register_logout_time, :register_last_activity_time, :register_last_ip_address
2320

2421
def merge_activity_logging_defaults!
2522
@defaults.merge!(:@register_login_time => true,

lib/sorcery/test_helpers/internal.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def cost
1717
# a patch to fix a bug in testing that happens when you 'destroy' a session twice.
1818
# After the first destroy, the session is an ordinary hash, and then when destroy
1919
# is called again there's an exception.
20-
class ::Hash # rubocop:disable Style/ClassAndModuleChildren
20+
class ::Hash
2121
def destroy
2222
clear
2323
end
@@ -70,8 +70,6 @@ def reload_user_class
7070
User && Object.send(:remove_const, 'User')
7171
load 'user.rb'
7272

73-
return unless User.respond_to?(:reset_column_information)
74-
7573
User.reset_column_information
7674
end
7775
end

lib/sorcery/test_helpers/internal/rails.rb

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,23 @@ def sorcery_reload!(submodules = [], options = {})
1919

2020
# remove all plugin before_actions so they won't fail other tests.
2121
# I don't like this way, but I didn't find another.
22-
chain = SorceryController._process_action_callbacks.send :chain
22+
callbacks = SorceryController._process_action_callbacks
23+
chain = callbacks.send :chain
2324
chain.delete_if { |c| SUBMODULES_AUTO_ADDED_CONTROLLER_FILTERS.include?(c.filter) }
25+
callbacks.instance_variable_set(:@all_callbacks, nil)
26+
callbacks.instance_variable_set(:@single_callbacks, {})
2427

2528
# configure
2629
::Sorcery::Controller::Config.submodules = submodules
27-
::Sorcery::Controller::Config.user_class = nil
28-
ActionController::Base.send(:include, ::Sorcery::Controller)
2930
::Sorcery::Controller::Config.user_class = 'User'
31+
ActionController::Base.include(::Sorcery::Controller)
3032

3133
::Sorcery::Controller::Config.user_config do |user|
3234
options.each do |property, value|
3335
user.send(:"#{property}=", value)
3436
end
3537
end
3638
User.authenticates_with_sorcery!
37-
return unless defined?(DataMapper) && User.ancestors.include?(DataMapper::Resource)
38-
39-
DataMapper.auto_migrate!
40-
User.finalize
41-
Authentication.finalize
4239
end
4340

4441
def sorcery_controller_property_set(property, value)
Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,24 @@
11
require 'spec_helper'
22

3-
# require 'shared_examples/controller_activity_logging_shared_examples'
4-
53
describe SorceryController, type: :controller do
4+
before(:all) do
5+
MigrationHelper.migrate("#{Rails.root}/db/migrate/activity_logging")
6+
end
7+
68
after(:all) do
9+
MigrationHelper.rollback("#{Rails.root}/db/migrate/activity_logging")
710
sorcery_controller_property_set(:register_login_time, true)
811
sorcery_controller_property_set(:register_logout_time, true)
912
sorcery_controller_property_set(:register_last_activity_time, true)
10-
# sorcery_controller_property_set(:last_login_from_ip_address_name, true)
1113
end
1214

1315
# ----------------- ACTIVITY LOGGING -----------------------
1416
context 'with activity logging features' do
15-
let(:adapter) { double('sorcery_adapter') }
16-
let(:user) { double('user', id: 42, sorcery_adapter: adapter) }
17+
let!(:user) { User.create!(username: 'test_user', email: '[email protected]', password: 'password') }
1718

18-
before(:all) do
19-
sorcery_reload!([:activity_logging])
20-
end
19+
before(:all) { sorcery_reload!([:activity_logging]) }
2120

2221
before(:each) do
23-
allow(user).to receive(:username)
24-
allow(user).to receive_message_chain(:sorcery_config, :username_attribute_names, :first) { :username }
25-
allow(User.sorcery_config).to receive(:last_login_at_attribute_name) { :last_login_at }
26-
allow(User.sorcery_config).to receive(:last_login_from_ip_address_name) { :last_login_from_ip_address }
27-
2822
sorcery_controller_property_set(:register_login_time, false)
2923
sorcery_controller_property_set(:register_last_ip_address, false)
3024
sorcery_controller_property_set(:register_last_activity_time, false)
@@ -35,20 +29,22 @@
3529
Timecop.freeze(now)
3630

3731
sorcery_controller_property_set(:register_login_time, true)
38-
expect(user).to receive(:set_last_login_at).with(be_within(0.1).of(now))
3932
login_user(user)
4033

34+
expect(user.reload.last_login_at).to be_within(0.1).of(now)
35+
4136
Timecop.return
4237
end
4338

4439
it 'logs logout time on logout' do
4540
login_user(user)
4641
now = Time.now.in_time_zone
4742
Timecop.freeze(now)
48-
expect(user).to receive(:set_last_logout_at).with(be_within(0.1).of(now))
4943

5044
logout_user
5145

46+
expect(user.reload.last_logout_at).to be_within(0.1).of(now)
47+
5248
Timecop.return
5349
end
5450

@@ -58,56 +54,66 @@
5854
login_user(user)
5955
now = Time.now.in_time_zone
6056
Timecop.freeze(now)
61-
expect(user).to receive(:set_last_activity_at).with(be_within(0.1).of(now))
6257

6358
get :some_action
6459

60+
expect(user.reload.last_activity_at).to be_within(0.1).of(now)
61+
6562
Timecop.return
6663
end
6764

6865
it 'logs last IP address when logged in' do
6966
sorcery_controller_property_set(:register_last_ip_address, true)
70-
expect(user).to receive(:set_last_ip_address).with('0.0.0.0')
7167

7268
login_user(user)
69+
70+
expect(user.reload.last_login_from_ip_address).to eq('0.0.0.0')
7371
end
7472

7573
it 'updates nothing but activity fields' do
76-
pending 'Move to model'
77-
original_user_name = User.last.username
74+
sorcery_controller_property_set(:register_last_activity_time, true)
75+
user = User.last
76+
original_email = user.email
77+
original_activity_at = user.last_activity_at
7878
login_user(user)
7979
get :some_action_making_a_non_persisted_change_to_the_user
80-
81-
expect(User.last.username).to eq original_user_name
80+
user.reload
81+
expect(user.email).to eq original_email
82+
expect(user.last_activity_at).not_to eq original_activity_at
8283
end
8384

8485
it 'does not register login time if configured so' do
8586
sorcery_controller_property_set(:register_login_time, false)
8687

87-
expect(user).to receive(:set_last_login_at).never
8888
login_user(user)
89+
90+
expect(user.reload.last_login_at).to be_nil
8991
end
9092

9193
it 'does not register logout time if configured so' do
9294
sorcery_controller_property_set(:register_logout_time, false)
9395
login_user(user)
9496

95-
expect(user).to receive(:set_last_logout_at).never
9697
logout_user
98+
99+
expect(user.reload.last_logout_at).to be_nil
97100
end
98101

99102
it 'does not register last activity time if configured so' do
100103
sorcery_controller_property_set(:register_last_activity_time, false)
101104

102-
expect(user).to receive(:set_last_activity_at).never
103105
login_user(user)
106+
get :some_action
107+
108+
expect(user.reload.last_activity_at).to be_nil
104109
end
105110

106111
it 'does not register last IP address if configured so' do
107112
sorcery_controller_property_set(:register_last_ip_address, false)
108-
expect(user).to receive(:set_last_ip_address).never
109113

110114
login_user(user)
115+
116+
expect(user.reload.last_login_from_ip_address).to be_nil
111117
end
112118
end
113119
end
Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
require 'spec_helper'
22

33
describe SorceryController, type: :controller do
4-
let(:user) { double('user', id: 42, email: '[email protected]') }
4+
let!(:user) { User.create!(username: 'test_user', email: '[email protected]', password: 'password') }
55

66
def request_test_login
77
get :test_login, params: { email: '[email protected]', password: 'blabla' }
88
end
99

10-
# ----------------- SESSION TIMEOUT -----------------------
10+
# ----------------- BRUTE FORCE PROTECTION -----------------------
1111
describe 'brute force protection features' do
1212
before(:all) do
13+
MigrationHelper.migrate("#{Rails.root}/db/migrate/brute_force_protection")
1314
sorcery_reload!([:brute_force_protection])
1415
end
1516

16-
after(:each) do
17-
Sorcery::Controller::Config.reset!
18-
sorcery_controller_property_set(:user_class, User)
19-
Timecop.return
17+
after(:all) do
18+
MigrationHelper.rollback("#{Rails.root}/db/migrate/brute_force_protection")
2019
end
2120

2221
it 'counts login retries' do
@@ -29,13 +28,15 @@ def request_test_login
2928
end
3029

3130
it 'resets the counter on a good login' do
32-
# dirty hack for rails 4
33-
allow(@controller).to receive(:register_last_activity_time_to_db)
31+
# Set failed_logins_count to a non-zero value first
32+
user.update!(failed_logins_count: 3)
3433

3534
allow(User).to receive(:authenticate) { |&block| block.call(user, nil) }
36-
expect(user).to receive_message_chain(:sorcery_adapter, :update_attribute).with(:failed_logins_count, 0)
3735

3836
get :test_login, params: { email: '[email protected]', password: 'secret' }
37+
38+
user.reload
39+
expect(user.failed_logins_count).to eq(0)
3940
end
4041
end
4142
end

spec/controllers/controller_http_basic_auth_spec.rb

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require 'spec_helper'
22

33
describe SorceryController, type: :controller do
4-
let(:user) { double('user', id: 42, email: '[email protected]') }
4+
let!(:user) { User.create!(username: 'test_user', email: '[email protected]', password: 'password') }
55

66
describe 'with http basic auth features' do
77
before(:all) do
@@ -21,9 +21,6 @@
2121
end
2222

2323
it 'authenticates from http basic if credentials are sent' do
24-
# dirty hack for rails 4
25-
allow(subject).to receive(:register_last_activity_time_to_db)
26-
2724
@request.env['HTTP_AUTHORIZATION'] = "Basic #{Base64.encode64("#{user.email}:secret")}"
2825
expect(User).to receive('authenticate').with('[email protected]', 'secret').and_return(user)
2926
get :test_http_basic_auth, params: {}, session: { http_authentication_used: true }
@@ -53,15 +50,12 @@
5350
end
5451

5552
it "signs in the user's session on successful login" do
56-
# dirty hack for rails 4
57-
allow(controller).to receive(:register_last_activity_time_to_db)
58-
5953
@request.env['HTTP_AUTHORIZATION'] = "Basic #{Base64.encode64("#{user.email}:secret")}"
6054
expect(User).to receive('authenticate').with('[email protected]', 'secret').and_return(user)
6155

6256
get :test_http_basic_auth, params: {}, session: { http_authentication_used: true }
6357

64-
expect(session[:user_id]).to eq '42'
58+
expect(session[:user_id]).to eq user.id.to_s
6559
end
6660
end
6761
end

0 commit comments

Comments
 (0)