graphql_devise 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/Appraisals +8 -0
  4. data/CHANGELOG.md +17 -0
  5. data/graphql_devise.gemspec +3 -3
  6. data/lib/graphql_devise.rb +20 -4
  7. data/lib/graphql_devise/default_operations/mutations.rb +20 -0
  8. data/lib/graphql_devise/default_operations/resolvers.rb +12 -0
  9. data/lib/graphql_devise/mount_method/operation_preparer.rb +41 -0
  10. data/lib/graphql_devise/mount_method/operation_preparers/custom_operation_preparer.rb +24 -0
  11. data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +32 -0
  12. data/lib/graphql_devise/mount_method/operation_preparers/gql_name_setter.rb +23 -0
  13. data/lib/graphql_devise/mount_method/operation_preparers/mutation_field_setter.rb +17 -0
  14. data/lib/graphql_devise/mount_method/operation_preparers/resolver_type_setter.rb +17 -0
  15. data/lib/graphql_devise/mount_method/operation_preparers/resource_name_setter.rb +17 -0
  16. data/lib/graphql_devise/mount_method/operation_sanitizer.rb +29 -0
  17. data/lib/graphql_devise/mount_method/option_sanitizer.rb +18 -0
  18. data/lib/graphql_devise/mount_method/option_sanitizers/array_checker.rb +26 -0
  19. data/lib/graphql_devise/mount_method/option_sanitizers/class_checker.rb +26 -0
  20. data/lib/graphql_devise/mount_method/option_sanitizers/hash_checker.rb +24 -0
  21. data/lib/graphql_devise/mount_method/option_sanitizers/string_checker.rb +21 -0
  22. data/lib/graphql_devise/mount_method/option_validators/provided_operations_validator.rb +24 -0
  23. data/lib/graphql_devise/mount_method/option_validators/skip_only_validator.rb +20 -0
  24. data/lib/graphql_devise/mount_method/option_validators/supported_operations_validator.rb +24 -0
  25. data/lib/graphql_devise/mount_method/options_validator.rb +16 -0
  26. data/lib/graphql_devise/mount_method/supported_options.rb +18 -0
  27. data/{app/graphql → lib}/graphql_devise/mutations/base.rb +0 -0
  28. data/{app/graphql → lib}/graphql_devise/mutations/login.rb +0 -0
  29. data/{app/graphql → lib}/graphql_devise/mutations/logout.rb +0 -0
  30. data/{app/graphql → lib}/graphql_devise/mutations/resend_confirmation.rb +0 -0
  31. data/{app/graphql → lib}/graphql_devise/mutations/send_password_reset.rb +0 -0
  32. data/{app/graphql → lib}/graphql_devise/mutations/sign_up.rb +0 -0
  33. data/{app/graphql → lib}/graphql_devise/mutations/update_password.rb +0 -0
  34. data/lib/graphql_devise/rails/routes.rb +57 -85
  35. data/{app/graphql → lib}/graphql_devise/resolvers/base.rb +0 -0
  36. data/{app/graphql → lib}/graphql_devise/resolvers/check_password_token.rb +0 -0
  37. data/{app/graphql → lib}/graphql_devise/resolvers/confirm_account.rb +0 -0
  38. data/{app/graphql → lib}/graphql_devise/resolvers/dummy.rb +0 -0
  39. data/{app/graphql → lib}/graphql_devise/types/authenticatable_type.rb +0 -0
  40. data/{app/graphql → lib}/graphql_devise/types/credential_type.rb +0 -0
  41. data/{app/graphql → lib}/graphql_devise/types/mutation_type.rb +0 -0
  42. data/{app/graphql → lib}/graphql_devise/types/query_type.rb +0 -0
  43. data/lib/graphql_devise/version.rb +1 -1
  44. data/spec/services/mount_method/operation_preparer_spec.rb +30 -0
  45. data/spec/services/mount_method/operation_preparers/custom_operation_preparer_spec.rb +43 -0
  46. data/spec/services/mount_method/operation_preparers/default_operation_preparer_spec.rb +60 -0
  47. data/spec/services/mount_method/operation_preparers/gql_name_setter_spec.rb +16 -0
  48. data/spec/services/mount_method/operation_preparers/mutation_field_setter_spec.rb +16 -0
  49. data/spec/services/mount_method/operation_preparers/resolver_type_setter_spec.rb +16 -0
  50. data/spec/services/mount_method/operation_preparers/resource_name_setter_spec.rb +14 -0
  51. data/spec/services/mount_method/operation_sanitizer_spec.rb +33 -0
  52. data/spec/services/mount_method/option_sanitizer_spec.rb +85 -0
  53. data/spec/services/mount_method/option_sanitizers/array_checker_spec.rb +38 -0
  54. data/spec/services/mount_method/option_sanitizers/class_checker_spec.rb +44 -0
  55. data/spec/services/mount_method/option_sanitizers/hash_checker_spec.rb +85 -0
  56. data/spec/services/mount_method/option_sanitizers/string_checker_spec.rb +30 -0
  57. data/spec/services/mount_method/option_validators/provided_operations_validator_spec.rb +57 -0
  58. data/spec/services/mount_method/option_validators/skip_only_validator_spec.rb +31 -0
  59. data/spec/services/mount_method/option_validators/supported_operations_validator_spec.rb +35 -0
  60. data/spec/services/mount_method/options_validator_spec.rb +36 -0
  61. metadata +79 -39
  62. data/gemfiles/.bundle/config +0 -2
  63. data/gemfiles/rails4.2_graphql1.8.gemfile +0 -10
  64. data/gemfiles/rails5.0_graphql1.8.gemfile +0 -11
  65. data/gemfiles/rails5.0_graphql1.9.gemfile +0 -9
  66. data/gemfiles/rails5.1_graphql1.8.gemfile +0 -11
  67. data/gemfiles/rails5.1_graphql1.9.gemfile +0 -9
  68. data/gemfiles/rails5.2_graphql1.10.gemfile +0 -9
  69. data/gemfiles/rails5.2_graphql1.8.gemfile +0 -11
  70. data/gemfiles/rails5.2_graphql1.9.gemfile +0 -9
  71. data/gemfiles/rails6.0_graphql1.10.gemfile +0 -10
  72. data/gemfiles/rails6.0_graphql1.8.gemfile +0 -10
  73. data/gemfiles/rails6.0_graphql1.9.gemfile +0 -10
  74. data/gemfiles/rails6.0_graphql_edge.gemfile +0 -11
  75. data/gemfiles/rails_edge_graphql_edge.gemfile +0 -11
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::DefaultOperationPreparer do
4
+ describe '#call' do
5
+ subject(:prepared) { default_preparer.call }
6
+
7
+ let(:default_preparer) { described_class.new(selected_operations: operations, custom_keys: custom_keys, mapping_name: mapping_name, preparer: preparer) }
8
+ let(:confirm_operation) { double(:confirm_operation, graphql_name: nil) }
9
+ let(:sign_up_operation) { double(:sign_up_operation, graphql_name: nil) }
10
+ let(:login_operation) { double(:confirm_operation, graphql_name: nil) }
11
+ let(:logout_operation) { double(:sign_up_operation, graphql_name: nil) }
12
+ let(:mapping_name) { 'user' }
13
+ let(:preparer) { double(:preparer) }
14
+ let(:operations) { { login: login_operation, logout: logout_operation, sign_up: sign_up_operation, confirm: confirm_operation } }
15
+ let(:custom_keys) { [:login, :logout] }
16
+
17
+ before do
18
+ allow(default_preparer).to receive(:child_class).with(confirm_operation).and_return(confirm_operation)
19
+ allow(default_preparer).to receive(:child_class).with(sign_up_operation).and_return(sign_up_operation)
20
+ allow(default_preparer).to receive(:child_class).with(login_operation).and_return(login_operation)
21
+ allow(default_preparer).to receive(:child_class).with(logout_operation).and_return(logout_operation)
22
+ allow(preparer).to receive(:call).with(confirm_operation).and_return(confirm_operation)
23
+ allow(preparer).to receive(:call).with(sign_up_operation).and_return(sign_up_operation)
24
+ allow(preparer).to receive(:call).with(login_operation).and_return(login_operation)
25
+ allow(preparer).to receive(:call).with(logout_operation).and_return(logout_operation)
26
+ end
27
+
28
+ it 'returns only those operations with no custom operation provided' do
29
+ expect(prepared.keys).to contain_exactly(:user_sign_up, :user_confirm)
30
+ end
31
+
32
+ it 'prepares default operations' do
33
+ expect(confirm_operation).to receive(:graphql_name).with('UserConfirm')
34
+ expect(sign_up_operation).to receive(:graphql_name).with('UserSignUp')
35
+ expect(preparer).to receive(:call).with(confirm_operation)
36
+ expect(preparer).to receive(:call).with(sign_up_operation)
37
+
38
+ prepared
39
+
40
+ expect(confirm_operation.instance_variable_get(:@resource_name)).to eq(:user)
41
+ expect(sign_up_operation.instance_variable_get(:@resource_name)).to eq(:user)
42
+ end
43
+
44
+ context 'when no custom keys are provided' do
45
+ let(:custom_keys) { [] }
46
+
47
+ it 'returns all selected operations' do
48
+ expect(prepared.keys).to contain_exactly(:user_sign_up, :user_confirm, :user_login, :user_logout)
49
+ end
50
+ end
51
+
52
+ context 'when no selected operations are provided' do
53
+ let(:operations) { {} }
54
+
55
+ it 'returns all selected operations' do
56
+ expect(prepared.keys).to eq([])
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::GqlNameSetter do
4
+ describe '#call' do
5
+ subject(:prepared_operation) { described_class.new(mapping_name).call(operation) }
6
+
7
+ let(:operation) { double(:operation) }
8
+ let(:mapping_name) { 'user_login' }
9
+
10
+ it 'sets a gql name to the operation' do
11
+ expect(operation).to receive(:graphql_name).with('UserLogin')
12
+
13
+ prepared_operation
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::MutationFieldSetter do
4
+ describe '#call' do
5
+ subject(:prepared_operation) { described_class.new(field_type).call(operation) }
6
+
7
+ let(:operation) { double(:operation) }
8
+ let(:field_type) { double(:type) }
9
+
10
+ it 'sets a field for the mutation' do
11
+ expect(operation).to receive(:field).with(:authenticatable, field_type, null: false)
12
+
13
+ prepared_operation
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::ResolverTypeSetter do
4
+ describe '#call' do
5
+ subject(:prepared_operation) { described_class.new(field_type).call(operation) }
6
+
7
+ let(:operation) { double(:operation) }
8
+ let(:field_type) { double(:type) }
9
+
10
+ it 'sets a field for the mutation' do
11
+ expect(operation).to receive(:type).with(field_type, null: false)
12
+
13
+ prepared_operation
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::ResourceNameSetter do
4
+ describe '#call' do
5
+ subject(:prepared_operation) { described_class.new(mapping_name).call(operation) }
6
+
7
+ let(:operation) { double(:operation) }
8
+ let(:mapping_name) { 'user' }
9
+
10
+ it 'sets a gql name to the operation' do
11
+ expect(prepared_operation.instance_variable_get(:@resource_name)).to eq(:user)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OperationSanitizer do
4
+ describe '.call' do
5
+ subject { described_class.call(default: default, only: only, skipped: skipped) }
6
+
7
+ let(:op_class1) { Class.new }
8
+ let(:op_class2) { Class.new }
9
+ let(:op_class3) { Class.new }
10
+
11
+ context 'when the operations passed are mutations' do
12
+ let(:skipped) { [] }
13
+ let(:only) { [] }
14
+ let(:default) { { operation1: op_class1, operation2: op_class2 } }
15
+
16
+ context 'when no other option besides default is passed' do
17
+ it { is_expected.to eq(default) }
18
+ end
19
+
20
+ context 'when there are only operations' do
21
+ let(:only) { [:operation1] }
22
+
23
+ it { is_expected.to eq(operation1: op_class1) }
24
+ end
25
+
26
+ context 'when there are skipped operations' do
27
+ let(:skipped) { [:operation2] }
28
+
29
+ it { is_expected.to eq(operation1: op_class1) }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OptionSanitizer do
4
+ subject(:clean_options) { described_class.new(options, supported_options).call! }
5
+
6
+ describe '#call!' do
7
+ let(:supported_options) do
8
+ {
9
+ my_string: GraphqlDevise::MountMethod::OptionSanitizers::StringChecker.new('default string'),
10
+ hash_multiple: GraphqlDevise::MountMethod::OptionSanitizers::HashChecker.new([String, Numeric]),
11
+ array: GraphqlDevise::MountMethod::OptionSanitizers::ArrayChecker.new(Symbol),
12
+ hash_single: GraphqlDevise::MountMethod::OptionSanitizers::HashChecker.new(Float),
13
+ my_class: GraphqlDevise::MountMethod::OptionSanitizers::ClassChecker.new(Numeric)
14
+ }
15
+ end
16
+
17
+ context 'when all options are provided and correct' do
18
+ let(:options) do
19
+ {
20
+ my_string: 'non default',
21
+ hash_multiple: { first: String, second: Float, third: Float },
22
+ array: [:one, :two, :three],
23
+ hash_single: { first: Float, second: Float },
24
+ my_class: Float
25
+ }
26
+ end
27
+
28
+ it 'returns a struct with clean options' do
29
+ expect(
30
+ my_string: clean_options.my_string,
31
+ hash_multiple: clean_options.hash_multiple,
32
+ array: clean_options.array,
33
+ hash_single: clean_options.hash_single,
34
+ my_class: clean_options.my_class
35
+ ).to match(
36
+ my_string: 'non default',
37
+ hash_multiple: { first: String, second: Float, third: Float },
38
+ array: [:one, :two, :three],
39
+ hash_single: { first: Float, second: Float },
40
+ my_class: Float
41
+ )
42
+ end
43
+ end
44
+
45
+ context 'when some options are provided but all correct' do
46
+ let(:options) do
47
+ {
48
+ hash_multiple: { first: String, second: Float, third: Float },
49
+ array: [:one, :two, :three],
50
+ my_class: Float
51
+ }
52
+ end
53
+
54
+ it 'returns a struct with clean options and default values' do
55
+ expect(
56
+ my_string: clean_options.my_string,
57
+ hash_multiple: clean_options.hash_multiple,
58
+ array: clean_options.array,
59
+ hash_single: clean_options.hash_single,
60
+ my_class: clean_options.my_class
61
+ ).to match(
62
+ my_string: 'default string',
63
+ hash_multiple: { first: String, second: Float, third: Float },
64
+ array: [:one, :two, :three],
65
+ hash_single: {},
66
+ my_class: Float
67
+ )
68
+ end
69
+ end
70
+
71
+ context 'when an option provided is invalid' do
72
+ let(:options) do
73
+ {
74
+ hash_multiple: { first: String, second: Float, third: Float },
75
+ array: ['not symbol 1', 'not symbol 2'],
76
+ my_class: Float
77
+ }
78
+ end
79
+
80
+ it 'raises an error' do
81
+ expect { clean_options }.to raise_error(GraphqlDevise::InvalidMountOptionsError, '`array` option has invalid elements. Symbol expected.')
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OptionSanitizers::ArrayChecker do
4
+ describe '#call!' do
5
+ subject(:clean_value) { described_class.new(element_type).call!(value, key) }
6
+
7
+ let(:key) { :any_option }
8
+ let(:element_type) { Symbol }
9
+
10
+ context 'when no value is provided' do
11
+ let(:value) { nil }
12
+
13
+ it { is_expected.to eq([]) }
14
+ end
15
+
16
+ context 'when provided value is not an array' do
17
+ let(:value) { 'not an array' }
18
+
19
+ it 'raises an error' do
20
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key}` option has an invalid value. Array expected.")
21
+ end
22
+ end
23
+
24
+ context 'when provided array contains invalid elements' do
25
+ let(:value) { [:valid, 'invalid'] }
26
+
27
+ it 'raises an error' do
28
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key}` option has invalid elements. #{element_type} expected.")
29
+ end
30
+ end
31
+
32
+ context 'when provided array contains all valid elements' do
33
+ let(:value) { [:valid1, :valid2] }
34
+
35
+ it { is_expected.to eq(value) }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OptionSanitizers::ClassChecker do
4
+ describe '#call!' do
5
+ subject(:clean_value) { described_class.new(expected_class).call!(value, key) }
6
+
7
+ let(:key) { :any_option }
8
+ let(:expected_class) { Numeric }
9
+
10
+ context 'when no value is provided' do
11
+ let(:value) { nil }
12
+
13
+ it { is_expected.to eq(nil) }
14
+ end
15
+
16
+ context 'when provided value is not a class' do
17
+ let(:value) { 'I\'m not a class' }
18
+
19
+ it 'raises an error' do
20
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key}` option has an invalid value. Class expected.")
21
+ end
22
+ end
23
+
24
+ context 'when provided class is not of the expected type' do
25
+ let(:value) { String }
26
+
27
+ it 'raises an error' do
28
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key}` option has an invalid value. #{expected_class} or descendants expected. Got String.")
29
+ end
30
+ end
31
+
32
+ context 'when provided class is of the expected type' do
33
+ let(:value) { Numeric }
34
+
35
+ it { is_expected.to eq(value) }
36
+ end
37
+
38
+ context 'when provided class has the expected type as an acestor' do
39
+ let(:value) { Float }
40
+
41
+ it { is_expected.to eq(value) }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OptionSanitizers::HashChecker do
4
+ describe '#call!' do
5
+ subject(:clean_value) { described_class.new(element_type).call!(value, key) }
6
+
7
+ let(:key) { :any_option }
8
+
9
+ context 'when a single valid type is provided' do
10
+ let(:element_type) { Numeric }
11
+
12
+ context 'when no value is provided' do
13
+ let(:value) { nil }
14
+
15
+ it { is_expected.to eq({}) }
16
+ end
17
+
18
+ context 'when provided value is not a hash' do
19
+ let(:value) { 'not a hash' }
20
+
21
+ it 'raises an error' do
22
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key}` option has an invalid value. Hash expected. Got String.")
23
+ end
24
+ end
25
+
26
+ context 'when provided hash contains invalid elements' do
27
+ let(:value) { { valid: Float, invalid: String } }
28
+
29
+ it 'raises an error' do
30
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key} -> invalid` option has an invalid value. #{element_type} or descendants expected. Got #{String}.")
31
+ end
32
+ end
33
+
34
+ context 'when provided array contains all valid elements' do
35
+ let(:value) { { valid1: Numeric, valid2: Numeric } }
36
+
37
+ it { is_expected.to eq(value) }
38
+ end
39
+
40
+ context 'when provided class has the expected type as an acestor' do
41
+ let(:value) { { valid: Float } }
42
+
43
+ it { is_expected.to eq(value) }
44
+ end
45
+ end
46
+
47
+ context 'when multiple value types are allowed' do
48
+ let(:element_type) { [String, Numeric] }
49
+
50
+ context 'when no value is provided' do
51
+ let(:value) { nil }
52
+
53
+ it { is_expected.to eq({}) }
54
+ end
55
+
56
+ context 'when provided array contains all valid elements' do
57
+ let(:value) { { valid1: String, valid2: Numeric } }
58
+
59
+ it { is_expected.to eq(value) }
60
+ end
61
+
62
+ context 'when provided class has the expected type as an acestor' do
63
+ let(:value) { { valid: Float } }
64
+
65
+ it { is_expected.to eq(value) }
66
+ end
67
+
68
+ context 'when provided value is not a hash' do
69
+ let(:value) { 'not a hash' }
70
+
71
+ it 'raises an error' do
72
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key}` option has an invalid value. Hash expected. Got String.")
73
+ end
74
+ end
75
+
76
+ context 'when provided hash contains invalid elements' do
77
+ let(:value) { { valid: String, invalid: StandardError } }
78
+
79
+ it 'raises an error' do
80
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key} -> invalid` option has an invalid value. #{element_type.join(', ')} or descendants expected. Got #{StandardError}.")
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe GraphqlDevise::MountMethod::OptionSanitizers::StringChecker do
4
+ describe '#call!' do
5
+ subject(:clean_value) { described_class.new(default_string).call!(value, key) }
6
+
7
+ let(:key) { :any_option }
8
+ let(:default_string) { 'default string' }
9
+
10
+ context 'when no value is provided' do
11
+ let(:value) { nil }
12
+
13
+ it { is_expected.to eq(default_string) }
14
+ end
15
+
16
+ context 'when provided value is not a String' do
17
+ let(:value) { 1000 }
18
+
19
+ it 'raises an error' do
20
+ expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key}` option has an invalid value. String expected.")
21
+ end
22
+ end
23
+
24
+ context 'when provided array contains all valid elements' do
25
+ let(:value) { 'custom valid string' }
26
+
27
+ it { is_expected.to eq(value) }
28
+ end
29
+ end
30
+ end