servactory 2.12.0.rc1 → 2.12.0.rc3
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/config/locales/en.yml +18 -12
- data/config/locales/ru.yml +18 -12
- data/lib/servactory/configuration/option_helpers/option_helpers_collection.rb +5 -1
- data/lib/servactory/configuration/setup.rb +9 -3
- data/lib/servactory/context/workspace/inputs.rb +0 -35
- data/lib/servactory/info/builder.rb +103 -0
- data/lib/servactory/info/dsl.rb +8 -51
- data/lib/servactory/info/result.rb +4 -4
- data/lib/servactory/inputs/dsl.rb +0 -1
- data/lib/servactory/inputs/input.rb +8 -9
- data/lib/servactory/internals/dsl.rb +0 -1
- data/lib/servactory/internals/internal.rb +5 -8
- data/lib/servactory/maintenance/attributes/option.rb +7 -13
- data/lib/servactory/maintenance/attributes/option_helper.rb +8 -2
- data/lib/servactory/maintenance/attributes/options/registrar.rb +2 -57
- data/lib/servactory/maintenance/attributes/translator/must.rb +1 -1
- data/lib/servactory/maintenance/attributes/translator/type.rb +3 -38
- data/lib/servactory/maintenance/attributes/validations/must.rb +8 -6
- data/lib/servactory/maintenance/validations/types.rb +3 -26
- data/lib/servactory/outputs/dsl.rb +0 -1
- data/lib/servactory/outputs/output.rb +5 -8
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/consists_of_matcher.rb +8 -13
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/inclusion_matcher.rb +7 -4
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/message_matcher.rb +91 -0
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/must_matcher.rb +6 -0
- data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/schema_matcher.rb +83 -0
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb +29 -7
- data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/valid_with_matcher.rb +12 -5
- data/lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb +31 -7
- data/lib/servactory/tool_kit/dynamic_options/inclusion.rb +63 -0
- data/lib/servactory/tool_kit/dynamic_options/must.rb +34 -6
- data/lib/servactory/tool_kit/dynamic_options/schema.rb +193 -0
- data/lib/servactory/version.rb +1 -1
- metadata +7 -5
- data/lib/servactory/maintenance/attributes/translator/inclusion.rb +0 -26
- data/lib/servactory/maintenance/attributes/validations/inclusion.rb +0 -63
- data/lib/servactory/maintenance/validations/object_schema.rb +0 -116
@@ -75,7 +75,6 @@ module Servactory
|
|
75
75
|
)
|
76
76
|
end
|
77
77
|
|
78
|
-
# rubocop:disable Metrics/MethodLength
|
79
78
|
def prepare_advanced_for(
|
80
79
|
body:,
|
81
80
|
body_key:,
|
@@ -83,22 +82,17 @@ module Servactory
|
|
83
82
|
body_fallback:
|
84
83
|
)
|
85
84
|
if body.is_a?(Hash)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
body: body.fetch(body_key, message.present? ? body_value : body_fallback),
|
94
|
-
message:
|
95
|
-
)
|
96
|
-
end
|
85
|
+
message = body.fetch(:message, nil)
|
86
|
+
|
87
|
+
DEFAULT_BODY.call(
|
88
|
+
key: body_key,
|
89
|
+
body: body.fetch(body_key, message.present? ? body_value : body_fallback),
|
90
|
+
message:
|
91
|
+
)
|
97
92
|
else
|
98
93
|
DEFAULT_BODY.call(key: body_key, body:)
|
99
94
|
end
|
100
95
|
end
|
101
|
-
# rubocop:enable Metrics/MethodLength
|
102
96
|
|
103
97
|
def prepare_methods_for(attribute)
|
104
98
|
attribute.instance_eval(define_methods_template) if define_methods_template.present?
|
@@ -5,11 +5,17 @@ module Servactory
|
|
5
5
|
module Attributes
|
6
6
|
class OptionHelper
|
7
7
|
attr_reader :name,
|
8
|
-
:equivalent
|
8
|
+
:equivalent,
|
9
|
+
:meta
|
9
10
|
|
10
|
-
def initialize(name:, equivalent:)
|
11
|
+
def initialize(name:, equivalent:, meta: {})
|
11
12
|
@name = name
|
12
13
|
@equivalent = equivalent
|
14
|
+
@meta = meta
|
15
|
+
end
|
16
|
+
|
17
|
+
def dynamic_option?
|
18
|
+
meta[:type] == :dynamic_option
|
13
19
|
end
|
14
20
|
end
|
15
21
|
end
|
@@ -10,8 +10,6 @@ module Servactory
|
|
10
10
|
required
|
11
11
|
default
|
12
12
|
collection
|
13
|
-
hash
|
14
|
-
inclusion
|
15
13
|
must
|
16
14
|
prepare
|
17
15
|
].freeze
|
@@ -20,8 +18,6 @@ module Servactory
|
|
20
18
|
required: false,
|
21
19
|
types: false,
|
22
20
|
default: false,
|
23
|
-
hash: false,
|
24
|
-
inclusion: false,
|
25
21
|
must: false,
|
26
22
|
prepare: false
|
27
23
|
}.freeze
|
@@ -32,26 +28,21 @@ module Servactory
|
|
32
28
|
new(...).register
|
33
29
|
end
|
34
30
|
|
35
|
-
def initialize(attribute:,
|
31
|
+
def initialize(attribute:, options:, features:)
|
36
32
|
@attribute = attribute
|
37
|
-
@hash_mode_class_names = hash_mode_class_names
|
38
33
|
@options = options
|
39
34
|
@features = DEFAULT_FEATURES.merge(features)
|
40
35
|
end
|
41
36
|
|
42
37
|
########################################################################
|
43
38
|
|
44
|
-
def register
|
39
|
+
def register
|
45
40
|
# Validation Class: Servactory::Inputs::Validations::Required
|
46
41
|
register_required_option if @features.fetch(:required)
|
47
42
|
|
48
43
|
# Validation Class: Servactory::Maintenance::Attributes::Validations::Type
|
49
44
|
register_types_option if @features.fetch(:types)
|
50
45
|
register_default_option if @features.fetch(:default)
|
51
|
-
register_hash_option if @features.fetch(:hash)
|
52
|
-
|
53
|
-
# Validation Class: Servactory::Maintenance::Attributes::Validations::Inclusion
|
54
|
-
register_inclusion_option if @features.fetch(:inclusion)
|
55
46
|
|
56
47
|
# Validation Class: Servactory::Maintenance::Attributes::Validations::Must
|
57
48
|
register_must_option if @features.fetch(:must)
|
@@ -121,47 +112,6 @@ module Servactory
|
|
121
112
|
)
|
122
113
|
end
|
123
114
|
|
124
|
-
def register_hash_option # rubocop:disable Metrics/MethodLength
|
125
|
-
collection << Servactory::Maintenance::Attributes::Option.new(
|
126
|
-
name: :schema,
|
127
|
-
attribute: @attribute,
|
128
|
-
validation_class: Servactory::Maintenance::Attributes::Validations::Type,
|
129
|
-
define_methods: [
|
130
|
-
Servactory::Maintenance::Attributes::DefineMethod.new(
|
131
|
-
name: :hash_mode?,
|
132
|
-
content: ->(**) { @hash_mode_class_names.include?(@options.fetch(:type)) }
|
133
|
-
)
|
134
|
-
],
|
135
|
-
define_conflicts: [
|
136
|
-
Servactory::Maintenance::Attributes::DefineConflict.new(
|
137
|
-
content: -> { :object_vs_inclusion if @attribute.hash_mode? && @attribute.inclusion_present? }
|
138
|
-
)
|
139
|
-
],
|
140
|
-
need_for_checks: false,
|
141
|
-
body_key: :is,
|
142
|
-
body_fallback: {},
|
143
|
-
**@options
|
144
|
-
)
|
145
|
-
end
|
146
|
-
|
147
|
-
def register_inclusion_option # rubocop:disable Metrics/MethodLength
|
148
|
-
collection << Servactory::Maintenance::Attributes::Option.new(
|
149
|
-
name: :inclusion,
|
150
|
-
attribute: @attribute,
|
151
|
-
validation_class: Servactory::Maintenance::Attributes::Validations::Inclusion,
|
152
|
-
define_methods: [
|
153
|
-
Servactory::Maintenance::Attributes::DefineMethod.new(
|
154
|
-
name: :inclusion_present?,
|
155
|
-
content: ->(option:) { option[:in].is_a?(Array) && option[:in].present? }
|
156
|
-
)
|
157
|
-
],
|
158
|
-
need_for_checks: true,
|
159
|
-
body_key: :in,
|
160
|
-
body_fallback: nil,
|
161
|
-
**@options
|
162
|
-
)
|
163
|
-
end
|
164
|
-
|
165
115
|
def register_must_option # rubocop:disable Metrics/MethodLength
|
166
116
|
collection << Servactory::Maintenance::Attributes::Option.new(
|
167
117
|
name: :must,
|
@@ -192,11 +142,6 @@ module Servactory
|
|
192
142
|
content: ->(option:) { option[:in].present? }
|
193
143
|
)
|
194
144
|
],
|
195
|
-
define_conflicts: [
|
196
|
-
Servactory::Maintenance::Attributes::DefineConflict.new(
|
197
|
-
content: -> { :prepare_vs_inclusion if @attribute.prepare_present? && @attribute.inclusion_present? }
|
198
|
-
)
|
199
|
-
],
|
200
145
|
need_for_checks: false,
|
201
146
|
body_key: :in,
|
202
147
|
body_fallback: false,
|
@@ -8,7 +8,7 @@ module Servactory
|
|
8
8
|
module_function
|
9
9
|
|
10
10
|
def default_message
|
11
|
-
lambda do |service:, value:, code:, input: nil, internal: nil, output: nil, reason: nil
|
11
|
+
lambda do |service:, value:, code:, input: nil, internal: nil, output: nil, reason: nil, **|
|
12
12
|
attribute = Servactory::Utils.define_attribute_with(input:, internal:, output:)
|
13
13
|
|
14
14
|
service.translate(
|
@@ -5,53 +5,18 @@ module Servactory
|
|
5
5
|
module Attributes
|
6
6
|
module Translator
|
7
7
|
module Type
|
8
|
-
|
8
|
+
module_function
|
9
9
|
|
10
10
|
def default_message
|
11
|
-
lambda do |service:, attribute:,
|
12
|
-
if attribute.hash_mode? && key_name.present?
|
13
|
-
for_hash_mode_with(service:, attribute:, key_name:,
|
14
|
-
expected_type:, given_type:)
|
15
|
-
else
|
16
|
-
for_others_with(service:, attribute:,
|
17
|
-
expected_type:, given_type:)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def for_hash_mode_with(service:, attribute:, key_name:, expected_type:, given_type:) # rubocop:disable Metrics/MethodLength
|
25
|
-
hash_message = attribute.schema.fetch(:message)
|
26
|
-
|
27
|
-
if hash_message.is_a?(Proc)
|
28
|
-
hash_message.call(
|
29
|
-
**Servactory::Utils.fetch_hash_with_desired_attribute(attribute),
|
30
|
-
key_name:,
|
31
|
-
expected_type:,
|
32
|
-
given_type:
|
33
|
-
)
|
34
|
-
elsif hash_message.is_a?(String) && hash_message.present?
|
35
|
-
hash_message
|
36
|
-
else
|
11
|
+
lambda do |service:, attribute:, expected_type:, given_type:, **|
|
37
12
|
service.translate(
|
38
|
-
"#{attribute.i18n_name}.validations.type.default_error.
|
13
|
+
"#{attribute.i18n_name}.validations.type.default_error.default",
|
39
14
|
"#{attribute.system_name}_name": attribute.name,
|
40
|
-
key_name:,
|
41
15
|
expected_type:,
|
42
16
|
given_type:
|
43
17
|
)
|
44
18
|
end
|
45
19
|
end
|
46
|
-
|
47
|
-
def for_others_with(service:, attribute:, expected_type:, given_type:)
|
48
|
-
service.translate(
|
49
|
-
"#{attribute.i18n_name}.validations.type.default_error.default",
|
50
|
-
"#{attribute.system_name}_name": attribute.name,
|
51
|
-
expected_type:,
|
52
|
-
given_type:
|
53
|
-
)
|
54
|
-
end
|
55
20
|
end
|
56
21
|
end
|
57
22
|
end
|
@@ -28,11 +28,11 @@ module Servactory
|
|
28
28
|
|
29
29
|
def check
|
30
30
|
@check_options.each do |code, options|
|
31
|
-
message, reason = call_or_fetch_message_from(code, options)
|
31
|
+
message, reason, meta = call_or_fetch_message_from(code, options)
|
32
32
|
|
33
33
|
next if message.blank?
|
34
34
|
|
35
|
-
add_error_with(message, code, reason)
|
35
|
+
add_error_with(message, code, reason, meta)
|
36
36
|
end
|
37
37
|
|
38
38
|
errors
|
@@ -43,14 +43,15 @@ module Servactory
|
|
43
43
|
def call_or_fetch_message_from(code, options) # rubocop:disable Metrics/MethodLength
|
44
44
|
check, message = options.values_at(:is, :message)
|
45
45
|
|
46
|
-
check_result, check_result_code =
|
46
|
+
check_result, check_result_code, meta =
|
47
47
|
check.call(value: @value, **Servactory::Utils.fetch_hash_with_desired_attribute(@attribute))
|
48
48
|
|
49
49
|
return if check_result
|
50
50
|
|
51
51
|
[
|
52
52
|
message.presence || Servactory::Maintenance::Attributes::Translator::Must.default_message,
|
53
|
-
check_result_code
|
53
|
+
check_result_code,
|
54
|
+
meta
|
54
55
|
]
|
55
56
|
rescue StandardError => e
|
56
57
|
add_syntax_error_with(
|
@@ -62,14 +63,15 @@ module Servactory
|
|
62
63
|
|
63
64
|
########################################################################
|
64
65
|
|
65
|
-
def add_error_with(message, code, reason)
|
66
|
+
def add_error_with(message, code, reason, meta = {})
|
66
67
|
add_error(
|
67
68
|
message:,
|
68
69
|
service: @context.send(:servactory_service_info),
|
69
70
|
**Servactory::Utils.fetch_hash_with_desired_attribute(@attribute),
|
70
71
|
value: @value,
|
71
72
|
code:,
|
72
|
-
reason
|
73
|
+
reason:,
|
74
|
+
meta:
|
73
75
|
)
|
74
76
|
end
|
75
77
|
|
@@ -16,32 +16,9 @@ module Servactory
|
|
16
16
|
@error_callback = error_callback
|
17
17
|
end
|
18
18
|
|
19
|
-
def validate! # rubocop:disable Metrics/MethodLength
|
20
|
-
|
21
|
-
|
22
|
-
if @attribute.hash_mode?
|
23
|
-
object_schema_validator = Servactory::Maintenance::Validations::ObjectSchema.validate(
|
24
|
-
object: @value,
|
25
|
-
schema: @attribute.schema
|
26
|
-
)
|
27
|
-
|
28
|
-
return if object_schema_validator.valid?
|
29
|
-
else
|
30
|
-
return if prepared_types.any? do |type| # rubocop:disable Style/IfInsideElse
|
31
|
-
@value.is_a?(type)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
if (first_error = object_schema_validator&.errors&.first).present?
|
36
|
-
return @error_callback.call(
|
37
|
-
message: Servactory::Maintenance::Attributes::Translator::Type.default_message,
|
38
|
-
service: @context.send(:servactory_service_info),
|
39
|
-
attribute: @attribute,
|
40
|
-
value: @value,
|
41
|
-
key_name: first_error.fetch(:key_name),
|
42
|
-
expected_type: first_error.fetch(:expected_type),
|
43
|
-
given_type: first_error.fetch(:given_type)
|
44
|
-
)
|
19
|
+
def validate! # rubocop:disable Metrics/MethodLength
|
20
|
+
return if prepared_types.any? do |type|
|
21
|
+
@value.is_a?(type)
|
45
22
|
end
|
46
23
|
|
47
24
|
@error_callback.call(
|
@@ -6,12 +6,12 @@ module Servactory
|
|
6
6
|
class Actor
|
7
7
|
attr_reader :name,
|
8
8
|
:types,
|
9
|
-
:
|
9
|
+
:options
|
10
10
|
|
11
11
|
def initialize(output)
|
12
12
|
@name = output.name
|
13
13
|
@types = output.types
|
14
|
-
@
|
14
|
+
@options = output.options
|
15
15
|
|
16
16
|
define_singleton_method(:system_name) { output.system_name }
|
17
17
|
define_singleton_method(:i18n_name) { output.i18n_name }
|
@@ -23,17 +23,16 @@ module Servactory
|
|
23
23
|
end
|
24
24
|
|
25
25
|
attr_reader :name,
|
26
|
-
:collection_of_options
|
26
|
+
:collection_of_options,
|
27
|
+
:options
|
27
28
|
|
28
29
|
def initialize(
|
29
30
|
name,
|
30
31
|
*helpers,
|
31
|
-
hash_mode_class_names:,
|
32
32
|
option_helpers:,
|
33
33
|
**options
|
34
34
|
)
|
35
35
|
@name = name
|
36
|
-
@hash_mode_class_names = hash_mode_class_names
|
37
36
|
@option_helpers = option_helpers
|
38
37
|
|
39
38
|
register_options(helpers:, options:)
|
@@ -59,16 +58,14 @@ module Servactory
|
|
59
58
|
|
60
59
|
options_registrar = Servactory::Maintenance::Attributes::Options::Registrar.register(
|
61
60
|
attribute: self,
|
62
|
-
hash_mode_class_names: @hash_mode_class_names,
|
63
61
|
options:,
|
64
62
|
features: {
|
65
63
|
types: true,
|
66
|
-
hash: true,
|
67
|
-
inclusion: true,
|
68
64
|
must: true
|
69
65
|
}
|
70
66
|
)
|
71
67
|
|
68
|
+
@options = options
|
72
69
|
@collection_of_options = options_registrar.collection
|
73
70
|
end
|
74
71
|
|
data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/consists_of_matcher.rb
CHANGED
@@ -6,17 +6,18 @@ module Servactory
|
|
6
6
|
module Matchers
|
7
7
|
module HaveServiceAttributeMatchers
|
8
8
|
class ConsistsOfMatcher
|
9
|
+
OPTION_NAME = :consists_of
|
10
|
+
OPTION_BODY_KEY = :type
|
11
|
+
|
9
12
|
attr_reader :missing_option
|
10
13
|
|
11
|
-
def initialize(described_class, attribute_type, attribute_name, option_types, consists_of_types
|
12
|
-
custom_message)
|
14
|
+
def initialize(described_class, attribute_type, attribute_name, option_types, consists_of_types)
|
13
15
|
@described_class = described_class
|
14
16
|
@attribute_type = attribute_type
|
15
17
|
@attribute_type_plural = attribute_type.to_s.pluralize.to_sym
|
16
18
|
@attribute_name = attribute_name
|
17
19
|
@option_types = option_types
|
18
20
|
@consists_of_types = consists_of_types
|
19
|
-
@custom_message = custom_message
|
20
21
|
|
21
22
|
@attribute_data = described_class.info.public_send(attribute_type_plural).fetch(attribute_name)
|
22
23
|
|
@@ -46,20 +47,14 @@ module Servactory
|
|
46
47
|
:attribute_name,
|
47
48
|
:option_types,
|
48
49
|
:consists_of_types,
|
49
|
-
:custom_message,
|
50
50
|
:attribute_data
|
51
51
|
|
52
52
|
def submatcher_passes?(_subject)
|
53
|
-
|
54
|
-
|
55
|
-
attribute_must_keys = attribute_must.keys
|
56
|
-
|
57
|
-
expected_keys = %i[consists_of]
|
58
|
-
|
59
|
-
attribute_must_keys = attribute_must_keys.select { |key| expected_keys.include?(key) }
|
53
|
+
attribute_consists_of = attribute_data.fetch(OPTION_NAME)
|
54
|
+
attribute_consists_of_types = Array(attribute_consists_of.fetch(OPTION_BODY_KEY))
|
60
55
|
|
61
|
-
|
62
|
-
|
56
|
+
attribute_consists_of_types.difference(consists_of_types).empty? &&
|
57
|
+
consists_of_types.difference(attribute_consists_of_types).empty?
|
63
58
|
end
|
64
59
|
|
65
60
|
def build_missing_option
|
data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/inclusion_matcher.rb
CHANGED
@@ -6,6 +6,9 @@ module Servactory
|
|
6
6
|
module Matchers
|
7
7
|
module HaveServiceAttributeMatchers
|
8
8
|
class InclusionMatcher
|
9
|
+
OPTION_NAME = :inclusion
|
10
|
+
OPTION_BODY_KEY = :in
|
11
|
+
|
9
12
|
attr_reader :missing_option
|
10
13
|
|
11
14
|
def initialize(described_class, attribute_type, attribute_name, values)
|
@@ -44,16 +47,16 @@ module Servactory
|
|
44
47
|
:attribute_data
|
45
48
|
|
46
49
|
def submatcher_passes?(_subject)
|
47
|
-
attribute_inclusion = attribute_data.fetch(
|
48
|
-
attribute_inclusion_in = attribute_inclusion.fetch(
|
50
|
+
attribute_inclusion = attribute_data.fetch(OPTION_NAME)
|
51
|
+
attribute_inclusion_in = attribute_inclusion.fetch(OPTION_BODY_KEY)
|
49
52
|
|
50
53
|
attribute_inclusion_in.difference(values).empty? &&
|
51
54
|
values.difference(attribute_inclusion_in).empty?
|
52
55
|
end
|
53
56
|
|
54
57
|
def build_missing_option
|
55
|
-
attribute_inclusion = attribute_data.fetch(
|
56
|
-
attribute_inclusion_in = attribute_inclusion.fetch(
|
58
|
+
attribute_inclusion = attribute_data.fetch(OPTION_NAME)
|
59
|
+
attribute_inclusion_in = attribute_inclusion.fetch(OPTION_BODY_KEY)
|
57
60
|
|
58
61
|
<<~MESSAGE
|
59
62
|
should include the expected values
|
data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/message_matcher.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module TestKit
|
5
|
+
module Rspec
|
6
|
+
module Matchers
|
7
|
+
module HaveServiceAttributeMatchers
|
8
|
+
class MessageMatcher
|
9
|
+
attr_reader :missing_option
|
10
|
+
|
11
|
+
def initialize(described_class, attribute_type, attribute_name, submatcher, custom_message)
|
12
|
+
@described_class = described_class
|
13
|
+
@attribute_type = attribute_type
|
14
|
+
@attribute_type_plural = attribute_type.to_s.pluralize.to_sym
|
15
|
+
@attribute_name = attribute_name
|
16
|
+
@custom_message = custom_message
|
17
|
+
|
18
|
+
attribute_data = described_class.info.public_send(attribute_type_plural).fetch(attribute_name)
|
19
|
+
|
20
|
+
attribute_schema = attribute_data.fetch(submatcher.class::OPTION_NAME)
|
21
|
+
@attribute_schema_is = attribute_schema.fetch(submatcher.class::OPTION_BODY_KEY)
|
22
|
+
@attribute_schema_message = attribute_schema.fetch(:message)
|
23
|
+
|
24
|
+
@missing_option = ""
|
25
|
+
end
|
26
|
+
|
27
|
+
def description
|
28
|
+
result = "message: "
|
29
|
+
result + attribute_schema_message
|
30
|
+
end
|
31
|
+
|
32
|
+
def matches?(subject)
|
33
|
+
if submatcher_passes?(subject)
|
34
|
+
true
|
35
|
+
else
|
36
|
+
@missing_option = build_missing_option
|
37
|
+
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :described_class,
|
45
|
+
:attribute_type,
|
46
|
+
:attribute_type_plural,
|
47
|
+
:attribute_name,
|
48
|
+
:option_types,
|
49
|
+
:custom_message,
|
50
|
+
:attribute_schema_is,
|
51
|
+
:attribute_schema_message
|
52
|
+
|
53
|
+
def submatcher_passes?(_subject)
|
54
|
+
schema_message_equal?
|
55
|
+
end
|
56
|
+
|
57
|
+
def schema_message_equal? # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
58
|
+
@schema_message_equal ||=
|
59
|
+
if custom_message.present? && !attribute_schema_message.nil?
|
60
|
+
if custom_message.is_a?(RSpec::Matchers::BuiltIn::BaseMatcher)
|
61
|
+
RSpec::Expectations::ValueExpectationTarget
|
62
|
+
.new(attribute_schema_message)
|
63
|
+
.to(custom_message)
|
64
|
+
|
65
|
+
true
|
66
|
+
elsif attribute_schema_message.is_a?(Proc)
|
67
|
+
attribute_schema_message.call.casecmp(custom_message).zero?
|
68
|
+
else
|
69
|
+
attribute_schema_message.casecmp(custom_message).zero?
|
70
|
+
end
|
71
|
+
else
|
72
|
+
true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def build_missing_option
|
77
|
+
unless schema_message_equal? # rubocop:disable Style/GuardClause
|
78
|
+
<<~MESSAGE
|
79
|
+
should return expected message in case of problem:
|
80
|
+
|
81
|
+
expected #{attribute_schema_message.inspect}
|
82
|
+
got #{custom_message.inspect}
|
83
|
+
MESSAGE
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -51,6 +51,12 @@ module Servactory
|
|
51
51
|
# NOTE: Even though the dynamic option `consists_of` is a `must`, here we are testing explicit `must`.
|
52
52
|
attribute_must_keys.delete(:consists_of)
|
53
53
|
|
54
|
+
# NOTE: Even though the dynamic option `schema` is a `must`, here we are testing explicit `must`.
|
55
|
+
attribute_must_keys.delete(:schema)
|
56
|
+
|
57
|
+
# NOTE: Even though the dynamic option `inclusion` is a `must`, here we are testing explicit `must`.
|
58
|
+
attribute_must_keys.delete(:inclusion)
|
59
|
+
|
54
60
|
attribute_must_keys.difference(must_names).empty? &&
|
55
61
|
must_names.difference(attribute_must_keys).empty?
|
56
62
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module TestKit
|
5
|
+
module Rspec
|
6
|
+
module Matchers
|
7
|
+
module HaveServiceAttributeMatchers
|
8
|
+
class SchemaMatcher
|
9
|
+
OPTION_NAME = :schema
|
10
|
+
OPTION_BODY_KEY = :is
|
11
|
+
|
12
|
+
attr_reader :missing_option
|
13
|
+
|
14
|
+
def initialize(described_class, attribute_type, attribute_name, option_types, schema_data) # rubocop:disable Metrics/MethodLength
|
15
|
+
@described_class = described_class
|
16
|
+
@attribute_type = attribute_type
|
17
|
+
@attribute_type_plural = attribute_type.to_s.pluralize.to_sym
|
18
|
+
@attribute_name = attribute_name
|
19
|
+
@option_types = option_types
|
20
|
+
@schema_data = schema_data
|
21
|
+
|
22
|
+
attribute_data = described_class.info.public_send(attribute_type_plural).fetch(attribute_name)
|
23
|
+
|
24
|
+
attribute_schema = attribute_data.fetch(OPTION_NAME)
|
25
|
+
@attribute_schema_is = attribute_schema.fetch(OPTION_BODY_KEY)
|
26
|
+
@attribute_schema_message = attribute_schema.fetch(:message)
|
27
|
+
|
28
|
+
@missing_option = ""
|
29
|
+
end
|
30
|
+
|
31
|
+
def description
|
32
|
+
result = "schema: "
|
33
|
+
result + schema_data
|
34
|
+
end
|
35
|
+
|
36
|
+
def matches?(subject)
|
37
|
+
if submatcher_passes?(subject)
|
38
|
+
true
|
39
|
+
else
|
40
|
+
@missing_option = build_missing_option
|
41
|
+
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
attr_reader :described_class,
|
49
|
+
:attribute_type,
|
50
|
+
:attribute_type_plural,
|
51
|
+
:attribute_name,
|
52
|
+
:option_types,
|
53
|
+
:schema_data,
|
54
|
+
:attribute_schema_is,
|
55
|
+
:attribute_schema_message
|
56
|
+
|
57
|
+
def submatcher_passes?(_subject)
|
58
|
+
schema_data_equal?
|
59
|
+
end
|
60
|
+
|
61
|
+
def schema_data_equal?
|
62
|
+
@schema_data_equal ||=
|
63
|
+
(
|
64
|
+
schema_data.present? && schema_data == attribute_schema_is
|
65
|
+
) || schema_data.blank?
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_missing_option
|
69
|
+
return if schema_data_equal?
|
70
|
+
|
71
|
+
<<~MESSAGE
|
72
|
+
should be schema with corresponding template
|
73
|
+
|
74
|
+
expected #{attribute_schema_is.inspect}
|
75
|
+
got #{schema_data.inspect}
|
76
|
+
MESSAGE
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|