light-service 0.13.0 → 0.17.0

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/project-build.yml +28 -0
  3. data/.travis.yml +3 -9
  4. data/Appraisals +0 -4
  5. data/Gemfile +0 -2
  6. data/README.md +287 -51
  7. data/RELEASES.md +21 -2
  8. data/gemfiles/activesupport_5.gemfile +0 -1
  9. data/gemfiles/activesupport_6.gemfile +0 -1
  10. data/lib/generators/light_service/action_generator.rb +90 -0
  11. data/lib/generators/light_service/generator_utils.rb +45 -0
  12. data/lib/generators/light_service/organizer_generator.rb +66 -0
  13. data/lib/generators/light_service/templates/action_spec_template.erb +31 -0
  14. data/lib/generators/light_service/templates/action_template.erb +30 -0
  15. data/lib/generators/light_service/templates/organizer_spec_template.erb +20 -0
  16. data/lib/generators/light_service/templates/organizer_template.erb +22 -0
  17. data/lib/light-service/action.rb +61 -4
  18. data/lib/light-service/context/key_verifier.rb +18 -1
  19. data/lib/light-service/context.rb +5 -3
  20. data/lib/light-service/errors.rb +1 -0
  21. data/lib/light-service/organizer/reduce_if_else.rb +21 -0
  22. data/lib/light-service/organizer/with_reducer.rb +12 -7
  23. data/lib/light-service/organizer/with_reducer_factory.rb +1 -1
  24. data/lib/light-service/organizer/with_reducer_log_decorator.rb +3 -0
  25. data/lib/light-service/organizer.rb +16 -3
  26. data/lib/light-service/version.rb +1 -1
  27. data/lib/light-service.rb +1 -0
  28. data/light-service.gemspec +6 -1
  29. data/spec/acceptance/after_actions_spec.rb +17 -0
  30. data/spec/acceptance/around_each_spec.rb +15 -0
  31. data/spec/acceptance/log_from_organizer_spec.rb +1 -1
  32. data/spec/acceptance/organizer/add_to_context_spec.rb +27 -0
  33. data/spec/acceptance/organizer/execute_with_add_to_context_spec.rb +28 -0
  34. data/spec/acceptance/organizer/iterate_spec.rb +7 -0
  35. data/spec/acceptance/organizer/reduce_if_else_spec.rb +60 -0
  36. data/spec/acceptance/organizer/reduce_if_spec.rb +6 -0
  37. data/spec/acceptance/organizer/reduce_until_spec.rb +6 -0
  38. data/spec/action_optional_expected_keys_spec.rb +82 -0
  39. data/spec/action_spec.rb +8 -0
  40. data/spec/lib/generators/action_generator_advanced_spec.rb +43 -0
  41. data/spec/lib/generators/action_generator_simple_spec.rb +37 -0
  42. data/spec/lib/generators/full_generator_test_blobs.rb +193 -0
  43. data/spec/lib/generators/organizer_generator_advanced_spec.rb +37 -0
  44. data/spec/lib/generators/organizer_generator_simple_spec.rb +37 -0
  45. data/spec/organizer_spec.rb +5 -0
  46. data/spec/spec_helper.rb +5 -1
  47. data/spec/test_doubles.rb +37 -0
  48. metadata +87 -9
  49. data/gemfiles/activesupport_3.gemfile +0 -8
  50. data/gemfiles/activesupport_4.gemfile +0 -8
  51. data/resources/orchestrators_deprecated.svg +0 -10
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+ require 'test_doubles'
3
+
4
+ describe ":expects macro using defaults" do
5
+ context "when all expected keys are supplied" do
6
+ it "is expected to ignore default values" do
7
+ outcome = TestDoubles::AddsNumbersWithOptionalDefaults.execute(
8
+ :first_number => 3,
9
+ :second_number => 5,
10
+ :third_number => 7
11
+ )
12
+
13
+ expect(outcome.total).to eq 15
14
+ end
15
+ end
16
+
17
+ context "when defaults are supplied" do
18
+ it "is expected to use static values" do
19
+ outcome = TestDoubles::AddsNumbersWithOptionalDefaults.execute(
20
+ :first_number => 3,
21
+ :second_number => 7
22
+ )
23
+
24
+ expect(outcome.total).to eq 20
25
+ end
26
+
27
+ it "is expected to use dynamic values" do
28
+ outcome = TestDoubles::AddsNumbersWithOptionalDefaults.execute(
29
+ :first_number => 3,
30
+ :third_number => 5
31
+ )
32
+
33
+ expect(outcome.total).to eq 18
34
+ end
35
+
36
+ it "is expected to process defaults in their defined order" do
37
+ outcome = TestDoubles::AddsNumbersWithOptionalDefaults.execute(
38
+ :third_number => 5,
39
+ :first_number => 3
40
+ )
41
+
42
+ expect(outcome.total).to eq 18
43
+ end
44
+
45
+ it "is expected to use all defaults if required" do
46
+ outcome = TestDoubles::AddsNumbersWithOptionalDefaults.execute(
47
+ :first_number => 3
48
+ )
49
+
50
+ expect(outcome.total).to eq 23
51
+ end
52
+ end
53
+
54
+ context "when used within an organizer" do
55
+ it "is expected to process required defaults" do
56
+ outcome = TestDoubles::OrganizerWithActionsUsingDefaults.call
57
+
58
+ expect(outcome.total).to eq 20
59
+ end
60
+ end
61
+
62
+ context "when defaults are misconfigured" do
63
+ it "is expected to raise an exception" do
64
+ expect do
65
+ # Needs to be specified in the block
66
+ # as error is raised at define time
67
+ class AddsNumbersWithIncorrectDefaults
68
+ extend LightService::Action
69
+
70
+ expects :first, :default => 10 # This one is fine. Other two arent
71
+ expects :second, :defalut => ->(ctx) { ctx[:first] + 7 }
72
+ expects :third, :deafult => 10
73
+ promises :total
74
+
75
+ executed do |ctx|
76
+ ctx.total = ctx.first + ctx.second + ctx.third
77
+ end
78
+ end
79
+ end.to raise_error(LightService::UnusableExpectKeyDefaultError)
80
+ end
81
+ end
82
+ end
data/spec/action_spec.rb CHANGED
@@ -68,6 +68,14 @@ describe LightService::Action do
68
68
  expect(result.to_hash).to eq(:number => 2)
69
69
  end
70
70
 
71
+ context "when called directly" do
72
+ it "is expected to not be organized" do
73
+ result = TestDoubles::AddsTwoActionWithFetch.execute(context)
74
+
75
+ expect(result.organized_by).to be_nil
76
+ end
77
+ end
78
+
71
79
  context "when invoked with hash" do
72
80
  it "creates LightService::Context implicitly" do
73
81
  ctx = { :some_key => "some value" }
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ require_relative '../../../lib/generators/light_service/action_generator.rb'
4
+ require_relative './full_generator_test_blobs'
5
+
6
+ describe LightService::Generators::ActionGenerator, :type => :generator do
7
+ destination File.expand_path('tmp', __dir__)
8
+
9
+ context "when generating an advanced action" do
10
+ before(:all) do
11
+ prepare_destination
12
+ run_generator
13
+ end
14
+
15
+ after(:all) do
16
+ FileUtils.rm_rf destination_root
17
+ end
18
+
19
+ arguments %w[
20
+ my/fancy/action
21
+ expects:foo,bar
22
+ promises:baz,qux
23
+ --no-roll-back
24
+ --dir=services
25
+ ]
26
+
27
+ specify do
28
+ expect(destination_root).to(have_structure do
29
+ directory "app/services/my/fancy" do
30
+ file "action.rb" do
31
+ contains FullGeneratorTestBlobs.advanced_action_blob
32
+ end
33
+ end
34
+
35
+ directory "spec/services/my/fancy" do
36
+ file "action_spec.rb" do
37
+ contains FullGeneratorTestBlobs.advanced_action_spec_blob
38
+ end
39
+ end
40
+ end)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ require_relative '../../../lib/generators/light_service/action_generator.rb'
4
+ require_relative './full_generator_test_blobs'
5
+
6
+ describe LightService::Generators::ActionGenerator, :type => :generator do
7
+ destination File.expand_path('tmp', __dir__)
8
+
9
+ context "when generating a simple action" do
10
+ before(:all) do
11
+ prepare_destination
12
+ run_generator
13
+ end
14
+
15
+ after(:all) do
16
+ FileUtils.rm_rf destination_root
17
+ end
18
+
19
+ arguments %w[my_action]
20
+
21
+ specify do
22
+ expect(destination_root).to(have_structure do
23
+ directory "app/actions" do
24
+ file "my_action.rb" do
25
+ contains FullGeneratorTestBlobs.simple_action_blob
26
+ end
27
+ end
28
+
29
+ directory "spec/actions" do
30
+ file "my_action_spec.rb" do
31
+ contains FullGeneratorTestBlobs.simple_action_spec_blob
32
+ end
33
+ end
34
+ end)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,193 @@
1
+ # rubocop:disable Metrics/ClassLength, Metrics/MethodLength
2
+ class FullGeneratorTestBlobs
3
+ def self.simple_action_blob
4
+ <<~BLOB
5
+ # frozen_string_literal: true
6
+
7
+ class MyAction
8
+ extend ::LightService::Action
9
+
10
+ executed do |ctx|
11
+ end
12
+
13
+ rolled_back do |ctx|
14
+ end
15
+ end
16
+ BLOB
17
+ end
18
+
19
+ def self.simple_action_spec_blob
20
+ <<~BLOB
21
+ # frozen_string_literal: true
22
+
23
+ require 'rails_helper'
24
+
25
+ RSpec.describe MyAction, type: :action do
26
+ subject { described_class.execute(ctx) }
27
+
28
+ let(:ctx) do
29
+ {
30
+ }
31
+ end
32
+
33
+ context "when executed" do
34
+ xit "is expected to be successful" do
35
+ expect(subject).to be_a_success
36
+ end
37
+ end
38
+ end
39
+ BLOB
40
+ end
41
+
42
+ # There's some weird whitespace issue which prevents
43
+ # using HEREDOCS :(
44
+ def self.advanced_action_blob
45
+ "# frozen_string_literal: true\n" \
46
+ "\n" \
47
+ "module My::Fancy\n" \
48
+ " class Action\n" \
49
+ " extend ::LightService::Action\n" \
50
+ "\n" \
51
+ " expects :foo, :bar\n" \
52
+ " promises :baz, :qux\n" \
53
+ "\n" \
54
+ " executed do |ctx|\n" \
55
+ " foo = ctx.foo\n" \
56
+ " bar = ctx.bar\n" \
57
+ " end\n" \
58
+ " end\n" \
59
+ "end"
60
+ end
61
+
62
+ def self.advanced_action_spec_blob
63
+ <<~BLOB
64
+ # frozen_string_literal: true
65
+
66
+ require 'rails_helper'
67
+
68
+ RSpec.describe My::Fancy::Action, type: :action do
69
+ subject { described_class.execute(ctx) }
70
+
71
+ let(:ctx) do
72
+ {
73
+ foo: nil,
74
+ bar: nil,
75
+ }
76
+ end
77
+
78
+ context "when executed" do
79
+ xit "is expected to be successful" do
80
+ expect(subject).to be_a_success
81
+ end
82
+
83
+ xit "is expected to promise 'baz'" do
84
+ expect(subject.baz).to eq SomeBazClass
85
+ end
86
+
87
+ xit "is expected to promise 'qux'" do
88
+ expect(subject.qux).to eq SomeQuxClass
89
+ end
90
+ end
91
+ end
92
+ BLOB
93
+ end
94
+
95
+ def self.simple_organizer_blob
96
+ <<~BLOB
97
+ # frozen_string_literal: true
98
+
99
+ class MyOrganizer
100
+ extend ::LightService::Organizer
101
+
102
+ def self.call(params)
103
+ with(
104
+ #foo: params[:foo],
105
+ #bar: params[:bar]
106
+ ).reduce(actions)
107
+ end
108
+
109
+ def self.actions
110
+ [
111
+ #OneAction,
112
+ #TwoAction,
113
+ ]
114
+ end
115
+ end
116
+ BLOB
117
+ end
118
+
119
+ def self.simple_organizer_spec_blob
120
+ <<~BLOB
121
+ # frozen_string_literal: true
122
+
123
+ require 'rails_helper'
124
+
125
+ RSpec.describe MyOrganizer, type: :organizer do
126
+ subject { described_class.call(ctx) }
127
+
128
+ let(:ctx) do
129
+ {
130
+ #foo: 'something foo',
131
+ #bar: { baz: qux },
132
+ }
133
+ end
134
+
135
+ context "when called" do
136
+ xit "is expected to be successful" do
137
+ expect(subject).to be_a_success
138
+ end
139
+ end
140
+ end
141
+ BLOB
142
+ end
143
+
144
+ def self.advanced_organizer_blob
145
+ "# frozen_string_literal: true\n" \
146
+ "\n" \
147
+ "module My::Fancy\n" \
148
+ " class Organizer\n" \
149
+ " extend ::LightService::Organizer\n" \
150
+ "\n" \
151
+ " def self.call(params)\n" \
152
+ " with(\n" \
153
+ " #foo: params[:foo],\n" \
154
+ " #bar: params[:bar]\n" \
155
+ " ).reduce(actions)\n" \
156
+ " end\n" \
157
+ "\n" \
158
+ " def self.actions\n" \
159
+ " [\n" \
160
+ " #My::Fancy::OneAction,\n" \
161
+ " #My::Fancy::TwoAction,\n" \
162
+ " ]\n" \
163
+ " end\n" \
164
+ " end\n" \
165
+ "end"
166
+ end
167
+
168
+ def self.advanced_organizer_spec_blob
169
+ <<~BLOB
170
+ # frozen_string_literal: true
171
+
172
+ require 'rails_helper'
173
+
174
+ RSpec.describe My::Fancy::Organizer, type: :organizer do
175
+ subject { described_class.call(ctx) }
176
+
177
+ let(:ctx) do
178
+ {
179
+ #foo: 'something foo',
180
+ #bar: { baz: qux },
181
+ }
182
+ end
183
+
184
+ context "when called" do
185
+ xit "is expected to be successful" do
186
+ expect(subject).to be_a_success
187
+ end
188
+ end
189
+ end
190
+ BLOB
191
+ end
192
+ end
193
+ # rubocop:enable Metrics/ClassLength, Metrics/MethodLength
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ require_relative '../../../lib/generators/light_service/organizer_generator.rb'
4
+ require_relative './full_generator_test_blobs'
5
+
6
+ describe LightService::Generators::OrganizerGenerator, :type => :generator do
7
+ destination File.expand_path('tmp', __dir__)
8
+
9
+ context "when generating an advanced organizer" do
10
+ before(:all) do
11
+ prepare_destination
12
+ run_generator
13
+ end
14
+
15
+ after(:all) do
16
+ FileUtils.rm_rf destination_root
17
+ end
18
+
19
+ arguments %w[my/fancy/organizer --dir=processes]
20
+
21
+ specify do
22
+ expect(destination_root).to(have_structure do
23
+ directory "app/processes/my/fancy" do
24
+ file "organizer.rb" do
25
+ contains FullGeneratorTestBlobs.advanced_organizer_blob
26
+ end
27
+ end
28
+
29
+ directory "spec/processes/my/fancy" do
30
+ file "organizer_spec.rb" do
31
+ contains FullGeneratorTestBlobs.advanced_organizer_spec_blob
32
+ end
33
+ end
34
+ end)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ require_relative '../../../lib/generators/light_service/organizer_generator.rb'
4
+ require_relative './full_generator_test_blobs'
5
+
6
+ describe LightService::Generators::OrganizerGenerator, :type => :generator do
7
+ destination File.expand_path('tmp', __dir__)
8
+
9
+ context "when generating a simple organizer" do
10
+ before(:all) do
11
+ prepare_destination
12
+ run_generator
13
+ end
14
+
15
+ after(:all) do
16
+ FileUtils.rm_rf destination_root
17
+ end
18
+
19
+ arguments %w[my_organizer]
20
+
21
+ specify do
22
+ expect(destination_root).to(have_structure do
23
+ directory "app/organizers" do
24
+ file "my_organizer.rb" do
25
+ contains FullGeneratorTestBlobs.simple_organizer_blob
26
+ end
27
+ end
28
+
29
+ directory "spec/organizers" do
30
+ file "my_organizer_spec.rb" do
31
+ contains FullGeneratorTestBlobs.simple_organizer_spec_blob
32
+ end
33
+ end
34
+ end)
35
+ end
36
+ end
37
+ end