light-service 0.3.6 → 0.4.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/README.md +66 -33
- data/RELEASES.md +39 -0
- data/lib/light-service.rb +6 -0
- data/lib/light-service/configuration.rb +19 -0
- data/lib/light-service/context_key_verifier.rb +8 -2
- data/lib/light-service/organizer.rb +8 -8
- data/lib/light-service/organizer/with_reducer.rb +21 -0
- data/lib/light-service/organizer/with_reducer_factory.rb +14 -0
- data/lib/light-service/organizer/with_reducer_log_decorator.rb +65 -0
- data/lib/light-service/version.rb +1 -1
- data/spec/acceptance/add_numbers_spec.rb +7 -8
- data/spec/acceptance/log_from_organizer_spec.rb +116 -0
- data/spec/action_expected_keys_spec.rb +25 -45
- data/spec/action_expects_and_promises_spec.rb +68 -70
- data/spec/action_promised_keys_spec.rb +53 -64
- data/spec/action_spec.rb +45 -58
- data/spec/context_spec.rb +86 -87
- data/spec/organizer_spec.rb +12 -29
- data/spec/sample/calculates_tax_spec.rb +2 -1
- data/spec/test_doubles.rb +132 -0
- metadata +11 -2
data/spec/context_spec.rb
CHANGED
@@ -1,125 +1,124 @@
|
|
1
1
|
require "spec_helper"
|
2
|
+
require 'test_doubles'
|
2
3
|
|
3
|
-
|
4
|
-
describe Context do
|
4
|
+
describe LightService::Context do
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
describe "can be made" do
|
7
|
+
context "with no arguments" do
|
8
|
+
subject { LightService::Context.make }
|
9
|
+
it { is_expected.to be_success }
|
10
|
+
its(:message) { should be_empty }
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
context "with a hash" do
|
14
|
+
it "has the hash values" do
|
15
|
+
context = LightService::Context.make(:one => 1)
|
16
16
|
|
17
|
-
|
18
|
-
end
|
17
|
+
expect(context[:one]).to eq(1)
|
19
18
|
end
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
context "with FAILURE" do
|
22
|
+
it "is failed" do
|
23
|
+
context = LightService::Context.new({}, ::LightService::Outcomes::FAILURE, '')
|
24
24
|
|
25
|
-
|
26
|
-
end
|
25
|
+
expect(context).to be_failure
|
27
26
|
end
|
28
27
|
end
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
30
|
+
describe "can't be made" do
|
31
|
+
specify "with invalid parameters" do
|
32
|
+
expect{LightService::Context.make([])}.to raise_error(ArgumentError)
|
34
33
|
end
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
it "can be asked for success?" do
|
37
|
+
context = LightService::Context.new({}, ::LightService::Outcomes::SUCCESS)
|
38
38
|
|
39
|
-
|
40
|
-
|
39
|
+
expect(context).to be_success
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
it "can be asked for failure?" do
|
43
|
+
context = LightService::Context.new({}, ::LightService::Outcomes::FAILURE)
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
it "can be asked for skip_all?" do
|
49
|
-
context = Context.make
|
50
|
-
context.skip_all!
|
45
|
+
expect(context).to be_failure
|
46
|
+
end
|
51
47
|
|
52
|
-
|
53
|
-
|
48
|
+
it "can be asked for skip_all?" do
|
49
|
+
context = LightService::Context.make
|
50
|
+
context.skip_all!
|
54
51
|
|
55
|
-
|
56
|
-
|
57
|
-
context.succeed!("a happy end")
|
52
|
+
expect(context.skip_all?).to be_truthy
|
53
|
+
end
|
58
54
|
|
59
|
-
|
60
|
-
|
55
|
+
it "can be pushed into a SUCCESS state" do
|
56
|
+
context = LightService::Context.make
|
57
|
+
context.succeed!("a happy end")
|
61
58
|
|
62
|
-
|
63
|
-
|
64
|
-
context.succeed!
|
59
|
+
expect(context).to be_success
|
60
|
+
end
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
62
|
+
it "can be pushed into a SUCCESS state without a message" do
|
63
|
+
context = LightService::Context.make
|
64
|
+
context.succeed!
|
69
65
|
|
70
|
-
|
71
|
-
|
72
|
-
|
66
|
+
expect(context).to be_success
|
67
|
+
expect(context.message).to be_nil
|
68
|
+
end
|
73
69
|
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
it "can be pushed into a FAILURE state without a message" do
|
71
|
+
context = LightService::Context.make
|
72
|
+
context.fail!
|
77
73
|
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
expect(context).to be_failure
|
75
|
+
expect(context.message).to be_nil
|
76
|
+
end
|
81
77
|
|
82
|
-
|
83
|
-
|
78
|
+
it "can be pushed into a FAILURE state with a message" do
|
79
|
+
context = LightService::Context.make
|
80
|
+
context.fail!("a sad end")
|
84
81
|
|
85
|
-
|
86
|
-
|
87
|
-
context.fail!("a sad end")
|
82
|
+
expect(context).to be_failure
|
83
|
+
end
|
88
84
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
85
|
+
it "can be pushed into a FAILURE state with a message in an options hash" do
|
86
|
+
context = LightService::Context.make
|
87
|
+
context.fail!("a sad end")
|
93
88
|
|
94
|
-
|
95
|
-
|
96
|
-
|
89
|
+
expect(context).to be_failure
|
90
|
+
expect(context.message).to eq("a sad end")
|
91
|
+
expect(context.error_code).to be_nil
|
92
|
+
end
|
97
93
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
94
|
+
it "can be pushed into a FAILURE state with an error code in an options hash" do
|
95
|
+
context = LightService::Context.make
|
96
|
+
context.fail!("a sad end", 10005)
|
102
97
|
|
103
|
-
|
104
|
-
|
105
|
-
|
98
|
+
expect(context).to be_failure
|
99
|
+
expect(context.message).to eq("a sad end")
|
100
|
+
expect(context.error_code).to eq(10005)
|
101
|
+
end
|
106
102
|
|
107
|
-
|
108
|
-
|
103
|
+
it "can set a flag to skip all subsequent actions" do
|
104
|
+
context = LightService::Context.make
|
105
|
+
context.skip_all!
|
109
106
|
|
110
|
-
context
|
111
|
-
|
107
|
+
expect(context).to be_skip_all
|
108
|
+
end
|
112
109
|
|
113
|
-
|
114
|
-
|
115
|
-
expect(context.stop_processing?).to be_truthy
|
116
|
-
end
|
110
|
+
context "stopping additional processing in an action" do
|
111
|
+
let(:context) { LightService::Context.make }
|
117
112
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
113
|
+
it "flags processing to stop on failure" do
|
114
|
+
context.fail!("on purpose")
|
115
|
+
expect(context.stop_processing?).to be_truthy
|
122
116
|
end
|
123
117
|
|
118
|
+
it "flags processing to stop when remaining actions should be skipped" do
|
119
|
+
context.skip_all!
|
120
|
+
expect(context.stop_processing?).to be_truthy
|
121
|
+
end
|
124
122
|
end
|
123
|
+
|
125
124
|
end
|
data/spec/organizer_spec.rb
CHANGED
@@ -1,77 +1,60 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'test_doubles'
|
2
3
|
|
3
4
|
describe LightService::Organizer do
|
4
|
-
class AnAction; end
|
5
|
-
class AnotherAction; end
|
6
5
|
|
7
|
-
|
8
|
-
include LightService::Organizer
|
9
|
-
|
10
|
-
def self.do_something(action_arguments)
|
11
|
-
with(action_arguments).reduce([AnAction, AnotherAction])
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.do_something_with_no_actions(action_arguments)
|
15
|
-
with(action_arguments).reduce
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.do_something_with_no_starting_context
|
19
|
-
reduce([AnAction, AnotherAction])
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
let(:context) { ::LightService::Context.make(user: user) }
|
6
|
+
let(:context) { LightService::Context.make(:user => user) }
|
24
7
|
let(:user) { double(:user) }
|
25
8
|
|
26
9
|
context "when #with is called with hash" do
|
27
10
|
before do
|
28
|
-
expect(AnAction).to receive(:execute) \
|
11
|
+
expect(TestDoubles::AnAction).to receive(:execute) \
|
29
12
|
.with(context) \
|
30
13
|
.and_return context
|
31
|
-
expect(AnotherAction).to receive(:execute) \
|
14
|
+
expect(TestDoubles::AnotherAction).to receive(:execute) \
|
32
15
|
.with(context) \
|
33
16
|
.and_return context
|
34
17
|
end
|
35
18
|
|
36
19
|
it "implicitly creates a Context" do
|
37
|
-
result = AnOrganizer.do_something(:user => user)
|
20
|
+
result = TestDoubles::AnOrganizer.do_something(:user => user)
|
38
21
|
expect(result).to eq(context)
|
39
22
|
end
|
40
23
|
end
|
41
24
|
|
42
25
|
context "when #with is called with Context" do
|
43
26
|
before do
|
44
|
-
expect(AnAction).to receive(:execute) \
|
27
|
+
expect(TestDoubles::AnAction).to receive(:execute) \
|
45
28
|
.with(context) \
|
46
29
|
.and_return context
|
47
|
-
expect(AnotherAction).to receive(:execute) \
|
30
|
+
expect(TestDoubles::AnotherAction).to receive(:execute) \
|
48
31
|
.with(context) \
|
49
32
|
.and_return context
|
50
33
|
end
|
51
34
|
|
52
35
|
it "uses that Context without recreating it" do
|
53
|
-
result = AnOrganizer.do_something(context)
|
36
|
+
result = TestDoubles::AnOrganizer.do_something(context)
|
54
37
|
expect(result).to eq(context)
|
55
38
|
end
|
56
39
|
end
|
57
40
|
|
58
41
|
context "when no Actions are specified" do
|
59
42
|
it "throws a Runtime error" do
|
60
|
-
expect { AnOrganizer.do_something_with_no_actions(context) }.to \
|
43
|
+
expect { TestDoubles::AnOrganizer.do_something_with_no_actions(context) }.to \
|
61
44
|
raise_error RuntimeError, "No action(s) were provided"
|
62
45
|
end
|
63
46
|
end
|
64
47
|
|
65
48
|
context "when no starting context is specified" do
|
66
49
|
it "creates one implicitly" do
|
67
|
-
expect(AnAction).to receive(:execute) \
|
50
|
+
expect(TestDoubles::AnAction).to receive(:execute) \
|
68
51
|
.with({}) \
|
69
52
|
.and_return(context)
|
70
|
-
expect(AnotherAction).to receive(:execute) \
|
53
|
+
expect(TestDoubles::AnotherAction).to receive(:execute) \
|
71
54
|
.with(context) \
|
72
55
|
.and_return(context)
|
73
56
|
|
74
|
-
expect { AnOrganizer.do_something_with_no_starting_context } \
|
57
|
+
expect { TestDoubles::AnOrganizer.do_something_with_no_starting_context } \
|
75
58
|
.not_to raise_error
|
76
59
|
end
|
77
60
|
end
|
@@ -6,7 +6,8 @@ require_relative 'tax/provides_free_shipping_action'
|
|
6
6
|
|
7
7
|
describe CalculatesTax do
|
8
8
|
let(:order) { double('order') }
|
9
|
-
let(:context) { double('context'
|
9
|
+
let(:context) { double('context', :keys => [:user],
|
10
|
+
:failure? => false, :skip_all? => false) }
|
10
11
|
|
11
12
|
it "calls the actions in order" do
|
12
13
|
allow(::LightService::Context).to receive(:make) \
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# A collection of Action and Organizer dummies used in specs
|
2
|
+
|
3
|
+
module TestDoubles
|
4
|
+
class AddsTwoAction
|
5
|
+
include LightService::Action
|
6
|
+
|
7
|
+
executed do |context|
|
8
|
+
number = context.fetch(:number, 0)
|
9
|
+
context[:number] = number + 2
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class AnAction; end
|
14
|
+
class AnotherAction; end
|
15
|
+
|
16
|
+
class AnOrganizer
|
17
|
+
include LightService::Organizer
|
18
|
+
|
19
|
+
def self.do_something(action_arguments)
|
20
|
+
with(action_arguments).reduce([AnAction, AnotherAction])
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.do_something_with_no_actions(action_arguments)
|
24
|
+
with(action_arguments).reduce
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.do_something_with_no_starting_context
|
28
|
+
reduce([AnAction, AnotherAction])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class MakesTeaWithMilkAction
|
33
|
+
include LightService::Action
|
34
|
+
expects :tea, :milk
|
35
|
+
promises :milk_tea
|
36
|
+
|
37
|
+
executed do |context|
|
38
|
+
context.milk_tea = "#{context.tea} - #{context.milk}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class MultipleExpectsAction
|
43
|
+
include LightService::Action
|
44
|
+
expects :tea
|
45
|
+
expects :milk, :chocolate
|
46
|
+
promises :milk_tea
|
47
|
+
|
48
|
+
executed do |context|
|
49
|
+
context.milk_tea = "#{context.tea} - #{context.milk} - with #{context.chocolate}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class MakesCappuccinoAction
|
54
|
+
include LightService::Action
|
55
|
+
expects :coffee, :milk
|
56
|
+
promises :cappuccino
|
57
|
+
end
|
58
|
+
|
59
|
+
class MakesLatteAction
|
60
|
+
include LightService::Action
|
61
|
+
expects :coffee, :milk
|
62
|
+
promises :latte
|
63
|
+
|
64
|
+
executed do |context|
|
65
|
+
if context.milk == :very_hot
|
66
|
+
context.fail!("Can't make a latte from a milk that's too hot!")
|
67
|
+
next context
|
68
|
+
end
|
69
|
+
|
70
|
+
context[:latte] = "#{context.coffee} - with lots of #{context.milk}"
|
71
|
+
|
72
|
+
if context.milk == "5%"
|
73
|
+
context.skip_all!("Can't make a latte with a fatty milk like that!")
|
74
|
+
next context
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class MultiplePromisesAction
|
80
|
+
include LightService::Action
|
81
|
+
expects :coffee, :milk
|
82
|
+
promises :cappuccino
|
83
|
+
promises :latte
|
84
|
+
|
85
|
+
executed do |context|
|
86
|
+
context.cappuccino = "Cappucino needs #{context.coffee} and a little milk"
|
87
|
+
context.latte = "Latte needs #{context.coffee} and a lot of milk"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class MakesTeaAndCappuccino
|
92
|
+
include LightService::Organizer
|
93
|
+
|
94
|
+
def self.call(tea, milk, coffee)
|
95
|
+
with(:tea => tea, :milk => milk, :coffee => coffee)
|
96
|
+
.reduce(TestDoubles::MakesTeaWithMilkAction,
|
97
|
+
TestDoubles::MakesLatteAction)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class MakesCappuccinoAddsTwo
|
102
|
+
include LightService::Organizer
|
103
|
+
|
104
|
+
def self.call(milk, coffee)
|
105
|
+
with(:milk => milk, :coffee => coffee)
|
106
|
+
.reduce(TestDoubles::AddsTwoAction,
|
107
|
+
TestDoubles::MakesLatteAction)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class MakesCappuccinoAddsTwoAndFails
|
112
|
+
include LightService::Organizer
|
113
|
+
|
114
|
+
def self.call(coffee)
|
115
|
+
with(:milk => :very_hot, :coffee => coffee)
|
116
|
+
.reduce(TestDoubles::MakesLatteAction,
|
117
|
+
TestDoubles::AddsTwoAction)
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class MakesCappuccinoSkipsAddsTwo
|
123
|
+
include LightService::Organizer
|
124
|
+
|
125
|
+
def self.call(coffee)
|
126
|
+
with(:milk => "5%", :coffee => coffee)
|
127
|
+
.reduce(TestDoubles::MakesLatteAction,
|
128
|
+
TestDoubles::AddsTwoAction)
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: light-service
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Attila Domokos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -79,17 +79,23 @@ files:
|
|
79
79
|
- Gemfile
|
80
80
|
- LICENSE
|
81
81
|
- README.md
|
82
|
+
- RELEASES.md
|
82
83
|
- Rakefile
|
83
84
|
- lib/light-service.rb
|
84
85
|
- lib/light-service/action.rb
|
86
|
+
- lib/light-service/configuration.rb
|
85
87
|
- lib/light-service/context.rb
|
86
88
|
- lib/light-service/context_key_verifier.rb
|
87
89
|
- lib/light-service/organizer.rb
|
90
|
+
- lib/light-service/organizer/with_reducer.rb
|
91
|
+
- lib/light-service/organizer/with_reducer_factory.rb
|
92
|
+
- lib/light-service/organizer/with_reducer_log_decorator.rb
|
88
93
|
- lib/light-service/version.rb
|
89
94
|
- light-service.gemspec
|
90
95
|
- resources/light-service.png
|
91
96
|
- resources/organizer_and_actions.png
|
92
97
|
- spec/acceptance/add_numbers_spec.rb
|
98
|
+
- spec/acceptance/log_from_organizer_spec.rb
|
93
99
|
- spec/action_expected_keys_spec.rb
|
94
100
|
- spec/action_expects_and_promises_spec.rb
|
95
101
|
- spec/action_promised_keys_spec.rb
|
@@ -105,6 +111,7 @@ files:
|
|
105
111
|
- spec/sample/tax/looks_up_tax_percentage_action.rb
|
106
112
|
- spec/sample/tax/provides_free_shipping_action.rb
|
107
113
|
- spec/spec_helper.rb
|
114
|
+
- spec/test_doubles.rb
|
108
115
|
homepage: https://github.com/adomokos/light-service
|
109
116
|
licenses:
|
110
117
|
- MIT
|
@@ -131,6 +138,7 @@ specification_version: 4
|
|
131
138
|
summary: A service skeleton with an emphasis on simplicity
|
132
139
|
test_files:
|
133
140
|
- spec/acceptance/add_numbers_spec.rb
|
141
|
+
- spec/acceptance/log_from_organizer_spec.rb
|
134
142
|
- spec/action_expected_keys_spec.rb
|
135
143
|
- spec/action_expects_and_promises_spec.rb
|
136
144
|
- spec/action_promised_keys_spec.rb
|
@@ -146,3 +154,4 @@ test_files:
|
|
146
154
|
- spec/sample/tax/looks_up_tax_percentage_action.rb
|
147
155
|
- spec/sample/tax/provides_free_shipping_action.rb
|
148
156
|
- spec/spec_helper.rb
|
157
|
+
- spec/test_doubles.rb
|