graphql_devise 0.14.3 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +7 -0
  3. data/CHANGELOG.md +58 -0
  4. data/README.md +186 -82
  5. data/app/controllers/graphql_devise/concerns/additional_controller_methods.rb +72 -0
  6. data/app/controllers/graphql_devise/concerns/set_user_by_token.rb +5 -27
  7. data/app/helpers/graphql_devise/mailer_helper.rb +2 -2
  8. data/app/models/graphql_devise/concerns/additional_model_methods.rb +21 -0
  9. data/app/models/graphql_devise/concerns/model.rb +6 -9
  10. data/app/views/graphql_devise/mailer/confirmation_instructions.html.erb +7 -1
  11. data/lib/generators/graphql_devise/install_generator.rb +1 -1
  12. data/lib/graphql_devise.rb +20 -6
  13. data/lib/graphql_devise/concerns/controller_methods.rb +3 -3
  14. data/lib/graphql_devise/default_operations/mutations.rb +14 -8
  15. data/lib/graphql_devise/default_operations/resolvers.rb +2 -2
  16. data/lib/graphql_devise/model/with_email_updater.rb +34 -8
  17. data/lib/graphql_devise/mount_method/operation_preparer.rb +6 -6
  18. data/lib/graphql_devise/mount_method/operation_preparers/custom_operation_preparer.rb +6 -4
  19. data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +7 -5
  20. data/lib/graphql_devise/mount_method/operation_preparers/{resource_name_setter.rb → resource_klass_setter.rb} +4 -4
  21. data/lib/graphql_devise/mount_method/operation_sanitizer.rb +13 -1
  22. data/lib/graphql_devise/mutations/confirm_registration_with_token.rb +30 -0
  23. data/lib/graphql_devise/mutations/login.rb +2 -0
  24. data/lib/graphql_devise/mutations/register.rb +60 -0
  25. data/lib/graphql_devise/mutations/resend_confirmation_with_token.rb +44 -0
  26. data/lib/graphql_devise/mutations/sign_up.rb +1 -1
  27. data/lib/graphql_devise/resolvers/confirm_account.rb +1 -1
  28. data/lib/graphql_devise/resource_loader.rb +26 -11
  29. data/lib/graphql_devise/schema_plugin.rb +20 -8
  30. data/lib/graphql_devise/version.rb +1 -1
  31. data/spec/dummy/app/controllers/api/v1/graphql_controller.rb +11 -0
  32. data/spec/dummy/app/graphql/dummy_schema.rb +4 -3
  33. data/spec/dummy/app/graphql/mutations/register.rb +14 -0
  34. data/spec/dummy/app/graphql/types/query_type.rb +5 -0
  35. data/spec/dummy/config/routes.rb +7 -5
  36. data/spec/dummy/db/migrate/20210516211417_add_vip_to_users.rb +5 -0
  37. data/spec/dummy/db/schema.rb +4 -3
  38. data/spec/generators/graphql_devise/install_generator_spec.rb +1 -1
  39. data/spec/graphql/user_queries_spec.rb +3 -1
  40. data/spec/graphql_devise/model/with_email_updater_spec.rb +97 -68
  41. data/spec/requests/graphql_controller_spec.rb +1 -1
  42. data/spec/requests/mutations/confirm_registration_with_token_spec.rb +117 -0
  43. data/spec/requests/mutations/register_spec.rb +166 -0
  44. data/spec/requests/mutations/resend_confirmation_with_token_spec.rb +137 -0
  45. data/spec/requests/user_controller_spec.rb +86 -25
  46. data/spec/services/mount_method/operation_preparer_spec.rb +5 -5
  47. data/spec/services/mount_method/operation_preparers/custom_operation_preparer_spec.rb +5 -5
  48. data/spec/services/mount_method/operation_preparers/default_operation_preparer_spec.rb +5 -5
  49. data/spec/services/mount_method/operation_preparers/{resource_name_setter_spec.rb → resource_klass_setter_spec.rb} +6 -6
  50. data/spec/services/mount_method/operation_sanitizer_spec.rb +3 -3
  51. data/spec/services/resource_loader_spec.rb +5 -5
  52. data/spec/support/contexts/graphql_request.rb +2 -2
  53. metadata +21 -6
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe 'Resend confirmation with token' do
6
+ include_context 'with graphql query request'
7
+
8
+ let(:confirmed_at) { nil }
9
+ let!(:user) { create(:user, confirmed_at: nil, email: 'mwallace@wallaceinc.com') }
10
+ let(:email) { user.email }
11
+ let(:id) { user.id }
12
+ let(:confirm_url) { 'https://google.com' }
13
+ let(:query) do
14
+ <<-GRAPHQL
15
+ mutation {
16
+ userResendConfirmationWithToken(
17
+ email:"#{email}",
18
+ confirmUrl:"#{confirm_url}"
19
+ ) {
20
+ message
21
+ }
22
+ }
23
+ GRAPHQL
24
+ end
25
+
26
+ context 'when confirm_url is not whitelisted' do
27
+ let(:confirm_url) { 'https://not-safe.com' }
28
+
29
+ it 'returns a not whitelisted confirm url error' do
30
+ expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
31
+
32
+ expect(json_response[:errors]).to containing_exactly(
33
+ hash_including(
34
+ message: "Redirect to '#{confirm_url}' not allowed.",
35
+ extensions: { code: 'USER_ERROR' }
36
+ )
37
+ )
38
+ end
39
+ end
40
+
41
+ context 'when params are correct' do
42
+ context 'when using the gem schema' do
43
+ it 'sends an email to the user with confirmation url and returns a success message' do
44
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
45
+ expect(json_response[:data][:userResendConfirmationWithToken]).to include(
46
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
47
+ )
48
+
49
+ email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
50
+ confirm_link = email.css('a').first['href']
51
+ confirm_token = confirm_link.match(/\?confirmationToken\=(?<token>.+)\z/)[:token]
52
+
53
+ expect(User.confirm_by_token(confirm_token)).to eq(user)
54
+ end
55
+ end
56
+
57
+ context 'when using a custom schema' do
58
+ let(:custom_path) { '/api/v1/graphql' }
59
+
60
+ it 'sends an email to the user with confirmation url and returns a success message' do
61
+ expect { post_request(custom_path) }.to change(ActionMailer::Base.deliveries, :count).by(1)
62
+ expect(json_response[:data][:userResendConfirmationWithToken]).to include(
63
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
64
+ )
65
+
66
+ email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
67
+ confirm_link = email.css('a').first['href']
68
+ confirm_token = confirm_link.match(/\?confirmationToken\=(?<token>.+)\z/)[:token]
69
+
70
+ expect(User.confirm_by_token(confirm_token)).to eq(user)
71
+ end
72
+ end
73
+
74
+ context 'when email address uses different casing' do
75
+ let(:email) { 'mWallace@wallaceinc.com' }
76
+
77
+ it 'honors devise configuration for case insensitive fields' do
78
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
79
+ expect(json_response[:data][:userResendConfirmationWithToken]).to include(
80
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
81
+ )
82
+ end
83
+ end
84
+
85
+ context 'when the user has already been confirmed' do
86
+ before { user.confirm }
87
+
88
+ it 'does *NOT* send an email and raises an error' do
89
+ expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
90
+ expect(json_response[:data][:userResendConfirmationWithToken]).to be_nil
91
+ expect(json_response[:errors]).to contain_exactly(
92
+ hash_including(
93
+ message: 'Email was already confirmed, please try signing in',
94
+ extensions: { code: 'USER_ERROR' }
95
+ )
96
+ )
97
+ end
98
+ end
99
+ end
100
+
101
+ context 'when the email was changed' do
102
+ let(:confirmed_at) { 2.seconds.ago }
103
+ let(:email) { 'new-email@wallaceinc.com' }
104
+ let(:new_email) { email }
105
+
106
+ before do
107
+ user.update_with_email(
108
+ email: new_email,
109
+ schema_url: 'http://localhost/test',
110
+ confirmation_success_url: 'https://google.com'
111
+ )
112
+ end
113
+
114
+ it 'sends new confirmation email' do
115
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
116
+ expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(new_email)
117
+ expect(json_response[:data][:userResendConfirmationWithToken]).to include(
118
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
119
+ )
120
+ end
121
+ end
122
+
123
+ context "when the email isn't in the system" do
124
+ let(:email) { 'notthere@gmail.com' }
125
+
126
+ it 'does *NOT* send an email and raises an error' do
127
+ expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
128
+ expect(json_response[:data][:userResendConfirmationWithToken]).to be_nil
129
+ expect(json_response[:errors]).to contain_exactly(
130
+ hash_including(
131
+ message: "Unable to find user with email '#{email}'.",
132
+ extensions: { code: 'USER_ERROR' }
133
+ )
134
+ )
135
+ end
136
+ end
137
+ end
@@ -5,6 +5,14 @@ require 'rails_helper'
5
5
  RSpec.describe "Integrations with the user's controller" do
6
6
  include_context 'with graphql query request'
7
7
 
8
+ shared_examples 'returns a must authenticate error' do |field|
9
+ it 'returns a must sign in error' do
10
+ expect(json_response[:errors]).to contain_exactly(
11
+ hash_including(message: "#{field} field requires authentication", extensions: { code: 'AUTHENTICATION_ERROR' })
12
+ )
13
+ end
14
+ end
15
+
8
16
  let(:user) { create(:user, :confirmed) }
9
17
 
10
18
  describe 'publicField' do
@@ -42,6 +50,22 @@ RSpec.describe "Integrations with the user's controller" do
42
50
  GRAPHQL
43
51
  end
44
52
 
53
+ context 'when authenticating before using the GQL schema' do
54
+ before { post_request('/api/v1/controller_auth') }
55
+
56
+ context 'when user is authenticated' do
57
+ let(:headers) { create(:schema_user).create_new_auth_token }
58
+
59
+ it 'allows authentication at the controller level' do
60
+ expect(json_response[:data][:privateField]).to eq('Field will always require authentication')
61
+ end
62
+ end
63
+
64
+ context 'when user is not authenticated' do
65
+ it_behaves_like 'returns a must authenticate error', 'privateField'
66
+ end
67
+ end
68
+
45
69
  context 'when using a regular schema' do
46
70
  before { post_request('/api/v1/graphql') }
47
71
 
@@ -62,11 +86,7 @@ RSpec.describe "Integrations with the user's controller" do
62
86
  end
63
87
 
64
88
  context 'when user is not authenticated' do
65
- it 'returns a must sign in error' do
66
- expect(json_response[:errors]).to contain_exactly(
67
- hash_including(message: 'privateField field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
68
- )
69
- end
89
+ it_behaves_like 'returns a must authenticate error', 'privateField'
70
90
  end
71
91
 
72
92
  context 'when using the failing route' do
@@ -91,11 +111,7 @@ RSpec.describe "Integrations with the user's controller" do
91
111
  end
92
112
 
93
113
  context 'when user is not authenticated' do
94
- it 'returns a must sign in error' do
95
- expect(json_response[:errors]).to contain_exactly(
96
- hash_including(message: 'privateField field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
97
- )
98
- end
114
+ it_behaves_like 'returns a must authenticate error', 'privateField'
99
115
  end
100
116
  end
101
117
  end
@@ -121,11 +137,7 @@ RSpec.describe "Integrations with the user's controller" do
121
137
  end
122
138
 
123
139
  context 'when user is not authenticated' do
124
- it 'returns a must sign in error' do
125
- expect(json_response[:errors]).to contain_exactly(
126
- hash_including(message: 'dummyMutation field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
127
- )
128
- end
140
+ it_behaves_like 'returns a must authenticate error', 'dummyMutation'
129
141
  end
130
142
  end
131
143
 
@@ -141,11 +153,7 @@ RSpec.describe "Integrations with the user's controller" do
141
153
  end
142
154
 
143
155
  context 'when user is not authenticated' do
144
- it 'returns a must sign in error' do
145
- expect(json_response[:errors]).to contain_exactly(
146
- hash_including(message: 'dummyMutation field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
147
- )
148
- end
156
+ it_behaves_like 'returns a must authenticate error', 'dummyMutation'
149
157
  end
150
158
  end
151
159
  end
@@ -179,11 +187,7 @@ RSpec.describe "Integrations with the user's controller" do
179
187
  end
180
188
 
181
189
  context 'when user is not authenticated' do
182
- it 'returns a must sign in error' do
183
- expect(json_response[:errors]).to contain_exactly(
184
- hash_including(message: 'user field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
185
- )
186
- end
190
+ it_behaves_like 'returns a must authenticate error', 'user'
187
191
  end
188
192
  end
189
193
 
@@ -251,4 +255,61 @@ RSpec.describe "Integrations with the user's controller" do
251
255
  )
252
256
  end
253
257
  end
258
+
259
+ describe 'vipField' do
260
+ let(:error_message) { 'Field available only for VIP Users' }
261
+ let(:query) do
262
+ <<-GRAPHQL
263
+ query { vipField }
264
+ GRAPHQL
265
+ end
266
+
267
+ context 'when using a regular schema' do
268
+ before { post_request('/api/v1/graphql') }
269
+
270
+ context 'when user is authenticated' do
271
+ let(:headers) { user.create_new_auth_token }
272
+
273
+ context 'when schema user is VIP' do
274
+ let(:user) { create(:user, :confirmed, vip: true) }
275
+
276
+ it 'allows to perform the query' do
277
+ expect(json_response[:data][:vipField]).to eq(error_message)
278
+ end
279
+ end
280
+
281
+ context 'when schema user is not VIP' do
282
+ it_behaves_like 'returns a must authenticate error', 'vipField'
283
+ end
284
+ end
285
+
286
+ context 'when user is not authenticated' do
287
+ it_behaves_like 'returns a must authenticate error', 'vipField'
288
+ end
289
+ end
290
+
291
+ context 'when using the interpreter schema' do
292
+ before { post_request('/api/v1/interpreter') }
293
+
294
+ context 'when user is authenticated' do
295
+ let(:headers) { user.create_new_auth_token }
296
+
297
+ context 'when schema user is VIP' do
298
+ let(:user) { create(:user, :confirmed, vip: true) }
299
+
300
+ it 'allows to perform the query' do
301
+ expect(json_response[:data][:vipField]).to eq(error_message)
302
+ end
303
+ end
304
+
305
+ context 'when schema user is not VIP' do
306
+ it_behaves_like 'returns a must authenticate error', 'vipField'
307
+ end
308
+ end
309
+
310
+ context 'when user is not authenticated' do
311
+ it_behaves_like 'returns a must authenticate error', 'vipField'
312
+ end
313
+ end
314
+ end
254
315
  end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require 'rails_helper'
4
4
 
5
5
  RSpec.describe GraphqlDevise::MountMethod::OperationPreparer do
6
6
  describe '#call' do
7
7
  subject(:prepared_operations) do
8
8
  described_class.new(
9
- mapping_name: mapping,
9
+ model: model,
10
10
  selected_operations: selected,
11
11
  preparer: preparer,
12
12
  custom: custom,
@@ -15,14 +15,14 @@ RSpec.describe GraphqlDevise::MountMethod::OperationPreparer do
15
15
  end
16
16
 
17
17
  let(:logout_class) { Class.new(GraphQL::Schema::Resolver) }
18
- let(:mapping) { :user }
18
+ let(:model) { User }
19
19
  let(:preparer) { double(:preparer, call: logout_class) }
20
20
  let(:custom) { { login: double(:custom_login, graphql_name: nil) } }
21
21
  let(:additional) { { user_additional: double(:user_additional) } }
22
22
  let(:selected) do
23
23
  {
24
- login: { klass: double(:login_default) },
25
- logout:{ klass: logout_class }
24
+ login: { klass: double(:login_default) },
25
+ logout: { klass: logout_class }
26
26
  }
27
27
  end
28
28
 
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require 'rails_helper'
4
4
 
5
5
  RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::CustomOperationPreparer do
6
6
  describe '#call' do
7
- subject(:prepared) { described_class.new(selected_keys: selected_keys, custom_operations: operations, mapping_name: mapping_name).call }
7
+ subject(:prepared) { described_class.new(selected_keys: selected_keys, custom_operations: operations, model: model).call }
8
8
 
9
9
  let(:login_operation) { double(:confirm_operation, graphql_name: nil) }
10
10
  let(:logout_operation) { double(:sign_up_operation, graphql_name: nil) }
11
- let(:mapping_name) { :user }
11
+ let(:model) { User }
12
12
  let(:operations) { { login: login_operation, logout: logout_operation, invalid: double(:invalid) } }
13
13
  let(:selected_keys) { [:login, :logout, :sign_up, :confirm] }
14
14
 
@@ -22,8 +22,8 @@ RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::CustomOperationPr
22
22
 
23
23
  prepared
24
24
 
25
- expect(login_operation.instance_variable_get(:@resource_name)).to eq(:user)
26
- expect(logout_operation.instance_variable_get(:@resource_name)).to eq(:user)
25
+ expect(login_operation.instance_variable_get(:@resource_klass)).to eq(User)
26
+ expect(logout_operation.instance_variable_get(:@resource_klass)).to eq(User)
27
27
  end
28
28
 
29
29
  context 'when no selected keys are provided' do
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require 'rails_helper'
4
4
 
5
5
  RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::DefaultOperationPreparer do
6
6
  describe '#call' do
7
7
  subject(:prepared) { default_preparer.call }
8
8
 
9
- let(:default_preparer) { described_class.new(selected_operations: operations, custom_keys: custom_keys, mapping_name: mapping_name, preparer: preparer) }
9
+ let(:default_preparer) { described_class.new(selected_operations: operations, custom_keys: custom_keys, model: model, preparer: preparer) }
10
10
  let(:confirm_operation) { double(:confirm_operation, graphql_name: nil) }
11
11
  let(:sign_up_operation) { double(:sign_up_operation, graphql_name: nil) }
12
12
  let(:login_operation) { double(:confirm_operation, graphql_name: nil) }
13
13
  let(:logout_operation) { double(:sign_up_operation, graphql_name: nil) }
14
- let(:mapping_name) { :user }
14
+ let(:model) { User }
15
15
  let(:preparer) { double(:preparer) }
16
16
  let(:custom_keys) { [:login, :logout] }
17
17
  let(:operations) do
@@ -46,8 +46,8 @@ RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::DefaultOperationP
46
46
 
47
47
  prepared
48
48
 
49
- expect(confirm_operation.instance_variable_get(:@resource_name)).to eq(:user)
50
- expect(sign_up_operation.instance_variable_get(:@resource_name)).to eq(:user)
49
+ expect(confirm_operation.instance_variable_get(:@resource_klass)).to eq(User)
50
+ expect(sign_up_operation.instance_variable_get(:@resource_klass)).to eq(User)
51
51
  end
52
52
 
53
53
  context 'when no custom keys are provided' do
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require 'rails_helper'
4
4
 
5
- RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::ResourceNameSetter do
5
+ RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::ResourceKlassSetter do
6
6
  describe '#call' do
7
- subject(:prepared_operation) { described_class.new(mapping_name).call(operation) }
7
+ subject(:prepared_operation) { described_class.new(model).call(operation) }
8
8
 
9
- let(:operation) { double(:operation) }
10
- let(:mapping_name) { :user }
9
+ let(:operation) { double(:operation) }
10
+ let(:model) { User }
11
11
 
12
12
  it 'sets a gql name to the operation' do
13
- expect(prepared_operation.instance_variable_get(:@resource_name)).to eq(:user)
13
+ expect(prepared_operation.instance_variable_get(:@resource_klass)).to eq(model)
14
14
  end
15
15
  end
16
16
  end
@@ -13,7 +13,7 @@ RSpec.describe GraphqlDevise::MountMethod::OperationSanitizer do
13
13
  context 'when the operations passed are mutations' do
14
14
  let(:skipped) { [] }
15
15
  let(:only) { [] }
16
- let(:default) { { operation1: op_class1, operation2: op_class2 } }
16
+ let(:default) { { operation1: { klass: op_class1 }, operation2: { klass: op_class2 } } }
17
17
 
18
18
  context 'when no other option besides default is passed' do
19
19
  it { is_expected.to eq(default) }
@@ -22,13 +22,13 @@ RSpec.describe GraphqlDevise::MountMethod::OperationSanitizer do
22
22
  context 'when there are only operations' do
23
23
  let(:only) { [:operation1] }
24
24
 
25
- it { is_expected.to eq(operation1: op_class1) }
25
+ it { is_expected.to eq(operation1: { klass: op_class1 }) }
26
26
  end
27
27
 
28
28
  context 'when there are skipped operations' do
29
29
  let(:skipped) { [:operation2] }
30
30
 
31
- it { is_expected.to eq(operation1: op_class1) }
31
+ it { is_expected.to eq(operation1: { klass: op_class1 }) }
32
32
  end
33
33
  end
34
34
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require 'rails_helper'
4
4
 
5
5
  RSpec.describe GraphqlDevise::ResourceLoader do
6
6
  describe '#call' do
@@ -15,8 +15,8 @@ RSpec.describe GraphqlDevise::ResourceLoader do
15
15
 
16
16
  before do
17
17
  allow(GraphqlDevise).to receive(:add_mapping).with(:user, resource)
18
- allow(GraphqlDevise).to receive(:resource_mounted?).with(:user).and_return(mounted)
19
- allow(GraphqlDevise).to receive(:mount_resource).with(:user)
18
+ allow(GraphqlDevise).to receive(:resource_mounted?).with(User).and_return(mounted)
19
+ allow(GraphqlDevise).to receive(:mount_resource).with(User)
20
20
  end
21
21
 
22
22
  it 'loads operations into the provided types' do
@@ -64,13 +64,13 @@ RSpec.describe GraphqlDevise::ResourceLoader do
64
64
 
65
65
  it 'adds mappings' do
66
66
  expect(GraphqlDevise).to receive(:add_mapping).with(:user, resource)
67
- expect(GraphqlDevise).to receive(:mount_resource).with(:user)
67
+ expect(GraphqlDevise).to receive(:mount_resource).with(User)
68
68
 
69
69
  loader
70
70
  end
71
71
 
72
72
  context 'when resource was already mounted' do
73
- before { allow(GraphqlDevise).to receive(:resource_mounted?).with(:user).and_return(true) }
73
+ before { allow(GraphqlDevise).to receive(:resource_mounted?).with(User).and_return(true) }
74
74
 
75
75
  it 'skips schema loading' do
76
76
  expect(query).not_to receive(:field)