exel 1.2.1 → 1.5.2

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.
Files changed (66) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +4 -4
  3. data/.gitignore +1 -2
  4. data/.rubocop.yml +23 -14
  5. data/.rubocop_airbnb.yml +2 -0
  6. data/.rubocop_todo.yml +1 -13
  7. data/.travis.yml +26 -0
  8. data/Gemfile +2 -2
  9. data/Gemfile.lock +118 -0
  10. data/Guardfile +1 -0
  11. data/README.md +96 -31
  12. data/Rakefile +2 -0
  13. data/exel.gemspec +7 -7
  14. data/lib/exel.rb +7 -1
  15. data/lib/exel/ast_node.rb +6 -10
  16. data/lib/exel/context.rb +4 -1
  17. data/lib/exel/deferred_context_value.rb +3 -1
  18. data/lib/exel/error/job_termination.rb +12 -0
  19. data/lib/exel/events.rb +6 -0
  20. data/lib/exel/instruction.rb +5 -2
  21. data/lib/exel/instruction_node.rb +2 -0
  22. data/lib/exel/job.rb +8 -4
  23. data/lib/exel/listen_instruction.rb +2 -0
  24. data/lib/exel/logging.rb +24 -1
  25. data/lib/exel/logging/logger_wrapper.rb +31 -0
  26. data/lib/exel/logging_helper.rb +36 -0
  27. data/lib/exel/middleware/chain.rb +67 -0
  28. data/lib/exel/middleware/logging.rb +30 -0
  29. data/lib/exel/null_instruction.rb +2 -0
  30. data/lib/exel/processor_helper.rb +9 -1
  31. data/lib/exel/processors/async_processor.rb +2 -8
  32. data/lib/exel/processors/run_processor.rb +2 -6
  33. data/lib/exel/processors/split_processor.rb +15 -10
  34. data/lib/exel/providers/local_file_provider.rb +9 -6
  35. data/lib/exel/providers/threaded_async_provider.rb +2 -0
  36. data/lib/exel/remote_value.rb +11 -0
  37. data/lib/exel/sequence_node.rb +2 -0
  38. data/lib/exel/value.rb +2 -0
  39. data/lib/exel/version.rb +3 -1
  40. data/spec/exel/ast_node_spec.rb +48 -27
  41. data/spec/exel/context_spec.rb +77 -77
  42. data/spec/exel/deferred_context_value_spec.rb +42 -42
  43. data/spec/exel/events_spec.rb +68 -59
  44. data/spec/exel/instruction_node_spec.rb +17 -16
  45. data/spec/exel/instruction_spec.rb +49 -42
  46. data/spec/exel/job_spec.rb +99 -84
  47. data/spec/exel/listen_instruction_spec.rb +11 -10
  48. data/spec/exel/logging/logger_wrapper_spec.rb +93 -0
  49. data/spec/exel/logging_helper_spec.rb +24 -0
  50. data/spec/exel/logging_spec.rb +69 -24
  51. data/spec/exel/middleware/chain_spec.rb +65 -0
  52. data/spec/exel/middleware/logging_spec.rb +31 -0
  53. data/spec/exel/middleware_spec.rb +68 -0
  54. data/spec/exel/null_instruction_spec.rb +4 -4
  55. data/spec/exel/processors/async_processor_spec.rb +17 -18
  56. data/spec/exel/processors/run_processor_spec.rb +10 -11
  57. data/spec/exel/processors/split_processor_spec.rb +99 -74
  58. data/spec/exel/providers/local_file_provider_spec.rb +26 -28
  59. data/spec/exel/providers/threaded_async_provider_spec.rb +37 -38
  60. data/spec/exel/sequence_node_spec.rb +12 -11
  61. data/spec/exel/value_spec.rb +33 -33
  62. data/spec/exel_spec.rb +9 -7
  63. data/spec/integration/integration_spec.rb +3 -1
  64. data/spec/spec_helper.rb +4 -2
  65. data/spec/support/integration_test_classes.rb +4 -3
  66. metadata +37 -48
@@ -1,65 +1,65 @@
1
- module EXEL
2
- describe DeferredContextValue do
3
- subject(:deferred_value) { DeferredContextValue.new }
1
+ # frozen_string_literal: true
4
2
 
5
- describe '.resolve' do
6
- subject(:deferred_value) { DeferredContextValue.new[:key] }
3
+ describe EXEL::DeferredContextValue do
4
+ subject(:deferred_value) { EXEL::DeferredContextValue.new }
7
5
 
8
- context 'at the top level' do
9
- let(:context) { {key: 'value', deferred_value: deferred_value} }
6
+ describe '.resolve' do
7
+ subject(:deferred_value) { EXEL::DeferredContextValue.new[:key] }
10
8
 
11
- it 'returns the lookup value from the context' do
12
- expect(DeferredContextValue.resolve(context[:deferred_value], context)).to eq(context[:key])
13
- end
9
+ context 'at the top level' do
10
+ let(:context) { {key: 'value', deferred_value: deferred_value} }
11
+
12
+ it 'returns the lookup value from the context' do
13
+ expect(EXEL::DeferredContextValue.resolve(context[:deferred_value], context)).to eq(context[:key])
14
14
  end
15
+ end
15
16
 
16
- context 'in an array' do
17
- let(:context) { {key: 'value', array: [1, 2, deferred_value]} }
17
+ context 'in an array' do
18
+ let(:context) { {key: 'value', array: [1, 2, deferred_value]} }
18
19
 
19
- it 'returns the lookup value from the context' do
20
- expect(DeferredContextValue.resolve(context[:array], context)).to eq([1, 2, context[:key]])
21
- end
20
+ it 'returns the lookup value from the context' do
21
+ expect(EXEL::DeferredContextValue.resolve(context[:array], context)).to eq([1, 2, context[:key]])
22
22
  end
23
+ end
23
24
 
24
- context 'in a hash' do
25
- let(:context) { {key: 'value', hash: {hash_key: deferred_value}} }
25
+ context 'in a hash' do
26
+ let(:context) { {key: 'value', hash: {hash_key: deferred_value}} }
26
27
 
27
- it 'returns the lookup value from the context' do
28
- expect(DeferredContextValue.resolve(context[:hash], context)).to eq(hash_key: context[:key])
29
- end
28
+ it 'returns the lookup value from the context' do
29
+ expect(EXEL::DeferredContextValue.resolve(context[:hash], context)).to eq(hash_key: context[:key])
30
30
  end
31
+ end
31
32
 
32
- context 'in a hash nested in an array' do
33
- let(:context) { {key: 'value', nested: [{}, {hash_key: deferred_value}]} }
33
+ context 'in a hash nested in an array' do
34
+ let(:context) { {key: 'value', nested: [{}, {hash_key: deferred_value}]} }
34
35
 
35
- it 'looks up a deferred context value in a hash nested in an array' do
36
- expect(DeferredContextValue.resolve(context[:nested], context)).to eq([{}, {hash_key: context[:key]}])
37
- end
36
+ it 'looks up a deferred context value in a hash nested in an array' do
37
+ expect(EXEL::DeferredContextValue.resolve(context[:nested], context)).to eq([{}, {hash_key: context[:key]}])
38
38
  end
39
+ end
39
40
 
40
- context 'in an array nested in a hash' do
41
- let(:context) { {key: 'value', nested: {hash_key: [1, deferred_value]}} }
41
+ context 'in an array nested in a hash' do
42
+ let(:context) { {key: 'value', nested: {hash_key: [1, deferred_value]}} }
42
43
 
43
- it 'looks up a deferred context value in an array nested in a hash' do
44
- expect(DeferredContextValue.resolve(context[:nested], context)).to eq(hash_key: [1, context[:key]])
45
- end
44
+ it 'looks up a deferred context value in an array nested in a hash' do
45
+ expect(EXEL::DeferredContextValue.resolve(context[:nested], context)).to eq(hash_key: [1, context[:key]])
46
46
  end
47
47
  end
48
+ end
48
49
 
49
- describe '#[]' do
50
- it 'stores the given key in the keys attribute' do
51
- deferred_value[:top_level_key]['sub_key']
52
- expect(deferred_value.keys).to eq([:top_level_key, 'sub_key'])
53
- end
50
+ describe '#[]' do
51
+ it 'stores the given key in the keys attribute' do
52
+ deferred_value[:top_level_key]['sub_key']
53
+ expect(deferred_value.keys).to eq([:top_level_key, 'sub_key'])
54
54
  end
55
+ end
55
56
 
56
- describe '#get' do
57
- it 'looks up the value of the keys attribute in the passed-in context' do
58
- allow(deferred_value).to receive(:keys).and_return([:top_level_key, 'sub_key'])
59
- value = 'example_value'
60
- context = Context.new(top_level_key: {'sub_key' => value})
61
- expect(deferred_value.get(context)).to eq(value)
62
- end
57
+ describe '#get' do
58
+ it 'looks up the value of the keys attribute in the passed-in context' do
59
+ allow(deferred_value).to receive(:keys).and_return([:top_level_key, 'sub_key'])
60
+ value = 'example_value'
61
+ context = EXEL::Context.new(top_level_key: {'sub_key' => value})
62
+ expect(deferred_value.get(context)).to eq(value)
63
63
  end
64
64
  end
65
65
  end
@@ -1,88 +1,97 @@
1
- module EXEL
2
- describe Events do
3
- class EventTest
4
- include Events
1
+ # frozen_string_literal: true
2
+
3
+ describe EXEL::Events do
4
+ class EventTest
5
+ include EXEL::Events
6
+
7
+ def initialize(context)
8
+ @context = context
5
9
  end
10
+ end
6
11
 
7
- subject(:events) { EventTest.new }
8
- let(:event_listener) { double(:event_listener) }
9
- let(:context) { EXEL::Context.new(Events::LISTENERS_KEY => {event: [event_listener]}) }
12
+ subject(:events) { EventTest.new(context) }
10
13
 
11
- describe '#register_listener' do
12
- context 'when no listeners have been defined' do
13
- let(:context) { EXEL::Context.new }
14
+ let(:event_listener) { double(:event_listener) }
15
+ let(:context) { EXEL::Context.new(EXEL::Events::LISTENERS_KEY => {event: [event_listener]}) }
14
16
 
15
- it 'adds a new listener to the context' do
16
- events.register_listener(context, :event, event_listener)
17
- expect(context[Events::LISTENERS_KEY].fetch(:event)).to contain_exactly(event_listener)
18
- end
19
- end
17
+ it 'defines an attr_reader for context on the class it is included in' do
18
+ expect(events.context).to eq(context)
19
+ end
20
20
 
21
- it 'registers multiple listeners for the same event' do
22
- new_listener = double(:event_listener2)
23
- events.register_listener(context, :event, new_listener)
24
- expect(context[Events::LISTENERS_KEY].fetch(:event)).to contain_exactly(event_listener, new_listener)
21
+ describe '#register_listener' do
22
+ context 'when no listeners have been defined' do
23
+ let(:context) { EXEL::Context.new }
24
+
25
+ it 'adds a new listener to the context' do
26
+ events.register_listener(context, :event, event_listener)
27
+ expect(context[EXEL::Events::LISTENERS_KEY].fetch(:event)).to contain_exactly(event_listener)
25
28
  end
26
29
  end
27
30
 
28
- describe '#trigger' do
29
- let(:context) { EXEL::Context.new }
30
- let(:data) { {foo: 1} }
31
+ it 'registers multiple listeners for the same event' do
32
+ new_listener = double(:event_listener2)
33
+ events.register_listener(context, :event, new_listener)
34
+ expect(context[EXEL::Events::LISTENERS_KEY].fetch(:event)).to contain_exactly(event_listener, new_listener)
35
+ end
36
+ end
37
+
38
+ describe '#trigger' do
39
+ let(:context) { EXEL::Context.new }
40
+ let(:data) { {foo: 1} }
31
41
 
32
- before { allow(events).to receive(:context).and_return(context) }
42
+ before { allow(events).to receive(:context).and_return(context) }
33
43
 
34
- context 'when no events have been registered' do
35
- it 'does not trigger anything' do
36
- expect(event_listener).not_to receive(:event)
44
+ context 'when no events have been registered' do
45
+ it 'does not trigger anything' do
46
+ expect(event_listener).not_to receive(:event)
37
47
 
38
- events.trigger(:event, data)
39
- end
48
+ events.trigger(:event, data)
40
49
  end
50
+ end
41
51
 
42
- context 'with a single listener registered for the event' do
43
- before do
44
- events.register_listener(context, :event, event_listener)
45
- end
52
+ context 'with a single listener registered for the event' do
53
+ before do
54
+ events.register_listener(context, :event, event_listener)
55
+ end
46
56
 
47
- it 'calls the listener with the context and event data' do
48
- expect(event_listener).to receive(:event).with(context, data)
57
+ it 'calls the listener with the context and event data' do
58
+ expect(event_listener).to receive(:event).with(context, data)
49
59
 
50
- events.trigger(:event, data)
51
- end
60
+ events.trigger(:event, data)
61
+ end
52
62
 
53
- it 'passes an empty hash if no data was given' do
54
- expect(event_listener).to receive(:event).with(context, {})
63
+ it 'passes an empty hash if no data was given' do
64
+ expect(event_listener).to receive(:event).with(context, {})
55
65
 
56
- events.trigger(:event)
57
- end
66
+ events.trigger(:event)
58
67
  end
68
+ end
59
69
 
60
- context 'with no listeners registered for the event' do
61
- before do
62
- events.register_listener(context, :other_event, event_listener)
63
- end
70
+ context 'with no listeners registered for the event' do
71
+ before do
72
+ events.register_listener(context, :other_event, event_listener)
73
+ end
64
74
 
65
- it 'does not trigger anything' do
66
- expect(event_listener).not_to receive(:event)
75
+ it 'does not trigger anything' do
76
+ expect(event_listener).not_to receive(:event)
67
77
 
68
- events.trigger(:event, data)
69
- end
78
+ events.trigger(:event, data)
70
79
  end
80
+ end
71
81
 
72
- context 'with multiple listeners registered for the event' do
73
- let(:event_listener2) { double(:event_listener2) }
82
+ context 'with multiple listeners registered for the event' do
83
+ let(:event_listener2) { double(:event_listener2) }
74
84
 
75
- before do
76
- events.register_listener(context, :event, event_listener)
77
- events.register_listener(context, :event, event_listener2)
78
- end
85
+ before do
86
+ events.register_listener(context, :event, event_listener)
87
+ events.register_listener(context, :event, event_listener2)
88
+ end
79
89
 
80
- it 'calls each listener with the context and event data' do
81
- expect(event_listener).to receive(:event).with(context, data)
82
- expect(event_listener2).to receive(:event).with(context, data)
90
+ it 'calls each listener with the context and event data' do
91
+ expect(event_listener).to receive(:event).with(context, data)
92
+ expect(event_listener2).to receive(:event).with(context, data)
83
93
 
84
- events.trigger(:event, data)
85
- end
94
+ events.trigger(:event, data)
86
95
  end
87
96
  end
88
97
  end
@@ -1,22 +1,23 @@
1
- module EXEL
2
- describe InstructionNode do
3
- let(:context) { {} }
4
- let(:instruction) { instance_double(Instruction, execute: nil) }
5
- let(:child) { instance_double(ASTNode) }
6
- subject(:node) { InstructionNode.new(instruction, [child]) }
1
+ # frozen_string_literal: true
7
2
 
8
- it { is_expected.to be_kind_of(ASTNode) }
3
+ describe EXEL::InstructionNode do
4
+ subject(:node) { EXEL::InstructionNode.new(instruction, children: [child]) }
9
5
 
10
- describe '#run' do
11
- it 'only executes the instruction' do
12
- expect(instruction).to receive(:execute).with(context).once
13
- node.run(context)
14
- end
6
+ let(:context) { {} }
7
+ let(:instruction) { instance_double(EXEL::Instruction, execute: nil) }
8
+ let(:child) { instance_double(EXEL::ASTNode) }
15
9
 
16
- it 'does not run it`s children' do
17
- expect(child).not_to receive(:run)
18
- node.run(context)
19
- end
10
+ it { is_expected.to be_kind_of(EXEL::ASTNode) }
11
+
12
+ describe '#run' do
13
+ it 'only executes the instruction' do
14
+ expect(instruction).to receive(:execute).with(context).once
15
+ node.run(context)
16
+ end
17
+
18
+ it 'does not run it`s children' do
19
+ expect(child).not_to receive(:run)
20
+ node.run(context)
20
21
  end
21
22
  end
22
23
  end
@@ -1,57 +1,64 @@
1
- module EXEL
2
- describe Instruction do
3
- subject(:instruction) { EXEL::Instruction.new(processor_class, args) }
4
- let(:processor_class) { double(:processor_class, new: processor_instance) }
5
- let(:processor_instance) { double(:processor_instance, process: nil) }
6
- let(:args) { {arg1: 'arg_value1', arg2: {}} }
7
- let(:context) { {context_key: 'context_value'} }
8
-
9
- describe '#execute' do
10
- it 'calls process on an instance of the processor class' do
11
- expect(processor_class).to receive(:new).and_return(processor_instance)
12
- expect(processor_instance).to receive(:process)
1
+ # frozen_string_literal: true
13
2
 
14
- instruction.execute(context)
15
- end
3
+ describe EXEL::Instruction do
4
+ subject(:instruction) { EXEL::Instruction.new(processor_class, args) }
16
5
 
17
- it 'does not pass a copy of the context' do
18
- allow(processor_class).to receive(:new) do |context_arg|
19
- expect(context_arg).to be(context)
20
- processor_instance
21
- end
6
+ let(:processor_class) { double(:processor_class, new: processor_instance) }
7
+ let(:processor_instance) { double(:processor_instance, process: nil) }
8
+ let(:args) { {arg1: 'arg_value1', arg2: {}} }
9
+ let(:context) { {context_key: 'context_value'} }
22
10
 
23
- instruction.execute(context)
24
- end
11
+ describe '#execute' do
12
+ it 'calls process on an instance of the processor class' do
13
+ expect(processor_class).to receive(:new).and_return(processor_instance)
14
+ expect(processor_instance).to receive(:process)
25
15
 
26
- it 'adds args to the context' do
27
- instruction.execute(context)
28
- expect(context.keys).to include(*args.keys)
16
+ instruction.execute(context)
17
+ end
18
+
19
+ it 'invokes the middleware chain' do
20
+ expect(EXEL.middleware).to receive(:invoke).with(processor_class, context, args)
21
+ instruction.execute(context)
22
+ end
23
+
24
+ it 'does not pass a copy of the context' do
25
+ allow(processor_class).to receive(:new) do |context_arg|
26
+ expect(context_arg).to be(context)
27
+ processor_instance
29
28
  end
30
29
 
31
- context 'with args' do
32
- it 'passes the args to the processor' do
33
- expect(processor_class).to receive(:new).with(hash_including(args))
34
- instruction.execute(context)
35
- end
30
+ instruction.execute(context)
31
+ end
32
+
33
+ it 'adds args to the context' do
34
+ instruction.execute(context)
35
+ expect(context.keys).to include(*args.keys)
36
+ end
37
+
38
+ context 'with args' do
39
+ it 'passes the args to the processor' do
40
+ expect(processor_class).to receive(:new).with(hash_including(args))
41
+ instruction.execute(context)
36
42
  end
43
+ end
37
44
 
38
- context 'without args' do
39
- let(:args) { nil }
45
+ context 'without args' do
46
+ let(:args) { nil }
40
47
 
41
- it 'passes only the context to the processor' do
42
- expect(processor_class).to receive(:new).with(context)
43
- instruction.execute(context)
44
- end
48
+ it 'passes only the context to the processor' do
49
+ expect(processor_class).to receive(:new).with(context)
50
+ instruction.execute(context)
45
51
  end
52
+ end
46
53
 
47
- context 'with a subtree' do
48
- let(:subtree) { double(:subtree) }
49
- subject(:instruction) { EXEL::Instruction.new(processor_class, args, subtree) }
54
+ context 'with a subtree' do
55
+ subject(:instruction) { EXEL::Instruction.new(processor_class, args, subtree: subtree) }
50
56
 
51
- it 'passes the subtree to the processor' do
52
- expect(processor_instance).to receive(:process).with(subtree)
53
- instruction.execute(context)
54
- end
57
+ let(:subtree) { double(:subtree) }
58
+
59
+ it 'passes the subtree to the processor' do
60
+ expect(processor_instance).to receive(:process).with(subtree)
61
+ instruction.execute(context)
55
62
  end
56
63
  end
57
64
  end
@@ -1,104 +1,119 @@
1
- module EXEL
2
- describe Job do
3
- describe '.define' do
4
- let(:ast) { instance_double(SequenceNode, run: nil, start: nil) }
5
- let(:block) { proc {} }
1
+ # frozen_string_literal: true
2
+
3
+ describe EXEL::Job do
4
+ describe '.define' do
5
+ let(:ast) { instance_double(EXEL::SequenceNode, run: nil, start: nil) }
6
+ let(:block) { proc {} }
7
+
8
+ after { EXEL::Job.registry.clear }
9
+
10
+ it 'registers job definitions' do
11
+ EXEL::Job.define :test_job, &block
12
+ expect(EXEL::Job.registry[:test_job]).to eq(block)
13
+ end
14
+
15
+ it 'raises an exception if a job name is already in use' do
16
+ EXEL::Job.define :test_job, &block
17
+ expect { EXEL::Job.define :test_job, &block }.to raise_error 'Job :test_job is already defined'
18
+ end
19
+ end
20
+
21
+ describe '.run' do
22
+ let(:ast) { instance_double(EXEL::SequenceNode, run: nil, start: nil) }
23
+ let(:context) { instance_double(EXEL::Context) }
6
24
 
7
- after { Job.registry.clear }
25
+ context 'with a string of DSL code' do
26
+ it 'parses the code' do
27
+ dsl_code = 'code'
28
+ expect(EXEL::Job::Parser).to receive(:parse).with(dsl_code).and_return(ast)
29
+ EXEL::Job.run(dsl_code, context)
30
+ end
8
31
 
9
- it 'registers job definitions' do
10
- Job.define :test_job, &block
11
- expect(Job.registry[:test_job]).to eq(block)
32
+ it 'runs the AST returned by the parser' do
33
+ allow(EXEL::Job::Parser).to receive(:parse).and_return(ast)
34
+ expect(ast).to receive(:start).with(context)
35
+ EXEL::Job.run('code', context)
12
36
  end
13
37
 
14
- it 'raises an exception if a job name is already in use' do
15
- Job.define :test_job, &block
16
- expect { Job.define :test_job, &block }.to raise_error 'Job :test_job is already defined'
38
+ it 'returns the context' do
39
+ allow(EXEL::Job::Parser).to receive(:parse).and_return(ast)
40
+ result = EXEL::Job.run('code', context)
41
+ expect(result).to be(context)
17
42
  end
18
43
  end
19
44
 
20
- describe '.run' do
21
- let(:ast) { instance_double(SequenceNode, run: nil, start: nil) }
22
- let(:context) { instance_double(Context) }
45
+ context 'with a job name' do
46
+ context 'of a defined job' do
47
+ let(:block) { proc {} }
23
48
 
24
- context 'with a string of DSL code' do
25
- it 'parses the code' do
26
- dsl_code = 'code'
27
- expect(Job::Parser).to receive(:parse).with(dsl_code).and_return(ast)
28
- Job.run(dsl_code, context)
49
+ before do
50
+ allow(EXEL::Job).to receive(:registry).and_return(test_job: block)
29
51
  end
30
52
 
31
- it 'runs the AST returned by the parser' do
32
- allow(Job::Parser).to receive(:parse).and_return(ast)
53
+ it 'runs the job' do
54
+ expect(EXEL::Job::Parser).to receive(:parse).with(block).and_return(ast)
33
55
  expect(ast).to receive(:start).with(context)
34
- Job.run('code', context)
56
+ EXEL::Job.run(:test_job, context)
35
57
  end
36
- end
37
-
38
- context 'with a job name' do
39
- context 'of a defined job' do
40
- let(:block) { proc {} }
41
58
 
42
- before do
43
- allow(Job).to receive(:registry).and_return(test_job: block)
44
- end
45
-
46
- it 'runs the job' do
47
- expect(Job::Parser).to receive(:parse).with(block).and_return(ast)
48
- expect(ast).to receive(:start).with(context)
49
- Job.run(:test_job, context)
50
- end
59
+ it 'returns the context' do
60
+ result = EXEL::Job.run(:test_job, context)
61
+ expect(result).to be(context)
51
62
  end
63
+ end
52
64
 
53
- context 'of a undefined job' do
54
- it 'returns nil' do
55
- expect { Job.run(:test_job, context) }.to raise_error('Job "test_job" not found')
56
- end
65
+ context 'of a undefined job' do
66
+ it 'returns nil' do
67
+ expect { EXEL::Job.run(:test_job, context) }.to raise_error('Job "test_job" not found')
57
68
  end
58
69
  end
59
70
  end
71
+ end
60
72
 
61
- describe 'mutation of arguments' do
62
- class TestProcessor
63
- def initialize(context)
64
- context[:array] << context[:arg]
65
- end
73
+ describe 'mutation of arguments' do
74
+ module EXEL
75
+ module Processors
76
+ class TestProcessor
77
+ def initialize(context)
78
+ context[:array] << context[:arg]
79
+ end
66
80
 
67
- def process(_callback)
81
+ def process(_callback)
82
+ end
68
83
  end
69
84
  end
85
+ end
70
86
 
71
- it 'does not persist between runs' do
72
- Job.define :test do
73
- process with: TestProcessor, array: [], arg: context[:value]
74
- end
87
+ it 'does not persist between runs' do
88
+ EXEL::Job.define :test do
89
+ process with: EXEL::Processors::TestProcessor, array: [], arg: context[:value]
90
+ end
75
91
 
76
- context = Context.new(value: 1)
77
- Job.run(:test, context)
78
- expect(context[:array]).to eq([1])
92
+ context = EXEL::Context.new(value: 1)
93
+ EXEL::Job.run(:test, context)
94
+ expect(context[:array]).to eq([1])
79
95
 
80
- context = Context.new(value: 2)
81
- Job.run(:test, context)
82
- expect(context[:array]).to eq([2])
83
- end
96
+ context = EXEL::Context.new(value: 2)
97
+ EXEL::Job.run(:test, context)
98
+ expect(context[:array]).to eq([2])
84
99
  end
85
100
  end
86
101
 
87
- describe Job::Parser do
88
- let(:parser) { Job::Parser.new }
89
- let(:ast) { instance_double(SequenceNode, run: nil) }
102
+ describe EXEL::Job::Parser do
103
+ let(:parser) { EXEL::Job::Parser.new }
104
+ let(:ast) { instance_double(EXEL::SequenceNode, run: nil) }
90
105
 
91
106
  describe '#initialize' do
92
107
  it 'initializes a sequence node' do
93
- expect(parser.ast).to be_kind_of(SequenceNode)
108
+ expect(parser.ast).to be_kind_of(EXEL::SequenceNode)
94
109
  end
95
110
  end
96
111
 
97
112
  describe '.parse' do
98
- let(:parser) { instance_double(Job::Parser, ast: ast, instance_eval: nil) }
113
+ let(:parser) { instance_double(EXEL::Job::Parser, ast: ast, instance_eval: nil) }
99
114
 
100
115
  before do
101
- allow(Job::Parser).to receive(:new).and_return(parser)
116
+ allow(EXEL::Job::Parser).to receive(:new).and_return(parser)
102
117
  end
103
118
 
104
119
  context 'given DSL code as a proc' do
@@ -108,7 +123,7 @@ module EXEL
108
123
  expect(block).to eq(dsl_proc)
109
124
  end
110
125
 
111
- Job::Parser.parse(dsl_proc)
126
+ EXEL::Job::Parser.parse(dsl_proc)
112
127
  end
113
128
  end
114
129
 
@@ -117,12 +132,12 @@ module EXEL
117
132
  dsl_code = 'code'
118
133
  expect(parser).to receive(:instance_eval).with(dsl_code)
119
134
 
120
- Job::Parser.parse(dsl_code)
135
+ EXEL::Job::Parser.parse(dsl_code)
121
136
  end
122
137
  end
123
138
 
124
139
  it 'returns the parsed AST' do
125
- expect(Job::Parser.parse(proc {})).to eq(ast)
140
+ expect(EXEL::Job::Parser.parse(proc {})).to eq(ast)
126
141
  end
127
142
  end
128
143
 
@@ -130,18 +145,18 @@ module EXEL
130
145
  let(:block) { proc {} }
131
146
  let(:processor_class) { class_double(Class) }
132
147
 
133
- before { allow(Job::Parser).to receive(:parse).and_return(ast) }
148
+ before { allow(EXEL::Job::Parser).to receive(:parse).and_return(ast) }
134
149
 
135
150
  context 'without a block' do
136
151
  it 'creates a process instruction' do
137
- expect(Instruction).to receive(:new).with(processor_class, {arg1: 'arg1_value'}, nil)
152
+ expect(EXEL::Instruction).to receive(:new).with(processor_class, {arg1: 'arg1_value'}, subtree: nil)
138
153
 
139
154
  parser.process with: processor_class, arg1: 'arg1_value'
140
155
  end
141
156
 
142
157
  it 'appends an instruction node to the AST with no children' do
143
158
  expect(parser.ast).to receive(:add_child) do |node|
144
- expect(node).to be_a_kind_of(InstructionNode)
159
+ expect(node).to be_a_kind_of(EXEL::InstructionNode)
145
160
  expect(node.children).to eq([])
146
161
  end
147
162
 
@@ -151,15 +166,15 @@ module EXEL
151
166
 
152
167
  context 'with a block' do
153
168
  it 'passes the parsed subtree to the instruction' do
154
- expect(Job::Parser).to receive(:parse).with(block).and_return(ast)
155
- expect(Instruction).to receive(:new).with(processor_class, {arg1: 'arg1_value'}, ast)
169
+ expect(EXEL::Job::Parser).to receive(:parse).with(block).and_return(ast)
170
+ expect(EXEL::Instruction).to receive(:new).with(processor_class, {arg1: 'arg1_value'}, subtree: ast)
156
171
 
157
172
  parser.process with: processor_class, arg1: 'arg1_value', &block
158
173
  end
159
174
 
160
175
  it 'appends an instruction node to the AST with the parsed block as its subtree' do
161
176
  expect(parser.ast).to receive(:add_child) do |node|
162
- expect(node).to be_a_kind_of(InstructionNode)
177
+ expect(node).to be_a_kind_of(EXEL::InstructionNode)
163
178
  expect(node.children).to eq([ast])
164
179
  end
165
180
 
@@ -169,30 +184,30 @@ module EXEL
169
184
  end
170
185
 
171
186
  [
172
- {method: :async, processor: Processors::AsyncProcessor},
173
- {method: :split, processor: Processors::SplitProcessor},
174
- {method: :run, processor: Processors::RunProcessor}
187
+ {method: :async, processor: EXEL::Processors::AsyncProcessor},
188
+ {method: :split, processor: EXEL::Processors::SplitProcessor},
189
+ {method: :run, processor: EXEL::Processors::RunProcessor},
175
190
  ].each do |data|
176
191
  describe "##{data[:method]}" do
177
192
  before do
178
- allow(Job::Parser).to receive(:parse).and_return(ast)
193
+ allow(EXEL::Job::Parser).to receive(:parse).and_return(ast)
179
194
  end
180
195
 
181
196
  it "creates a #{data[:method]} instruction" do
182
- expect(Instruction).to receive(:new).with(data[:processor], {arg1: 'arg1_value'}, ast)
197
+ expect(EXEL::Instruction).to receive(:new).with(data[:processor], {arg1: 'arg1_value'}, subtree: ast)
183
198
  parser.send(data[:method], arg1: 'arg1_value') {}
184
199
  end
185
200
 
186
201
  it 'parses the block given' do
187
202
  block = -> {}
188
- expect(Job::Parser).to receive(:parse).with(block).and_return(ast)
203
+ expect(EXEL::Job::Parser).to receive(:parse).with(block).and_return(ast)
189
204
 
190
205
  parser.send(data[:method], &block)
191
206
  end
192
207
 
193
208
  it 'adds parsed subtree and instruction to the AST' do
194
209
  expect(parser.ast).to receive(:add_child) do |node|
195
- expect(node).to be_a_kind_of(InstructionNode)
210
+ expect(node).to be_a_kind_of(EXEL::InstructionNode)
196
211
  expect(node.children).to eq([ast])
197
212
  end
198
213
 
@@ -203,7 +218,7 @@ module EXEL
203
218
 
204
219
  describe '#context' do
205
220
  it 'returns a DeferredContextValue' do
206
- expect(parser.context).to be_a_kind_of(DeferredContextValue)
221
+ expect(parser.context).to be_a_kind_of(EXEL::DeferredContextValue)
207
222
  end
208
223
  end
209
224
 
@@ -211,15 +226,15 @@ module EXEL
211
226
  let(:listener_class) { class_double(Class) }
212
227
 
213
228
  it 'creates a listen instruction' do
214
- expect(ListenInstruction).to receive(:new).with(:event, listener_class)
229
+ expect(EXEL::ListenInstruction).to receive(:new).with(:event, listener_class)
215
230
  parser.listen for: :event, with: listener_class
216
231
  end
217
232
 
218
233
  it 'adds an InstructionNode containing the listen instruction' do
219
234
  parser.listen for: :event, with: listener_class
220
235
  node = parser.ast.children.first
221
- expect(node).to be_a_kind_of(InstructionNode)
222
- expect(node.instruction).to be_a_kind_of(ListenInstruction)
236
+ expect(node).to be_a_kind_of(EXEL::InstructionNode)
237
+ expect(node.instruction).to be_a_kind_of(EXEL::ListenInstruction)
223
238
  end
224
239
  end
225
240
  end