light-service 0.11.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/project-build.yml +28 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +7 -11
  6. data/Appraisals +4 -4
  7. data/Gemfile +0 -2
  8. data/README.md +257 -42
  9. data/RELEASES.md +21 -0
  10. data/gemfiles/activesupport_5.gemfile +0 -1
  11. data/gemfiles/{activesupport_3.gemfile → activesupport_6.gemfile} +1 -2
  12. data/lib/generators/light_service/action_generator.rb +90 -0
  13. data/lib/generators/light_service/generator_utils.rb +45 -0
  14. data/lib/generators/light_service/organizer_generator.rb +66 -0
  15. data/lib/generators/light_service/templates/action_spec_template.erb +31 -0
  16. data/lib/generators/light_service/templates/action_template.erb +30 -0
  17. data/lib/generators/light_service/templates/organizer_spec_template.erb +20 -0
  18. data/lib/generators/light_service/templates/organizer_template.erb +22 -0
  19. data/lib/light-service.rb +1 -0
  20. data/lib/light-service/action.rb +3 -0
  21. data/lib/light-service/context.rb +8 -4
  22. data/lib/light-service/context/key_verifier.rb +18 -1
  23. data/lib/light-service/localization_adapter.rb +1 -1
  24. data/lib/light-service/organizer.rb +27 -0
  25. data/lib/light-service/organizer/with_reducer.rb +8 -1
  26. data/lib/light-service/organizer/with_reducer_factory.rb +11 -7
  27. data/lib/light-service/organizer/with_reducer_log_decorator.rb +5 -2
  28. data/lib/light-service/version.rb +1 -1
  29. data/light-service.gemspec +10 -4
  30. data/spec/acceptance/after_actions_spec.rb +17 -0
  31. data/spec/acceptance/custom_log_from_organizer_spec.rb +60 -0
  32. data/spec/acceptance/fail_spec.rb +42 -16
  33. data/spec/acceptance/organizer/add_aliases_spec.rb +28 -0
  34. data/spec/acceptance/organizer/add_to_context_spec.rb +57 -0
  35. data/spec/acceptance/organizer/execute_spec.rb +1 -1
  36. data/spec/acceptance/organizer/execute_with_add_to_context_spec.rb +28 -0
  37. data/spec/acceptance/organizer/iterate_spec.rb +7 -0
  38. data/spec/acceptance/organizer/reduce_if_spec.rb +38 -0
  39. data/spec/acceptance/organizer/reduce_until_spec.rb +6 -0
  40. data/spec/action_spec.rb +8 -0
  41. data/spec/lib/generators/action_generator_advanced_spec.rb +43 -0
  42. data/spec/lib/generators/action_generator_simple_spec.rb +37 -0
  43. data/spec/lib/generators/full_generator_test_blobs.rb +193 -0
  44. data/spec/lib/generators/organizer_generator_advanced_spec.rb +37 -0
  45. data/spec/lib/generators/organizer_generator_simple_spec.rb +37 -0
  46. data/spec/organizer_spec.rb +21 -0
  47. data/spec/sample/provides_free_shipping_action_spec.rb +1 -1
  48. data/spec/spec_helper.rb +7 -2
  49. data/spec/test_doubles.rb +47 -0
  50. metadata +111 -21
  51. data/gemfiles/activesupport_3.gemfile.lock +0 -76
  52. data/gemfiles/activesupport_4.gemfile +0 -8
  53. data/gemfiles/activesupport_4.gemfile.lock +0 -82
  54. data/gemfiles/activesupport_5.gemfile.lock +0 -82
  55. data/resources/orchestrators_deprecated.svg +0 -10
@@ -40,4 +40,10 @@ RSpec.describe LightService::Organizer do
40
40
  result = TestReduceUntil.call(empty_context)
41
41
  expect(result).to be_success
42
42
  end
43
+
44
+ it "is expected to know its organizer when reducing until a condition" do
45
+ result = TestReduceUntil.call(:number => 1)
46
+
47
+ expect(result.organized_by).to eq TestReduceUntil
48
+ end
43
49
  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
@@ -19,6 +19,11 @@ describe LightService::Organizer do
19
19
  result = TestDoubles::AnOrganizer.call(:user => user)
20
20
  expect(result).to eq(ctx)
21
21
  end
22
+
23
+ it "sets itself as the organizer" do
24
+ result = TestDoubles::AnOrganizer.call(:user => user)
25
+ expect(result.organized_by).to eq TestDoubles::AnOrganizer
26
+ end
22
27
  end
23
28
 
24
29
  context "when #with is called with Context" do
@@ -90,4 +95,20 @@ describe LightService::Organizer do
90
95
  expect(reduced).to eq(ctx)
91
96
  end
92
97
  end
98
+
99
+ context 'can add items to the context' do
100
+ specify 'with #add_to_context' do
101
+ result = TestDoubles::AnOrganizerThatAddsToContext.call
102
+ expect(result[:strongest_avenger]).to eq 'The Thor'
103
+ expect(result[:last_jedi]).to eq 'Rey'
104
+ end
105
+ end
106
+
107
+ context 'can assign key aliaeses' do
108
+ it 'with #add_aliases' do
109
+ result = TestDoubles::AnOrganizerThatAddsAliases.call
110
+ expect(result[:foo]).to eq :bar
111
+ expect(result[:baz]).to eq :bar
112
+ end
113
+ end
93
114
  end
@@ -15,7 +15,7 @@ describe ProvidesFreeShippingAction do
15
15
  end
16
16
 
17
17
  context "when the order total with tax is <= 200" do
18
- specify "order gets free shipping" do
18
+ specify "order does not get free shipping" do
19
19
  allow(order).to receive_messages(:total_with_tax => 200)
20
20
  expect(order).not_to receive(:provide_free_shipping!)
21
21
 
data/spec/spec_helper.rb CHANGED
@@ -8,15 +8,20 @@ if ENV['RUN_COVERAGE_REPORT']
8
8
  add_filter 'vendor/'
9
9
  add_filter %r{^/spec/}
10
10
  end
11
-
12
11
  SimpleCov.minimum_coverage_by_file 90
12
+
13
+ require 'codecov'
14
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
13
15
  end
14
16
 
15
17
  require 'light-service'
16
18
  require 'light-service/testing'
17
19
  require 'ostruct'
18
- require 'active_support/core_ext/string'
19
20
  require 'pry'
20
21
  require 'support'
22
+ require 'test_doubles'
23
+ require 'stringio'
24
+ require 'fileutils'
25
+ require 'generator_spec'
21
26
 
22
27
  I18n.enforce_available_locales = true