servactory 2.16.1 → 3.0.0.rc1

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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -9
  3. data/config/locales/de.yml +134 -0
  4. data/config/locales/en.yml +15 -0
  5. data/config/locales/es.yml +134 -0
  6. data/config/locales/fr.yml +134 -0
  7. data/config/locales/it.yml +134 -0
  8. data/config/locales/ru.yml +15 -0
  9. data/lib/generators/README.md +45 -0
  10. data/lib/generators/servactory/base.rb +82 -0
  11. data/lib/generators/servactory/extension/USAGE +54 -0
  12. data/lib/generators/servactory/extension/extension_generator.rb +41 -0
  13. data/lib/generators/servactory/extension/templates/extension.rb.tt +62 -0
  14. data/lib/generators/servactory/install/USAGE +27 -0
  15. data/lib/generators/servactory/install/install_generator.rb +94 -0
  16. data/lib/generators/servactory/{templates/services/application_service/base.rb → install/templates/application_service/base.rb.tt} +29 -19
  17. data/lib/generators/servactory/{templates/services/application_service/exceptions.rb → install/templates/application_service/exceptions.rb.tt} +1 -1
  18. data/lib/generators/servactory/{templates/services/application_service/result.rb → install/templates/application_service/result.rb.tt} +1 -1
  19. data/lib/generators/servactory/rspec/USAGE +46 -0
  20. data/lib/generators/servactory/rspec/rspec_generator.rb +95 -0
  21. data/lib/generators/servactory/rspec/templates/service_spec.rb.tt +58 -0
  22. data/lib/generators/servactory/service/USAGE +51 -0
  23. data/lib/generators/servactory/service/service_generator.rb +56 -0
  24. data/lib/generators/servactory/service/templates/service.rb.tt +22 -0
  25. data/lib/servactory/actions/collection.rb +56 -1
  26. data/lib/servactory/actions/dsl.rb +11 -11
  27. data/lib/servactory/actions/tools/rules.rb +1 -1
  28. data/lib/servactory/actions/tools/runner.rb +111 -28
  29. data/lib/servactory/base.rb +1 -7
  30. data/lib/servactory/configuration/actions/aliases/collection.rb +5 -0
  31. data/lib/servactory/configuration/actions/rescue_handlers/collection.rb +5 -0
  32. data/lib/servactory/configuration/actions/shortcuts/collection.rb +5 -0
  33. data/lib/servactory/configuration/collection_mode/class_names_collection.rb +5 -0
  34. data/lib/servactory/configuration/config.rb +36 -0
  35. data/lib/servactory/configuration/configurable.rb +95 -0
  36. data/lib/servactory/configuration/dsl.rb +3 -27
  37. data/lib/servactory/configuration/factory.rb +20 -20
  38. data/lib/servactory/configuration/hash_mode/class_names_collection.rb +5 -0
  39. data/lib/servactory/configuration/option_helpers/option_helpers_collection.rb +5 -0
  40. data/lib/servactory/context/warehouse/inputs.rb +2 -2
  41. data/lib/servactory/context/workspace/inputs.rb +2 -2
  42. data/lib/servactory/context/workspace/internals.rb +2 -2
  43. data/lib/servactory/context/workspace/outputs.rb +2 -2
  44. data/lib/servactory/context/workspace.rb +11 -7
  45. data/lib/servactory/dsl.rb +10 -8
  46. data/lib/servactory/maintenance/attributes/tools/validation.rb +1 -1
  47. data/lib/servactory/result.rb +2 -2
  48. data/lib/servactory/stroma/dsl.rb +118 -0
  49. data/lib/servactory/stroma/entry.rb +32 -0
  50. data/lib/servactory/stroma/exceptions/base.rb +45 -0
  51. data/lib/servactory/stroma/exceptions/invalid_hook_type.rb +29 -0
  52. data/lib/servactory/stroma/exceptions/key_already_registered.rb +32 -0
  53. data/lib/servactory/stroma/exceptions/registry_frozen.rb +33 -0
  54. data/lib/servactory/stroma/exceptions/registry_not_finalized.rb +33 -0
  55. data/lib/servactory/stroma/exceptions/unknown_hook_target.rb +39 -0
  56. data/lib/servactory/stroma/hooks/applier.rb +63 -0
  57. data/lib/servactory/stroma/hooks/collection.rb +103 -0
  58. data/lib/servactory/stroma/hooks/factory.rb +80 -0
  59. data/lib/servactory/stroma/hooks/hook.rb +74 -0
  60. data/lib/servactory/stroma/registry.rb +94 -0
  61. data/lib/servactory/stroma/settings/collection.rb +90 -0
  62. data/lib/servactory/stroma/settings/registry_settings.rb +88 -0
  63. data/lib/servactory/stroma/settings/setting.rb +113 -0
  64. data/lib/servactory/stroma/state.rb +59 -0
  65. data/lib/servactory/test_kit/fake_type.rb +23 -0
  66. data/lib/servactory/test_kit/result.rb +45 -0
  67. data/lib/servactory/test_kit/rspec/helpers/argument_matchers.rb +97 -0
  68. data/lib/servactory/test_kit/rspec/helpers/concerns/error_messages.rb +179 -0
  69. data/lib/servactory/test_kit/rspec/helpers/concerns/service_class_validation.rb +74 -0
  70. data/lib/servactory/test_kit/rspec/helpers/fluent.rb +110 -0
  71. data/lib/servactory/test_kit/rspec/helpers/input_validator.rb +149 -0
  72. data/lib/servactory/test_kit/rspec/helpers/legacy.rb +228 -0
  73. data/lib/servactory/test_kit/rspec/helpers/mock_executor.rb +256 -0
  74. data/lib/servactory/test_kit/rspec/helpers/output_validator.rb +121 -0
  75. data/lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb +422 -0
  76. data/lib/servactory/test_kit/rspec/helpers/service_mock_config.rb +129 -0
  77. data/lib/servactory/test_kit/rspec/helpers.rb +51 -84
  78. data/lib/servactory/test_kit/rspec/matchers/base/attribute_matcher.rb +324 -0
  79. data/lib/servactory/test_kit/rspec/matchers/base/submatcher.rb +133 -0
  80. data/lib/servactory/test_kit/rspec/matchers/base/submatcher_context.rb +101 -0
  81. data/lib/servactory/test_kit/rspec/matchers/base/submatcher_registry.rb +205 -0
  82. data/lib/servactory/test_kit/rspec/matchers/concerns/attribute_data_access.rb +100 -0
  83. data/lib/servactory/test_kit/rspec/matchers/concerns/error_message_builder.rb +106 -0
  84. data/lib/servactory/test_kit/rspec/matchers/concerns/value_comparison.rb +97 -0
  85. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb +89 -219
  86. data/lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb +74 -166
  87. data/lib/servactory/test_kit/rspec/matchers/have_service_output_matcher.rb +238 -0
  88. data/lib/servactory/test_kit/rspec/matchers/result/be_failure_service_matcher.rb +257 -0
  89. data/lib/servactory/test_kit/rspec/matchers/result/be_success_service_matcher.rb +185 -0
  90. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/default_submatcher.rb +81 -0
  91. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/optional_submatcher.rb +62 -0
  92. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/required_submatcher.rb +93 -0
  93. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/valid_with_submatcher.rb +271 -0
  94. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/consists_of_submatcher.rb +85 -0
  95. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/inclusion_submatcher.rb +120 -0
  96. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/message_submatcher.rb +115 -0
  97. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/must_submatcher.rb +82 -0
  98. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/schema_submatcher.rb +102 -0
  99. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/target_submatcher.rb +125 -0
  100. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/types_submatcher.rb +77 -0
  101. data/lib/servactory/test_kit/rspec/matchers.rb +126 -285
  102. data/lib/servactory/test_kit/utils/faker.rb +62 -2
  103. data/lib/servactory/tool_kit/dynamic_options/consists_of.rb +166 -0
  104. data/lib/servactory/tool_kit/dynamic_options/format.rb +195 -8
  105. data/lib/servactory/tool_kit/dynamic_options/inclusion.rb +219 -17
  106. data/lib/servactory/tool_kit/dynamic_options/max.rb +143 -0
  107. data/lib/servactory/tool_kit/dynamic_options/min.rb +143 -0
  108. data/lib/servactory/tool_kit/dynamic_options/multiple_of.rb +157 -8
  109. data/lib/servactory/tool_kit/dynamic_options/must.rb +194 -0
  110. data/lib/servactory/tool_kit/dynamic_options/schema.rb +226 -2
  111. data/lib/servactory/tool_kit/dynamic_options/target.rb +252 -0
  112. data/lib/servactory/version.rb +4 -4
  113. data/lib/servactory.rb +4 -0
  114. metadata +73 -19
  115. data/lib/generators/servactory/install_generator.rb +0 -21
  116. data/lib/generators/servactory/rspec_generator.rb +0 -88
  117. data/lib/generators/servactory/service_generator.rb +0 -49
  118. data/lib/servactory/configuration/setup.rb +0 -97
  119. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/consists_of_matcher.rb +0 -68
  120. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/inclusion_matcher.rb +0 -73
  121. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/message_matcher.rb +0 -91
  122. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/must_matcher.rb +0 -72
  123. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/schema_matcher.rb +0 -92
  124. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/types_matcher.rb +0 -72
  125. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/default_matcher.rb +0 -69
  126. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/optional_matcher.rb +0 -63
  127. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/required_matcher.rb +0 -81
  128. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/valid_with_matcher.rb +0 -199
@@ -1,310 +1,151 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # RSpec matchers for testing Servactory service definitions and results.
4
+ #
5
+ # ## Purpose
6
+ #
7
+ # This module provides custom RSpec matchers for validating:
8
+ # - Service attribute definitions (inputs, internals, outputs)
9
+ # - Service execution results (success/failure)
10
+ #
11
+ # ## Usage
12
+ #
13
+ # Include matchers in RSpec configuration:
14
+ #
15
+ # ```ruby
16
+ # RSpec.configure do |config|
17
+ # config.include Servactory::TestKit::Rspec::Matchers, type: :service
18
+ # end
19
+ # ```
20
+ #
21
+ # Then use in specs:
22
+ #
23
+ # ```ruby
24
+ # RSpec.describe MyService, type: :service do
25
+ # it { is_expected.to have_service_input(:user_id).type(Integer).required }
26
+ # it { is_expected.to have_service_output(:result).type(String) }
27
+ #
28
+ # it "succeeds with valid input" do
29
+ # result = described_class.call(user_id: 123)
30
+ # expect(result).to be_success_service.with_output(:data, "value")
31
+ # end
32
+ # end
33
+ # ```
34
+ #
35
+ # ## Available Matchers
36
+ #
37
+ # - `have_service_input` / `have_input` - validates input attribute definitions
38
+ # - `have_service_internal` / `have_internal` - validates internal attribute definitions
39
+ # - `have_service_output` / `have_output` - validates output values on results
40
+ # - `be_success_service` - validates successful service result
41
+ # - `be_failure_service` - validates failed service result
42
+
43
+ # Concerns (must be loaded first, as they are used in Base classes)
44
+ require_relative "matchers/concerns/attribute_data_access"
45
+ require_relative "matchers/concerns/error_message_builder"
46
+ require_relative "matchers/concerns/value_comparison"
47
+
48
+ # Base classes (loaded after concerns)
49
+ require_relative "matchers/base/submatcher_context"
50
+ require_relative "matchers/base/submatcher"
51
+ require_relative "matchers/base/submatcher_registry"
52
+ require_relative "matchers/base/attribute_matcher"
53
+
54
+ # Shared submatchers
55
+ require_relative "matchers/submatchers/shared/types_submatcher"
56
+ require_relative "matchers/submatchers/shared/consists_of_submatcher"
57
+ require_relative "matchers/submatchers/shared/schema_submatcher"
58
+ require_relative "matchers/submatchers/shared/inclusion_submatcher"
59
+ require_relative "matchers/submatchers/shared/must_submatcher"
60
+ require_relative "matchers/submatchers/shared/message_submatcher"
61
+ require_relative "matchers/submatchers/shared/target_submatcher"
62
+
63
+ # Input submatchers
64
+ require_relative "matchers/submatchers/input/required_submatcher"
65
+ require_relative "matchers/submatchers/input/optional_submatcher"
66
+ require_relative "matchers/submatchers/input/default_submatcher"
67
+ require_relative "matchers/submatchers/input/valid_with_submatcher"
68
+
69
+ # Main matchers
3
70
  require_relative "matchers/have_service_input_matcher"
4
71
  require_relative "matchers/have_service_internal_matcher"
72
+ require_relative "matchers/have_service_output_matcher"
73
+
74
+ # Result matchers
75
+ require_relative "matchers/result/be_success_service_matcher"
76
+ require_relative "matchers/result/be_failure_service_matcher"
5
77
 
6
78
  module Servactory
7
79
  module TestKit
8
80
  module Rspec
9
- module Matchers # rubocop:disable Metrics/ModuleLength
81
+ # RSpec matchers for Servactory service testing.
82
+ module Matchers
83
+ # Creates a matcher for validating service input attribute definitions.
84
+ #
85
+ # @param input_name [Symbol] The name of the input to validate
86
+ # @return [HaveServiceInputMatcher] Matcher with fluent chain methods
87
+ #
88
+ # @example
89
+ # expect(MyService).to have_service_input(:user_id)
90
+ # .type(Integer)
91
+ # .required
10
92
  def have_service_input(input_name) # rubocop:disable Naming/PredicatePrefix
11
93
  HaveServiceInputMatcher.new(described_class, input_name)
12
94
  end
13
95
 
14
- RSpec::Matchers.alias_matcher :have_input, :have_service_input
15
-
96
+ # Creates a matcher for validating service internal attribute definitions.
97
+ #
98
+ # @param internal_name [Symbol] The name of the internal to validate
99
+ # @return [HaveServiceInternalMatcher] Matcher with fluent chain methods
100
+ #
101
+ # @example
102
+ # expect(MyService).to have_service_internal(:processed_data)
103
+ # .type(Hash)
16
104
  def have_service_internal(internal_name) # rubocop:disable Naming/PredicatePrefix
17
105
  HaveServiceInternalMatcher.new(described_class, internal_name)
18
106
  end
19
107
 
20
- RSpec::Matchers.alias_matcher :have_internal, :have_service_internal
21
-
22
- ########################################################################
23
- ########################################################################
24
- ########################################################################
25
-
26
- RSpec::Matchers.define :have_service_output do |output_name| # rubocop:disable Metrics/BlockLength
27
- description { "service output" }
28
-
29
- match do |actual|
30
- match_for(actual, output_name)
31
- end
32
-
33
- chain :instance_of do |class_or_name|
34
- @instance_of = Servactory::Utils.constantize_class(class_or_name)
35
- end
36
-
37
- chain :nested do |*values|
38
- @nested = values
39
- end
40
-
41
- chain :contains do |value|
42
- @value = value
43
- end
44
-
45
- failure_message do |actual|
46
- match_for(actual, output_name)
47
- end
48
-
49
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
50
- def match_for(actual, output_name)
51
- given_value = actual.public_send(output_name)
52
-
53
- if defined?(@instance_of)
54
- expect(given_value).to(
55
- RSpec::Matchers::BuiltIn::BeAnInstanceOf.new(@instance_of)
56
- )
57
- end
58
-
59
- if defined?(@nested) && @nested.present?
60
- @nested.each do |method_name|
61
- next unless given_value.respond_to?(method_name)
62
-
63
- given_value = given_value.public_send(method_name)
64
- end
65
- end
66
-
67
- return true if !defined?(@value) && @value.nil?
68
-
69
- expect(given_value).to(
70
- case @value
71
- when Array
72
- RSpec::Matchers::BuiltIn::ContainExactly.new(@value)
73
- when Hash
74
- RSpec::Matchers::BuiltIn::Match.new(@value)
75
- when TrueClass, FalseClass
76
- RSpec::Matchers::BuiltIn::Equal.new(@value)
77
- when NilClass
78
- RSpec::Matchers::BuiltIn::BeNil.new(@value)
79
- else
80
- RSpec::Matchers::BuiltIn::Eq.new(@value)
81
- end
82
- )
83
- end
108
+ # Creates a matcher for validating service result output values.
109
+ #
110
+ # @param output_name [Symbol] The name of the output to validate
111
+ # @return [HaveServiceOutputMatcher] Matcher with fluent chain methods
112
+ #
113
+ # @example
114
+ # expect(result).to have_service_output(:user)
115
+ # .instance_of(User)
116
+ # .contains(name: "John")
117
+ def have_service_output(output_name) # rubocop:disable Naming/PredicatePrefix
118
+ HaveServiceOutputMatcher.new(output_name)
84
119
  end
85
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
86
-
87
- RSpec::Matchers.alias_matcher :have_output, :have_service_output
88
-
89
- RSpec::Matchers.define :be_success_service do # rubocop:disable Metrics/BlockLength
90
- description { "service success" }
91
-
92
- def expected_data
93
- @expected_data ||= {}
94
- end
95
-
96
- match do |actual|
97
- matched = actual.is_a?(Servactory::Result)
98
- matched &&= actual.success?
99
- matched &&= !actual.failure?
100
-
101
- if defined?(expected_data)
102
- matched &&= expected_data.all? do |key, value|
103
- if actual.respond_to?(key)
104
- actual.public_send(key) == value
105
- else
106
- false
107
- end
108
- end
109
- end
110
-
111
- matched
112
- end
113
-
114
- chain :with_output do |key, value|
115
- expected_data[key] = value
116
- end
117
-
118
- chain :with_outputs do |attributes|
119
- attributes.each do |key, value|
120
- expected_data[key] = value
121
- end
122
- end
123
-
124
- failure_message do |actual| # rubocop:disable Metrics/BlockLength
125
- unless actual.is_a?(Servactory::Result)
126
- break <<~MESSAGE
127
- Incorrect service result:
128
-
129
- expected Servactory::Result
130
- got #{actual.class.name}
131
- MESSAGE
132
- end
133
-
134
- if actual.failure?
135
- break <<~MESSAGE
136
- Incorrect service result:
137
-
138
- expected success
139
- got failure
140
- MESSAGE
141
- end
142
-
143
- if defined?(expected_data)
144
- message = expected_data.each do |key, value|
145
- unless actual.respond_to?(key)
146
- break <<~MESSAGE
147
- Non-existent value key in result:
148
-
149
- expected #{actual.inspect}
150
- got #{key}
151
- MESSAGE
152
- end
153
-
154
- received_value = actual.public_send(key)
155
- next if actual.public_send(key) == value
156
-
157
- break <<~MESSAGE
158
- Incorrect result value for #{key}:
159
120
 
160
- expected #{value.inspect}
161
- got #{received_value.inspect}
162
- MESSAGE
163
- end
164
- end
165
-
166
- break message if message.present?
167
-
168
- <<~MESSAGE
169
- Unexpected case when using `be_success_service`.
170
-
171
- Please try to build an example based on the documentation.
172
- Or report your problem to us:
173
-
174
- https://github.com/servactory/servactory/issues
175
- MESSAGE
176
- end
121
+ # Creates a matcher for validating successful service results.
122
+ #
123
+ # @return [Result::BeSuccessServiceMatcher] Matcher with output chain methods
124
+ #
125
+ # @example
126
+ # expect(result).to be_success_service
127
+ # .with_output(:data, "value")
128
+ def be_success_service
129
+ Result::BeSuccessServiceMatcher.new
177
130
  end
178
131
 
179
- RSpec::Matchers.define :be_failure_service do # rubocop:disable Metrics/BlockLength
180
- description { "service failure" }
181
-
182
- match do |actual|
183
- expected_failure_class =
184
- defined?(@expected_failure_class) ? @expected_failure_class : Servactory::Exceptions::Failure
185
-
186
- expected_type = defined?(@expected_type) ? @expected_type : :base
187
- expected_message = defined?(@expected_message) ? @expected_message : nil
188
- expected_meta = defined?(@expected_meta) ? @expected_meta : nil
189
-
190
- matched = actual.is_a?(Servactory::Result)
191
- matched &&= !actual.success?
192
- matched &&= actual.failure?
193
- matched &&= actual.error.is_a?(Servactory::Exceptions::Failure)
194
- matched &&= actual.error.is_a?(expected_failure_class)
195
- matched &&= actual.error.type == expected_type
196
- matched &&= actual.error.message == expected_message if defined?(@expected_message)
197
- matched &&= actual.error.meta == expected_meta if defined?(@expected_meta)
198
- matched
199
- end
200
-
201
- chain :with do |expected_failure_class|
202
- @expected_failure_class = expected_failure_class
203
- end
204
-
205
- chain :type do |expected_type|
206
- @expected_type = expected_type
207
- end
208
-
209
- chain :message do |expected_message|
210
- @expected_message = expected_message
211
- end
212
-
213
- chain :meta do |expected_meta|
214
- @expected_meta = expected_meta
215
- end
216
-
217
- failure_message do |actual| # rubocop:disable Metrics/BlockLength
218
- unless actual.is_a?(Servactory::Result)
219
- break <<~MESSAGE
220
- Incorrect service result:
221
-
222
- expected Servactory::Result
223
- got #{actual.class.name}
224
- MESSAGE
225
- end
226
-
227
- if actual.success?
228
- break <<~MESSAGE
229
- Incorrect service result:
230
-
231
- expected failure
232
- got success
233
- MESSAGE
234
- end
235
-
236
- unless actual.error.is_a?(Servactory::Exceptions::Failure)
237
- break <<~MESSAGE
238
- Incorrect error object:
239
-
240
- expected Servactory::Exceptions::Failure
241
- got #{actual.error.class.name}
242
- MESSAGE
243
- end
244
-
245
- if defined?(@expected_failure_class)
246
- unless actual.error.is_a?(@expected_failure_class)
247
- break <<~MESSAGE
248
- Incorrect instance error:
249
-
250
- expected #{@expected_failure_class}
251
- got #{actual.error.class.name}
252
- MESSAGE
253
- end
254
- else
255
- unless actual.error.is_a?(Servactory::Exceptions::Failure)
256
- break <<~MESSAGE
257
- Incorrect error object:
258
-
259
- expected Servactory::Exceptions::Failure
260
- got #{actual.error.class.name}
261
- MESSAGE
262
- end
263
- end
264
-
265
- if defined?(@expected_type) && actual.error.type != @expected_type
266
- break <<~MESSAGE
267
- Incorrect error type:
268
-
269
- expected #{actual.error.type.inspect}
270
- got #{@expected_type.inspect}
271
- MESSAGE
272
- end
273
-
274
- if defined?(@expected_message) && actual.error.message != @expected_message
275
- break <<~MESSAGE
276
- Incorrect error message:
277
-
278
- expected #{actual.error.message.inspect}
279
- got #{@expected_message.inspect}
280
- MESSAGE
281
- end
282
-
283
- if defined?(@expected_meta) && actual.error.meta != @expected_meta
284
- break <<~MESSAGE
285
- Incorrect error meta:
286
-
287
- expected #{actual.error.meta.inspect}
288
- got #{@expected_meta.inspect}
289
- MESSAGE
290
- end
291
-
292
- <<~MESSAGE
293
- Unexpected case when using `be_failure_service`.
294
-
295
- Exception: #{actual.error.inspect}
296
- Type: #{actual.error.type.inspect}
297
- Message: #{actual.error.message.inspect}
298
- Meta: #{actual.error.meta.inspect}
299
-
300
- Please try to build an example based on the documentation.
301
- Or report your problem to us:
302
-
303
- https://github.com/servactory/servactory/issues
304
- MESSAGE
305
- end
132
+ # Creates a matcher for validating failed service results.
133
+ #
134
+ # @return [Result::BeFailureServiceMatcher] Matcher with error chain methods
135
+ #
136
+ # @example
137
+ # expect(result).to be_failure_service
138
+ # .type(:validation_error)
139
+ # .message("Invalid input")
140
+ def be_failure_service
141
+ Result::BeFailureServiceMatcher.new
306
142
  end
307
143
  end
308
144
  end
309
145
  end
310
146
  end
147
+
148
+ # Register shorter aliases for convenience.
149
+ RSpec::Matchers.alias_matcher :have_input, :have_service_input
150
+ RSpec::Matchers.alias_matcher :have_internal, :have_service_internal
151
+ RSpec::Matchers.alias_matcher :have_output, :have_service_output
@@ -3,9 +3,43 @@
3
3
  module Servactory
4
4
  module TestKit
5
5
  module Utils
6
+ # Generates fake test values for different Ruby types.
7
+ #
8
+ # ## Purpose
9
+ #
10
+ # Provides fake values for testing input validations. Used by
11
+ # ValidWithSubmatcher to generate values that will trigger specific
12
+ # validation failures (e.g., wrong inclusion values).
13
+ #
14
+ # ## Usage
15
+ #
16
+ # ```ruby
17
+ # # Get a fake value for a type
18
+ # Faker.fetch_value_for(String) # => "fake"
19
+ # Faker.fetch_value_for(Integer) # => 123
20
+ # Faker.fetch_value_for(Array, of: :integer) # => [1, 2, 3]
21
+ # ```
22
+ #
23
+ # ## Supported Types
24
+ #
25
+ # - Symbol - returns `:fake`
26
+ # - String - returns `"fake"`
27
+ # - Integer - returns `123`
28
+ # - Float - returns `12.3`
29
+ # - Range - returns `1..3`
30
+ # - Array - returns `["fake"]` or `[1, 2, 3]` based on `of:` param
31
+ # - Hash - returns `{ fake: :yes }` or `{ fake: 1 }` based on `of:` param
32
+ # - TrueClass - returns `true`
33
+ # - FalseClass - returns `false`
34
+ # - NilClass - returns `nil`
6
35
  module Faker
7
36
  extend self
8
37
 
38
+ # Generates a fake value for the given type.
39
+ #
40
+ # @param class_or_name [Class, String] Type to generate value for
41
+ # @param of [Symbol] Element type for Array/Hash (:string or :integer)
42
+ # @return [Object] Fake value of the requested type
9
43
  def fetch_value_for(class_or_name, of: :string) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
10
44
  class_for_fake = Servactory::Utils.constantize_class(class_or_name)
11
45
  of = of.to_sym
@@ -23,52 +57,78 @@ module Servactory
23
57
  NilClass => method(:fake_nil_class)
24
58
  }
25
59
 
26
- fake_klass = faker[class_for_fake] || -> { unsupported_faker(class_for_fake) }
27
- fake_klass.call
60
+ fake_class = faker[class_for_fake] || -> { unsupported_faker(class_for_fake) }
61
+ fake_class.call
28
62
  end
29
63
 
30
64
  private
31
65
 
66
+ # Returns fake Symbol value.
67
+ # @return [Symbol]
32
68
  def fake_symbol
33
69
  :fake
34
70
  end
35
71
 
72
+ # Returns fake String value.
73
+ # @return [String]
36
74
  def fake_string
37
75
  "fake"
38
76
  end
39
77
 
78
+ # Returns fake Integer value.
79
+ # @return [Integer]
40
80
  def fake_integer
41
81
  123
42
82
  end
43
83
 
84
+ # Returns fake Float value.
85
+ # @return [Float]
44
86
  def fake_float
45
87
  12.3
46
88
  end
47
89
 
90
+ # Returns fake Range value.
91
+ # @return [Range]
48
92
  def fake_range
49
93
  1..3
50
94
  end
51
95
 
96
+ # Returns fake Array value.
97
+ # @param of [Symbol] Element type (:string or :integer)
98
+ # @return [Array]
52
99
  def fake_array(of)
53
100
  of == :integer ? [1, 2, 3] : ["fake"]
54
101
  end
55
102
 
103
+ # Returns fake Hash value.
104
+ # @param of [Symbol] Value type (:string or :integer)
105
+ # @return [Hash]
56
106
  def fake_hash(of)
57
107
  of == :integer ? { fake: 1 } : { fake: :yes }
58
108
  end
59
109
 
110
+ # Returns true (fake TrueClass value).
111
+ # @return [Boolean]
60
112
  def fake_true_class # rubocop:disable Naming/PredicateMethod
61
113
  true
62
114
  end
63
115
 
116
+ # Returns false (fake FalseClass value).
117
+ # @return [Boolean]
64
118
  def fake_false_class # rubocop:disable Naming/PredicateMethod
65
119
  false
66
120
  end
67
121
 
122
+ # Returns nil (fake NilClass value).
123
+ # @return [nil]
68
124
  def fake_nil_class
69
125
  nil
70
126
  end
71
127
 
128
+ # Handles unsupported types by attempting to instantiate them.
129
+ #
130
+ # @param class_for_fake [Class] The unsupported type class
131
+ # @return [Object] New instance or the class itself
72
132
  def unsupported_faker(class_for_fake)
73
133
  class_for_fake.respond_to?(:new) ? class_for_fake.new : class_for_fake
74
134
  end