convenient_service 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +6 -6
  3. data/CHANGELOG.md +9 -0
  4. data/ROADMAP.md +3 -0
  5. data/Taskfile.yml +3 -3
  6. data/env.rb +4 -0
  7. data/lib/convenient_service/examples/dry/gemfile/dry_service/config.rb +3 -1
  8. data/lib/convenient_service/examples/dry/gemfile/services/assert_file_exists.rb +1 -1
  9. data/lib/convenient_service/examples/dry/gemfile/services/assert_file_not_empty.rb +1 -1
  10. data/lib/convenient_service/examples/dry/gemfile/services/assert_npm_package_available.rb +1 -1
  11. data/lib/convenient_service/examples/dry/gemfile/services/parse_content.rb +1 -1
  12. data/lib/convenient_service/examples/dry/gemfile/services/print_shell_command.rb +1 -1
  13. data/lib/convenient_service/examples/dry/gemfile/services/read_file_content.rb +1 -1
  14. data/lib/convenient_service/examples/dry/gemfile/services/run_shell.rb +1 -1
  15. data/lib/convenient_service/examples/dry/gemfile/services/strip_comments.rb +1 -1
  16. data/lib/convenient_service/examples/rails/gemfile/rails_service/config.rb +3 -1
  17. data/lib/convenient_service/rspec/matchers/custom/cache_its_value.rb +7 -7
  18. data/lib/convenient_service/rspec/matchers/custom/delegate_to.rb +50 -12
  19. data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/concern/instance_methods.rb +29 -17
  20. data/lib/convenient_service/service/plugins/has_result_params_validations/using_dry_validation/middleware.rb +19 -9
  21. data/lib/convenient_service/service/plugins/has_result_steps/middleware.rb +1 -1
  22. data/lib/convenient_service/version.rb +1 -1
  23. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03335557e59a7d6c469fe20e478efb1d7f9563d7651b5e0761e61d820e7515e6
4
- data.tar.gz: 055c3cfaa2b176689bf8cc105d649a40779788279c89bd1f5a6bdfde8d7994c1
3
+ metadata.gz: 70d36eabeb3ea9598979a7158d06e0bfc627398066abc5180411f13fce9142e8
4
+ data.tar.gz: 6c6ea0ce690bb915c32f2e810afe70f87e74961f7a3c01b4e3a6389b8f98b1dc
5
5
  SHA512:
6
- metadata.gz: f9f55f6baab2736bcbb8661a55bb494bdfb1f7e000a87b3c7c78f326b417e44bcd69cccb992b54435ec10ce919afc2e3a7cd73695858025fa241aff609b9882c
7
- data.tar.gz: 72778dcdb0df0003b3c9b13a266af24a9c8de4150ed7d048887bd5007b223c88ce34c9494c186c5ac49ba0102ca5bd31858e37d55698fe1cfb49fe22dd6ed6e7
6
+ metadata.gz: aa610f3ac041e97849914d6bf15e626cceef9d8abd9aed0e5244b112595c89c9ac1eb91438bf67a84065bc8b90e91ebd8fff19cbcfb3c4a77e9b1246100b25fd
7
+ data.tar.gz: d704307543e1a14efa13f2701a109ee2748af75ed2260bbf9e4e64bc06b5bbe2a23ac208eabea1ec2d536578c9b9ec97c76541fa79181b9e896f4f844594d743
@@ -128,14 +128,14 @@ jobs:
128
128
  run: task rspec:standard
129
129
  - name: Install dependencies for appraisals
130
130
  run: task deps:install
131
- - name: Run RSpec with Rails 5.2
132
- run: task rspec:rails_5.2
133
- - name: Run RSpec with Rails 6.0
134
- run: task rspec:rails_6.0
135
- - name: Run RSpec with Rails 6.1
136
- run: task rspec:rails_6.1
137
131
  - name: Run RSpec with Rails 7.0
138
132
  run: task rspec:rails_7.0
133
+ - name: Run RSpec with Rails 6.1
134
+ run: task rspec:rails_6.1
135
+ - name: Run RSpec with Rails 6.0
136
+ run: task rspec:rails_6.0
137
+ - name: Run RSpec with Rails 5.2
138
+ run: task rspec:rails_5.2
139
139
  - name: Run RSpec with Dry
140
140
  run: task rspec:dry
141
141
  ##
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.1](https://github.com/marian13/convenient_service/compare/v0.2.0...v0.2.1) (2022-12-14)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **has_result_steps:** return step copy to have fresh state ([55cc368](https://github.com/marian13/convenient_service/commit/55cc368484641040c0c76ecb38872cc9a268397c), [fc7cebb](https://github.com/marian13/convenient_service/commit/fc7cebb4e159af7b35eac3cf8c25c7009e14c9d1))
9
+ * **standard:** place UsingActiveModelValidations before HasResultSteps ([4c43205](https://github.com/marian13/convenient_service/commit/4c43205382da2e7ae395fea6639c2bcc43d1eec2))
10
+ * **standard:** place UsingDryValidation before HasResultSteps ([63c31c0](https://github.com/marian13/convenient_service/commit/63c31c04ac7c2581defd3557aad13db3188806ba))
11
+
3
12
  ## [0.2.0](https://github.com/marian13/convenient_service/compare/v0.1.0...v0.2.0) (2022-11-26)
4
13
 
5
14
 
data/ROADMAP.md CHANGED
@@ -48,5 +48,8 @@
48
48
  | Low | 🚧 | [Receive Counts](https://relishapp.com/rspec/rspec-mocks/docs/setting-constraints/receive-counts) for `delegate_to` | |
49
49
  | Low | 🚧 | Prefer versioning instead of modification plugin | |
50
50
  | Low | 🚧 | Consider to move `__steps__` and `__callbacks__` to `internals_class` | Benefit? |
51
+ | Medium | 🚧 | User friendly `raise` that removes lib backtrace from caller | Should have a `debug` mode. Should work well with examples. Check RSpec `CallerFilter.first_non_rspec_line` |
52
+ | High | 🚧 | A plugin that catches `StandardError` and returns `failure` | Should be the lowest in the stack |
53
+ | High | 🚧 | `Support::Command` alias | Should be visible to the end user |
51
54
 
52
55
  Search for `TODO`s in the codebase for more tasks.
data/Taskfile.yml CHANGED
@@ -201,10 +201,10 @@ tasks:
201
201
  rspec:
202
202
  cmds:
203
203
  - task: rspec:standard
204
- - task: rspec:rails_5.2
205
- - task: rspec:rails_6.0
206
- - task: rspec:rails_6.1
207
204
  - task: rspec:rails_7.0
205
+ - task: rspec:rails_6.1
206
+ - task: rspec:rails_6.0
207
+ - task: rspec:rails_5.2
208
208
  - task: rspec:dry
209
209
 
210
210
  ##
data/env.rb CHANGED
@@ -12,8 +12,12 @@
12
12
  #
13
13
  ENV["APPRAISAL_NAME"] ||= ENV["BUNDLE_GEMFILE"].to_s.then(&File.method(:basename)).then { |name| name.end_with?(".gemfile") ? name.delete_suffix(".gemfile") : "" }
14
14
 
15
+ puts "ENV[\"APPRAISAL_NAME\"] -> `#{ENV["APPRAISAL_NAME"]}`"
16
+
15
17
  ##
16
18
  # NOTE: Ruby version may be set by docker.
17
19
  # https://github.com/docker-library/ruby/blob/master/3.1/alpine3.16/Dockerfile#L30
18
20
  #
19
21
  ENV["RUBY_VERSION"] ||= ::RUBY_VERSION
22
+
23
+ puts "ENV[\"RUBY_VERSION\"] -> `#{ENV["RUBY_VERSION"]}`"
@@ -31,7 +31,9 @@ module ConvenientService
31
31
  end
32
32
 
33
33
  middlewares :result do
34
- use Plugins::Service::HasResultParamsValidations::UsingDryValidation::Middleware
34
+ insert_before \
35
+ Plugins::Service::HasResultSteps::Middleware,
36
+ Plugins::Service::HasResultParamsValidations::UsingDryValidation::Middleware
35
37
  end
36
38
  end
37
39
  end
@@ -12,7 +12,7 @@ module ConvenientService
12
12
 
13
13
  contract do
14
14
  schema do
15
- required(:path).value(:string)
15
+ required(:path).filled(:string)
16
16
  end
17
17
  end
18
18
 
@@ -12,7 +12,7 @@ module ConvenientService
12
12
 
13
13
  contract do
14
14
  schema do
15
- required(:path).value(:string)
15
+ required(:path).filled(:string)
16
16
  end
17
17
  end
18
18
 
@@ -17,7 +17,7 @@ module ConvenientService
17
17
 
18
18
  contract do
19
19
  schema do
20
- required(:name).value(:string)
20
+ required(:name).filled(:string)
21
21
  end
22
22
  end
23
23
 
@@ -44,7 +44,7 @@ module ConvenientService
44
44
 
45
45
  contract do
46
46
  schema do
47
- required(:content).value(:string)
47
+ required(:content).filled(:string)
48
48
  end
49
49
  end
50
50
 
@@ -18,7 +18,7 @@ module ConvenientService
18
18
 
19
19
  contract do
20
20
  schema do
21
- required(:text).value(:string)
21
+ required(:text).filled(:string)
22
22
  end
23
23
  end
24
24
 
@@ -12,7 +12,7 @@ module ConvenientService
12
12
 
13
13
  contract do
14
14
  schema do
15
- required(:path).value(:string)
15
+ required(:path).filled(:string)
16
16
  end
17
17
  end
18
18
 
@@ -13,7 +13,7 @@ module ConvenientService
13
13
 
14
14
  contract do
15
15
  schema do
16
- required(:command).value(:string)
16
+ required(:command).filled(:string)
17
17
  optional(:debug).value(:bool)
18
18
  end
19
19
  end
@@ -17,7 +17,7 @@ module ConvenientService
17
17
 
18
18
  contract do
19
19
  schema do
20
- required(:content).value(:string)
20
+ required(:content).filled(:string)
21
21
  end
22
22
  end
23
23
 
@@ -42,7 +42,9 @@ module ConvenientService
42
42
  end
43
43
 
44
44
  middlewares :result do
45
- use Plugins::Service::HasResultParamsValidations::UsingActiveModelValidations::Middleware
45
+ insert_before \
46
+ Plugins::Service::HasResultSteps::Middleware,
47
+ Plugins::Service::HasResultParamsValidations::UsingActiveModelValidations::Middleware
46
48
  end
47
49
  end
48
50
  end
@@ -23,26 +23,26 @@ module ConvenientService
23
23
  end
24
24
 
25
25
  def failure_message
26
- "expected #{printable_block} to cache its value"
26
+ "expected #{printable_block_expectation} to cache its value"
27
27
  end
28
28
 
29
29
  def failure_message_when_negated
30
- "expected #{printable_block} NOT to cache its value"
30
+ "expected #{printable_block_expectation} NOT to cache its value"
31
31
  end
32
32
 
33
33
  ##
34
34
  # NOTE: An example of how RSpec extracts block source, but they marked it as private.
35
35
  # https://github.com/rspec/rspec-expectations/blob/311aaf245f2c5493572bf683b8c441cb5f7e44c8/lib/rspec/matchers/built_in/change.rb#L437
36
36
  #
37
- # TODO: `printable_block` when `method_source` is available.
37
+ # TODO: `printable_block_expectation` when `method_source` is available.
38
38
  # https://github.com/banister/method_source
39
39
  #
40
- # def printable_block
41
- # @printable_block ||= block_expectation.source
40
+ # def printable_block_expectation
41
+ # @printable_block_expectation ||= block_expectation.source
42
42
  # end
43
43
  #
44
- def printable_block
45
- @printable_block ||= "{ ... }"
44
+ def printable_block_expectation
45
+ @printable_block_expectation ||= "{ ... }"
46
46
  end
47
47
 
48
48
  private
@@ -1,5 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ##
4
+ # IMPORTANT: This matcher has a dedicated end-user doc. Do NOT forget to update it when needed.
5
+ # https://github.com/marian13/convenient_service_docs/blob/main/docs/api/tests/rspec/matchers/delegate_to.mdx
6
+ #
7
+ # TODO: Refactor into composition:
8
+ # - Ability to compose when `delegate_to` is used `without_arguments`.
9
+ # - Ability to compose when `delegate_to` is used `with_arguments`.
10
+ # - Ability to compose when `delegate_to` is used `and_return_its_value`.
11
+ #
12
+ # TODO: Refactor to NOT use `expect` inside this matcher.
13
+ # This way the matcher will return true or false, but never raise exceptions (descendant of Exception, not StandardError).
14
+ # Then it will be easier to developer a fully comprehensive spec suite for `delegate_to`.
15
+ #
3
16
  module ConvenientService
4
17
  module RSpec
5
18
  module Matchers
@@ -81,15 +94,7 @@ module ConvenientService
81
94
  # https://relishapp.com/rspec/rspec-mocks/docs/configuring-responses/wrapping-the-original-implementation
82
95
  #
83
96
  allow(object).to receive(method).and_wrap_original do |original, *actual_args, **actual_kwargs, &actual_block|
84
- ##
85
- # TODO: Provide customized error messages?
86
- # https://relishapp.com/rspec/rspec-expectations/docs/customized-message
87
- #
88
- # NOTE: `delegate_to` expects that delegation is executed only once during `block_expectation`.
89
- #
90
- expect(actual_args).to eq(expected_args)
91
- expect(actual_kwargs).to eq(expected_kwargs)
92
- expect(actual_block).to eq(expected_block)
97
+ actual_arguments_collection << [actual_args, actual_kwargs, actual_block]
93
98
 
94
99
  ##
95
100
  # NOTE: Imitates `and_call_original`.
@@ -108,7 +113,7 @@ module ConvenientService
108
113
  ##
109
114
  # NOTE: If this expectation fails, it means `delegate_to` is NOT met.
110
115
  #
111
- expect(object).to have_received(method)
116
+ expect(object).to have_received(method).at_least(1) unless used_with_arguments?
112
117
 
113
118
  ##
114
119
  # IMPORTANT: `and_return_its_value` works only when `delegate_to` checks a pure function.
@@ -166,7 +171,13 @@ module ConvenientService
166
171
  # NOTE: RSpec raises exception when any `expect` is NOT satisfied.
167
172
  # So, this `true` is returned only when all `expect` are successful.
168
173
  #
169
- true
174
+ if used_with_arguments?
175
+ actual_arguments_collection.any? do |(actual_args, actual_kwargs, actual_block)|
176
+ actual_args == expected_args && actual_kwargs == expected_kwargs && actual_block == expected_block
177
+ end
178
+ else
179
+ true
180
+ end
170
181
  end
171
182
 
172
183
  ##
@@ -184,8 +195,16 @@ module ConvenientService
184
195
  "delegate to `#{printable_method}`"
185
196
  end
186
197
 
198
+ def failure_message
199
+ if used_with_arguments?
200
+ "expected `#{printable_block_expectation}` to delegate to `#{printable_method}` with expected arguments at least once, but it didn't."
201
+ else
202
+ "expected `#{printable_block_expectation}` to delegate to `#{printable_method}` at least once, but it didn't."
203
+ end
204
+ end
205
+
187
206
  ##
188
- # IMPORTANT: `failure_message`, `failure_message_when_negated` are NOT implemented, since they are never called (since `matches?` always returns `true`).
207
+ # IMPORTANT: `failure_message_when_negated` is NOT supported yet.
189
208
  #
190
209
 
191
210
  def with_arguments(*args, **kwargs, &block)
@@ -248,6 +267,25 @@ module ConvenientService
248
267
  end
249
268
 
250
269
  alias_method :expected_block, :block
270
+
271
+ def actual_arguments_collection
272
+ @actual_arguments_collection ||= []
273
+ end
274
+
275
+ ##
276
+ # NOTE: An example of how RSpec extracts block source, but they marked it as private.
277
+ # https://github.com/rspec/rspec-expectations/blob/311aaf245f2c5493572bf683b8c441cb5f7e44c8/lib/rspec/matchers/built_in/change.rb#L437
278
+ #
279
+ # TODO: `printable_block_expectation` when `method_source` is available.
280
+ # https://github.com/banister/method_source
281
+ #
282
+ # def printable_block_expectation
283
+ # @printable_block_expectation ||= block_expectation.source
284
+ # end
285
+ #
286
+ def printable_block_expectation
287
+ @printable_block_expectation ||= "{ ... }"
288
+ end
251
289
  end
252
290
  end
253
291
  end
@@ -49,36 +49,48 @@ module ConvenientService
49
49
  ##
50
50
  # @return [Class]
51
51
  #
52
- def service
53
- internals.cache[:jsend_attributes].service
54
- end
52
+ delegate :service, to: :jsend_attributes
55
53
 
56
54
  ##
57
55
  # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJsendStatusAndAttributes::Entities::Status]
58
56
  #
59
- def status
60
- internals.cache[:jsend_attributes].status
61
- end
57
+ delegate :status, to: :jsend_attributes
62
58
 
63
59
  ##
64
60
  # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJsendStatusAndAttributes::Entities::Data]
65
61
  #
66
- def data
67
- internals.cache[:jsend_attributes].data
68
- end
62
+ delegate :data, to: :jsend_attributes
63
+
64
+ ##
65
+ # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJsendStatusAndAttributes::Entities::Data]
66
+ #
67
+ alias_method :unsafe_data, :data
69
68
 
70
69
  ##
71
70
  # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJsendStatusAndAttributes::Entities::Message]
72
71
  #
73
- def message
74
- internals.cache[:jsend_attributes].message
75
- end
72
+ delegate :message, to: :jsend_attributes
73
+
74
+ ##
75
+ # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJsendStatusAndAttributes::Entities::Message]
76
+ #
77
+ alias_method :unsafe_message, :message
76
78
 
77
79
  ##
78
80
  # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJsendStatusAndAttributes::Entities::Code]
79
81
  #
80
- def code
81
- internals.cache[:jsend_attributes].code
82
+ delegate :code, to: :jsend_attributes
83
+
84
+ ##
85
+ # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJsendStatusAndAttributes::Entities::Code]
86
+ #
87
+ alias_method :unsafe_code, :code
88
+
89
+ ##
90
+ # @return [ConvenientService::Service::Plugins::HasResult::Entities::Result::Plugins::HasJsendStatusAndAttributes::Structs::JSendAttributes]
91
+ #
92
+ def jsend_attributes
93
+ internals.cache[:jsend_attributes]
82
94
  end
83
95
 
84
96
  ##
@@ -90,9 +102,9 @@ module ConvenientService
90
102
 
91
103
  return false if service.class != other.service.class
92
104
  return false if status != other.status
93
- return false if data != other.data
94
- return false if message != other.message
95
- return false if code != other.code
105
+ return false if unsafe_data != other.unsafe_data
106
+ return false if unsafe_message != other.unsafe_message
107
+ return false if unsafe_code != other.unsafe_code
96
108
 
97
109
  true
98
110
  end
@@ -21,15 +21,25 @@ module ConvenientService
21
21
  # TODO: Return one or all errors?
22
22
  #
23
23
  def errors
24
- @errors ||=
25
- entity
26
- .class
27
- .contract
28
- .new
29
- .call(**entity.constructor_params.kwargs)
30
- .errors
31
- .to_h
32
- .transform_values(&:first)
24
+ @errors ||= resolve_errors
25
+ end
26
+
27
+ def constructor_kwargs
28
+ @constructor_kwargs ||= entity.constructor_params.kwargs
29
+ end
30
+
31
+ def contract
32
+ @contract ||= entity.class.contract
33
+ end
34
+
35
+ def resolve_errors
36
+ return {} unless contract.schema
37
+
38
+ contract.new
39
+ .call(constructor_kwargs)
40
+ .errors
41
+ .to_h
42
+ .transform_values(&:first)
33
43
  end
34
44
  end
35
45
  end
@@ -8,7 +8,7 @@ module ConvenientService
8
8
  def next(...)
9
9
  return chain.next(...) if entity.steps.none?
10
10
 
11
- last_step.result
11
+ last_step.result.copy
12
12
  end
13
13
 
14
14
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConvenientService
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: convenient_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marian Kostyk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-29 00:00:00.000000000 Z
11
+ date: 2022-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal