convenient_service 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.dev/.tmuxinator.yml +17 -0
  3. data/CHANGELOG.md +15 -0
  4. data/README.md +8 -8
  5. data/Taskfile.yml +30 -0
  6. data/lib/convenient_service/rspec/matchers/custom/results/base.rb +245 -0
  7. data/lib/convenient_service/rspec/matchers/custom/results/be_error.rb +3 -139
  8. data/lib/convenient_service/rspec/matchers/custom/results/be_failure.rb +3 -106
  9. data/lib/convenient_service/rspec/matchers/custom/results/be_not_error.rb +20 -0
  10. data/lib/convenient_service/rspec/matchers/custom/results/be_not_failure.rb +20 -0
  11. data/lib/convenient_service/rspec/matchers/custom/results/be_not_success.rb +20 -0
  12. data/lib/convenient_service/rspec/matchers/custom/results/be_success.rb +3 -112
  13. data/lib/convenient_service/rspec/matchers/custom/results.rb +6 -0
  14. data/lib/convenient_service/rspec/matchers/results/be_not_error.rb +15 -0
  15. data/lib/convenient_service/rspec/matchers/results/be_not_failure.rb +15 -0
  16. data/lib/convenient_service/rspec/matchers/results/be_not_success.rb +15 -0
  17. data/lib/convenient_service/rspec/matchers/results.rb +8 -0
  18. data/lib/convenient_service/service/plugins/has_result/constants.rb +1 -4
  19. data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/data.rb +8 -0
  20. data/lib/convenient_service/service/plugins/has_result/entities/result/plugins/has_jsend_status_and_attributes/entities/status.rb +4 -0
  21. data/lib/convenient_service/service/plugins/has_result_method_steps/middleware.rb +1 -4
  22. data/lib/convenient_service/service/plugins/has_result_steps/concern.rb +8 -2
  23. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/commands/cast_method_caller.rb +1 -1
  24. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/commands/cast_method_key.rb +1 -1
  25. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/commands/cast_method_name.rb +1 -1
  26. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/commands/define_method_in_container.rb +15 -8
  27. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/entities.rb +0 -1
  28. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/errors.rb +15 -1
  29. data/lib/convenient_service/service/plugins/has_result_steps/entities/step/concern/instance_methods.rb +10 -0
  30. data/lib/convenient_service/support/gems/rspec.rb +9 -2
  31. data/lib/convenient_service/support/raw_value.rb +52 -0
  32. data/lib/convenient_service/support.rb +1 -0
  33. data/lib/convenient_service/version.rb +1 -1
  34. metadata +11 -4
  35. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/values/raw.rb +0 -48
  36. data/lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/values.rb +0 -3
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Custom
7
+ module Results
8
+ class BeNotSuccess < Results::Base
9
+ def statuses
10
+ [
11
+ Service::Plugins::HasResult::Constants::ERROR_STATUS,
12
+ Service::Plugins::HasResult::Constants::FAILURE_STATUS
13
+ ]
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -5,118 +5,9 @@ module ConvenientService
5
5
  module Matchers
6
6
  module Custom
7
7
  module Results
8
- class BeSuccess
9
- def matches?(result)
10
- @result = result
11
-
12
- rules = []
13
-
14
- rules << ->(result) { result.class.include?(ConvenientService::Service::Plugins::HasResult::Entities::Result::Concern) }
15
- rules << ->(result) { result.success? }
16
- rules << ->(result) { result.service.instance_of?(service_class) } if used_of?
17
- rules << ->(result) { result.data == data } if used_data?
18
-
19
- condition = ConvenientService::Utils::Proc.conjunct(rules)
20
-
21
- condition.call(result)
22
- end
23
-
24
- def with_data(data)
25
- chain[:data] = data
26
-
27
- self
28
- end
29
-
30
- def without_data
31
- chain[:data] = {}
32
-
33
- self
34
- end
35
-
36
- def of(service_class)
37
- chain[:service_class] = service_class
38
-
39
- self
40
- end
41
-
42
- def description
43
- ##
44
- # TODO: of
45
- #
46
- parts = []
47
-
48
- parts << "be a `success`"
49
- parts << "of `#{service_class}`" if used_of?
50
- parts << "with data `#{data}`" if used_data?
51
- parts << "\n\n"
52
- parts << "got `#{result.status}`"
53
- parts << "of `#{result.service.class}`" if used_of?
54
- parts << "with data `#{result.data.to_h}`" if used_data?
55
-
56
- parts.join(" ")
57
- end
58
-
59
- def failure_message
60
- ##
61
- # TODO: got text after expect text.
62
- #
63
- parts = []
64
-
65
- parts << "expected that `#{result}` would be a `success`"
66
- parts << "of `#{service_class}`" if used_of?
67
- parts << "with data `#{data}`" if used_data?
68
- parts << "\n\n"
69
- parts << "got `#{result.status}`"
70
- parts << "of `#{result.service.class}`" if used_of?
71
- parts << "with data `#{result.data.to_h}`" if used_data?
72
-
73
- parts.join(" ")
74
- end
75
-
76
- ##
77
- # https://relishapp.com/rspec/rspec-expectations/v/3-11/docs/custom-matchers/define-a-custom-matcher#overriding-the-failure-message-when-negated
78
- #
79
- def failure_message_when_negated
80
- ##
81
- # TODO: got text after expect text.
82
- #
83
- parts = []
84
-
85
- parts << "expected that #{result} would NOT be a `success`"
86
- parts << "of `#{service_class}`" if used_of?
87
- parts << "with data `#{data}`" if used_data?
88
- parts << "\n\n"
89
- parts << "got `#{result.status}`"
90
- parts << "of `#{result.service.class}`" if used_of?
91
- parts << "with data `#{result.data.to_h}`" if used_data?
92
-
93
- parts.join(" ")
94
- end
95
-
96
- private
97
-
98
- attr_reader :result
99
-
100
- def used_data?
101
- chain.key?(:data)
102
- end
103
-
104
- def used_of?
105
- chain.key?(:service_class)
106
- end
107
-
108
- def chain
109
- @chain ||= {}
110
- end
111
-
112
- def data
113
- @data ||= chain[:data] || {}
114
- end
115
-
116
- def service_class
117
- return @service_class if defined? @service_class
118
-
119
- @service_class = chain[:service_class]
8
+ class BeSuccess < Results::Base
9
+ def statuses
10
+ [Service::Plugins::HasResult::Constants::SUCCESS_STATUS]
120
11
  end
121
12
  end
122
13
  end
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "results/base"
4
+
3
5
  require_relative "results/be_error"
4
6
  require_relative "results/be_failure"
5
7
  require_relative "results/be_success"
8
+
9
+ require_relative "results/be_not_error"
10
+ require_relative "results/be_not_failure"
11
+ require_relative "results/be_not_success"
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Results
7
+ module BeNotError
8
+ def be_not_error(...)
9
+ Custom::Results::BeNotError.new(...)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Results
7
+ module BeNotFailure
8
+ def be_not_failure(...)
9
+ Custom::Results::BeNotFailure.new(...)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module RSpec
5
+ module Matchers
6
+ module Results
7
+ module BeNotSuccess
8
+ def be_not_success(...)
9
+ Custom::Results::BeNotSuccess.new(...)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -4,6 +4,10 @@ require_relative "results/be_error"
4
4
  require_relative "results/be_failure"
5
5
  require_relative "results/be_success"
6
6
 
7
+ require_relative "results/be_not_error"
8
+ require_relative "results/be_not_failure"
9
+ require_relative "results/be_not_success"
10
+
7
11
  module ConvenientService
8
12
  module RSpec
9
13
  module Matchers
@@ -14,6 +18,10 @@ module ConvenientService
14
18
  include Results::BeError
15
19
  include Results::BeFailure
16
20
  include Results::BeSuccess
21
+
22
+ include Results::BeNotError
23
+ include Results::BeNotFailure
24
+ include Results::BeNotSuccess
17
25
  end
18
26
  end
19
27
  end
@@ -5,10 +5,7 @@ module ConvenientService
5
5
  module Plugins
6
6
  module HasResult
7
7
  module Constants
8
- ##
9
- # TODO: Consider to include `::ConvenientService::Configs::Minimal`
10
- #
11
- DEFAULT_SERVICE_CLASS = ::Class.new { include ::ConvenientService::Core }
8
+ DEFAULT_SERVICE_CLASS = ::Class.new { include ::ConvenientService::Service::Plugins::HasResult::Concern }
12
9
  DEFAULT_SERVICE_INSTANCE = DEFAULT_SERVICE_CLASS.new
13
10
 
14
11
  SUCCESS_STATUS = :success
@@ -22,6 +22,14 @@ module ConvenientService
22
22
  @value = value
23
23
  end
24
24
 
25
+ ##
26
+ # @param key [String, Symbol]
27
+ # @return [Boolean]
28
+ #
29
+ def has_attribute?(key)
30
+ value.has_key?(key.to_sym)
31
+ end
32
+
25
33
  def ==(other)
26
34
  casted = cast(other)
27
35
 
@@ -54,6 +54,10 @@ module ConvenientService
54
54
  !error?
55
55
  end
56
56
 
57
+ def in?(statuses)
58
+ statuses.any? { |status| self == status }
59
+ end
60
+
57
61
  def to_s
58
62
  @to_s ||= value.to_s
59
63
  end
@@ -24,11 +24,8 @@ module ConvenientService
24
24
 
25
25
  private
26
26
 
27
- ##
28
- # TODO: `Plugins::HasResultSteps::Entities::Method.raw_value`.
29
- #
30
27
  def raw(object)
31
- Plugins::HasResultSteps::Entities::Method::Entities::Values::Raw.wrap(object)
28
+ Support::RawValue.wrap(object)
32
29
  end
33
30
  end
34
31
  end
@@ -33,10 +33,16 @@ module ConvenientService
33
33
  end
34
34
 
35
35
  ##
36
- # NOTE: Allows to pass a value to `in` method without processing it.
36
+ # Allows to pass a value to `in` method without its intermediate processing.
37
+ # @see https://marian13.github.io/convenient_service_docs/basics/step_to_result_translation_table
38
+ #
39
+ # @example `:chat_v2` is passed to `AssertFeatureEnabled` as it is.
40
+ # step AssertFeatureEnabled, in: {name: raw(:chat_v2)}
41
+ # # that is converted to the following service invocation:
42
+ # AssertFeatureEnabled.result(name: :chat_v2)
37
43
  #
38
44
  def raw(value)
39
- Entities::Method::Entities::Values::Raw.wrap(value)
45
+ Support::RawValue.wrap(value)
40
46
  end
41
47
 
42
48
  def steps
@@ -49,7 +49,7 @@ module ConvenientService
49
49
  Entities::Callers::Alias.new(value)
50
50
  when ::Proc
51
51
  Entities::Callers::Proc.new(value)
52
- when Entities::Values::Raw
52
+ when Support::RawValue
53
53
  Entities::Callers::Raw.new(value)
54
54
  end
55
55
  end
@@ -53,7 +53,7 @@ module ConvenientService
53
53
  Entities::Key.new(key)
54
54
  when ::Proc
55
55
  Entities::Key.new(key)
56
- when Entities::Values::Raw
56
+ when Support::RawValue
57
57
  Entities::Key.new(key)
58
58
  end
59
59
  end
@@ -53,7 +53,7 @@ module ConvenientService
53
53
  Entities::Name.new(value)
54
54
  when ::Proc
55
55
  Entities::Name.new(key)
56
- when Entities::Values::Raw
56
+ when Support::RawValue
57
57
  Entities::Name.new(key)
58
58
  end
59
59
  end
@@ -26,11 +26,13 @@ module ConvenientService
26
26
  #
27
27
  <<~RUBY.tap { |code| container.klass.class_eval(code, __FILE__, __LINE__ + 1) }
28
28
  def #{name}
29
- step, key, name, error = steps[#{index}], :#{key}, :#{name}, #{error}
29
+ step, key, method_name = steps[#{index}], :#{key}, :#{name}
30
30
 
31
- return step.result.data[key] if step.completed?
31
+ raise #{not_completed_step_error}.new(step: step, method_name: method_name) unless step.completed?
32
32
 
33
- raise ::#{error}.new(step: step, method_name: name)
33
+ raise #{not_existing_step_result_data_attribute_error}.new(step: step, key: key) unless step.result.data.has_attribute?(key)
34
+
35
+ step.result.data[key]
34
36
  end
35
37
  RUBY
36
38
 
@@ -39,11 +41,16 @@ module ConvenientService
39
41
 
40
42
  private
41
43
 
42
- def error
43
- @error ||=
44
- <<~RUBY.chomp
45
- ConvenientService::Service::Plugins::HasResultSteps::Entities::Method::Errors::NotCompletedStep
46
- RUBY
44
+ def not_completed_step_error
45
+ <<~RUBY.chomp
46
+ ::ConvenientService::Service::Plugins::HasResultSteps::Entities::Method::Errors::NotCompletedStep
47
+ RUBY
48
+ end
49
+
50
+ def not_existing_step_result_data_attribute_error
51
+ <<~RUBY.chomp
52
+ ::ConvenientService::Service::Plugins::HasResultSteps::Entities::Method::Errors::NotExistingStepResultDataAttribute
53
+ RUBY
47
54
  end
48
55
  end
49
56
  end
@@ -4,4 +4,3 @@ require_relative "entities/directions"
4
4
  require_relative "entities/callers"
5
5
  require_relative "entities/key"
6
6
  require_relative "entities/name"
7
- require_relative "entities/values"
@@ -110,7 +110,7 @@ module ConvenientService
110
110
  class NotCompletedStep < ConvenientService::Error
111
111
  def initialize(method_name:, step:)
112
112
  message = <<~TEXT
113
- `out` method `#{method_name}` is called before its corresponding step `#{step.service}` is completed.
113
+ `out` method `#{method_name}` is called before its corresponding step `#{step.printable_service}` is completed.
114
114
 
115
115
  Maybe it makes sense to change the steps order?
116
116
  TEXT
@@ -118,6 +118,20 @@ module ConvenientService
118
118
  super(message)
119
119
  end
120
120
  end
121
+
122
+ class NotExistingStepResultDataAttribute < ConvenientService::Error
123
+ def initialize(key:, step:)
124
+ message = <<~TEXT
125
+ Step `#{step.printable_service}` result does NOT return `#{key}` data attribute.
126
+
127
+ Maybe there is a typo in `out` definition?
128
+
129
+ Or `success` of `#{step.printable_service}` accepts a wrong key?
130
+ TEXT
131
+
132
+ super(message)
133
+ end
134
+ end
121
135
  end
122
136
  end
123
137
  end
@@ -70,6 +70,16 @@ module ConvenientService
70
70
  @result ||= calculate_result
71
71
  end
72
72
 
73
+ ##
74
+ # @return [String]
75
+ #
76
+ # @internal
77
+ # TODO: printable service for methods steps.
78
+ #
79
+ def printable_service
80
+ service.klass.to_s
81
+ end
82
+
73
83
  def validate!
74
84
  inputs.each { |input| input.validate_as_input_for_container!(container) }
75
85
 
@@ -34,7 +34,7 @@ module ConvenientService
34
34
  # @return [RSpec::Core::Example, nil]
35
35
  #
36
36
  # @internal
37
- # NOTE: Returns `nil` in a non-test environment
37
+ # NOTE: Returns `nil` in environments where RSpec is NOT fully loaded, e.g: irb, rails console, etc.
38
38
  #
39
39
  # `::RSpec.current_example` docs:
40
40
  # - https://www.rubydoc.info/github/rspec/rspec-core/RSpec.current_example
@@ -42,7 +42,14 @@ module ConvenientService
42
42
  # - https://relishapp.com/rspec/rspec-core/docs/metadata/current-example
43
43
  #
44
44
  def current_example
45
- ::RSpec.current_example if loaded?
45
+ return unless loaded?
46
+
47
+ ##
48
+ # NOTE: This happens in Ruby-only projects where RSpec is loaded by `Bundler.require`, not by `bundle exec rspec`.
49
+ #
50
+ return unless ::RSpec.respond_to?(:current_example)
51
+
52
+ ::RSpec.current_example
46
53
  end
47
54
  end
48
55
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConvenientService
4
+ module Support
5
+ class RawValue
6
+ ##
7
+ # @param object [Object] Can be any type.
8
+ # @return [void]
9
+ #
10
+ def initialize(object)
11
+ @object = object
12
+ end
13
+
14
+ class << self
15
+ ##
16
+ # @param object [Object] Can be any type.
17
+ # @return [ConvenientService::Support::RawValue]
18
+ #
19
+ def wrap(object)
20
+ new(object)
21
+ end
22
+
23
+ private :new
24
+ end
25
+
26
+ ##
27
+ # @return [Object] Can be any type.
28
+ #
29
+ def unwrap
30
+ object
31
+ end
32
+
33
+ ##
34
+ # @return [Boolean, nil]
35
+ #
36
+ def ==(other)
37
+ return unless other.instance_of?(self.class)
38
+
39
+ return false if object != other.object
40
+
41
+ true
42
+ end
43
+
44
+ protected
45
+
46
+ ##
47
+ # @return [Object] Can be any type.
48
+ #
49
+ attr_reader :object
50
+ end
51
+ end
52
+ end
@@ -11,5 +11,6 @@ require_relative "support/delegate"
11
11
  require_relative "support/finite_loop"
12
12
  require_relative "support/gems"
13
13
  require_relative "support/middleware"
14
+ require_relative "support/raw_value"
14
15
  require_relative "support/ruby"
15
16
  require_relative "support/version"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConvenientService
4
- VERSION = "0.3.1"
4
+ VERSION = "0.4.0"
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.3.1
4
+ version: 0.4.0
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-12-19 00:00:00.000000000 Z
11
+ date: 2023-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -301,6 +301,7 @@ executables: []
301
301
  extensions: []
302
302
  extra_rdoc_files: []
303
303
  files:
304
+ - ".dev/.tmuxinator.yml"
304
305
  - ".dockerignore"
305
306
  - ".gem_release.yml"
306
307
  - ".github/issue_template.md"
@@ -529,8 +530,12 @@ files:
529
530
  - lib/convenient_service/rspec/matchers/custom/include_module.rb
530
531
  - lib/convenient_service/rspec/matchers/custom/prepend_module.rb
531
532
  - lib/convenient_service/rspec/matchers/custom/results.rb
533
+ - lib/convenient_service/rspec/matchers/custom/results/base.rb
532
534
  - lib/convenient_service/rspec/matchers/custom/results/be_error.rb
533
535
  - lib/convenient_service/rspec/matchers/custom/results/be_failure.rb
536
+ - lib/convenient_service/rspec/matchers/custom/results/be_not_error.rb
537
+ - lib/convenient_service/rspec/matchers/custom/results/be_not_failure.rb
538
+ - lib/convenient_service/rspec/matchers/custom/results/be_not_success.rb
534
539
  - lib/convenient_service/rspec/matchers/custom/results/be_success.rb
535
540
  - lib/convenient_service/rspec/matchers/delegate_to.rb
536
541
  - lib/convenient_service/rspec/matchers/extend_module.rb
@@ -544,6 +549,9 @@ files:
544
549
  - lib/convenient_service/rspec/matchers/results.rb
545
550
  - lib/convenient_service/rspec/matchers/results/be_error.rb
546
551
  - lib/convenient_service/rspec/matchers/results/be_failure.rb
552
+ - lib/convenient_service/rspec/matchers/results/be_not_error.rb
553
+ - lib/convenient_service/rspec/matchers/results/be_not_failure.rb
554
+ - lib/convenient_service/rspec/matchers/results/be_not_success.rb
547
555
  - lib/convenient_service/rspec/matchers/results/be_success.rb
548
556
  - lib/convenient_service/service.rb
549
557
  - lib/convenient_service/service/plugins.rb
@@ -660,8 +668,6 @@ files:
660
668
  - lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/directions/output.rb
661
669
  - lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/key.rb
662
670
  - lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/name.rb
663
- - lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/values.rb
664
- - lib/convenient_service/service/plugins/has_result_steps/entities/method/entities/values/raw.rb
665
671
  - lib/convenient_service/service/plugins/has_result_steps/entities/method/errors.rb
666
672
  - lib/convenient_service/service/plugins/has_result_steps/entities/service.rb
667
673
  - lib/convenient_service/service/plugins/has_result_steps/entities/service/class_methods.rb
@@ -702,6 +708,7 @@ files:
702
708
  - lib/convenient_service/support/gems/rspec.rb
703
709
  - lib/convenient_service/support/middleware.rb
704
710
  - lib/convenient_service/support/middleware/stack_builder.rb
711
+ - lib/convenient_service/support/raw_value.rb
705
712
  - lib/convenient_service/support/ruby.rb
706
713
  - lib/convenient_service/support/version.rb
707
714
  - lib/convenient_service/support/version/null_version.rb
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ConvenientService
4
- module Service
5
- module Plugins
6
- module HasResultSteps
7
- module Entities
8
- class Method
9
- module Entities
10
- module Values
11
- ##
12
- # TODO: Specs.
13
- #
14
- class Raw
15
- def initialize(object)
16
- @object = object
17
- end
18
-
19
- class << self
20
- def wrap(object)
21
- new(object)
22
- end
23
-
24
- private :new
25
- end
26
-
27
- def unwrap
28
- object
29
- end
30
-
31
- def ==(other)
32
- return unless other.instance_of?(self.class)
33
-
34
- object == other.object
35
- end
36
-
37
- protected
38
-
39
- attr_reader :object
40
- end
41
- end
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "values/raw"