light-service 0.13.0 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
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