graphql_devise 0.11.2 → 0.12.2

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rspec +1 -0
  4. data/.travis.yml +9 -3
  5. data/CHANGELOG.md +50 -1
  6. data/README.md +185 -32
  7. data/app/controllers/graphql_devise/application_controller.rb +4 -1
  8. data/app/controllers/graphql_devise/concerns/set_user_by_token.rb +25 -0
  9. data/app/controllers/graphql_devise/graphql_controller.rb +2 -0
  10. data/app/helpers/graphql_devise/mailer_helper.rb +2 -2
  11. data/app/views/graphql_devise/mailer/confirmation_instructions.html.erb +1 -1
  12. data/app/views/graphql_devise/mailer/reset_password_instructions.html.erb +1 -1
  13. data/config/locales/en.yml +1 -0
  14. data/config/routes.rb +2 -0
  15. data/graphql_devise.gemspec +6 -4
  16. data/lib/generators/graphql_devise/install_generator.rb +63 -30
  17. data/lib/graphql_devise.rb +24 -10
  18. data/lib/graphql_devise/default_operations/mutations.rb +6 -6
  19. data/lib/graphql_devise/default_operations/resolvers.rb +2 -2
  20. data/lib/graphql_devise/errors/authentication_error.rb +7 -0
  21. data/lib/graphql_devise/{detailed_user_error.rb → errors/detailed_user_error.rb} +1 -1
  22. data/lib/graphql_devise/errors/error_codes.rb +6 -0
  23. data/lib/graphql_devise/errors/execution_error.rb +4 -0
  24. data/lib/graphql_devise/{user_error.rb → errors/user_error.rb} +1 -1
  25. data/lib/graphql_devise/mount_method/operation_preparer.rb +2 -2
  26. data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +6 -2
  27. data/lib/graphql_devise/mount_method/operation_preparers/gql_name_setter.rb +1 -1
  28. data/lib/graphql_devise/mount_method/operation_preparers/mutation_field_setter.rb +3 -2
  29. data/lib/graphql_devise/mount_method/operation_preparers/resolver_type_setter.rb +1 -1
  30. data/lib/graphql_devise/mount_method/operation_preparers/resource_name_setter.rb +2 -2
  31. data/lib/graphql_devise/mutations/resend_confirmation.rb +3 -5
  32. data/lib/graphql_devise/mutations/send_password_reset.rb +5 -2
  33. data/lib/graphql_devise/mutations/sign_up.rb +3 -6
  34. data/lib/graphql_devise/rails/routes.rb +5 -72
  35. data/lib/graphql_devise/resource_loader.rb +87 -0
  36. data/lib/graphql_devise/schema_plugin.rb +106 -0
  37. data/lib/graphql_devise/version.rb +1 -1
  38. data/spec/dummy/app/controllers/api/v1/graphql_controller.rb +41 -3
  39. data/spec/dummy/app/controllers/application_controller.rb +1 -0
  40. data/spec/dummy/app/graphql/dummy_schema.rb +18 -0
  41. data/spec/dummy/app/graphql/interpreter_schema.rb +9 -0
  42. data/spec/dummy/app/graphql/types/mutation_type.rb +1 -1
  43. data/spec/dummy/app/graphql/types/query_type.rb +10 -0
  44. data/spec/dummy/config/routes.rb +3 -0
  45. data/spec/generators/graphql_devise/install_generator_spec.rb +62 -30
  46. data/spec/rails_helper.rb +4 -1
  47. data/spec/requests/graphql_controller_spec.rb +80 -0
  48. data/spec/requests/mutations/resend_confirmation_spec.rb +44 -29
  49. data/spec/requests/mutations/send_password_reset_spec.rb +40 -12
  50. data/spec/requests/queries/confirm_account_spec.rb +7 -1
  51. data/spec/requests/user_controller_spec.rb +189 -24
  52. data/spec/services/mount_method/operation_preparer_spec.rb +8 -3
  53. data/spec/services/mount_method/operation_preparers/custom_operation_preparer_spec.rb +1 -1
  54. data/spec/services/mount_method/operation_preparers/default_operation_preparer_spec.rb +15 -8
  55. data/spec/services/mount_method/operation_preparers/mutation_field_setter_spec.rb +18 -4
  56. data/spec/services/mount_method/operation_preparers/resource_name_setter_spec.rb +1 -1
  57. data/spec/services/resource_loader_spec.rb +82 -0
  58. data/spec/services/schema_plugin_spec.rb +26 -0
  59. data/spec/spec_helper.rb +1 -1
  60. metadata +107 -89
  61. data/lib/graphql_devise/error_codes.rb +0 -5
  62. data/spec/support/generators/file_helpers.rb +0 -12
@@ -27,5 +27,8 @@ Rails.application.routes.draw do
27
27
  at: '/api/v1/user_customer/graphql_auth'
28
28
  )
29
29
 
30
+ get '/api/v1/graphql', to: 'api/v1/graphql#graphql'
30
31
  post '/api/v1/graphql', to: 'api/v1/graphql#graphql'
32
+ post '/api/v1/interpreter', to: 'api/v1/graphql#interpreter'
33
+ post '/api/v1/failing', to: 'api/v1/graphql#failing_resource_name'
31
34
  end
@@ -3,50 +3,82 @@ require 'rails_helper'
3
3
  require 'generators/graphql_devise/install_generator'
4
4
 
5
5
  RSpec.describe GraphqlDevise::InstallGenerator, type: :generator do
6
- destination File.expand_path('../../../tmp', __FILE__)
6
+ destination File.expand_path('../../../../gqld_dummy', __dir__)
7
+
8
+ let(:routes_path) { "#{destination_root}/config/routes.rb" }
9
+ let(:routes_content) { File.read(routes_path) }
10
+ let(:dta_route) { 'mount_devise_token_auth_for' }
11
+
12
+ after(:all) { FileUtils.rm_rf(destination_root) }
7
13
 
8
14
  before do
9
15
  prepare_destination
16
+ create_rails_project
17
+ run_generator(args)
10
18
  end
11
19
 
12
- let(:routes_path) { "#{destination_root}/config/routes.rb" }
13
- let(:routes_content) { File.read(routes_path) }
14
- let(:dta_route) { "mount_devise_token_auth_for 'User', at: 'auth'" }
15
-
16
- xcontext 'when the file exists' do
17
- before do
18
- create_file_with_content(
19
- routes_path,
20
- "Rails.application.routes.draw do\n#{dta_route}\nend"
21
- )
22
- end
20
+ context 'when mount option is schema' do
21
+ let(:args) { ['Admin', '--mount', 'GqldDummySchema'] }
22
+
23
+ it 'mounts the SchemaPlugin' do
24
+ assert_file 'config/initializers/devise.rb'
25
+ assert_file 'config/initializers/devise_token_auth.rb', /^\s{2}#{Regexp.escape('config.change_headers_on_each_request = false')}/
26
+ assert_file 'config/locales/devise.en.yml'
27
+
28
+ assert_migration 'db/migrate/devise_token_auth_create_admins.rb'
23
29
 
24
- context 'when passing no params to the generator' do
25
- before { run_generator }
30
+ assert_file 'app/models/admin.rb', /^\s{2}devise :.+include GraphqlDevise::Concerns::Model/m
26
31
 
27
- it 'replaces dta route using the default values for class and path' do
28
- generator_added_route = / mount_graphql_devise_for 'User', at: 'auth'/
29
- expect(routes_content).to match(generator_added_route)
30
- expect(routes_content).not_to match(dta_route)
31
- end
32
+ assert_file 'app/controllers/application_controller.rb', /^\s{2}include GraphqlDevise::Concerns::SetUserByToken/
33
+
34
+ assert_file 'app/graphql/gqld_dummy_schema.rb', /\s+#{Regexp.escape("GraphqlDevise::ResourceLoader.new('Admin')")}/
32
35
  end
36
+ end
37
+
38
+ context 'when passing no params to the generator' do
39
+ let(:args) { [] }
33
40
 
34
- context 'when passing custom params to the generator' do
35
- before { run_generator %w[Admin api] }
41
+ it 'creates and updated required files' do
42
+ assert_file 'config/routes.rb', /^\s{2}mount_graphql_devise_for 'User', at: 'auth'/
43
+ expect(routes_content).not_to match(dta_route)
36
44
 
37
- it 'add the routes using the provided values for class and path and keeps dta route' do
38
- generator_added_route = / mount_graphql_devise_for 'Admin', at: 'api'/
39
- expect(routes_content).to match(generator_added_route)
40
- expect(routes_content).to match(dta_route)
41
- end
45
+ assert_file 'config/initializers/devise.rb'
46
+ assert_file 'config/initializers/devise_token_auth.rb', /^\s{2}#{Regexp.escape('config.change_headers_on_each_request = false')}/
47
+ assert_file 'config/locales/devise.en.yml'
48
+
49
+ assert_migration 'db/migrate/devise_token_auth_create_users.rb'
50
+
51
+ assert_file 'app/models/user.rb', /^\s{2}devise :.+include GraphqlDevise::Concerns::Model/m
52
+
53
+ assert_file 'app/controllers/application_controller.rb', /^\s{2}include GraphqlDevise::Concerns::SetUserByToken/
42
54
  end
43
55
  end
44
56
 
45
- xcontext 'when file does *NOT* exist' do
46
- before { run_generator }
57
+ context 'when passing custom params to the generator' do
58
+ let(:args) { %w[Admin api] }
59
+
60
+ it 'creates and updated required files' do
61
+ assert_file 'config/routes.rb', /^\s{2}mount_graphql_devise_for 'Admin', at: 'api'/
62
+ expect(routes_content).not_to match(dta_route)
63
+
64
+ assert_file 'config/initializers/devise.rb'
65
+ assert_file 'config/initializers/devise_token_auth.rb', /^\s{2}#{Regexp.escape('config.change_headers_on_each_request = false')}/
66
+ assert_file 'config/locales/devise.en.yml'
67
+
68
+ assert_migration 'db/migrate/devise_token_auth_create_admins.rb'
47
69
 
48
- it 'does *NOT* create the file and throw no exception' do
49
- expect(File.exist?(routes_path)).to be_falsey
70
+ assert_file 'app/models/admin.rb', /^\s{2}devise :.+include GraphqlDevise::Concerns::Model/m
71
+
72
+ assert_file 'app/controllers/application_controller.rb', /^\s{2}include GraphqlDevise::Concerns::SetUserByToken/
73
+ end
74
+ end
75
+
76
+ def create_rails_project
77
+ FileUtils.cd(File.join(destination_root, '..')) do
78
+ `rails new gqld_dummy -S -C --skip-action-mailbox --skip-action-text -T --skip-spring --skip-bundle --skip-keeps -G --skip-active-storage -J --skip-listen --skip-bootsnap`
79
+ end
80
+ FileUtils.cd(File.join(destination_root, '../gqld_dummy')) do
81
+ `rails generate graphql:install`
50
82
  end
51
83
  end
52
84
  end
@@ -38,5 +38,8 @@ RSpec.configure do |config|
38
38
  config.include(Requests::JsonHelpers, type: :request)
39
39
  config.include(Requests::AuthHelpers, type: :request)
40
40
  config.include(ActiveSupport::Testing::TimeHelpers)
41
- config.include(Generators::FileHelpers, type: :generator)
41
+
42
+ config.before(:suite) do
43
+ ActionController::Base.allow_forgery_protection = true
44
+ end
42
45
  end
@@ -0,0 +1,80 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe GraphqlDevise::GraphqlController do
4
+ let(:password) { 'password123' }
5
+ let(:user) { create(:user, :confirmed, password: password) }
6
+ let(:params) { { query: query, variables: variables } }
7
+ let(:request_params) do
8
+ if Rails::VERSION::MAJOR >= 5
9
+ { params: params }
10
+ else
11
+ params
12
+ end
13
+ end
14
+
15
+ context 'when variables are a string' do
16
+ let(:variables) { "{\"email\": \"#{user.email}\"}" }
17
+ let(:query) { "mutation($email: String!) { userLogin(email: $email, password: \"#{password}\") { user { email name signInCount } } }" }
18
+
19
+ it 'parses the string variables' do
20
+ post '/api/v1/graphql_auth', request_params
21
+
22
+ expect(json_response).to match(
23
+ data: { userLogin: { user: { email: user.email, name: user.name, signInCount: 1 } } }
24
+ )
25
+ end
26
+
27
+ context 'when variables is an empty string' do
28
+ let(:variables) { '' }
29
+ let(:query) { "mutation { userLogin(email: \"#{user.email}\", password: \"#{password}\") { user { email name signInCount } } }" }
30
+
31
+ it 'returns an empty hash as variables' do
32
+ post '/api/v1/graphql_auth', request_params
33
+
34
+ expect(json_response).to match(
35
+ data: { userLogin: { user: { email: user.email, name: user.name, signInCount: 1 } } }
36
+ )
37
+ end
38
+ end
39
+ end
40
+
41
+ context 'when variables are not a string or hash' do
42
+ let(:variables) { 1 }
43
+ let(:query) { "mutation($email: String!) { userLogin(email: $email, password: \"#{password}\") { user { email name signInCount } } }" }
44
+
45
+ it 'raises an error' do
46
+ expect do
47
+ post '/api/v1/graphql_auth', request_params
48
+ end.to raise_error(ArgumentError)
49
+ end
50
+ end
51
+
52
+ context 'when multiplexing queries' do
53
+ let(:params) do
54
+ {
55
+ _json: [
56
+ { query: "mutation { userLogin(email: \"#{user.email}\", password: \"#{password}\") { user { email name signInCount } } }" },
57
+ { query: "mutation { userLogin(email: \"#{user.email}\", password: \"wrong password\") { user { email name signInCount } } }" }
58
+ ]
59
+ }
60
+ end
61
+
62
+ it 'executes multiple queries in the same request' do
63
+ post '/api/v1/graphql_auth', request_params
64
+
65
+ expect(json_response).to match(
66
+ [
67
+ { data: { userLogin: { user: { email: user.email, name: user.name, signInCount: 1 } } } },
68
+ {
69
+ data: { userLogin: nil },
70
+ errors: [
71
+ hash_including(
72
+ message: 'Invalid login credentials. Please try again.', extensions: { code: 'USER_ERROR' }
73
+ )
74
+ ]
75
+ }
76
+ ]
77
+ )
78
+ end
79
+ end
80
+ end
@@ -15,39 +15,58 @@ RSpec.describe 'Resend confirmation' do
15
15
  redirectUrl:"#{redirect}"
16
16
  ) {
17
17
  message
18
- authenticatable {
19
- id
20
- email
21
- }
22
18
  }
23
19
  }
24
20
  GRAPHQL
25
21
  end
26
22
 
27
23
  context 'when params are correct' do
28
- it 'sends an email to the user with confirmation url and returns a success message' do
29
- expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
30
- expect(json_response[:data][:userResendConfirmation]).to include(
31
- message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.',
32
- authenticatable: {
33
- id: id,
34
- email: email
35
- }
36
- )
24
+ context 'when using the gem schema' do
25
+ it 'sends an email to the user with confirmation url and returns a success message' do
26
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
27
+ expect(json_response[:data][:userResendConfirmation]).to include(
28
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
29
+ )
30
+
31
+ email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
32
+ link = email.css('a').first
33
+ confirm_link_msg_text = email.css('p')[1].inner_html
34
+ confirm_account_link_text = link.inner_html
37
35
 
38
- email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
39
- link = email.css('a').first
40
- confirm_link_msg_text = email.css('p')[1].inner_html
41
- confirm_account_link_text = link.inner_html
36
+ expect(link['href']).to include('/api/v1/graphql_auth?')
37
+ expect(confirm_link_msg_text).to eq('You can confirm your account email through the link below:')
38
+ expect(confirm_account_link_text).to eq('Confirm my account')
42
39
 
43
- expect(confirm_link_msg_text).to eq('You can confirm your account email through the link below:')
44
- expect(confirm_account_link_text).to eq('Confirm my account')
40
+ expect do
41
+ get link['href']
42
+ user.reload
43
+ end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
44
+ end
45
+ end
45
46
 
46
- # TODO: Move to feature spec
47
- expect do
48
- get link['href']
49
- user.reload
50
- end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
47
+ context 'when using a custom schema' do
48
+ let(:custom_path) { '/api/v1/graphql' }
49
+
50
+ it 'sends an email to the user with confirmation url and returns a success message' do
51
+ expect { post_request(custom_path) }.to change(ActionMailer::Base.deliveries, :count).by(1)
52
+ expect(json_response[:data][:userResendConfirmation]).to include(
53
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
54
+ )
55
+
56
+ email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
57
+ link = email.css('a').first
58
+ confirm_link_msg_text = email.css('p')[1].inner_html
59
+ confirm_account_link_text = link.inner_html
60
+
61
+ expect(link['href']).to include("#{custom_path}?")
62
+ expect(confirm_link_msg_text).to eq('You can confirm your account email through the link below:')
63
+ expect(confirm_account_link_text).to eq('Confirm my account')
64
+
65
+ expect do
66
+ get link['href']
67
+ user.reload
68
+ end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
69
+ end
51
70
  end
52
71
 
53
72
  context 'when email address uses different casing' do
@@ -56,11 +75,7 @@ RSpec.describe 'Resend confirmation' do
56
75
  it 'honors devise configuration for case insensitive fields' do
57
76
  expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
58
77
  expect(json_response[:data][:userResendConfirmation]).to include(
59
- message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.',
60
- authenticatable: {
61
- id: id,
62
- email: user.email
63
- }
78
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
64
79
  )
65
80
  end
66
81
  end
@@ -13,26 +13,51 @@ RSpec.describe 'Send Password Reset Requests' do
13
13
  email: "#{email}",
14
14
  redirectUrl: "#{redirect_url}"
15
15
  ) {
16
- authenticatable {
17
- email
18
- }
16
+ message
19
17
  }
20
18
  }
21
19
  GRAPHQL
22
20
  end
23
21
 
24
22
  context 'when params are correct' do
25
- it 'sends password reset email' do
26
- expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
23
+ context 'when using the gem schema' do
24
+ it 'sends password reset email' do
25
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
26
+
27
+ expect(json_response[:data][:userSendPasswordReset]).to include(
28
+ message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
29
+ )
27
30
 
28
- email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
29
- link = email.css('a').first
31
+ email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
32
+ link = email.css('a').first
33
+ expect(link['href']).to include('/api/v1/graphql_auth?')
30
34
 
31
- # TODO: Move to feature spec
32
- expect do
33
- get link['href']
34
- user.reload
35
- end.to change(user, :allow_password_change).from(false).to(true)
35
+ expect do
36
+ get link['href']
37
+ user.reload
38
+ end.to change(user, :allow_password_change).from(false).to(true)
39
+ end
40
+ end
41
+
42
+ context 'when using a custom schema' do
43
+ let(:custom_path) { '/api/v1/graphql' }
44
+
45
+ it 'sends password reset email' do
46
+ expect { post_request(custom_path) }.to change(ActionMailer::Base.deliveries, :count).by(1)
47
+
48
+ expect(json_response[:data][:userSendPasswordReset]).to include(
49
+ message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
50
+ )
51
+
52
+ email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
53
+ link = email.css('a').first
54
+ expect(link['href']).to include("#{custom_path}?")
55
+
56
+ expect do
57
+ get link['href']
58
+ user.reload
59
+ end.to change(user, :allow_password_change).from(false).to(true)
60
+ end
36
61
  end
37
62
  end
38
63
 
@@ -41,6 +66,9 @@ RSpec.describe 'Send Password Reset Requests' do
41
66
 
42
67
  it 'honors devise configuration for case insensitive fields' do
43
68
  expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
69
+ expect(json_response[:data][:userSendPasswordReset]).to include(
70
+ message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
71
+ )
44
72
  end
45
73
  end
46
74
 
@@ -22,7 +22,13 @@ RSpec.describe 'Account confirmation' do
22
22
  context 'when confirmation token is correct' do
23
23
  let(:token) { user.confirmation_token }
24
24
 
25
- before { user.send_confirmation_instructions(template_path: ['graphql_devise/mailer']) }
25
+ before do
26
+ user.send_confirmation_instructions(
27
+ template_path: ['graphql_devise/mailer'],
28
+ controller: 'graphql_devise/graphql',
29
+ action: 'auth'
30
+ )
31
+ end
26
32
 
27
33
  it 'confirms the resource and redirects to the sent url' do
28
34
  expect do
@@ -1,40 +1,205 @@
1
1
  require 'rails_helper'
2
2
 
3
- RSpec.describe 'Integrations with the user controller' do
3
+ RSpec.describe "Integrations with the user's controller" do
4
4
  include_context 'with graphql query request'
5
5
 
6
6
  let(:user) { create(:user, :confirmed) }
7
- let(:query) do
8
- <<-GRAPHQL
9
- query {
10
- user(
11
- id: #{user.id}
12
- ) {
13
- id
14
- email
7
+
8
+ describe 'publicField' do
9
+ let(:query) do
10
+ <<-GRAPHQL
11
+ query {
12
+ publicField
13
+ }
14
+ GRAPHQL
15
+ end
16
+
17
+ context 'when using a regular schema' do
18
+ before { post_request('/api/v1/graphql') }
19
+
20
+ it 'does not require authentication' do
21
+ expect(json_response[:data][:publicField]).to eq('Field does not require authentication')
22
+ end
23
+ end
24
+
25
+ context 'when using an interpreter schema' do
26
+ before { post_request('/api/v1/interpreter') }
27
+
28
+ it 'does not require authentication' do
29
+ expect(json_response[:data][:publicField]).to eq('Field does not require authentication')
30
+ end
31
+ end
32
+
33
+ context 'when using the failing route' do
34
+ it 'raises an invalid resource_name error' do
35
+ expect { post_request('/api/v1/failing') }.to raise_error(
36
+ GraphqlDevise::Error,
37
+ 'Invalid resource_name `fail` provided to `graphql_context`. Possible values are: [:user, :admin, :guest, :users_customer].'
38
+ )
39
+ end
40
+ end
41
+ end
42
+
43
+ describe 'privateField' do
44
+ let(:query) do
45
+ <<-GRAPHQL
46
+ query {
47
+ privateField
15
48
  }
16
- }
17
- GRAPHQL
49
+ GRAPHQL
50
+ end
51
+
52
+ context 'when using a regular schema' do
53
+ before { post_request('/api/v1/graphql') }
54
+
55
+ context 'when user is authenticated' do
56
+ let(:headers) { user.create_new_auth_token }
57
+
58
+ it 'allow to perform the query' do
59
+ expect(json_response[:data][:privateField]).to eq('Field will always require authentication')
60
+ end
61
+ end
62
+
63
+ context 'when user is not authenticated' do
64
+ it 'returns a must sign in error' do
65
+ expect(json_response[:errors]).to contain_exactly(
66
+ hash_including(message: 'privateField field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
67
+ )
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'when using an interpreter schema' do
73
+ before { post_request('/api/v1/interpreter') }
74
+
75
+ context 'when user is authenticated' do
76
+ let(:headers) { user.create_new_auth_token }
77
+
78
+ it 'allow to perform the query' do
79
+ expect(json_response[:data][:privateField]).to eq('Field will always require authentication')
80
+ end
81
+ end
82
+
83
+ context 'when user is not authenticated' do
84
+ it 'returns a must sign in error' do
85
+ expect(json_response[:errors]).to contain_exactly(
86
+ hash_including(message: 'privateField field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
87
+ )
88
+ end
89
+ end
90
+ end
18
91
  end
19
92
 
20
- before { post_request('/api/v1/graphql') }
93
+ describe 'dummyMutation' do
94
+ let(:query) do
95
+ <<-GRAPHQL
96
+ mutation {
97
+ dummyMutation
98
+ }
99
+ GRAPHQL
100
+ end
101
+
102
+ context 'when using a regular schema' do
103
+ before { post_request('/api/v1/graphql') }
104
+
105
+ context 'when user is authenticated' do
106
+ let(:headers) { user.create_new_auth_token }
107
+
108
+ it 'allow to perform the query' do
109
+ expect(json_response[:data][:dummyMutation]).to eq('Necessary so GraphQL gem does not complain about empty mutation type')
110
+ end
111
+ end
112
+
113
+ context 'when user is not authenticated' do
114
+ it 'returns a must sign in error' do
115
+ expect(json_response[:errors]).to contain_exactly(
116
+ hash_including(message: 'dummyMutation field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
117
+ )
118
+ end
119
+ end
120
+ end
121
+
122
+ context 'when using an interpreter schema' do
123
+ before { post_request('/api/v1/interpreter') }
124
+
125
+ context 'when user is authenticated' do
126
+ let(:headers) { user.create_new_auth_token }
21
127
 
22
- context 'when user is authenticated' do
23
- let(:headers) { user.create_new_auth_token }
128
+ it 'allow to perform the query' do
129
+ expect(json_response[:data][:dummyMutation]).to eq('Necessary so GraphQL gem does not complain about empty mutation type')
130
+ end
131
+ end
24
132
 
25
- it 'allow to perform the query' do
26
- expect(json_response[:data][:user]).to match(
27
- email: user.email,
28
- id: user.id
29
- )
133
+ context 'when user is not authenticated' do
134
+ it 'returns a must sign in error' do
135
+ expect(json_response[:errors]).to contain_exactly(
136
+ hash_including(message: 'dummyMutation field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
137
+ )
138
+ end
139
+ end
30
140
  end
31
141
  end
32
142
 
33
- context 'when user is not authenticated' do
34
- it 'returns a must sign in error' do
35
- expect(json_response[:errors]).to contain_exactly(
36
- 'You need to sign in or sign up before continuing.'
37
- )
143
+ describe 'user' do
144
+ let(:query) do
145
+ <<-GRAPHQL
146
+ query {
147
+ user(
148
+ id: #{user.id}
149
+ ) {
150
+ id
151
+ email
152
+ }
153
+ }
154
+ GRAPHQL
155
+ end
156
+
157
+ context 'when using a regular schema' do
158
+ before { post_request('/api/v1/graphql') }
159
+
160
+ context 'when user is authenticated' do
161
+ let(:headers) { user.create_new_auth_token }
162
+
163
+ it 'allow to perform the query' do
164
+ expect(json_response[:data][:user]).to match(
165
+ email: user.email,
166
+ id: user.id
167
+ )
168
+ end
169
+ end
170
+
171
+ context 'when user is not authenticated' do
172
+ it 'returns a must sign in error' do
173
+ expect(json_response[:errors]).to contain_exactly(
174
+ hash_including(message: 'user field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
175
+ )
176
+ end
177
+ end
178
+ end
179
+
180
+ context 'when using an interpreter schema' do
181
+ before { post_request('/api/v1/interpreter') }
182
+
183
+ context 'when user is authenticated' do
184
+ let(:headers) { user.create_new_auth_token }
185
+
186
+ it 'allow to perform the query' do
187
+ expect(json_response[:data][:user]).to match(
188
+ email: user.email,
189
+ id: user.id
190
+ )
191
+ end
192
+ end
193
+
194
+ context 'when user is not authenticated' do
195
+ # Interpreter schema fields are public unless specified otherwise (plugin setting)
196
+ it 'allow to perform the query' do
197
+ expect(json_response[:data][:user]).to match(
198
+ email: user.email,
199
+ id: user.id
200
+ )
201
+ end
202
+ end
38
203
  end
39
204
  end
40
205
  end