devise_token_auth_multi_email 0.9.3 → 0.9.5
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.
- checksums.yaml +4 -4
- data/README.md +3 -0
- data/Rakefile +4 -8
- data/app/controllers/devise_token_auth/concerns/resource_finder.rb +2 -9
- data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +35 -5
- data/app/controllers/devise_token_auth/registrations_controller.rb +24 -18
- data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +6 -3
- data/lib/devise_token_auth/engine.rb +40 -1
- data/lib/devise_token_auth/version.rb +1 -1
- data/lib/devise_token_auth_multi_email.rb +3 -0
- data/test/controllers/devise_token_auth/confirmations_controller_test.rb +4 -4
- data/test/controllers/devise_token_auth/multi_email_coexistence_test.rb +130 -0
- data/test/controllers/devise_token_auth/multi_email_confirmations_controller_test.rb +210 -0
- data/test/controllers/devise_token_auth/multi_email_passwords_controller_test.rb +247 -0
- data/test/controllers/devise_token_auth/multi_email_registrations_controller_test.rb +137 -0
- data/test/controllers/devise_token_auth/multi_email_sessions_controller_test.rb +191 -0
- data/test/controllers/devise_token_auth/multi_email_token_validations_controller_test.rb +140 -0
- data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +5 -4
- data/test/controllers/devise_token_auth/standard_user_registrations_controller_test.rb +165 -0
- data/test/coverage/assets/0.13.2/colorbox/loading.gif +0 -0
- data/test/coverage/assets/0.13.2/loading.gif +0 -0
- data/test/dummy/app/active_record/multi_email_user.rb +45 -0
- data/test/dummy/app/active_record/multi_email_user_email.rb +21 -0
- data/test/dummy/config/application.rb +6 -1
- data/test/dummy/config/initializers/omniauth.rb +15 -1
- data/test/dummy/config/routes.rb +8 -0
- data/test/dummy/db/migrate/20260401000001_devise_token_auth_create_multi_email_users.rb +49 -0
- data/test/dummy/db/migrate/20260401000002_devise_token_auth_create_multi_email_user_emails.rb +29 -0
- data/test/dummy/db/schema.rb +81 -41
- data/test/dummy/db/test.sqlite3-shm +0 -0
- data/test/dummy/tmp/generators/app/controllers/application_controller.rb +6 -0
- data/test/dummy/tmp/generators/app/models/{user.rb → azpire/v1/human_resource/user.rb} +1 -1
- data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +11 -5
- data/test/dummy/tmp/generators/db/migrate/{20210305040222_devise_token_auth_create_users.rb → 20260408021432_devise_token_auth_create_azpire_v1_human_resource_users.rb} +7 -7
- data/test/factories/users.rb +1 -0
- data/test/lib/devise_token_auth/controllers/helpers_test.rb +402 -0
- data/test/lib/devise_token_auth/token_factory_test.rb +18 -18
- data/test/lib/generators/devise_token_auth/install_generator_test.rb +60 -0
- data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +1 -1
- data/test/lib/generators/devise_token_auth/install_mongoid_generator_test.rb +218 -0
- data/test/models/multi_email_user_email_test.rb +95 -0
- data/test/models/multi_email_user_test.rb +225 -0
- data/test/test_helper.rb +21 -11
- data/test/validators/devise_token_auth_email_validator_test.rb +114 -0
- metadata +59 -27
- data/test/dummy/tmp/generators/app/models/mang.rb +0 -9
- data/test/dummy/tmp/generators/config/routes.rb +0 -9
- data/test/dummy/tmp/generators/db/migrate/20210305040222_devise_token_auth_create_mangs.rb +0 -49
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
require 'generators/devise_token_auth/install_mongoid_generator'
|
|
6
|
+
|
|
7
|
+
module DeviseTokenAuth
|
|
8
|
+
class InstallMongoidGeneratorTest < Rails::Generators::TestCase
|
|
9
|
+
tests InstallMongoidGenerator
|
|
10
|
+
destination Rails.root.join('tmp/generators')
|
|
11
|
+
|
|
12
|
+
describe 'default values, clean install' do
|
|
13
|
+
setup :prepare_destination
|
|
14
|
+
|
|
15
|
+
before do
|
|
16
|
+
run_generator
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test 'user model is created from mongoid template' do
|
|
20
|
+
assert_file 'app/models/user.rb'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
test 'created user model includes Mongoid::Document' do
|
|
24
|
+
assert_file 'app/models/user.rb' do |model|
|
|
25
|
+
assert_match(/include Mongoid::Document/, model)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
test 'created user model includes Mongoid::Timestamps' do
|
|
30
|
+
assert_file 'app/models/user.rb' do |model|
|
|
31
|
+
assert_match(/include Mongoid::Timestamps/, model)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
test 'created user model includes Mongoid::Locker' do
|
|
36
|
+
assert_file 'app/models/user.rb' do |model|
|
|
37
|
+
assert_match(/include Mongoid::Locker/, model)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test 'created user model declares locker fields' do
|
|
42
|
+
assert_file 'app/models/user.rb' do |model|
|
|
43
|
+
assert_match(/field :locker_locked_at/, model)
|
|
44
|
+
assert_match(/field :locker_locked_until/, model)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
test 'created user model declares required devise token auth fields' do
|
|
49
|
+
assert_file 'app/models/user.rb' do |model|
|
|
50
|
+
assert_match(/field :provider/, model)
|
|
51
|
+
assert_match(/field :uid/, model)
|
|
52
|
+
assert_match(/field :tokens/, model)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
test 'created user model includes devise' do
|
|
57
|
+
assert_file 'app/models/user.rb' do |model|
|
|
58
|
+
assert_match(/devise :database_authenticatable/, model)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
test 'created user model includes DeviseTokenAuth concern' do
|
|
63
|
+
assert_file 'app/models/user.rb' do |model|
|
|
64
|
+
assert_match(/include DeviseTokenAuth::Concerns::User/, model)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
test 'created user model declares uid_provider_index' do
|
|
69
|
+
assert_file 'app/models/user.rb' do |model|
|
|
70
|
+
assert_match(/uid_provider_index/, model)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
test 'initializer is created' do
|
|
75
|
+
assert_file 'config/initializers/devise_token_auth.rb'
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
test 'subsequent runs raise no errors' do
|
|
79
|
+
run_generator
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe 'existing user model' do
|
|
84
|
+
setup :prepare_destination
|
|
85
|
+
|
|
86
|
+
before do
|
|
87
|
+
@dir = File.join(destination_root, 'app', 'models')
|
|
88
|
+
@fname = File.join(@dir, 'user.rb')
|
|
89
|
+
FileUtils.mkdir_p(@dir)
|
|
90
|
+
|
|
91
|
+
File.open(@fname, 'w') do |f|
|
|
92
|
+
f.write <<-'RUBY'
|
|
93
|
+
class User
|
|
94
|
+
|
|
95
|
+
def whatever
|
|
96
|
+
puts 'whatever'
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
RUBY
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
run_generator
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
test 'concern is injected into existing model' do
|
|
106
|
+
assert_file 'app/models/user.rb' do |model|
|
|
107
|
+
assert_match(/include DeviseTokenAuth::Concerns::User/, model)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
test 'mongoid locker fields are injected into existing model' do
|
|
112
|
+
assert_file 'app/models/user.rb' do |model|
|
|
113
|
+
assert_match(/include Mongoid::Locker/, model)
|
|
114
|
+
assert_match(/field :locker_locked_at/, model)
|
|
115
|
+
assert_match(/field :locker_locked_until/, model)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
test 'required fields are injected into existing model' do
|
|
120
|
+
assert_file 'app/models/user.rb' do |model|
|
|
121
|
+
assert_match(/field :provider/, model)
|
|
122
|
+
assert_match(/field :uid/, model)
|
|
123
|
+
assert_match(/field :tokens/, model)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
test 'devise declaration is injected into existing model' do
|
|
128
|
+
assert_file 'app/models/user.rb' do |model|
|
|
129
|
+
assert_match(/devise :database_authenticatable/, model)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
test 'index declaration is injected into existing model' do
|
|
134
|
+
assert_file 'app/models/user.rb' do |model|
|
|
135
|
+
assert_match(/uid_provider_index/, model)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
test 'subsequent runs do not duplicate the concern inclusion' do
|
|
140
|
+
run_generator
|
|
141
|
+
assert_file 'app/models/user.rb' do |model|
|
|
142
|
+
matches = model.scan(/include DeviseTokenAuth::Concerns::User/m).size
|
|
143
|
+
assert_equal 1, matches
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
describe 'routes' do
|
|
149
|
+
setup :prepare_destination
|
|
150
|
+
|
|
151
|
+
before do
|
|
152
|
+
@dir = File.join(destination_root, 'config')
|
|
153
|
+
@fname = File.join(@dir, 'routes.rb')
|
|
154
|
+
FileUtils.mkdir_p(@dir)
|
|
155
|
+
|
|
156
|
+
File.open(@fname, 'w') do |f|
|
|
157
|
+
f.write <<-RUBY
|
|
158
|
+
Rails.application.routes.draw do
|
|
159
|
+
patch '/chong', to: 'bong#index'
|
|
160
|
+
end
|
|
161
|
+
RUBY
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
run_generator
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
test 'route method is appended to routes file' do
|
|
168
|
+
assert_file 'config/routes.rb' do |routes|
|
|
169
|
+
assert_match(/mount_devise_token_auth_for 'User', at: 'auth'/, routes)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
test 'subsequent runs do not add duplicate routes' do
|
|
174
|
+
run_generator
|
|
175
|
+
assert_file 'config/routes.rb' do |routes|
|
|
176
|
+
matches = routes.scan(/mount_devise_token_auth_for 'User', at: 'auth'/m).size
|
|
177
|
+
assert_equal 1, matches
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
describe 'application controller' do
|
|
183
|
+
setup :prepare_destination
|
|
184
|
+
|
|
185
|
+
before do
|
|
186
|
+
@dir = File.join(destination_root, 'app', 'controllers')
|
|
187
|
+
@fname = File.join(@dir, 'application_controller.rb')
|
|
188
|
+
FileUtils.mkdir_p(@dir)
|
|
189
|
+
|
|
190
|
+
File.open(@fname, 'w') do |f|
|
|
191
|
+
f.write <<-RUBY
|
|
192
|
+
class ApplicationController < ActionController::Base
|
|
193
|
+
def whatever
|
|
194
|
+
'whatever'
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
RUBY
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
run_generator
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
test 'controller concern is appended to application controller' do
|
|
204
|
+
assert_file 'app/controllers/application_controller.rb' do |controller|
|
|
205
|
+
assert_match(/include DeviseTokenAuth::Concerns::SetUserByToken/, controller)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
test 'subsequent runs do not duplicate the concern inclusion' do
|
|
210
|
+
run_generator
|
|
211
|
+
assert_file 'app/controllers/application_controller.rb' do |controller|
|
|
212
|
+
matches = controller.scan(/include DeviseTokenAuth::Concerns::SetUserByToken/m).size
|
|
213
|
+
assert_equal 1, matches
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
# Tests for the MultiEmailUserEmail model — the email-record side of the
|
|
6
|
+
# MultiEmailUser multi-email relationship. These tests are ActiveRecord-only
|
|
7
|
+
# because the model and its table only exist in AR runs.
|
|
8
|
+
return unless DEVISE_TOKEN_AUTH_ORM == :active_record
|
|
9
|
+
|
|
10
|
+
class MultiEmailUserEmailTest < ActiveSupport::TestCase
|
|
11
|
+
describe MultiEmailUserEmail do
|
|
12
|
+
# -------------------------------------------------------------------------
|
|
13
|
+
# Association
|
|
14
|
+
# -------------------------------------------------------------------------
|
|
15
|
+
describe 'association' do
|
|
16
|
+
test 'belongs_to user association points to MultiEmailUser' do
|
|
17
|
+
reflection = MultiEmailUserEmail.reflect_on_association(:user)
|
|
18
|
+
assert reflection, 'Expected a :user belongs_to association'
|
|
19
|
+
assert_equal 'MultiEmailUser', reflection.class_name
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
test 'foreign key for the user association is multi_email_user_id' do
|
|
23
|
+
reflection = MultiEmailUserEmail.reflect_on_association(:user)
|
|
24
|
+
assert_equal 'multi_email_user_id', reflection.foreign_key.to_s
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
test 'email record is destroyed when parent user is destroyed' do
|
|
28
|
+
user = MultiEmailUser.new(provider: 'email', uid: '')
|
|
29
|
+
user.emails.build(email: Faker::Internet.unique.email, primary: true)
|
|
30
|
+
user.password = user.password_confirmation = 'password123'
|
|
31
|
+
user.save(validate: false)
|
|
32
|
+
|
|
33
|
+
email_id = user.emails.first.id
|
|
34
|
+
user.destroy
|
|
35
|
+
|
|
36
|
+
refute MultiEmailUserEmail.exists?(email_id),
|
|
37
|
+
'Email record should be destroyed when the parent user is destroyed'
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# -------------------------------------------------------------------------
|
|
42
|
+
# Primary flag
|
|
43
|
+
# -------------------------------------------------------------------------
|
|
44
|
+
describe 'primary column' do
|
|
45
|
+
test 'primary? returns true when primary is true' do
|
|
46
|
+
email_record = MultiEmailUserEmail.new(primary: true)
|
|
47
|
+
assert email_record.primary?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
test 'primary? returns false when primary is false' do
|
|
51
|
+
email_record = MultiEmailUserEmail.new(primary: false)
|
|
52
|
+
refute email_record.primary?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
test 'primary defaults to false' do
|
|
56
|
+
email_record = MultiEmailUserEmail.new
|
|
57
|
+
refute email_record.primary?,
|
|
58
|
+
'primary should default to false per the migration'
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# -------------------------------------------------------------------------
|
|
63
|
+
# Email uniqueness (added by Devise::MultiEmail::EmailValidatable)
|
|
64
|
+
# -------------------------------------------------------------------------
|
|
65
|
+
describe 'email uniqueness' do
|
|
66
|
+
# Trigger ParentModelExtensions setup so EmailValidatable is included
|
|
67
|
+
before { MultiEmailUser }
|
|
68
|
+
|
|
69
|
+
test 'has an email UniquenessValidator (added by EmailValidatable)' do
|
|
70
|
+
assert MultiEmailUserEmail.validators_on(:email).any? { |v|
|
|
71
|
+
v.is_a?(ActiveRecord::Validations::UniquenessValidator)
|
|
72
|
+
}, 'Expected UniquenessValidator on MultiEmailUserEmail#email from EmailValidatable'
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
test 'two email records with the same address are invalid' do
|
|
76
|
+
shared_email = Faker::Internet.unique.email
|
|
77
|
+
|
|
78
|
+
user1 = MultiEmailUser.new(provider: 'email', uid: '')
|
|
79
|
+
user1.emails.build(email: shared_email, primary: true)
|
|
80
|
+
user1.password = user1.password_confirmation = 'password123'
|
|
81
|
+
user1.save(validate: false)
|
|
82
|
+
|
|
83
|
+
user2 = MultiEmailUser.new(provider: 'email', uid: '')
|
|
84
|
+
email_record = user2.emails.build(email: shared_email, primary: true)
|
|
85
|
+
user2.password = user2.password_confirmation = 'password123'
|
|
86
|
+
|
|
87
|
+
# The email record itself should fail uniqueness validation
|
|
88
|
+
refute email_record.valid?,
|
|
89
|
+
'Expected duplicate email record to be invalid'
|
|
90
|
+
assert email_record.errors[:email].any? { |e| e.include?('taken') },
|
|
91
|
+
"Expected 'taken' error on email, got: #{email_record.errors[:email].inspect}"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
# Tests for the MultiEmailUser model — the AR model that uses devise-multi_email
|
|
6
|
+
# alongside DeviseTokenAuth. These tests are ActiveRecord-only because
|
|
7
|
+
# MultiEmailUser and its email association table are not available in Mongoid
|
|
8
|
+
# runs.
|
|
9
|
+
return unless DEVISE_TOKEN_AUTH_ORM == :active_record
|
|
10
|
+
|
|
11
|
+
class MultiEmailUserTest < ActiveSupport::TestCase
|
|
12
|
+
describe MultiEmailUser do
|
|
13
|
+
# -------------------------------------------------------------------------
|
|
14
|
+
# Model configuration
|
|
15
|
+
# -------------------------------------------------------------------------
|
|
16
|
+
describe 'model configuration' do
|
|
17
|
+
test 'has multi_email_association class method (added by :multi_email_authenticatable)' do
|
|
18
|
+
assert MultiEmailUser.respond_to?(:multi_email_association)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test 'has emails has_many association' do
|
|
22
|
+
assert MultiEmailUser.reflect_on_association(:emails),
|
|
23
|
+
'Expected MultiEmailUser to have an :emails association'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
test 'has find_by_email class method (added by MultiEmailAuthenticatable::ClassMethods)' do
|
|
27
|
+
assert MultiEmailUser.respond_to?(:find_by_email)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test 'does NOT carry a column-level email uniqueness validator' do
|
|
31
|
+
# email uniqueness is managed by the emails association table, not the
|
|
32
|
+
# user model itself
|
|
33
|
+
refute MultiEmailUser.validators_on(:email).any? { |v|
|
|
34
|
+
v.is_a?(ActiveRecord::Validations::UniquenessValidator)
|
|
35
|
+
}, 'MultiEmailUser should NOT have an email UniquenessValidator on the model'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test 'includes DeviseTokenAuth::Concerns::User' do
|
|
39
|
+
assert MultiEmailUser.ancestors.include?(DeviseTokenAuth::Concerns::User)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
test 'has devise module multi_email_authenticatable' do
|
|
43
|
+
assert MultiEmailUser.devise_modules.include?(:multi_email_authenticatable)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# -------------------------------------------------------------------------
|
|
48
|
+
# Serialization
|
|
49
|
+
# -------------------------------------------------------------------------
|
|
50
|
+
describe 'serialization' do
|
|
51
|
+
test 'tokens are not exposed in as_json' do
|
|
52
|
+
@resource = build(:multi_email_user)
|
|
53
|
+
refute @resource.as_json.key?('tokens'),
|
|
54
|
+
'tokens should be excluded from as_json output'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
test 'email is included in as_json via :methods delegation' do
|
|
58
|
+
# MultiEmailUser overrides as_json to include :email as a method so
|
|
59
|
+
# the delegated primary email appears in API responses.
|
|
60
|
+
@resource = build(:multi_email_user)
|
|
61
|
+
json_keys = @resource.as_json.keys
|
|
62
|
+
assert json_keys.include?('email'),
|
|
63
|
+
"Expected 'email' in as_json output, got: #{json_keys.inspect}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# -------------------------------------------------------------------------
|
|
68
|
+
# Creation — uid is required for non-email (OAuth) providers
|
|
69
|
+
# -------------------------------------------------------------------------
|
|
70
|
+
describe 'creation' do
|
|
71
|
+
test 'save fails when uid is missing for OAuth provider' do
|
|
72
|
+
# For email providers, uid is auto-synced from the primary email via the
|
|
73
|
+
# sync_uid before_save callback. The explicit presence validation on uid
|
|
74
|
+
# only applies to non-email (OAuth) providers.
|
|
75
|
+
@resource = MultiEmailUser.new(provider: 'facebook')
|
|
76
|
+
@resource.uid = nil
|
|
77
|
+
@resource.save
|
|
78
|
+
|
|
79
|
+
assert @resource.errors[:uid].present?,
|
|
80
|
+
'Expected a validation error on :uid when provider is non-email and uid is nil'
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# -------------------------------------------------------------------------
|
|
85
|
+
# Email association and delegation
|
|
86
|
+
# -------------------------------------------------------------------------
|
|
87
|
+
describe 'email association' do
|
|
88
|
+
test 'email record is created when user is registered via the gem' do
|
|
89
|
+
# Simulate what the gem does: build a user and add an email record via
|
|
90
|
+
# the association directly (mirrors what :multi_email_authenticatable
|
|
91
|
+
# does internally on registration).
|
|
92
|
+
@resource = MultiEmailUser.new(provider: 'email', uid: '')
|
|
93
|
+
@resource.emails.build(email: Faker::Internet.unique.email, primary: true)
|
|
94
|
+
@resource.password = @resource.password_confirmation = 'password123'
|
|
95
|
+
@resource.save(validate: false) # bypass confirmable for unit test
|
|
96
|
+
|
|
97
|
+
assert_equal 1, @resource.emails.count
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
test 'primary email record is flagged as primary' do
|
|
101
|
+
@resource = MultiEmailUser.new(provider: 'email', uid: '')
|
|
102
|
+
email_addr = Faker::Internet.unique.email
|
|
103
|
+
@resource.emails.build(email: email_addr, primary: true)
|
|
104
|
+
@resource.password = @resource.password_confirmation = 'password123'
|
|
105
|
+
@resource.save(validate: false)
|
|
106
|
+
|
|
107
|
+
assert @resource.emails.first.primary?,
|
|
108
|
+
'Expected the first email record to be marked primary'
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
test 'email delegation returns the primary email address' do
|
|
112
|
+
@resource = MultiEmailUser.new(provider: 'email', uid: '')
|
|
113
|
+
email_addr = Faker::Internet.unique.email
|
|
114
|
+
@resource.emails.build(email: email_addr, primary: true)
|
|
115
|
+
@resource.password = @resource.password_confirmation = 'password123'
|
|
116
|
+
@resource.save(validate: false)
|
|
117
|
+
|
|
118
|
+
assert_equal email_addr, @resource.email
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# -------------------------------------------------------------------------
|
|
123
|
+
# Token management — mirrors user_test.rb but for MultiEmailUser
|
|
124
|
+
# -------------------------------------------------------------------------
|
|
125
|
+
describe 'token expiry' do
|
|
126
|
+
before do
|
|
127
|
+
@resource = MultiEmailUser.new(provider: 'email', uid: '')
|
|
128
|
+
email_addr = Faker::Internet.unique.email
|
|
129
|
+
@resource.emails.build(email: email_addr, primary: true)
|
|
130
|
+
@resource.password = @resource.password_confirmation = 'password123'
|
|
131
|
+
@resource.save(validate: false)
|
|
132
|
+
|
|
133
|
+
@auth_headers = @resource.create_new_auth_token
|
|
134
|
+
@token = @auth_headers['access-token']
|
|
135
|
+
@client_id = @auth_headers['client']
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
test 'token_is_current? returns true for a fresh token' do
|
|
139
|
+
assert @resource.token_is_current?(@token, @client_id)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
test 'token_is_current? returns false for an expired token' do
|
|
143
|
+
@resource.tokens[@client_id]['expiry'] = Time.zone.now.to_i - 10.seconds
|
|
144
|
+
refute @resource.token_is_current?(@token, @client_id)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
describe 'valid_token?' do
|
|
149
|
+
before do
|
|
150
|
+
@resource = MultiEmailUser.new(provider: 'email', uid: '')
|
|
151
|
+
@resource.emails.build(email: Faker::Internet.unique.email, primary: true)
|
|
152
|
+
@resource.password = @resource.password_confirmation = 'password123'
|
|
153
|
+
@resource.save(validate: false)
|
|
154
|
+
|
|
155
|
+
@auth_headers = @resource.create_new_auth_token
|
|
156
|
+
@token = @auth_headers['access-token']
|
|
157
|
+
@client_id = @auth_headers['client']
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
test 'returns true for a valid token/client pair' do
|
|
161
|
+
assert @resource.valid_token?(@token, @client_id)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
test 'returns false when client does not exist' do
|
|
165
|
+
refute @resource.valid_token?(@token, 'nonexistent_client')
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
test 'returns false when token is wrong' do
|
|
169
|
+
refute @resource.valid_token?('wrong_token', @client_id)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe 'expired tokens are destroyed on save' do
|
|
174
|
+
before do
|
|
175
|
+
@resource = MultiEmailUser.new(provider: 'email', uid: '')
|
|
176
|
+
@resource.emails.build(email: Faker::Internet.unique.email, primary: true)
|
|
177
|
+
@resource.password = @resource.password_confirmation = 'password123'
|
|
178
|
+
@resource.save(validate: false)
|
|
179
|
+
|
|
180
|
+
@old_auth_headers = @resource.create_new_auth_token
|
|
181
|
+
@new_auth_headers = @resource.create_new_auth_token
|
|
182
|
+
expire_token(@resource, @old_auth_headers['client'])
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
test 'expired token is removed from tokens' do
|
|
186
|
+
refute @resource.tokens[@old_auth_headers['client']],
|
|
187
|
+
'Expired token should have been removed'
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
test 'current token is not removed' do
|
|
191
|
+
assert @resource.tokens[@new_auth_headers['client']],
|
|
192
|
+
'Current token should still be present'
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
describe 'nil tokens are handled properly' do
|
|
197
|
+
before do
|
|
198
|
+
@resource = MultiEmailUser.new(provider: 'email', uid: '')
|
|
199
|
+
@resource.emails.build(email: Faker::Internet.unique.email, primary: true)
|
|
200
|
+
@resource.password = @resource.password_confirmation = 'password123'
|
|
201
|
+
@resource.save(validate: false)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
test 'tokens can be set to nil and record still saves' do
|
|
205
|
+
@resource.tokens = nil
|
|
206
|
+
assert @resource.save
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# -------------------------------------------------------------------------
|
|
211
|
+
# Password requirements
|
|
212
|
+
# -------------------------------------------------------------------------
|
|
213
|
+
describe 'password_required?' do
|
|
214
|
+
test 'password is not required for OAuth (non-email) provider' do
|
|
215
|
+
@resource = MultiEmailUser.new(provider: 'facebook', uid: '12345')
|
|
216
|
+
refute @resource.password_required?
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
test 'password is required for email provider' do
|
|
220
|
+
@resource = MultiEmailUser.new(provider: 'email', uid: 'test@example.com')
|
|
221
|
+
assert @resource.password_required?
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
data/test/test_helper.rb
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'simplecov'
|
|
4
|
-
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
|
|
5
|
-
SimpleCov.start 'rails' do
|
|
6
|
-
add_filter ['.bundle', 'test', 'config']
|
|
7
|
-
end
|
|
8
4
|
|
|
9
5
|
if ENV['CI']
|
|
10
6
|
require 'coveralls'
|
|
11
|
-
Coveralls
|
|
7
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
|
8
|
+
else
|
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
SimpleCov.start 'rails' do
|
|
13
|
+
add_filter ['.bundle', 'test', 'config']
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
ENV['RAILS_ENV'] = 'test'
|
|
@@ -18,7 +20,11 @@ puts "\n==> DeviseTokenAuth.orm = #{DEVISE_TOKEN_AUTH_ORM.inspect}"
|
|
|
18
20
|
|
|
19
21
|
require File.expand_path('dummy/config/environment', __dir__)
|
|
20
22
|
require 'active_support/testing/autorun'
|
|
21
|
-
|
|
23
|
+
# Replace minitest/rails with plain minitest to avoid SIGTRAP on Ruby 3.3.6/ARM64
|
|
24
|
+
require 'minitest'
|
|
25
|
+
require 'minitest/spec'
|
|
26
|
+
require 'minitest/reporters'
|
|
27
|
+
# Load mocha after minitest but before running tests
|
|
22
28
|
require 'mocha/minitest'
|
|
23
29
|
if DEVISE_TOKEN_AUTH_ORM == :active_record
|
|
24
30
|
require 'database_cleaner'
|
|
@@ -48,11 +54,15 @@ class ActiveSupport::TestCase
|
|
|
48
54
|
ActiveRecord::Migration.check_pending!
|
|
49
55
|
end
|
|
50
56
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
if DEVISE_TOKEN_AUTH_ORM == :active_record
|
|
58
|
+
DatabaseCleaner.strategy = :transaction
|
|
59
|
+
setup { DatabaseCleaner.start }
|
|
60
|
+
teardown { DatabaseCleaner.clean }
|
|
61
|
+
else
|
|
62
|
+
DatabaseCleaner[:mongoid].strategy = :deletion
|
|
63
|
+
setup { DatabaseCleaner[:mongoid].start }
|
|
64
|
+
teardown { DatabaseCleaner[:mongoid].clean }
|
|
65
|
+
end
|
|
56
66
|
|
|
57
67
|
# Add more helper methods to be used by all tests here...
|
|
58
68
|
|