light-service 0.8.4 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -2
  3. data/README.md +149 -52
  4. data/RELEASES.md +6 -0
  5. data/gemfiles/activesupport_3.gemfile +1 -1
  6. data/gemfiles/activesupport_4.gemfile +1 -1
  7. data/gemfiles/activesupport_5.gemfile +1 -1
  8. data/lib/light-service.rb +7 -0
  9. data/lib/light-service/action.rb +22 -2
  10. data/lib/light-service/orchestrator.rb +21 -3
  11. data/lib/light-service/organizer.rb +42 -20
  12. data/lib/light-service/organizer/execute.rb +14 -0
  13. data/lib/light-service/organizer/iterate.rb +22 -0
  14. data/lib/light-service/organizer/reduce_if.rb +17 -0
  15. data/lib/light-service/organizer/reduce_until.rb +20 -0
  16. data/lib/light-service/organizer/scoped_reducable.rb +13 -0
  17. data/lib/light-service/organizer/verify_call_method_exists.rb +28 -0
  18. data/lib/light-service/organizer/with_callback.rb +26 -0
  19. data/lib/light-service/organizer/with_reducer.rb +14 -4
  20. data/lib/light-service/organizer/with_reducer_factory.rb +2 -0
  21. data/lib/light-service/version.rb +1 -1
  22. data/light-service.gemspec +2 -2
  23. data/resources/orchestrators_deprecated.svg +10 -0
  24. data/spec/acceptance/add_numbers_spec.rb +3 -3
  25. data/spec/acceptance/after_actions_spec.rb +67 -0
  26. data/spec/acceptance/before_actions_spec.rb +109 -0
  27. data/spec/acceptance/orchestrator/context_failure_and_skipping_spec.rb +12 -10
  28. data/spec/acceptance/orchestrator/execute_spec.rb +8 -6
  29. data/spec/acceptance/orchestrator/iterate_spec.rb +9 -7
  30. data/spec/acceptance/orchestrator/organizer_action_combination_spec.rb +13 -11
  31. data/spec/acceptance/orchestrator/reduce_if_spec.rb +9 -7
  32. data/spec/acceptance/orchestrator/reduce_until_spec.rb +7 -5
  33. data/spec/acceptance/orchestrator/with_callback_spec.rb +8 -6
  34. data/spec/acceptance/organizer/around_each_with_reduce_if_spec.rb +42 -0
  35. data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +65 -0
  36. data/spec/acceptance/organizer/execute_spec.rb +46 -0
  37. data/spec/acceptance/organizer/iterate_spec.rb +37 -0
  38. data/spec/acceptance/organizer/reduce_if_spec.rb +51 -0
  39. data/spec/acceptance/organizer/reduce_until_spec.rb +43 -0
  40. data/spec/acceptance/organizer/with_callback_spec.rb +110 -0
  41. data/spec/organizer/with_reducer_spec.rb +2 -7
  42. data/spec/sample/calculates_tax_spec.rb +1 -4
  43. data/spec/spec_helper.rb +12 -0
  44. data/spec/support.rb +9 -0
  45. data/spec/test_doubles.rb +84 -17
  46. metadata +34 -6
@@ -2,24 +2,26 @@ require 'spec_helper'
2
2
  require 'test_doubles'
3
3
 
4
4
  describe LightService::Orchestrator do
5
- class TestSkipState
5
+ include_context 'expect orchestrator warning'
6
+
7
+ class OrchestratorTestSkipState
6
8
  extend LightService::Orchestrator
7
9
  def self.run_skip_before
8
10
  with(:number => 1).reduce([
9
11
  TestDoubles::SkipAllAction,
10
12
  reduce_until(->(ctx) { ctx.number == 3 },
11
- TestDoubles::AddOneAction)
13
+ TestDoubles::AddsOneAction)
12
14
  ])
13
15
  end
14
16
 
15
17
  def self.run_skip_after
16
18
  with(:number => 1).reduce([
17
- TestDoubles::AddOneAction,
19
+ TestDoubles::AddsOneAction,
18
20
  reduce_until(->(ctx) { ctx.number == 3 }, [
19
- TestDoubles::AddOneAction
21
+ TestDoubles::AddsOneAction
20
22
  ]),
21
23
  TestDoubles::SkipAllAction,
22
- TestDoubles::AddOneAction
24
+ TestDoubles::AddsOneAction
23
25
  ])
24
26
  end
25
27
 
@@ -27,28 +29,28 @@ describe LightService::Orchestrator do
27
29
  with(:number => 1).reduce([
28
30
  TestDoubles::FailureAction,
29
31
  reduce_until(->(ctx) { ctx[:number] == 3 },
30
- TestDoubles::AddOneAction),
31
- TestDoubles::AddOneAction
32
+ TestDoubles::AddsOneAction),
33
+ TestDoubles::AddsOneAction
32
34
  ])
33
35
  end
34
36
  end
35
37
 
36
38
  it 'skips all the rest of the actions' do
37
- result = TestSkipState.run_skip_before
39
+ result = OrchestratorTestSkipState.run_skip_before
38
40
 
39
41
  expect(result).to be_success
40
42
  expect(result[:number]).to eq(1)
41
43
  end
42
44
 
43
45
  it 'skips after an action in nested context' do
44
- result = TestSkipState.run_skip_after
46
+ result = OrchestratorTestSkipState.run_skip_after
45
47
 
46
48
  expect(result).to be_success
47
49
  expect(result[:number]).to eq(3)
48
50
  end
49
51
 
50
52
  it 'respects failure across all nestings' do
51
- result = TestSkipState.run_failure
53
+ result = OrchestratorTestSkipState.run_failure
52
54
 
53
55
  expect(result).to be_failure
54
56
  expect(result[:number]).to eq(1)
@@ -2,7 +2,9 @@ require 'spec_helper'
2
2
  require 'test_doubles'
3
3
 
4
4
  describe LightService::Orchestrator do
5
- class TestExecute
5
+ include_context 'expect orchestrator warning'
6
+
7
+ class OrchestratorTestExecute
6
8
  extend LightService::Orchestrator
7
9
 
8
10
  def self.run(context)
@@ -11,10 +13,10 @@ describe LightService::Orchestrator do
11
13
 
12
14
  def self.steps
13
15
  [
14
- TestDoubles::AddOneAction,
16
+ TestDoubles::AddsOneAction,
15
17
  execute(->(ctx) { ctx.number += 1 }),
16
18
  execute(->(ctx) { ctx[:something] = 'hello' }),
17
- TestDoubles::AddOneAction
19
+ TestDoubles::AddsOneAction
18
20
  ]
19
21
  end
20
22
  end
@@ -22,7 +24,7 @@ describe LightService::Orchestrator do
22
24
  let(:empty_context) { LightService::Context.make }
23
25
 
24
26
  it 'calls the lambda in the execute block using the context' do
25
- result = TestExecute.run(:number => 0)
27
+ result = OrchestratorTestExecute.run(:number => 0)
26
28
 
27
29
  expect(result).to be_success
28
30
  expect(result.number).to eq(3)
@@ -32,7 +34,7 @@ describe LightService::Orchestrator do
32
34
  it 'will not execute a failed context' do
33
35
  empty_context.fail!('Something bad happened')
34
36
 
35
- result = TestExecute.run(empty_context)
37
+ result = OrchestratorTestExecute.run(empty_context)
36
38
 
37
39
  expect(result).to be_failure
38
40
  end
@@ -40,7 +42,7 @@ describe LightService::Orchestrator do
40
42
  it 'does not execute over a skipped context' do
41
43
  empty_context.skip_remaining!('No more needed')
42
44
 
43
- result = TestExecute.run(empty_context)
45
+ result = OrchestratorTestExecute.run(empty_context)
44
46
  expect(result).to be_success
45
47
  end
46
48
  end
@@ -2,20 +2,22 @@ require 'spec_helper'
2
2
  require 'test_doubles'
3
3
 
4
4
  describe LightService::Orchestrator do
5
- class TestIterate
5
+ include_context 'expect orchestrator warning'
6
+
7
+ class OrchestratorTestIterate
6
8
  extend LightService::Orchestrator
7
9
 
8
10
  def self.run(context)
9
11
  with(context).reduce([
10
12
  iterate(:numbers, [
11
- TestDoubles::AddOneAction
13
+ TestDoubles::AddsOneAction
12
14
  ])
13
15
  ])
14
16
  end
15
17
 
16
18
  def self.run_single(context)
17
19
  with(context).reduce([
18
- iterate(:numbers, TestDoubles::AddOneAction)
20
+ iterate(:numbers, TestDoubles::AddsOneAction)
19
21
  ])
20
22
  end
21
23
  end
@@ -23,14 +25,14 @@ describe LightService::Orchestrator do
23
25
  let(:empty_context) { LightService::Context.make }
24
26
 
25
27
  it 'reduces each item of a collection and singularizes the collection key' do
26
- result = TestIterate.run(:numbers => [1, 2, 3, 4])
28
+ result = OrchestratorTestIterate.run(:numbers => [1, 2, 3, 4])
27
29
 
28
30
  expect(result).to be_success
29
31
  expect(result.number).to eq(5)
30
32
  end
31
33
 
32
34
  it 'accepts a single action or organizer' do
33
- result = TestIterate.run_single(:numbers => [1, 2, 3, 4])
35
+ result = OrchestratorTestIterate.run_single(:numbers => [1, 2, 3, 4])
34
36
 
35
37
  expect(result).to be_success
36
38
  expect(result.number).to eq(5)
@@ -39,7 +41,7 @@ describe LightService::Orchestrator do
39
41
  it 'will not iterate over a failed context' do
40
42
  empty_context.fail!('Something bad happened')
41
43
 
42
- result = TestIterate.run(empty_context)
44
+ result = OrchestratorTestIterate.run(empty_context)
43
45
 
44
46
  expect(result).to be_failure
45
47
  end
@@ -47,7 +49,7 @@ describe LightService::Orchestrator do
47
49
  it 'does not iterate over a skipped context' do
48
50
  empty_context.skip_remaining!('No more needed')
49
51
 
50
- result = TestIterate.run(empty_context)
52
+ result = OrchestratorTestIterate.run(empty_context)
51
53
  expect(result).to be_success
52
54
  end
53
55
  end
@@ -2,7 +2,9 @@ require 'spec_helper'
2
2
  require 'test_doubles'
3
3
 
4
4
  describe LightService::Orchestrator do
5
- class TestReduce
5
+ include_context 'expect orchestrator warning'
6
+
7
+ class OrchestratorTestReduce
6
8
  extend LightService::Orchestrator
7
9
 
8
10
  def self.run(context, steps)
@@ -11,21 +13,21 @@ describe LightService::Orchestrator do
11
13
  end
12
14
 
13
15
  it 'responds to both actions and organizers' do
14
- result = TestReduce.run({ :number => 0 }, [
15
- TestDoubles::AddTwoOrganizer,
16
- TestDoubles::AddOneAction
17
- ])
16
+ result = OrchestratorTestReduce.run({ :number => 0 }, [
17
+ TestDoubles::AddTwoOrganizer,
18
+ TestDoubles::AddsOneAction
19
+ ])
18
20
 
19
21
  expect(result).to be_success
20
22
  expect(result.number).to eq(3)
21
23
  end
22
24
 
23
25
  it 'fails fast by skipping proceeding actions/organizers after failure' do
24
- result = TestReduce.run({ :number => 0 }, [
25
- TestDoubles::AddTwoOrganizer,
26
- TestDoubles::FailureAction,
27
- TestDoubles::AddOneAction
28
- ])
26
+ result = OrchestratorTestReduce.run({ :number => 0 }, [
27
+ TestDoubles::AddTwoOrganizer,
28
+ TestDoubles::FailureAction,
29
+ TestDoubles::AddsOneAction
30
+ ])
29
31
 
30
32
  expect(result).not_to be_success
31
33
  expect(result.number).to eq(2)
@@ -33,7 +35,7 @@ describe LightService::Orchestrator do
33
35
 
34
36
  it 'does not allow anything but actions and organizers' do
35
37
  expect do
36
- TestReduce.run({}, [double])
38
+ OrchestratorTestReduce.run({}, [double])
37
39
  end.to raise_error(RuntimeError)
38
40
  end
39
41
  end
@@ -2,7 +2,9 @@ require 'spec_helper'
2
2
  require 'test_doubles'
3
3
 
4
4
  describe LightService::Orchestrator do
5
- class TestReduceIf
5
+ include_context 'expect orchestrator warning'
6
+
7
+ class OrchestratorTestReduceIf
6
8
  extend LightService::Orchestrator
7
9
 
8
10
  def self.run(context)
@@ -11,9 +13,9 @@ describe LightService::Orchestrator do
11
13
 
12
14
  def self.steps
13
15
  [
14
- TestDoubles::AddOneAction,
16
+ TestDoubles::AddsOneAction,
15
17
  reduce_if(->(ctx) { ctx.number == 1 },
16
- TestDoubles::AddOneAction)
18
+ TestDoubles::AddsOneAction)
17
19
  ]
18
20
  end
19
21
  end
@@ -21,14 +23,14 @@ describe LightService::Orchestrator do
21
23
  let(:empty_context) { LightService::Context.make }
22
24
 
23
25
  it 'reduces if the block evaluates to true' do
24
- result = TestReduceIf.run(:number => 0)
26
+ result = OrchestratorTestReduceIf.run(:number => 0)
25
27
 
26
28
  expect(result).to be_success
27
29
  expect(result[:number]).to eq(2)
28
30
  end
29
31
 
30
32
  it 'does not reduce if the block evaluates to false' do
31
- result = TestReduceIf.run(:number => 2)
33
+ result = OrchestratorTestReduceIf.run(:number => 2)
32
34
 
33
35
  expect(result).to be_success
34
36
  expect(result[:number]).to eq(3)
@@ -37,7 +39,7 @@ describe LightService::Orchestrator do
37
39
  it 'will not reduce over a failed context' do
38
40
  empty_context.fail!('Something bad happened')
39
41
 
40
- result = TestReduceIf.run(empty_context)
42
+ result = OrchestratorTestReduceIf.run(empty_context)
41
43
 
42
44
  expect(result).to be_failure
43
45
  end
@@ -45,7 +47,7 @@ describe LightService::Orchestrator do
45
47
  it 'does not reduce over a skipped context' do
46
48
  empty_context.skip_remaining!('No more needed')
47
49
 
48
- result = TestReduceIf.run(empty_context)
50
+ result = OrchestratorTestReduceIf.run(empty_context)
49
51
  expect(result).to be_success
50
52
  end
51
53
  end
@@ -2,7 +2,9 @@ require 'spec_helper'
2
2
  require 'test_doubles'
3
3
 
4
4
  RSpec.describe LightService::Orchestrator do
5
- class TestReduceUntil
5
+ include_context 'expect orchestrator warning'
6
+
7
+ class OrchestratorTestReduceUntil
6
8
  extend LightService::Orchestrator
7
9
 
8
10
  def self.run(context)
@@ -12,7 +14,7 @@ RSpec.describe LightService::Orchestrator do
12
14
  def self.steps
13
15
  [
14
16
  reduce_until(->(ctx) { ctx.number == 3 },
15
- TestDoubles::AddOneAction)
17
+ TestDoubles::AddsOneAction)
16
18
  ]
17
19
  end
18
20
  end
@@ -21,7 +23,7 @@ RSpec.describe LightService::Orchestrator do
21
23
 
22
24
  it 'reduces until the block evaluates to true' do
23
25
  context = { :number => 1 }
24
- result = TestReduceUntil.run(context)
26
+ result = OrchestratorTestReduceUntil.run(context)
25
27
 
26
28
  expect(result).to be_success
27
29
  expect(result.number).to eq(3)
@@ -30,14 +32,14 @@ RSpec.describe LightService::Orchestrator do
30
32
  it 'does not execute on failed context' do
31
33
  empty_context.fail!('Something bad happened')
32
34
 
33
- result = TestReduceUntil.run(empty_context)
35
+ result = OrchestratorTestReduceUntil.run(empty_context)
34
36
  expect(result).to be_failure
35
37
  end
36
38
 
37
39
  it 'does not execute a skipped context' do
38
40
  empty_context.skip_remaining!('No more needed')
39
41
 
40
- result = TestReduceUntil.run(empty_context)
42
+ result = OrchestratorTestReduceUntil.run(empty_context)
41
43
  expect(result).to be_success
42
44
  end
43
45
  end
@@ -2,7 +2,9 @@ require 'spec_helper'
2
2
  require 'test_doubles'
3
3
 
4
4
  describe LightService::Orchestrator do
5
- class TestWithCallback
5
+ include_context 'expect orchestrator warning'
6
+
7
+ class OrchestratorTestWithCallback
6
8
  extend LightService::Orchestrator
7
9
 
8
10
  def self.run(context = {})
@@ -63,7 +65,7 @@ describe LightService::Orchestrator do
63
65
 
64
66
  describe 'a simple case with a single callback' do
65
67
  it 'calls the actions defined with callback' do
66
- result = TestWithCallback.run
68
+ result = OrchestratorTestWithCallback.run
67
69
 
68
70
  expect(result.counter).to eq(3)
69
71
  expect(result.total).to eq(6)
@@ -71,7 +73,7 @@ describe LightService::Orchestrator do
71
73
  end
72
74
 
73
75
  describe 'a more complex example with nested callbacks' do
74
- class TestWithNestedCallback
76
+ class OrchestratorTestWithNextedCallback
75
77
  extend LightService::Orchestrator
76
78
 
77
79
  def self.run(context = {})
@@ -127,7 +129,7 @@ describe LightService::Orchestrator do
127
129
  end
128
130
 
129
131
  it 'calls both the action and the nested callbacks' do
130
- result = TestWithNestedCallback.run
132
+ result = OrchestratorTestWithNextedCallback.run
131
133
 
132
134
  expect(result.outer_counter).to eq(2)
133
135
  # Counts and total are the duplicates of
@@ -141,7 +143,7 @@ describe LightService::Orchestrator do
141
143
  end
142
144
 
143
145
  describe 'with failed or skipped context' do
144
- class TestWithFailureCallback
146
+ class OrchestratorTestWithFailureCallback
145
147
  extend LightService::Orchestrator
146
148
 
147
149
  def self.run(context = {})
@@ -159,7 +161,7 @@ describe LightService::Orchestrator do
159
161
  end
160
162
 
161
163
  it 'will not process the routine' do
162
- result = TestWithFailureCallback.run
164
+ result = OrchestratorTestWithFailureCallback.run
163
165
 
164
166
  expect(result).to be_failure
165
167
  expect(result.counter).to eq(1)
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'test_doubles'
3
+
4
+ RSpec.describe LightService::Organizer do
5
+ class TestReduceIfWithAroundEach
6
+ extend LightService::Organizer
7
+
8
+ def self.call(context)
9
+ with(context)
10
+ .around_each(TestDoubles::AroundEachLoggerHandler)
11
+ .reduce(actions)
12
+ end
13
+
14
+ def self.actions
15
+ [
16
+ TestDoubles::AddsOneAction,
17
+ reduce_if(->(ctx) { ctx.number == 1 },
18
+ TestDoubles::AddsOneAction)
19
+ ]
20
+ end
21
+ end
22
+
23
+ it 'can be used to log data' do
24
+ result =
25
+ TestReduceIfWithAroundEach
26
+ .call(:number => 0,
27
+ :logger => TestDoubles::TestLogger.new)
28
+
29
+ expect(result.fetch(:number)).to eq(2)
30
+ expect(result[:logger].logs).to eq(
31
+ [{
32
+ :action => TestDoubles::AddsOneAction,
33
+ :before => 0,
34
+ :after => 1
35
+ }, {
36
+ :action => TestDoubles::AddsOneAction,
37
+ :before => 1,
38
+ :after => 2
39
+ }]
40
+ )
41
+ end
42
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+ require 'test_doubles'
3
+
4
+ RSpec.describe LightService::Organizer do
5
+ class TestSkipBefore
6
+ extend LightService::Organizer
7
+ def self.call
8
+ with(:number => 1)
9
+ .reduce([
10
+ TestDoubles::SkipAllAction,
11
+ reduce_until(->(ctx) { ctx.number == 3 },
12
+ TestDoubles::AddsOneAction)
13
+ ])
14
+ end
15
+ end
16
+
17
+ class TestSkipAfter
18
+ extend LightService::Organizer
19
+ def self.call
20
+ with(:number => 1)
21
+ .reduce([
22
+ TestDoubles::AddsOneAction,
23
+ reduce_until(->(ctx) { ctx.number == 3 }, [
24
+ TestDoubles::AddsOneAction
25
+ ]),
26
+ TestDoubles::SkipAllAction,
27
+ TestDoubles::AddsOneAction
28
+ ])
29
+ end
30
+ end
31
+
32
+ class TestContextFailure
33
+ extend LightService::Organizer
34
+ def self.call
35
+ with(:number => 1)
36
+ .reduce([
37
+ TestDoubles::FailureAction,
38
+ reduce_until(->(ctx) { ctx[:number] == 3 },
39
+ TestDoubles::AddsOneAction),
40
+ TestDoubles::AddsOneAction
41
+ ])
42
+ end
43
+ end
44
+
45
+ it 'skips all the rest of the actions' do
46
+ result = TestSkipBefore.call
47
+
48
+ expect(result).to be_success
49
+ expect(result[:number]).to eq(1)
50
+ end
51
+
52
+ it 'skips after an action in nested context' do
53
+ result = TestSkipAfter.call
54
+
55
+ expect(result).to be_success
56
+ expect(result[:number]).to eq(3)
57
+ end
58
+
59
+ it 'respects failure across all nestings' do
60
+ result = TestContextFailure.call
61
+
62
+ expect(result).to be_failure
63
+ expect(result[:number]).to eq(1)
64
+ end
65
+ end