diff --git a/lib/producer/core/cli.rb b/lib/producer/core/cli.rb index f0726db..6c6baaf 100644 --- a/lib/producer/core/cli.rb +++ b/lib/producer/core/cli.rb @@ -12,7 +12,6 @@ module Producer def run! check_arguments! - recipe.evaluate(env) worker.process recipe.tasks end @@ -25,7 +24,7 @@ module Producer end def recipe - @recipe ||= Recipe.from_file(@arguments.first) + @recipe ||= Recipe.evaluate_from_file(@arguments.first, env) end def worker diff --git a/lib/producer/core/recipe.rb b/lib/producer/core/recipe.rb index 05c9c3f..50e5c39 100644 --- a/lib/producer/core/recipe.rb +++ b/lib/producer/core/recipe.rb @@ -1,22 +1,14 @@ module Producer module Core class Recipe - attr_reader :code, :filepath, :tasks + attr_accessor :tasks - def self.from_file(filepath) - new(File.read(filepath), filepath) + def self.evaluate_from_file(filepath, env) + DSL.evaluate(File.read(filepath), env) end - def initialize(code, filepath = nil) - @code = code - @filepath = filepath - @tasks = [] - end - - def evaluate(env) - dsl = DSL.new(@code).evaluate(env) - dsl.tasks.map { |e| e.evaluate env } - @tasks = dsl.tasks + def initialize(tasks = []) + @tasks = tasks end end end diff --git a/lib/producer/core/recipe/dsl.rb b/lib/producer/core/recipe/dsl.rb index 2a41355..a088209 100644 --- a/lib/producer/core/recipe/dsl.rb +++ b/lib/producer/core/recipe/dsl.rb @@ -4,6 +4,11 @@ module Producer class DSL attr_reader :tasks + def self.evaluate(code, env) + dsl = new(code).evaluate(env) + Recipe.new(dsl.tasks) + end + def initialize(code = nil, &block) @code = code @block = block @@ -17,6 +22,7 @@ module Producer else instance_eval &@block end + @tasks.each { |e| e.evaluate env } self end diff --git a/spec/producer/core/cli_spec.rb b/spec/producer/core/cli_spec.rb index 953b02c..f99cdf6 100644 --- a/spec/producer/core/cli_spec.rb +++ b/spec/producer/core/cli_spec.rb @@ -27,11 +27,6 @@ module Producer::Core cli.run! end - it 'evaluates the recipe with the environment' do - expect(cli.recipe).to receive(:evaluate).with(cli.env) - cli.run! - end - it 'processes the tasks with the worker' do allow(cli.recipe).to receive(:tasks) { [:some_task] } expect(cli.worker).to receive(:process).with([:some_task]) @@ -80,12 +75,12 @@ module Producer::Core describe '#recipe' do it 'builds a recipe' do expect(Recipe) - .to receive(:from_file).with(recipe_file) + .to receive(:evaluate_from_file).with(recipe_file, cli.env) cli.recipe end it 'returns the recipe' do - recipe = double('recipe') + recipe = double('recipe').as_null_object allow(Recipe).to receive(:new) { recipe } expect(cli.recipe).to be recipe end diff --git a/spec/producer/core/recipe/dsl_spec.rb b/spec/producer/core/recipe/dsl_spec.rb index eb62a63..d8dd6a7 100644 --- a/spec/producer/core/recipe/dsl_spec.rb +++ b/spec/producer/core/recipe/dsl_spec.rb @@ -8,6 +8,35 @@ module Producer::Core let(:env) { double('env').as_null_object } subject(:dsl) { Recipe::DSL.new &code } + describe '.evaluate' do + let(:code) { 'nil' } + + it 'builds a new DSL sandbox with given code' do + expect(Recipe::DSL).to receive(:new).once.with(code).and_call_original + Recipe::DSL.evaluate(code, env) + end + + it 'evaluates the DSL sandbox code with given environment' do + dsl = double('dsl').as_null_object + allow(Recipe::DSL).to receive(:new) { dsl } + expect(dsl).to receive(:evaluate).with(env) + Recipe::DSL.evaluate(code, env) + end + + it 'builds a recipe with evaluated tasks' do + dsl = Recipe::DSL.new('task(:some_task) { }') + allow(Recipe::DSL).to receive(:new) { dsl } + expect(Recipe).to receive(:new).with(dsl.tasks) + Recipe::DSL.evaluate(code, env) + end + + it 'returns the recipe' do + recipe = double('recipe').as_null_object + allow(Recipe).to receive(:new) { recipe } + expect(Recipe::DSL.evaluate(code, env)).to be recipe + end + end + describe '#initialize' do it 'assigns no task' do expect(dsl.instance_eval { @tasks }).to be_empty @@ -30,7 +59,7 @@ module Producer::Core end describe '#tasks' do - let(:code) { proc { task(:some_task) } } + let(:code) { proc { task(:some_task) { } } } it 'returns registered tasks' do dsl.evaluate(env) @@ -44,6 +73,14 @@ module Producer::Core expect { dsl.evaluate(env) }.to throw_symbol :recipe_code end + it 'evaluates the registered tasks' do + task = double('task') + allow(Task).to receive(:new) { task } + dsl = Recipe::DSL.new { task(:some_task) } + expect(task).to receive(:evaluate).with(env) + dsl.evaluate(env) + end + it 'returns itself' do expect(dsl.evaluate(env)).to eq dsl end @@ -81,11 +118,11 @@ module Producer::Core end describe '#task' do - let(:code) { proc { task(:first) { throw :first_task }; task(:last) } } + let(:code) { proc { task(:first) { :some_value }; task(:last) { } } } it 'register a task with its code' do - expect(dsl.tasks.first.name).to eq :first - expect { dsl.tasks.first.evaluate(env) }.to throw_symbol :first_task + expect(dsl.tasks.first.instance_eval { @block.call }) + .to eq :some_value end it 'registers tasks in declaration order' do diff --git a/spec/producer/core/recipe_spec.rb b/spec/producer/core/recipe_spec.rb index 5a673cf..ab25003 100644 --- a/spec/producer/core/recipe_spec.rb +++ b/spec/producer/core/recipe_spec.rb @@ -4,76 +4,39 @@ module Producer::Core describe Recipe do include FixturesHelpers - let(:code) { 'nil' } - subject(:recipe) { Recipe.new(code) } + subject(:recipe) { Recipe.new } - describe '.from_file' do - let(:filepath) { fixture_path_for 'recipes/empty.rb' } - subject(:recipe) { Recipe.from_file(filepath) } + describe '.evaluate_from_file' do + let(:env) { double('env') } + let(:filepath) { fixture_path_for 'recipes/empty.rb' } - it 'builds a recipe whose code is read from given file path' do - expect(recipe.code).to eq File.read(filepath) + it 'delegates to DSL.evaluate with the recipe file content' do + expect(Recipe::DSL) + .to receive(:evaluate).with(File.read(filepath), env) + Recipe.evaluate_from_file(filepath, env) end - it 'builds a recipe whose file path is set from given file path' do - expect(recipe.filepath).to eq filepath + it 'returns the evaluated recipe' do + recipe = double('recipe') + allow(Recipe::DSL).to receive(:evaluate) { recipe } + expect(Recipe.evaluate_from_file(filepath, env)).to be recipe end end describe '#initialize' do - it 'assigns nil as a default filepath' do - expect(recipe.filepath).to be nil + context 'without arguments' do + it 'assigns no task' do + expect(recipe.tasks).to be_empty + end end - it 'has no task' do - expect(recipe.tasks).to be_empty - end - end + context 'when tasks are given as argument' do + let(:tasks) { [Task.new(:some_task)] } + let(:recipe) { Recipe.new(tasks) } - describe '#code' do - it 'returns the assigned code' do - expect(recipe.code).to be code - end - end - - describe '#filepath' do - let(:filepath) { 'some_file_path' } - let(:recipe) { Recipe.new(code, filepath) } - - it 'returns the assigned file path' do - expect(recipe.filepath).to eq filepath - end - end - - describe '#evaluate' do - let(:env) { double('env').as_null_object } - - it 'builds a recipe DSL sandbox' do - expect(Recipe::DSL).to receive(:new).once.with(code).and_call_original - recipe.evaluate(env) - end - - it 'evaluates the DSL sandbox with the environment given as argument' do - dsl = double('dsl').as_null_object - allow(Recipe::DSL).to receive(:new) { dsl } - expect(dsl).to receive(:evaluate) - recipe.evaluate(env) - end - - it 'evaluates the DSL sandbox tasks' do - task = double('task') - allow(Task).to receive(:new) { task } - dsl = Recipe::DSL.new { task(:some_task) } - allow(Recipe::DSL).to receive(:new) { dsl } - expect(task).to receive(:evaluate).with(env) - recipe.evaluate(env) - end - - it 'assigns the evaluated tasks' do - dsl = Recipe::DSL.new { task(:some_task) { } } - allow(Recipe::DSL).to receive(:new) { dsl } - recipe.evaluate(env) - expect(recipe.tasks.first.name).to eq :some_task + it 'assigns the tasks' do + expect(recipe.tasks).to eq tasks + end end end end