light-service 0.11.0 → 0.16.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.
- checksums.yaml +5 -5
- data/.github/workflows/project-build.yml +28 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +7 -11
- data/Appraisals +4 -4
- data/Gemfile +0 -2
- data/README.md +257 -42
- data/RELEASES.md +21 -0
- data/gemfiles/activesupport_5.gemfile +0 -1
- data/gemfiles/{activesupport_3.gemfile → activesupport_6.gemfile} +1 -2
- data/lib/generators/light_service/action_generator.rb +90 -0
- data/lib/generators/light_service/generator_utils.rb +45 -0
- data/lib/generators/light_service/organizer_generator.rb +66 -0
- data/lib/generators/light_service/templates/action_spec_template.erb +31 -0
- data/lib/generators/light_service/templates/action_template.erb +30 -0
- data/lib/generators/light_service/templates/organizer_spec_template.erb +20 -0
- data/lib/generators/light_service/templates/organizer_template.erb +22 -0
- data/lib/light-service.rb +1 -0
- data/lib/light-service/action.rb +3 -0
- data/lib/light-service/context.rb +8 -4
- data/lib/light-service/context/key_verifier.rb +18 -1
- data/lib/light-service/localization_adapter.rb +1 -1
- data/lib/light-service/organizer.rb +27 -0
- data/lib/light-service/organizer/with_reducer.rb +8 -1
- data/lib/light-service/organizer/with_reducer_factory.rb +11 -7
- data/lib/light-service/organizer/with_reducer_log_decorator.rb +5 -2
- data/lib/light-service/version.rb +1 -1
- data/light-service.gemspec +10 -4
- data/spec/acceptance/after_actions_spec.rb +17 -0
- data/spec/acceptance/custom_log_from_organizer_spec.rb +60 -0
- data/spec/acceptance/fail_spec.rb +42 -16
- data/spec/acceptance/organizer/add_aliases_spec.rb +28 -0
- data/spec/acceptance/organizer/add_to_context_spec.rb +57 -0
- data/spec/acceptance/organizer/execute_spec.rb +1 -1
- data/spec/acceptance/organizer/execute_with_add_to_context_spec.rb +28 -0
- data/spec/acceptance/organizer/iterate_spec.rb +7 -0
- data/spec/acceptance/organizer/reduce_if_spec.rb +38 -0
- data/spec/acceptance/organizer/reduce_until_spec.rb +6 -0
- data/spec/action_spec.rb +8 -0
- data/spec/lib/generators/action_generator_advanced_spec.rb +43 -0
- data/spec/lib/generators/action_generator_simple_spec.rb +37 -0
- data/spec/lib/generators/full_generator_test_blobs.rb +193 -0
- data/spec/lib/generators/organizer_generator_advanced_spec.rb +37 -0
- data/spec/lib/generators/organizer_generator_simple_spec.rb +37 -0
- data/spec/organizer_spec.rb +21 -0
- data/spec/sample/provides_free_shipping_action_spec.rb +1 -1
- data/spec/spec_helper.rb +7 -2
- data/spec/test_doubles.rb +47 -0
- metadata +111 -21
- data/gemfiles/activesupport_3.gemfile.lock +0 -76
- data/gemfiles/activesupport_4.gemfile +0 -8
- data/gemfiles/activesupport_4.gemfile.lock +0 -82
- data/gemfiles/activesupport_5.gemfile.lock +0 -82
- 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
|
data/spec/organizer_spec.rb
CHANGED
@@ -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
|
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
|