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.
- checksums.yaml +4 -4
- data/.github/workflows/project-build.yml +28 -0
- data/.travis.yml +3 -9
- data/Appraisals +0 -4
- data/Gemfile +0 -2
- data/README.md +287 -51
- data/RELEASES.md +21 -2
- data/gemfiles/activesupport_5.gemfile +0 -1
- data/gemfiles/activesupport_6.gemfile +0 -1
- 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/action.rb +61 -4
- data/lib/light-service/context/key_verifier.rb +18 -1
- data/lib/light-service/context.rb +5 -3
- data/lib/light-service/errors.rb +1 -0
- data/lib/light-service/organizer/reduce_if_else.rb +21 -0
- data/lib/light-service/organizer/with_reducer.rb +12 -7
- data/lib/light-service/organizer/with_reducer_factory.rb +1 -1
- data/lib/light-service/organizer/with_reducer_log_decorator.rb +3 -0
- data/lib/light-service/organizer.rb +16 -3
- data/lib/light-service/version.rb +1 -1
- data/lib/light-service.rb +1 -0
- data/light-service.gemspec +6 -1
- data/spec/acceptance/after_actions_spec.rb +17 -0
- data/spec/acceptance/around_each_spec.rb +15 -0
- data/spec/acceptance/log_from_organizer_spec.rb +1 -1
- data/spec/acceptance/organizer/add_to_context_spec.rb +27 -0
- 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_else_spec.rb +60 -0
- data/spec/acceptance/organizer/reduce_if_spec.rb +6 -0
- data/spec/acceptance/organizer/reduce_until_spec.rb +6 -0
- data/spec/action_optional_expected_keys_spec.rb +82 -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 +5 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/test_doubles.rb +37 -0
- metadata +87 -9
- data/gemfiles/activesupport_3.gemfile +0 -8
- data/gemfiles/activesupport_4.gemfile +0 -8
- 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
|