diff --git a/features/condition.feature b/features/condition.feature new file mode 100644 index 0000000..d12a74d --- /dev/null +++ b/features/condition.feature @@ -0,0 +1,15 @@ +Feature: condition + + Scenario: prevents task evaluation when condition is not met + Given a recipe with: + """ + task :hello do + condition { false } + + puts 'evaluated' + exit 70 + end + """ + When I execute the recipe + Then the exit status must be 0 + And the output must not contain "evaluated" diff --git a/lib/producer/core/task.rb b/lib/producer/core/task.rb index 457d7a7..e5ce5b0 100644 --- a/lib/producer/core/task.rb +++ b/lib/producer/core/task.rb @@ -9,7 +9,21 @@ module Producer end def evaluate - instance_eval &@block + DSL.new &@block + end + + + class DSL + ConditionNotMetError = Class.new(RuntimeError) + + def initialize(&block) + instance_eval &block + rescue ConditionNotMetError + end + + def condition(&block) + raise ConditionNotMetError unless block.call + end end end end diff --git a/spec/producer/core/task_spec.rb b/spec/producer/core/task_spec.rb index 59513ba..44307e3 100644 --- a/spec/producer/core/task_spec.rb +++ b/spec/producer/core/task_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Producer::Core describe Task do let(:name) { :some_task } - let(:block) { } + let(:block) { Proc.new { } } subject(:task) { Task.new(name, &block) } describe '#name' do @@ -12,11 +12,46 @@ module Producer::Core end end - describe 'evaluate' do - let(:block) { Proc.new { raise 'error from task' } } + describe '#evaluate' do + it 'builds a task DSL sandbox' do + expect(Task::DSL).to receive(:new).with(&block) + task.evaluate + end + end - it 'evaluates its block' do - expect { task.evaluate }.to raise_error(RuntimeError, 'error from task') + describe Task::DSL do + let(:dsl) { Task::DSL.new &block } + + describe '#initialize' do + let(:block) { Proc.new { raise 'error from task' } } + + it 'evaluates its block' do + expect { dsl }.to raise_error(RuntimeError, 'error from task') + end + end + + describe '#condition' do + context 'condition is met (block evals to true)' do + let(:block) { Proc.new { + condition { true } + raise 'error after condition' + } } + + it 'evaluates all the block' do + expect { dsl }.to raise_error(RuntimeError, 'error after condition') + end + end + + context 'condition is not met (block evals to false)' do + let(:block) { Proc.new { + condition { false } + raise + } } + + it 'evaluates all the block' do + expect { dsl }.not_to raise_error + end + end end end end