exel 1.2.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
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