producer-core 0.1.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.
Files changed (65) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +5 -0
  3. data/Guardfile +11 -0
  4. data/LICENSE +30 -0
  5. data/Rakefile +13 -0
  6. data/bin/producer +5 -0
  7. data/features/actions/echo.feature +12 -0
  8. data/features/actions/sh.feature +39 -0
  9. data/features/cli/usage.feature +9 -0
  10. data/features/recipes/env.feature +9 -0
  11. data/features/recipes/evaluation.feature +10 -0
  12. data/features/recipes/source.feature +16 -0
  13. data/features/recipes/target.feature +12 -0
  14. data/features/steps/recipe_steps.rb +7 -0
  15. data/features/support/env.rb +0 -0
  16. data/features/support/env_aruba.rb +16 -0
  17. data/features/support/env_cucumber-doc_string.rb +23 -0
  18. data/features/support/ssh.rb +106 -0
  19. data/features/tasks/condition.feature +14 -0
  20. data/features/tasks/evaluation.feature +12 -0
  21. data/features/tests/has_env.feature +32 -0
  22. data/lib/producer/core/action.rb +12 -0
  23. data/lib/producer/core/actions/echo.rb +11 -0
  24. data/lib/producer/core/actions/shell_command.rb +11 -0
  25. data/lib/producer/core/cli.rb +43 -0
  26. data/lib/producer/core/condition/dsl.rb +35 -0
  27. data/lib/producer/core/condition.rb +26 -0
  28. data/lib/producer/core/env.rb +21 -0
  29. data/lib/producer/core/errors.rb +7 -0
  30. data/lib/producer/core/interpreter.rb +13 -0
  31. data/lib/producer/core/recipe/dsl.rb +48 -0
  32. data/lib/producer/core/recipe.rb +15 -0
  33. data/lib/producer/core/remote/environment.rb +27 -0
  34. data/lib/producer/core/remote.rb +40 -0
  35. data/lib/producer/core/task/dsl.rb +42 -0
  36. data/lib/producer/core/task.rb +21 -0
  37. data/lib/producer/core/test.rb +12 -0
  38. data/lib/producer/core/tests/has_env.rb +11 -0
  39. data/lib/producer/core/version.rb +5 -0
  40. data/lib/producer/core.rb +22 -0
  41. data/producer-core.gemspec +28 -0
  42. data/spec/fixtures/recipes/empty.rb +1 -0
  43. data/spec/fixtures/recipes/throw.rb +1 -0
  44. data/spec/producer/core/action_spec.rb +21 -0
  45. data/spec/producer/core/actions/echo_spec.rb +21 -0
  46. data/spec/producer/core/actions/shell_command_spec.rb +27 -0
  47. data/spec/producer/core/cli_spec.rb +102 -0
  48. data/spec/producer/core/condition/dsl_spec.rb +102 -0
  49. data/spec/producer/core/condition_spec.rb +96 -0
  50. data/spec/producer/core/env_spec.rb +54 -0
  51. data/spec/producer/core/interpreter_spec.rb +41 -0
  52. data/spec/producer/core/recipe/dsl_spec.rb +131 -0
  53. data/spec/producer/core/recipe_spec.rb +43 -0
  54. data/spec/producer/core/remote/environment_spec.rb +34 -0
  55. data/spec/producer/core/remote_spec.rb +87 -0
  56. data/spec/producer/core/task/dsl_spec.rb +131 -0
  57. data/spec/producer/core/task_spec.rb +91 -0
  58. data/spec/producer/core/test_spec.rb +30 -0
  59. data/spec/producer/core/tests/has_env_spec.rb +41 -0
  60. data/spec/spec_helper.rb +16 -0
  61. data/spec/support/exit_helpers.rb +6 -0
  62. data/spec/support/fixtures_helpers.rb +7 -0
  63. data/spec/support/net_ssh_story_helpers.rb +17 -0
  64. data/spec/support/tests_helpers.rb +9 -0
  65. metadata +230 -0
@@ -0,0 +1,27 @@
1
+ module Producer
2
+ module Core
3
+ class Remote
4
+ class Environment
5
+ require 'forwardable'
6
+
7
+ extend Forwardable
8
+ def_delegator :@variables, :has_key?
9
+
10
+ def initialize(variables)
11
+ case variables
12
+ when String
13
+ @variables = parse_from_string variables
14
+ else
15
+ @variables = variables
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def parse_from_string(str)
22
+ Hash[str.each_line.map { |l| l.chomp.split '=', 2 }]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,40 @@
1
+ module Producer
2
+ module Core
3
+ class Remote
4
+ require 'etc'
5
+ require 'net/ssh'
6
+
7
+ attr_accessor :hostname
8
+
9
+ def initialize(hostname)
10
+ @hostname = hostname
11
+ end
12
+
13
+ def session
14
+ @session ||= Net::SSH.start(@hostname, Etc.getlogin)
15
+ end
16
+
17
+ def execute(command)
18
+ output = ''
19
+ session.open_channel do |channel|
20
+ channel.exec command do |ch, success|
21
+ ch.on_data do |c, data|
22
+ output << data
23
+ end
24
+
25
+ ch.on_request('exit-status') do |c, data|
26
+ exit_status = data.read_long
27
+ raise RemoteCommandExecutionError if exit_status != 0
28
+ end
29
+ end
30
+ end
31
+ session.loop
32
+ output
33
+ end
34
+
35
+ def environment
36
+ Environment.new(execute 'env')
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,42 @@
1
+ module Producer
2
+ module Core
3
+ class Task
4
+ class DSL
5
+ class << self
6
+ def evaluate(name, env, &block)
7
+ dsl = new(&block)
8
+ dsl.evaluate(env)
9
+ Task.new(name, dsl.actions, dsl.condition)
10
+ end
11
+
12
+ def define_action(keyword, klass)
13
+ define_method(keyword) do |*args|
14
+ @actions << klass.new(@env, *args)
15
+ end
16
+ end
17
+ end
18
+
19
+ define_action :echo, Actions::Echo
20
+ define_action :sh, Actions::ShellCommand
21
+
22
+ attr_accessor :actions
23
+
24
+ def initialize(&block)
25
+ @block = block
26
+ @actions = []
27
+ @condition = true
28
+ end
29
+
30
+ def evaluate(env)
31
+ @env = env
32
+ instance_eval &@block
33
+ end
34
+
35
+ def condition(&block)
36
+ @condition = Condition.evaluate(@env, &block) if block
37
+ @condition
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ module Producer
2
+ module Core
3
+ class Task
4
+ attr_reader :name, :actions, :condition
5
+
6
+ def self.evaluate(name, env, &block)
7
+ DSL.evaluate(name, env, &block)
8
+ end
9
+
10
+ def initialize(name, actions = [], condition = true)
11
+ @name = name
12
+ @actions = actions
13
+ @condition = condition
14
+ end
15
+
16
+ def condition_met?
17
+ !!@condition
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ module Producer
2
+ module Core
3
+ class Test
4
+ attr_reader :env, :arguments
5
+
6
+ def initialize(env, *arguments)
7
+ @env = env
8
+ @arguments = arguments
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module Producer
2
+ module Core
3
+ class Tests
4
+ class HasEnv < Test
5
+ def success?
6
+ env.remote.environment.has_key? arguments.first.to_s.upcase
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module Producer
2
+ module Core
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ # task actions
2
+ require 'producer/core/action'
3
+ require 'producer/core/actions/echo'
4
+ require 'producer/core/actions/shell_command'
5
+
6
+ # condition tests (need to be defined before the condition DSL)
7
+ require 'producer/core/test'
8
+ require 'producer/core/tests/has_env'
9
+
10
+ require 'producer/core/cli'
11
+ require 'producer/core/condition'
12
+ require 'producer/core/condition/dsl'
13
+ require 'producer/core/env'
14
+ require 'producer/core/errors'
15
+ require 'producer/core/interpreter'
16
+ require 'producer/core/recipe'
17
+ require 'producer/core/recipe/dsl'
18
+ require 'producer/core/remote'
19
+ require 'producer/core/remote/environment'
20
+ require 'producer/core/task'
21
+ require 'producer/core/task/dsl'
22
+ require 'producer/core/version'
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH << lib unless $LOAD_PATH.include? lib
3
+ require 'producer/core/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'producer-core'
7
+ s.version = Producer::Core::VERSION
8
+ s.summary = "producer-core-#{Producer::Core::VERSION}"
9
+ s.description = <<-eoh.gsub(/^ +/, '')
10
+ blah
11
+ eoh
12
+ s.homepage = 'https://rubygems.org/gems/producer-core'
13
+
14
+ s.authors = 'Thibault Jouan'
15
+ s.email = 'tj@a13.fr'
16
+
17
+ s.files = `git ls-files`.split $/
18
+ s.test_files = s.files.grep /\A(spec|features)\//
19
+ s.executables = s.files.grep(/\Abin\//) { |f| File.basename(f) }
20
+
21
+
22
+ s.add_dependency 'net-ssh'
23
+
24
+ s.add_development_dependency 'rspec'
25
+ s.add_development_dependency 'cucumber'
26
+ s.add_development_dependency 'aruba'
27
+ s.add_development_dependency 'rake'
28
+ end
@@ -0,0 +1 @@
1
+ # can contain tasks written in ruby language.
@@ -0,0 +1 @@
1
+ throw :recipe_code
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Action do
5
+ let(:env) { double 'env' }
6
+ let(:arguments) { [:some, :arguments] }
7
+ subject(:action) { Action.new(env, *arguments) }
8
+
9
+ describe '#env' do
10
+ it 'returns the assigned env' do
11
+ expect(action.env).to be env
12
+ end
13
+ end
14
+
15
+ describe '#arguments' do
16
+ it 'returns the assigned arguments' do
17
+ expect(action.arguments).to eq arguments
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Actions::Echo do
5
+ let(:env) { Env.new }
6
+ let(:text) { 'hello' }
7
+ subject(:echo) { Actions::Echo.new(env, text) }
8
+
9
+ describe '#apply' do
10
+ before do
11
+ env.output = StringIO.new
12
+ end
13
+
14
+ it 'outputs the string given as argument through env.output' do
15
+ expect(env).to receive(:output).with(text)
16
+ echo.apply
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Actions::ShellCommand do
5
+ let(:env) { Env.new }
6
+ let(:command_args) { 'hello from remote host' }
7
+ let(:command) { "echo #{command_args}" }
8
+ subject(:sh) { Actions::ShellCommand.new(env, command) }
9
+
10
+ describe '#apply' do
11
+ before do
12
+ env.output = StringIO.new
13
+ end
14
+
15
+ it 'delegates the call to env.remote.execute method' do
16
+ expect(env.remote).to receive(:execute).with(command)
17
+ sh.apply
18
+ end
19
+
20
+ it 'forwards the returned output to env.output' do
21
+ allow(env.remote).to receive(:execute) { command_args }
22
+ expect(env).to receive(:output).with(command_args)
23
+ sh.apply
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe CLI do
5
+ include ExitHelpers
6
+ include FixturesHelpers
7
+
8
+ let(:recipe_file) { fixture_path_for('recipes/empty.rb') }
9
+ let(:arguments) { [recipe_file] }
10
+ subject(:cli) { CLI.new(arguments) }
11
+
12
+ describe '#initialize' do
13
+ it 'assigns $stdout as the default standard output' do
14
+ expect(cli.instance_eval { @stdout }).to be $stdout
15
+ end
16
+ end
17
+
18
+ describe '#arguments' do
19
+ it 'returns the assigned arguments' do
20
+ expect(cli.arguments).to eq arguments
21
+ end
22
+ end
23
+
24
+ describe '#run!' do
25
+ it 'checks the arguments' do
26
+ expect(cli).to receive(:check_arguments!)
27
+ cli.run!
28
+ end
29
+
30
+ it 'processes the tasks with the interpreter' do
31
+ allow(cli.recipe).to receive(:tasks) { [:some_task] }
32
+ expect(cli.interpreter).to receive(:process).with([:some_task])
33
+ cli.run!
34
+ end
35
+ end
36
+
37
+ describe '#check_arguments!' do
38
+ context 'when recipe argument is provided' do
39
+ it 'does not raise any error' do
40
+ expect { cli.check_arguments! }.to_not raise_error
41
+ end
42
+ end
43
+
44
+ context 'when recipe argument is missing' do
45
+ let(:arguments) { [] }
46
+ let(:stdout) { StringIO.new }
47
+ subject(:cli) { CLI.new(arguments, stdout) }
48
+
49
+ it 'exits with a return status of 64' do
50
+ expect { cli.check_arguments! }.to raise_error(SystemExit) { |e|
51
+ expect(e.status).to eq 64
52
+ }
53
+ end
54
+
55
+ it 'prints the usage' do
56
+ trap_exit { cli.check_arguments! }
57
+ expect(stdout.string).to match /\AUsage: .+/
58
+ end
59
+ end
60
+ end
61
+
62
+ describe '#env' do
63
+ it 'builds an environment with the current recipe' do
64
+ expect(Env).to receive(:new)
65
+ cli.env
66
+ end
67
+
68
+ it 'returns the env' do
69
+ env = double('env')
70
+ allow(Env).to receive(:new) { env }
71
+ expect(cli.env).to be env
72
+ end
73
+ end
74
+
75
+ describe '#recipe' do
76
+ it 'builds a recipe' do
77
+ expect(Recipe)
78
+ .to receive(:evaluate_from_file).with(recipe_file, cli.env)
79
+ cli.recipe
80
+ end
81
+
82
+ it 'returns the recipe' do
83
+ recipe = double('recipe').as_null_object
84
+ allow(Recipe).to receive(:new) { recipe }
85
+ expect(cli.recipe).to be recipe
86
+ end
87
+ end
88
+
89
+ describe '#interpreter' do
90
+ it 'builds a interpreter' do
91
+ expect(Interpreter).to receive(:new)
92
+ cli.interpreter
93
+ end
94
+
95
+ it 'returns the interpreter' do
96
+ interpreter = double('interpreter')
97
+ allow(Interpreter).to receive(:new) { interpreter }
98
+ expect(cli.interpreter).to be interpreter
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Condition::DSL do
5
+ let(:block) { proc { :some_condition_code } }
6
+ let(:env) { double('env') }
7
+ subject(:dsl) { Condition::DSL.new(env, &block) }
8
+
9
+ %w[has_env].each do |test|
10
+ it "has `#{test}' test defined" do
11
+ expect(dsl).to respond_to test.to_sym
12
+ end
13
+ end
14
+
15
+ describe '.evaluate' do
16
+ it 'builds a new DSL sandbox with given env and code' do
17
+ expect(Condition::DSL)
18
+ .to receive(:new).with(env, &block).and_call_original
19
+ Condition::DSL.evaluate(env, &block)
20
+ end
21
+
22
+ it 'evaluates the DSL sandbox code' do
23
+ dsl = double('dsl').as_null_object
24
+ allow(Condition::DSL).to receive(:new) { dsl }
25
+ expect(dsl).to receive(:evaluate)
26
+ Condition::DSL.evaluate(env, &block)
27
+ end
28
+
29
+ it 'builds a condition with its test and block return value' do
30
+ expect(Condition)
31
+ .to receive(:new).with(dsl.tests, :some_condition_code)
32
+ Condition::DSL.evaluate(env, &block)
33
+ end
34
+
35
+ it 'returns the condition' do
36
+ condition = double('task')
37
+ allow(Condition).to receive(:new) { condition }
38
+ expect(Condition::DSL.evaluate(env, &block)).to be condition
39
+ end
40
+ end
41
+
42
+ describe '.define_test' do
43
+ let(:some_test_class) { double('SomeTest class') }
44
+
45
+ before do
46
+ Condition::DSL.define_test(:some_test, some_test_class)
47
+ end
48
+
49
+ it 'defines a new test keyword' do
50
+ expect(dsl).to respond_to :some_test
51
+ end
52
+ end
53
+
54
+ describe '#initialize' do
55
+ it 'assigns the code' do
56
+ expect(dsl.instance_eval { @block }).to be block
57
+ end
58
+
59
+ it 'assigns the env' do
60
+ expect(dsl.instance_eval { @env }).to be env
61
+ end
62
+
63
+ it 'assigns no test' do
64
+ expect(dsl.tests).to be_empty
65
+ end
66
+ end
67
+
68
+ describe '#tests' do
69
+ it 'returns the assigned tests' do
70
+ dsl.instance_eval { @tests = [:some_test] }
71
+ expect(dsl.tests).to eq [:some_test]
72
+ end
73
+ end
74
+
75
+ describe '#evaluate' do
76
+ it 'returns the value returned by the assigned block' do
77
+ expect(dsl.evaluate).to eq block.call
78
+ end
79
+
80
+ context 'when a defined test keyword is called' do
81
+ let(:some_test_class) { double('SomeTest class') }
82
+ let(:block) { proc { some_test :some, :args } }
83
+
84
+ before do
85
+ Condition::DSL.define_test(:some_test, some_test_class)
86
+ end
87
+
88
+ it 'builds a new test with the env and given arguments' do
89
+ expect(some_test_class).to receive(:new).with(env, :some, :args)
90
+ dsl.evaluate
91
+ end
92
+
93
+ it 'registers the new test' do
94
+ some_test = double('SomeTest instance')
95
+ allow(some_test_class).to receive(:new) { some_test }
96
+ dsl.evaluate
97
+ expect(dsl.tests).to include(some_test)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Condition do
5
+ include TestsHelpers
6
+
7
+ let(:tests) { [test_ok, test_ko] }
8
+ subject(:condition) { Condition.new(tests) }
9
+
10
+ describe '.evaluate' do
11
+ let(:env) { double('env') }
12
+ let(:block) { proc { :some_condition_code } }
13
+
14
+ it 'delegates to DSL.evaluate' do
15
+ expect(Condition::DSL)
16
+ .to receive(:evaluate).with(env) do |&b|
17
+ expect(b.call).to eq :some_condition_code
18
+ end
19
+ Condition.evaluate(env, &block)
20
+ end
21
+
22
+ it 'returns the evaluated condition' do
23
+ condition = double('condition')
24
+ allow(Condition::DSL).to receive(:evaluate) { condition }
25
+ expect(Condition.evaluate(env, &block)).to be condition
26
+ end
27
+ end
28
+
29
+ describe '#initialize' do
30
+ it 'assigns the tests' do
31
+ expect(condition.instance_eval { @tests }).to eq tests
32
+ end
33
+
34
+ it 'assigns nil as a default return value' do
35
+ expect(condition.instance_eval { @return_value }).to be nil
36
+ end
37
+
38
+ context 'when a return value is given as argument' do
39
+ let(:return_value) { :some_return_value }
40
+ subject(:condition) { Condition.new(tests, return_value) }
41
+
42
+ it 'assigns the return value' do
43
+ expect(condition.instance_eval { @return_value }).to eq return_value
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#met?' do
49
+ context 'when all tests are successful' do
50
+ let(:tests) { [test_ok, test_ok] }
51
+
52
+ it 'returns true' do
53
+ expect(condition.met?).to be true
54
+ end
55
+ end
56
+
57
+ context 'when one test is unsuccessful' do
58
+ let(:tests) { [test_ok, test_ko] }
59
+
60
+ it 'returns false' do
61
+ expect(condition.met?).to be false
62
+ end
63
+ end
64
+
65
+ context 'when there are no test' do
66
+ subject(:condition) { Condition.new([], return_value) }
67
+
68
+ context 'and return value is truthy' do
69
+ let(:return_value) { :some_truthy_value }
70
+
71
+ it 'returns true' do
72
+ expect(condition.met?).to be true
73
+ end
74
+ end
75
+
76
+ context 'and return value is falsy' do
77
+ let(:return_value) { nil }
78
+
79
+ it 'returns false' do
80
+ expect(condition.met?).to be false
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#!' do
87
+ %w[true false].each do |b|
88
+ context "when #met? return #{b}" do
89
+ it 'returns the negated #met?' do
90
+ expect(condition.!).to be !condition.met?
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Env do
5
+ subject(:env) { Env.new }
6
+
7
+ describe '#initialize' do
8
+ it 'assigns $stdout as the default output' do
9
+ expect(env.instance_eval { @output }).to eq $stdout
10
+ end
11
+
12
+ it 'assigns nil as a default target' do
13
+ expect(env.target).not_to be
14
+ end
15
+ end
16
+
17
+ describe '#output' do
18
+ let(:stdout) { StringIO.new }
19
+
20
+ it 'writes the given string to the assigned IO with a record separator' do
21
+ env.output = stdout
22
+ env.output 'some content'
23
+ expect(stdout.string).to eq "some content\n"
24
+ end
25
+ end
26
+
27
+ describe '#target' do
28
+ let(:target) { Object.new }
29
+
30
+ it 'returns the defined target' do
31
+ env.target = target
32
+ expect(env.target).to eq target
33
+ end
34
+ end
35
+
36
+ describe '#remote' do
37
+ it 'builds a Remote with the current target' do
38
+ env.target = 'some_hostname.example'
39
+ expect(Remote).to receive(:new).with(env.target)
40
+ env.remote
41
+ end
42
+
43
+ it 'returns the remote' do
44
+ remote = double('remote')
45
+ allow(Remote).to receive(:new) { remote }
46
+ expect(env.remote).to eq remote
47
+ end
48
+
49
+ it 'memoizes the remote' do
50
+ expect(env.remote).to be env.remote
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module Producer::Core
4
+ describe Interpreter do
5
+ subject(:interpreter) { Interpreter.new }
6
+
7
+ describe '#process' do
8
+ it 'processes each task' do
9
+ expect(interpreter).to receive(:process_task).with(:some_task)
10
+ interpreter.process [:some_task]
11
+ end
12
+ end
13
+
14
+ describe '#process_task' do
15
+ let(:action) { double('action') }
16
+ let(:task) { double('task').as_null_object }
17
+
18
+ before do
19
+ allow(task).to receive(:actions) { [action] }
20
+ end
21
+
22
+ context 'when task condition is met' do
23
+ it 'applies the actions' do
24
+ expect(action).to receive(:apply)
25
+ interpreter.process_task(task)
26
+ end
27
+ end
28
+
29
+ context 'when task condition is not met' do
30
+ before do
31
+ allow(task).to receive(:condition_met?) { false }
32
+ end
33
+
34
+ it 'does not apply the actions' do
35
+ expect(action).not_to receive(:apply)
36
+ interpreter.process_task(task)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end