omniauth-identity 3.0.2 → 3.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,123 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class ExampleModel
4
- include OmniAuth::Identity::Model
5
- end
6
-
7
3
  RSpec.describe OmniAuth::Identity::Model do
8
- context 'Class Methods' do
9
- subject { ExampleModel }
10
-
11
- describe '.locate' do
12
- it('is abstract') { expect { subject.locate('abc') }.to raise_error(NotImplementedError) }
4
+ before do
5
+ identity_test_klass = Class.new do
6
+ include OmniAuth::Identity::Model
13
7
  end
8
+ stub_const('IdentityTestClass', identity_test_klass)
9
+ end
14
10
 
15
- describe '.authenticate' do
16
- it 'calls locate and then authenticate' do
17
- mocked_instance = double('ExampleModel', authenticate: 'abbadoo')
18
- allow(subject).to receive(:locate).with('email' => 'example').and_return(mocked_instance)
19
- expect(subject.authenticate({ 'email' => 'example' }, 'pass')).to eq('abbadoo')
20
- end
11
+ describe 'Class Methods' do
12
+ subject(:model_klass) { IdentityTestClass }
21
13
 
22
- it 'calls locate with additional scopes when provided' do
23
- mocked_instance = double('ExampleModel', authenticate: 'abbadoo')
24
- allow(subject).to receive(:locate).with('email' => 'example',
25
- 'user_type' => 'admin').and_return(mocked_instance)
26
- expect(subject.authenticate({ 'email' => 'example', 'user_type' => 'admin' }, 'pass')).to eq('abbadoo')
27
- end
14
+ include_context 'model with class methods'
28
15
 
29
- it 'recovers gracefully if locate is nil' do
30
- allow(subject).to receive(:locate).and_return(nil)
31
- expect(subject.authenticate('blah', 'foo')).to be false
16
+ describe '::locate' do
17
+ it('is abstract') do
18
+ expect { model_klass.locate('email' => 'example') }.to raise_error(NotImplementedError)
32
19
  end
33
20
  end
34
21
  end
35
22
 
36
- context 'Instance Methods' do
37
- subject { ExampleModel.new }
23
+ describe 'Instance Methods' do
24
+ subject(:instance) { IdentityTestClass.new }
38
25
 
39
- describe '#authenticate' do
40
- it('is abstract') { expect { subject.authenticate('abc') }.to raise_error(NotImplementedError) }
41
- end
26
+ include_context 'instance with instance methods'
42
27
 
43
- describe '#uid' do
44
- it 'defaults to #id' do
45
- allow(subject).to receive(:respond_to?).with(:id).and_return(true)
46
- allow(subject).to receive(:id).and_return 'wakka-do'
47
- expect(subject.uid).to eq('wakka-do')
48
- end
49
-
50
- it 'stringifies it' do
51
- allow(subject).to receive(:id).and_return 123
52
- expect(subject.uid).to eq('123')
53
- end
54
-
55
- it 'raises NotImplementedError if #id is not defined' do
56
- allow(subject).to receive(:respond_to?).with(:id).and_return(false)
57
- expect { subject.uid }.to raise_error(NotImplementedError)
58
- end
28
+ describe '#authenticate' do
29
+ it('is abstract') { expect { instance.authenticate('my-password') }.to raise_error(NotImplementedError) }
59
30
  end
60
31
 
61
32
  describe '#auth_key' do
62
- it 'defaults to #email' do
63
- allow(subject).to receive(:respond_to?).with(:email).and_return(true)
64
- allow(subject).to receive(:email).and_return('bob@bob.com')
65
- expect(subject.auth_key).to eq('bob@bob.com')
66
- end
67
-
68
- it 'uses the class .auth_key' do
69
- subject.class.auth_key 'login'
70
- allow(subject).to receive(:login).and_return 'bob'
71
- expect(subject.auth_key).to eq('bob')
72
- subject.class.auth_key nil
73
- end
74
-
75
33
  it 'raises a NotImplementedError if the auth_key method is not defined' do
76
- expect { subject.auth_key }.to raise_error(NotImplementedError)
34
+ expect { instance.auth_key }.to raise_error(NotImplementedError)
77
35
  end
78
36
  end
79
37
 
80
38
  describe '#auth_key=' do
81
- it 'defaults to setting email' do
82
- allow(subject).to receive(:respond_to?).with(:email=).and_return(true)
83
- expect(subject).to receive(:email=).with 'abc'
84
-
85
- subject.auth_key = 'abc'
86
- end
87
-
88
- it 'uses a custom .auth_key if one is provided' do
89
- subject.class.auth_key 'login'
90
- allow(subject).to receive(:respond_to?).with(:login=).and_return(true)
91
- expect(subject).to receive(:login=).with('abc')
92
-
93
- subject.auth_key = 'abc'
94
- end
95
-
96
- it 'raises a NotImplementedError if the autH_key method is not defined' do
97
- expect { subject.auth_key = 'broken' }.to raise_error(NotImplementedError)
98
- end
99
- end
100
-
101
- describe '#info' do
102
- it 'includes attributes that are set' do
103
- allow(subject).to receive(:name).and_return('Bob Bobson')
104
- allow(subject).to receive(:nickname).and_return('bob')
105
-
106
- expect(subject.info).to eq({
107
- 'name' => 'Bob Bobson',
108
- 'nickname' => 'bob'
109
- })
110
- end
111
-
112
- it 'automaticallies set name off of nickname' do
113
- allow(subject).to receive(:nickname).and_return('bob')
114
- subject.info['name'] == 'bob'
115
- end
116
-
117
- it 'does not overwrite a provided name' do
118
- allow(subject).to receive(:name).and_return('Awesome Dude')
119
- allow(subject).to receive(:first_name).and_return('Frank')
120
- expect(subject.info['name']).to eq('Awesome Dude')
39
+ it 'raises a NotImplementedError if the auth_key method is not defined' do
40
+ expect { instance.auth_key = 'broken' }.to raise_error(NotImplementedError)
121
41
  end
122
42
  end
123
43
  end
@@ -1,11 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.describe(OmniAuth::Identity::Models::ActiveRecord, db: true) do
3
+ require 'sqlite3'
4
+ require 'active_record'
5
+ require 'anonymous_active_record'
6
+
7
+ class TestIdentity < OmniAuth::Identity::Models::ActiveRecord; end
8
+
9
+ RSpec.describe(OmniAuth::Identity::Models::ActiveRecord, sqlite3: true) do
4
10
  describe 'model', type: :model do
5
11
  subject(:model_klass) do
6
12
  AnonymousActiveRecord.generate(
7
13
  parent_klass: 'OmniAuth::Identity::Models::ActiveRecord',
8
- columns: %w[name provider],
14
+ columns: OmniAuth::Identity::Model::SCHEMA_ATTRIBUTES | %w[provider password_digest],
9
15
  connection_params: { adapter: 'sqlite3', encoding: 'utf8', database: ':memory:' }
10
16
  ) do
11
17
  def flower
@@ -14,17 +20,20 @@ RSpec.describe(OmniAuth::Identity::Models::ActiveRecord, db: true) do
14
20
  end
15
21
  end
16
22
 
17
- it 'delegates locate to the where query method' do
18
- allow(model_klass).to receive(:where).with('ham_sandwich' => 'open faced', 'category' => 'sandwiches',
19
- 'provider' => 'identity').and_return(['wakka'])
20
- expect(model_klass.locate('ham_sandwich' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
23
+ include_context 'persistable model'
24
+
25
+ describe '::table_name' do
26
+ it 'does not use STI rules for its table name' do
27
+ expect(TestIdentity.table_name).to eq('test_identities')
28
+ end
21
29
  end
22
- end
23
30
 
24
- describe '#table_name' do
25
- class TestIdentity < OmniAuth::Identity::Models::ActiveRecord; end
26
- it 'does not use STI rules for its table name' do
27
- expect(TestIdentity.table_name).to eq('test_identities')
31
+ describe '::locate' do
32
+ it 'delegates locate to the where query method' do
33
+ allow(model_klass).to receive(:where).with('email' => 'open faced', 'category' => 'sandwiches',
34
+ 'provider' => 'identity').and_return(['wakka'])
35
+ expect(model_klass.locate('email' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
36
+ end
28
37
  end
29
38
  end
30
39
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sqlite3'
4
+ require 'sequel'
5
+
6
+ DB = Sequel.sqlite
7
+
8
+ RSpec.describe(OmniAuth::Identity::Models::Sequel, sqlite3: true) do
9
+ before(:all) do
10
+ # Connect to an in-memory sqlite3 database.
11
+ DB.create_table :sequel_test_identities do
12
+ primary_key :id
13
+ String :email, null: false
14
+ String :password_digest, null: false
15
+ end
16
+ end
17
+
18
+ before do
19
+ sequel_test_identity = Class.new(Sequel::Model(:sequel_test_identities)) do
20
+ include ::OmniAuth::Identity::Models::Sequel
21
+ end
22
+ stub_const('SequelTestIdentity', sequel_test_identity)
23
+ end
24
+
25
+ describe 'model', type: :model do
26
+ subject(:model_klass) { SequelTestIdentity }
27
+
28
+ include_context 'persistable model'
29
+
30
+ describe '::locate' do
31
+ it 'delegates to the where query method' do
32
+ allow(model_klass).to receive(:where).with('email' => 'open faced',
33
+ 'category' => 'sandwiches').and_return(['wakka'])
34
+ expect(model_klass.locate('email' => 'open faced', 'category' => 'sandwiches')).to eq('wakka')
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,14 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.describe OmniAuth::Strategies::Identity do
3
+ require 'sqlite3'
4
+ require 'active_record'
5
+ require 'anonymous_active_record'
6
+
7
+ RSpec.describe OmniAuth::Strategies::Identity, sqlite3: true do
4
8
  attr_accessor :app
5
9
 
6
- let(:auth_hash) { last_response.headers['env']['omniauth.auth'] }
7
- let(:identity_hash) { last_response.headers['env']['omniauth.identity'] }
10
+ let(:env_hash) { last_response.headers['env'] }
11
+ let(:auth_hash) { env_hash['omniauth.auth'] }
12
+ let(:identity_hash) { env_hash['omniauth.identity'] }
8
13
  let(:identity_options) { {} }
9
14
  let(:anon_ar) do
10
15
  AnonymousActiveRecord.generate(
11
- columns: %w[name provider],
16
+ parent_klass: 'OmniAuth::Identity::Models::ActiveRecord',
17
+ columns: OmniAuth::Identity::Model::SCHEMA_ATTRIBUTES | %w[provider password_digest],
12
18
  connection_params: { adapter: 'sqlite3', encoding: 'utf8', database: ':memory:' }
13
19
  ) do
14
20
  def balloon
@@ -192,7 +198,7 @@ RSpec.describe OmniAuth::Strategies::Identity do
192
198
  end
193
199
  end
194
200
 
195
- context 'with successful creation' do
201
+ context 'with good identity' do
196
202
  let(:properties) do
197
203
  {
198
204
  name: 'Awesome Dude',
@@ -203,20 +209,71 @@ RSpec.describe OmniAuth::Strategies::Identity do
203
209
  }
204
210
  end
205
211
 
206
- before do
207
- allow(anon_ar).to receive('auth_key').and_return('email')
208
- m = double(uid: 'abc', name: 'Awesome Dude', email: 'awesome@example.com',
209
- info: { name: 'DUUUUDE!' }, persisted?: true)
210
- expect(anon_ar).to receive(:create).with(properties).and_return(m)
211
- end
212
-
213
212
  it 'sets the auth hash' do
214
213
  post '/auth/identity/register', properties
215
- expect(auth_hash['uid']).to eq('abc')
214
+ expect(auth_hash['uid']).to match(/\d+/)
215
+ expect(auth_hash['provider']).to eq('identity')
216
+ end
217
+
218
+ context 'with on_validation proc' do
219
+ let(:identity_options) do
220
+ { model: anon_ar, on_validation: on_validation_proc }
221
+ end
222
+ let(:on_validation_proc) do
223
+ lambda { |_env|
224
+ false
225
+ }
226
+ end
227
+
228
+ context 'when validation fails' do
229
+ it 'does not set the env hash' do
230
+ post '/auth/identity/register', properties
231
+ expect(env_hash).to eq(nil)
232
+ end
233
+
234
+ it 'renders registration form' do
235
+ post '/auth/identity/register', properties
236
+ expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
237
+ end
238
+
239
+ it 'displays validation failure message' do
240
+ post '/auth/identity/register', properties
241
+ expect(last_response.body).to be_include(described_class.default_options[:validation_failure_message])
242
+ end
243
+ end
244
+
245
+ context 'when validation succeeds' do
246
+ let(:on_validation_proc) do
247
+ lambda { |_env|
248
+ true
249
+ }
250
+ end
251
+
252
+ it 'sets the auth hash' do
253
+ post '/auth/identity/register', properties
254
+ expect(auth_hash['uid']).to match(/\d+/)
255
+ expect(auth_hash['provider']).to eq('identity')
256
+ end
257
+
258
+ it 'does not render registration form' do
259
+ post '/auth/identity/register', properties
260
+ expect(last_response.body).not_to be_include(described_class.default_options[:registration_form_title])
261
+ end
262
+
263
+ it 'does not display validation failure message' do
264
+ post '/auth/identity/register', properties
265
+ expect(last_response.body).not_to be_include(described_class.default_options[:validation_failure_message])
266
+ end
267
+
268
+ it 'does not display registration failure message' do
269
+ post '/auth/identity/register', properties
270
+ expect(last_response.body).not_to be_include(described_class.default_options[:registration_failure_message])
271
+ end
272
+ end
216
273
  end
217
274
  end
218
275
 
219
- context 'with invalid identity' do
276
+ context 'with bad identity' do
220
277
  let(:properties) do
221
278
  {
222
279
  name: 'Awesome Dude',
@@ -226,16 +283,17 @@ RSpec.describe OmniAuth::Strategies::Identity do
226
283
  provider: 'identity'
227
284
  }
228
285
  end
229
- let(:invalid_identity) { double(persisted?: false) }
286
+ let(:invalid_identity) { double(persisted?: false, save: false) }
230
287
 
231
288
  before do
232
- expect(anon_ar).to receive(:create).with(properties).and_return(invalid_identity)
289
+ expect(anon_ar).to receive(:new).with(properties).and_return(invalid_identity)
233
290
  end
234
291
 
235
292
  context 'default' do
236
293
  it 'shows registration form' do
237
294
  post '/auth/identity/register', properties
238
295
  expect(last_response.body).to be_include('Register Identity')
296
+ expect(last_response.body).to be_include('One or more fields were invalid')
239
297
  end
240
298
  end
241
299
 
@@ -250,6 +308,63 @@ RSpec.describe OmniAuth::Strategies::Identity do
250
308
  post '/auth/identity/register', properties
251
309
  expect(identity_hash).to eq(invalid_identity)
252
310
  expect(last_response.body).to be_include("FAIL'DOH!")
311
+ expect(last_response.body).not_to be_include('One or more fields were invalid')
312
+ end
313
+ end
314
+
315
+ context 'with on_validation proc' do
316
+ let(:identity_options) do
317
+ { model: anon_ar, on_validation: on_validation_proc }
318
+ end
319
+ let(:on_validation_proc) do
320
+ lambda { |_env|
321
+ false
322
+ }
323
+ end
324
+
325
+ context 'when validation fails' do
326
+ it 'does not set the env hash' do
327
+ post '/auth/identity/register', properties
328
+ expect(env_hash).to eq(nil)
329
+ end
330
+
331
+ it 'renders registration form' do
332
+ post '/auth/identity/register', properties
333
+ expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
334
+ end
335
+
336
+ it 'displays validation failure message' do
337
+ post '/auth/identity/register', properties
338
+ expect(last_response.body).to be_include(described_class.default_options[:validation_failure_message])
339
+ end
340
+ end
341
+
342
+ context 'when validation succeeds' do
343
+ let(:on_validation_proc) do
344
+ lambda { |_env|
345
+ true
346
+ }
347
+ end
348
+
349
+ it 'does not set the env hash' do
350
+ post '/auth/identity/register', properties
351
+ expect(env_hash).to eq(nil)
352
+ end
353
+
354
+ it 'renders registration form' do
355
+ post '/auth/identity/register', properties
356
+ expect(last_response.body).to be_include(described_class.default_options[:registration_form_title])
357
+ end
358
+
359
+ it 'does not display validation failure message' do
360
+ post '/auth/identity/register', properties
361
+ expect(last_response.body).not_to be_include(described_class.default_options[:validation_failure_message])
362
+ end
363
+
364
+ it 'display registration failure message' do
365
+ post '/auth/identity/register', properties
366
+ expect(last_response.body).to be_include(described_class.default_options[:registration_failure_message])
367
+ end
253
368
  end
254
369
  end
255
370
  end
data/spec/spec_helper.rb CHANGED
@@ -1,20 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # NOTE: mongoid and no_brainer can't be loaded at the same time.
4
+ # If you try it, one or both of them will not work.
5
+ # This is why the ORM specs are split into a separate directory and run in separate threads.
6
+
7
+ ENV['RUBY_ENV'] = 'test' # Used by NoBrainer
8
+ ENV['MONGOID_ENV'] = 'test' # Used by Mongoid
9
+
3
10
  ruby_version = Gem::Version.new(RUBY_VERSION)
4
11
  require 'simplecov' if ruby_version >= Gem::Version.new('2.7') && RUBY_ENGINE == 'ruby'
5
12
 
6
13
  require 'rack/test'
7
- require 'mongoid-rspec'
8
- require 'sqlite3'
9
- require 'anonymous_active_record'
14
+ require 'rspec/block_is_expected'
10
15
  require 'byebug' if RUBY_ENGINE == 'ruby'
11
16
 
12
17
  # This gem
13
18
  require 'omniauth/identity'
14
19
 
20
+ spec_root_matcher = %r{#{__dir__}/(.+)\.rb\Z}
21
+ Dir.glob(Pathname.new(__dir__).join('support/**/', '*.rb')).each { |f| require f.match(spec_root_matcher)[1] }
22
+
23
+ DEFAULT_PASSWORD = 'hang-a-left-at-the-diner'
24
+ DEFAULT_EMAIL = 'mojo@example.com'
25
+
15
26
  RSpec.configure do |config|
16
27
  config.include Rack::Test::Methods
17
- config.include Mongoid::Matchers, type: :model
28
+
29
+ # config.include ::Mongoid::Matchers, db: :mongodb
18
30
 
19
31
  # Enable flags like --only-failures and --next-failure
20
32
  config.example_status_persistence_file_path = '.rspec_status'