Skip to content

Commit e711e03

Browse files
test: add unit tests for two-factor model, strategy, and registration
Add model tests for TwoFactorAuthenticatable (enabled/disabled states, multiple methods, unknown method errors, model concern inclusion). Add strategy tests for the base TwoFactor strategy. Add registration tests for register_two_factor_method in devise_test.
1 parent 5509d98 commit e711e03

3 files changed

Lines changed: 152 additions & 0 deletions

File tree

test/devise_test.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,39 @@ class DeviseTest < ActiveSupport::TestCase
8686
Devise::CONTROLLERS.delete(:kivi)
8787
end
8888

89+
test 'register_two_factor_method stores config and populates STRATEGIES' do
90+
Devise.register_two_factor_method(:fake_2fa, model: 'devise/models/fake_2fa', strategy: :fake_2fa_strategy)
91+
assert_equal({ model: 'devise/models/fake_2fa', strategy: :fake_2fa_strategy }, Devise.two_factor_method_configs[:fake_2fa])
92+
assert_equal :fake_2fa_strategy, Devise::STRATEGIES[:fake_2fa]
93+
ensure
94+
Devise.two_factor_method_configs.delete(:fake_2fa)
95+
Devise::STRATEGIES.delete(:fake_2fa)
96+
end
97+
98+
test 'register_two_factor_method with route populates ROUTES and URL_HELPERS' do
99+
Devise.register_two_factor_method(:fake_rt, model: 'x', route: { fake_rt: [nil, :new] })
100+
assert_equal :fake_rt, Devise::ROUTES[:fake_rt]
101+
assert_equal [nil, :new], Devise::URL_HELPERS[:fake_rt]
102+
ensure
103+
Devise.two_factor_method_configs.delete(:fake_rt)
104+
Devise::ROUTES.delete(:fake_rt)
105+
Devise::URL_HELPERS.delete(:fake_rt)
106+
end
107+
108+
test 'register_two_factor_method rejects unknown options' do
109+
assert_raises(ArgumentError) do
110+
Devise.register_two_factor_method(:bad, model: 'x', unknown: true)
111+
end
112+
end
113+
114+
test 'add_module no longer accepts two_factor option' do
115+
assert_raises(ArgumentError) do
116+
Devise.add_module(:test_mod, two_factor: true)
117+
end
118+
ensure
119+
Devise::ALL.delete(:test_mod)
120+
end
121+
89122
test 'Devise.secure_compare fails when comparing different strings or nil' do
90123
[nil, ""].each do |empty|
91124
assert_not Devise.secure_compare(empty, "something")
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
5+
class TwoFactorAuthenticatableTest < ActiveSupport::TestCase
6+
test '.two_factor_modules returns the configured two_factor_methods' do
7+
klass = Class.new do
8+
extend Devise::Models::TwoFactorAuthenticatable::ClassMethods
9+
end
10+
klass.instance_variable_set(:@two_factor_methods, [:fake_method])
11+
12+
assert_equal [:fake_method], klass.two_factor_modules
13+
end
14+
15+
test '.two_factor_modules returns empty array when no methods configured' do
16+
klass = Class.new do
17+
extend Devise::Models::TwoFactorAuthenticatable::ClassMethods
18+
end
19+
20+
assert_equal [], klass.two_factor_modules
21+
end
22+
23+
test '#two_factor_enabled? returns true when any method reports enabled' do
24+
klass = Class.new do
25+
include Devise::Models::TwoFactorAuthenticatable
26+
end
27+
klass.instance_variable_set(:@two_factor_methods, [:fake_method])
28+
29+
instance = klass.new
30+
instance.define_singleton_method(:fake_method_two_factor_enabled?) { true }
31+
32+
assert instance.two_factor_enabled?
33+
assert_equal [:fake_method], instance.enabled_two_factors
34+
end
35+
36+
test '#two_factor_enabled? returns false when no method reports enabled' do
37+
klass = Class.new do
38+
include Devise::Models::TwoFactorAuthenticatable
39+
end
40+
klass.instance_variable_set(:@two_factor_methods, [:fake_method])
41+
42+
instance = klass.new
43+
instance.define_singleton_method(:fake_method_two_factor_enabled?) { false }
44+
45+
assert_not instance.two_factor_enabled?
46+
assert_empty instance.enabled_two_factors
47+
end
48+
49+
test '#enabled_two_factors returns only enabled methods' do
50+
klass = Class.new do
51+
include Devise::Models::TwoFactorAuthenticatable
52+
end
53+
klass.instance_variable_set(:@two_factor_methods, [:method_a, :method_b])
54+
55+
instance = klass.new
56+
instance.define_singleton_method(:method_a_two_factor_enabled?) { true }
57+
instance.define_singleton_method(:method_b_two_factor_enabled?) { false }
58+
59+
assert_equal [:method_a], instance.enabled_two_factors
60+
end
61+
62+
test '.two_factor_methods= raises on unknown method' do
63+
klass = Class.new do
64+
extend Devise::Models::TwoFactorAuthenticatable::ClassMethods
65+
end
66+
67+
assert_raises(RuntimeError, /Unknown two-factor method/) do
68+
klass.two_factor_methods = [:nonexistent]
69+
end
70+
end
71+
72+
test '.two_factor_methods= includes model concern from registry' do
73+
# Register a fake method
74+
Devise.register_two_factor_method(:includable_test,
75+
model: 'devise/models/test_otp',
76+
strategy: :test_strategy)
77+
78+
klass = Class.new do
79+
extend Devise::Models::TwoFactorAuthenticatable::ClassMethods
80+
81+
# Stub include to track what gets included
82+
def self.included_modules_tracker
83+
@included_modules_tracker ||= []
84+
end
85+
86+
def self.include(mod)
87+
included_modules_tracker << mod
88+
super
89+
end
90+
end
91+
92+
klass.two_factor_methods = [:includable_test]
93+
assert_equal [:includable_test], Array(klass.instance_variable_get(:@two_factor_methods))
94+
ensure
95+
Devise.two_factor_method_configs.delete(:includable_test)
96+
Devise::STRATEGIES.delete(:includable_test)
97+
end
98+
end

test/strategies/two_factor_test.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
5+
class TwoFactorStrategyTest < ActiveSupport::TestCase
6+
test 'TwoFactor strategy can be loaded' do
7+
assert defined?(Devise::Strategies::TwoFactor)
8+
end
9+
10+
test 'TwoFactor base strategy is never valid' do
11+
strategy = Devise::Strategies::TwoFactor.new(nil)
12+
assert_equal false, strategy.valid?
13+
end
14+
15+
test 'verify_two_factor! raises NotImplementedError by default' do
16+
strategy = Devise::Strategies::TwoFactor.new(nil)
17+
assert_raises(NotImplementedError) do
18+
strategy.verify_two_factor!(Object.new)
19+
end
20+
end
21+
end

0 commit comments

Comments
 (0)