servactory 3.1.0.rc3 → 3.1.0.rc4

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -0
  3. data/lib/generators/README.md +1 -1
  4. data/lib/generators/servactory/extension/USAGE +1 -1
  5. data/lib/generators/servactory/install/USAGE +2 -2
  6. data/lib/generators/servactory/rspec/USAGE +4 -4
  7. data/lib/generators/servactory/rspec/rspec_generator.rb +2 -2
  8. data/lib/generators/servactory/service/USAGE +5 -5
  9. data/lib/servactory/actions/collection.rb +21 -5
  10. data/lib/servactory/actions/stages/collection.rb +19 -1
  11. data/lib/servactory/actions/tools/rules.rb +1 -1
  12. data/lib/servactory/actions/tools/runner.rb +1 -1
  13. data/lib/servactory/configuration/collection_mode/class_names_collection.rb +1 -1
  14. data/lib/servactory/configuration/configurable.rb +1 -1
  15. data/lib/servactory/configuration/factory.rb +30 -3
  16. data/lib/servactory/configuration/hash_mode/class_names_collection.rb +2 -1
  17. data/lib/servactory/configuration/option_helpers/option_helpers_collection.rb +150 -37
  18. data/lib/servactory/context/warehouse/inputs.rb +1 -1
  19. data/lib/servactory/context/workspace/inputs.rb +2 -2
  20. data/lib/servactory/context/workspace/internals.rb +2 -2
  21. data/lib/servactory/context/workspace/outputs.rb +2 -2
  22. data/lib/servactory/context/workspace.rb +7 -7
  23. data/lib/servactory/info/builder.rb +4 -3
  24. data/lib/servactory/inputs/dsl.rb +5 -1
  25. data/lib/servactory/inputs/input.rb +1 -2
  26. data/lib/servactory/internals/dsl.rb +7 -1
  27. data/lib/servactory/maintenance/attributes/base.rb +4 -1
  28. data/lib/servactory/maintenance/attributes/collection.rb +61 -6
  29. data/lib/servactory/maintenance/options/collection.rb +46 -15
  30. data/lib/servactory/maintenance/options/option.rb +3 -12
  31. data/lib/servactory/maintenance/options/registrar.rb +2 -12
  32. data/lib/servactory/maintenance/validations/checkers/type.rb +23 -5
  33. data/lib/servactory/outputs/dsl.rb +7 -1
  34. data/lib/servactory/result.rb +21 -8
  35. data/lib/servactory/test_kit/rspec/helpers/exception_validator.rb +112 -0
  36. data/lib/servactory/test_kit/rspec/helpers/input_validator.rb +3 -1
  37. data/lib/servactory/test_kit/rspec/helpers/mock_executor.rb +125 -129
  38. data/lib/servactory/test_kit/rspec/helpers/service_inputs_guard.rb +98 -0
  39. data/lib/servactory/test_kit/rspec/helpers/service_inputs_matcher.rb +75 -0
  40. data/lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb +110 -45
  41. data/lib/servactory/test_kit/rspec/helpers/service_mock_config.rb +26 -8
  42. data/lib/servactory/test_kit/rspec/helpers/wrap_block_adapter.rb +74 -0
  43. data/lib/servactory/test_kit/rspec/helpers.rb +4 -0
  44. data/lib/servactory/test_kit/rspec/matchers/base/attribute_matcher.rb +72 -16
  45. data/lib/servactory/test_kit/rspec/matchers/base/message_expectation.rb +194 -0
  46. data/lib/servactory/test_kit/rspec/matchers/base/submatcher.rb +8 -0
  47. data/lib/servactory/test_kit/rspec/matchers/concerns/option_helper_rules.rb +148 -0
  48. data/lib/servactory/test_kit/rspec/matchers/concerns/proc_message.rb +117 -0
  49. data/lib/servactory/test_kit/rspec/matchers/concerns/required_message.rb +92 -0
  50. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb +27 -4
  51. data/lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb +10 -3
  52. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/required_submatcher.rb +58 -23
  53. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/valid_with_submatcher.rb +124 -59
  54. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/message_submatcher.rb +133 -39
  55. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/must_submatcher.rb +192 -17
  56. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/target_submatcher.rb +4 -2
  57. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/types_submatcher.rb +6 -0
  58. data/lib/servactory/test_kit/rspec/matchers.rb +15 -0
  59. data/lib/servactory/tool_kit/dynamic_options/consists_of.rb +29 -8
  60. data/lib/servactory/tool_kit/dynamic_options/format.rb +2 -3
  61. data/lib/servactory/tool_kit/dynamic_options/inclusion.rb +1 -1
  62. data/lib/servactory/tool_kit/dynamic_options/max.rb +1 -1
  63. data/lib/servactory/tool_kit/dynamic_options/min.rb +1 -1
  64. data/lib/servactory/tool_kit/dynamic_options/multiple_of.rb +33 -5
  65. data/lib/servactory/tool_kit/dynamic_options/must.rb +2 -3
  66. data/lib/servactory/tool_kit/dynamic_options/schema.rb +34 -21
  67. data/lib/servactory/tool_kit/dynamic_options/target.rb +1 -1
  68. data/lib/servactory/utils.rb +13 -3
  69. data/lib/servactory/version.rb +1 -1
  70. data/lib/servactory.rb +3 -0
  71. metadata +10 -2
@@ -129,7 +129,7 @@ module Servactory
129
129
  # @param option_name [Symbol] The option name (default: :schema)
130
130
  # @param default_hash_mode_class_names [Servactory::Configuration::HashMode::ClassNamesCollection]
131
131
  # Valid Hash-like types
132
- # @return [Servactory::Maintenance::Attributes::OptionHelper]
132
+ # @return [Servactory::Maintenance::Options::Helper]
133
133
  def self.use(option_name = :schema, default_hash_mode_class_names:)
134
134
  instance = new(option_name, :is, false)
135
135
  instance.assign(default_hash_mode_class_names)
@@ -181,13 +181,15 @@ module Servactory
181
181
  # @param value [Object] Hash value to validate
182
182
  # @param option [WorkOption] Schema configuration
183
183
  # @return [Boolean, Array] true if valid, or [false, reason, meta]
184
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
184
+ # rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
185
185
  def common_condition_with(attribute:, value:, option:)
186
186
  # Schema disabled, skip validation.
187
187
  return true if option.value == false
188
188
 
189
189
  # Attribute type must be Hash-compatible.
190
- return [false, :wrong_type] unless @default_hash_mode_class_names.intersect?(attribute.types)
190
+ unless @default_hash_mode_class_names.intersect?(attribute.types)
191
+ return [false, :wrong_type, wrong_type_meta_for(attribute:)]
192
+ end
191
193
 
192
194
  # Skip validation for blank optional values.
193
195
  if value.blank? && ((attribute.input? && attribute.optional?) || attribute.internal? || attribute.output?)
@@ -208,7 +210,19 @@ module Servactory
208
210
 
209
211
  [is_success, reason, meta]
210
212
  end
211
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
213
+
214
+ # Builds failure metadata for an attribute whose type is not Hash-compatible.
215
+ #
216
+ # @param attribute [Object] The attribute being validated
217
+ # @return [Hash] Metadata with the Hash-compatible types as expected
218
+ # and the declared attribute types as given
219
+ def wrong_type_meta_for(attribute:)
220
+ {
221
+ key_name: nil,
222
+ expected_type: @default_hash_mode_class_names.to_a.join(", "),
223
+ given_type: attribute.types.join(", ")
224
+ }
225
+ end
212
226
 
213
227
  # Recursively validates object against schema definition.
214
228
  #
@@ -231,16 +245,18 @@ module Servactory
231
245
  end
232
246
 
233
247
  # Validate each schema field.
234
- errors = schema.map do |schema_key, schema_value|
248
+ schema.each do |schema_key, schema_value|
235
249
  attribute_type = schema_value.fetch(:type, String)
236
250
 
237
251
  if attribute_type == Hash
238
252
  # Recursively validate nested Hash.
239
- validate_for!(
253
+ result = validate_for!(
240
254
  object: object.fetch(schema_key, {}),
241
255
  schema: schema_value.except(*RESERVED_OPTIONS),
242
256
  root_schema_key: schema_key
243
257
  )
258
+
259
+ return result unless result == true
244
260
  else
245
261
  is_success, given_type = validate_with(
246
262
  object:,
@@ -252,12 +268,11 @@ module Servactory
252
268
 
253
269
  next if is_success
254
270
 
255
- [false, :wrong_element_type, { key_name: schema_key, expected_type: attribute_type, given_type: }]
271
+ return [false, :wrong_element_type, { key_name: schema_key, expected_type: attribute_type, given_type: }]
256
272
  end
257
273
  end
258
274
 
259
- # Return first error or true.
260
- errors.compact.first || true
275
+ true
261
276
  end
262
277
 
263
278
  # Validates a single field against its type specification.
@@ -279,11 +294,11 @@ module Servactory
279
294
  return true
280
295
  end
281
296
 
282
- value = object[schema_key]
297
+ value = object.fetch(schema_key, nil)
283
298
  prepared_value = prepare_value_from(schema_value:, value:, required: attribute_required)
284
299
 
285
300
  [
286
- Array(attribute_type).uniq.any? { |type| prepared_value.is_a?(type) },
301
+ Array(attribute_type).any? { |type| prepared_value.is_a?(type) },
287
302
  prepared_value.class.name
288
303
  ]
289
304
  end
@@ -299,7 +314,7 @@ module Servactory
299
314
  required || (
300
315
  !required && !fetch_default_from(schema_value).nil?
301
316
  ) || (
302
- !required && !object[schema_key].nil?
317
+ !required && !object.fetch(schema_key, nil).nil?
303
318
  )
304
319
  end
305
320
 
@@ -332,19 +347,18 @@ module Servactory
332
347
  # @param object [Hash] Object to modify
333
348
  # @param schema [Hash] Schema definition
334
349
  # @return [void]
335
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
350
+ # rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
336
351
  def prepare_object_with!(object:, schema:)
337
- schema.map do |schema_key, schema_value|
352
+ schema.each do |schema_key, schema_value|
338
353
  attribute_type = schema_value.fetch(:type, String)
339
354
  required = schema_value.fetch(:required, true)
340
- object_value = object[schema_key]
355
+ object_value = object.fetch(schema_key, nil)
341
356
 
342
357
  if attribute_type == Hash
343
358
  # Apply nested Hash defaults.
344
- default_value = schema_value.fetch(:default, {})
345
-
346
- if !required && !default_value.nil? && !Servactory::Utils.value_present?(object_value)
347
- object[schema_key] = default_value
359
+ if !required && !Servactory::Utils.value_present?(object_value)
360
+ default_value = schema_value.key?(:default) ? schema_value[:default].deep_dup : {}
361
+ object[schema_key] = default_value unless default_value.nil?
348
362
  end
349
363
 
350
364
  # Recursively prepare nested objects.
@@ -362,14 +376,13 @@ module Servactory
362
376
 
363
377
  # Execute prepare callback if defined.
364
378
  unless (input_prepare = schema_value[:prepare]).nil?
365
- object[schema_key] = input_prepare.call(value: object[schema_key])
379
+ object[schema_key] = input_prepare.call(value: object.fetch(schema_key, nil))
366
380
  end
367
381
 
368
382
  object
369
383
  end
370
384
  end
371
385
  end
372
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
373
386
 
374
387
  ########################################################################
375
388
  ########################################################################
@@ -100,7 +100,7 @@ module Servactory
100
100
  # Creates a Target validator instance.
101
101
  #
102
102
  # @param option_name [Symbol] The option name (default: :target)
103
- # @return [Servactory::Maintenance::Attributes::OptionHelper]
103
+ # @return [Servactory::Maintenance::Options::Helper]
104
104
  def self.use(option_name = :target)
105
105
  instance = new(option_name, :in)
106
106
  instance.must(:"be_#{option_name}")
@@ -5,13 +5,17 @@ module Servactory
5
5
  extend self
6
6
 
7
7
  def adapt(data)
8
- if defined?(Datory::Base) && data.is_a?(Datory::Base)
9
- data = Servactory::Utils.send(:instance_variables_to_hash_from, data)
10
- end
8
+ data = instance_variables_to_hash_from(data) if datory?(data)
11
9
 
12
10
  data.symbolize_keys
13
11
  end
14
12
 
13
+ # @param data [Object]
14
+ # @return [Boolean] True if #adapt accepts the data as service arguments
15
+ def adaptable?(data)
16
+ data.is_a?(Hash) || datory?(data)
17
+ end
18
+
15
19
  def define_attribute_with(input: nil, internal: nil, output: nil)
16
20
  return input if really_input?(input)
17
21
  return internal if really_internal?(internal)
@@ -108,6 +112,12 @@ module Servactory
108
112
 
109
113
  private
110
114
 
115
+ def datory?(data)
116
+ return false unless defined?(Datory::Base)
117
+
118
+ data.is_a?(Datory::Base)
119
+ end
120
+
111
121
  def instance_variables_to_hash_from(data) # rubocop:disable Metrics/MethodLength
112
122
  data.instance_variables.to_h do |key|
113
123
  value = data.instance_variable_get(key)
@@ -5,7 +5,7 @@ module Servactory
5
5
  MAJOR = 3
6
6
  MINOR = 1
7
7
  PATCH = 0
8
- PRE = "rc3"
8
+ PRE = "rc4"
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join(".")
11
11
  end
data/lib/servactory.rb CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "zeitwerk"
4
4
 
5
+ require "forwardable"
6
+
5
7
  require "stroma"
6
8
 
7
9
  require "active_support/all"
@@ -10,6 +12,7 @@ require "uri"
10
12
 
11
13
  loader = Zeitwerk::Loader.for_gem
12
14
  loader.ignore("#{__dir__}/generators")
15
+ loader.ignore("#{__dir__}/servactory/engine.rb")
13
16
  loader.ignore("#{__dir__}/servactory/test_kit/rspec")
14
17
  loader.inflector.inflect(
15
18
  "dsl" => "DSL"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: servactory
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0.rc3
4
+ version: 3.1.0.rc4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Sokolov
@@ -298,20 +298,28 @@ files:
298
298
  - lib/servactory/test_kit/rspec/helpers/argument_matchers.rb
299
299
  - lib/servactory/test_kit/rspec/helpers/concerns/error_messages.rb
300
300
  - lib/servactory/test_kit/rspec/helpers/concerns/service_class_validation.rb
301
+ - lib/servactory/test_kit/rspec/helpers/exception_validator.rb
301
302
  - lib/servactory/test_kit/rspec/helpers/fluent.rb
302
303
  - lib/servactory/test_kit/rspec/helpers/input_validator.rb
303
304
  - lib/servactory/test_kit/rspec/helpers/legacy.rb
304
305
  - lib/servactory/test_kit/rspec/helpers/mock_executor.rb
305
306
  - lib/servactory/test_kit/rspec/helpers/output_validator.rb
307
+ - lib/servactory/test_kit/rspec/helpers/service_inputs_guard.rb
308
+ - lib/servactory/test_kit/rspec/helpers/service_inputs_matcher.rb
306
309
  - lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb
307
310
  - lib/servactory/test_kit/rspec/helpers/service_mock_config.rb
311
+ - lib/servactory/test_kit/rspec/helpers/wrap_block_adapter.rb
308
312
  - lib/servactory/test_kit/rspec/matchers.rb
309
313
  - lib/servactory/test_kit/rspec/matchers/base/attribute_matcher.rb
314
+ - lib/servactory/test_kit/rspec/matchers/base/message_expectation.rb
310
315
  - lib/servactory/test_kit/rspec/matchers/base/submatcher.rb
311
316
  - lib/servactory/test_kit/rspec/matchers/base/submatcher_context.rb
312
317
  - lib/servactory/test_kit/rspec/matchers/base/submatcher_registry.rb
313
318
  - lib/servactory/test_kit/rspec/matchers/concerns/attribute_data_access.rb
314
319
  - lib/servactory/test_kit/rspec/matchers/concerns/error_message_builder.rb
320
+ - lib/servactory/test_kit/rspec/matchers/concerns/option_helper_rules.rb
321
+ - lib/servactory/test_kit/rspec/matchers/concerns/proc_message.rb
322
+ - lib/servactory/test_kit/rspec/matchers/concerns/required_message.rb
315
323
  - lib/servactory/test_kit/rspec/matchers/concerns/value_comparison.rb
316
324
  - lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb
317
325
  - lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb
@@ -365,7 +373,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
365
373
  - !ruby/object:Gem::Version
366
374
  version: '0'
367
375
  requirements: []
368
- rubygems_version: 4.0.6
376
+ rubygems_version: 4.0.21
369
377
  specification_version: 4
370
378
  summary: A set of tools for building reliable services of any complexity
371
379
  test_files: []