diff --git a/features/tests/negated_test.feature b/features/tests/negated_test.feature new file mode 100644 index 0000000..e494f4b --- /dev/null +++ b/features/tests/negated_test.feature @@ -0,0 +1,44 @@ +@sshd +Feature: negated test prefix (no_) + + Scenario: prefixed test fails when non-prefixed test is successful + Given a recipe with: + """ + target 'some_host.test' + + task :successful_test do + condition { has_env :shell } + + echo 'successful_test' + end + + task :negated_test do + condition { no_has_env :shell } + + echo 'negated_test' + end + """ + When I successfully execute the recipe + Then the output must contain "successful_test" + And the output must not contain "negated_test" + + Scenario: prefixed test fails when non-prefixed test is failing + Given a recipe with: + """ + target 'some_host.test' + + task :failing_test do + condition { has_env :inexistent_var } + + echo 'failing_test' + end + + task :negated_test do + condition { no_has_env :inexistent_var } + + echo 'negated_test' + end + """ + When I successfully execute the recipe + Then the output must not contain "failing_test" + And the output must contain "negated_test" diff --git a/lib/producer/core/condition.rb b/lib/producer/core/condition.rb index c74b8ba..46a6f7a 100644 --- a/lib/producer/core/condition.rb +++ b/lib/producer/core/condition.rb @@ -14,7 +14,7 @@ module Producer def met? return !!@return_value if @tests.empty? - @tests.each { |t| return false unless t.success? } + @tests.each { |t| return false unless t.pass? } true end diff --git a/lib/producer/core/condition/dsl.rb b/lib/producer/core/condition/dsl.rb index 46da5fe..36f2161 100644 --- a/lib/producer/core/condition/dsl.rb +++ b/lib/producer/core/condition/dsl.rb @@ -13,6 +13,9 @@ module Producer define_method(keyword) do |*args| @tests << klass.new(@env, *args) end + define_method("no_#{keyword}") do |*args| + @tests << klass.new(@env, *args, negated: true) + end end end diff --git a/lib/producer/core/test.rb b/lib/producer/core/test.rb index 4183b3a..b60c5dd 100644 --- a/lib/producer/core/test.rb +++ b/lib/producer/core/test.rb @@ -3,9 +3,18 @@ module Producer class Test attr_reader :env, :arguments - def initialize(env, *arguments) + def initialize(env, *arguments, negated: false) @env = env @arguments = arguments + @negated = negated + end + + def negated? + @negated + end + + def pass? + verify ^ negated? end end end diff --git a/lib/producer/core/tests/has_env.rb b/lib/producer/core/tests/has_env.rb index 8d5fc8f..fbdcc3f 100644 --- a/lib/producer/core/tests/has_env.rb +++ b/lib/producer/core/tests/has_env.rb @@ -2,7 +2,7 @@ module Producer module Core module Tests class HasEnv < Test - def success? + def verify env.remote.environment.has_key? arguments.first.to_s.upcase end end diff --git a/lib/producer/core/tests/has_file.rb b/lib/producer/core/tests/has_file.rb index fcec3d6..90f8459 100644 --- a/lib/producer/core/tests/has_file.rb +++ b/lib/producer/core/tests/has_file.rb @@ -2,7 +2,7 @@ module Producer module Core module Tests class HasFile < Test - def success? + def verify env.remote.fs.has_file? arguments.first end end diff --git a/spec/producer/core/condition/dsl_spec.rb b/spec/producer/core/condition/dsl_spec.rb index 5ab38b9..e9f486a 100644 --- a/spec/producer/core/condition/dsl_spec.rb +++ b/spec/producer/core/condition/dsl_spec.rb @@ -49,6 +49,10 @@ module Producer::Core it 'defines a new test keyword' do expect(dsl).to respond_to :some_test end + + it 'defines the negated test' do + expect(dsl).to respond_to :no_some_test + end end describe '#initialize' do @@ -96,6 +100,16 @@ module Producer::Core dsl.evaluate expect(dsl.tests).to include(some_test) end + + context 'when keyword is prefixed with "no_"' do + let(:block) { proc { no_some_test :some, :args } } + + it 'builds a negated test' do + expect(some_test_class) + .to receive(:new).with(env, :some, :args, negated: true) + dsl.evaluate + end + end end end end diff --git a/spec/producer/core/test_spec.rb b/spec/producer/core/test_spec.rb index 3c2778e..1746ef4 100644 --- a/spec/producer/core/test_spec.rb +++ b/spec/producer/core/test_spec.rb @@ -14,6 +14,18 @@ module Producer::Core it 'assigns the arguments' do expect(test.instance_eval { @arguments }).to eq arguments end + + it 'assigns negated as false by default' do + expect(test.instance_eval { @negated }).to be false + end + + context 'when negated option is true' do + subject(:test) { Test.new(env, *arguments, negated: true) } + + it 'assigns negated as true' do + expect(test.instance_eval { @negated }).to be true + end + end end describe '#env' do @@ -27,5 +39,45 @@ module Producer::Core expect(test.arguments).to eq arguments end end + + describe '#negated?' do + it 'returns false' do + expect(test.negated?).to be false + end + + context 'when test is negated' do + subject(:test) { Test.new(env, *arguments, negated: true) } + + it 'returns true' do + expect(test.negated?).to be true + end + end + end + + describe '#pass?' do + it 'returns true when #verify is true' do + allow(test).to receive(:verify) { true } + expect(test.pass?).to be true + end + + it 'returns false when #verify is false' do + allow(test).to receive(:verify) { false } + expect(test.pass?).to be false + end + + context 'when test is negated' do + subject(:test) { Test.new(env, *arguments, negated: true) } + + it 'returns false when #verify is true' do + allow(test).to receive(:verify) { true } + expect(test.pass?).to be false + end + + it 'returns true when #verify is false' do + allow(test).to receive(:verify) { false } + expect(test.pass?).to be true + end + end + end end end diff --git a/spec/producer/core/tests/has_env_spec.rb b/spec/producer/core/tests/has_env_spec.rb index 66b98c7..e79ee01 100644 --- a/spec/producer/core/tests/has_env_spec.rb +++ b/spec/producer/core/tests/has_env_spec.rb @@ -10,7 +10,7 @@ module Producer::Core expect(has_env).to be_a Test end - describe '#success?' do + describe '#verify' do let(:environment) { double('environment') } before do @@ -19,22 +19,22 @@ module Producer::Core it 'stringifies the queried variable name' do expect(environment).to receive(:has_key?).with(kind_of(String)) - has_env.success? + has_env.verify end it 'upcases the queried variable name' do expect(environment).to receive(:has_key?).with('SOME_VARIABLE_NAME') - has_env.success? + has_env.verify end it 'returns true when remote environment var is defined' do allow(environment).to receive(:has_key?) { true } - expect(has_env.success?).to be true + expect(has_env.verify).to be true end it 'returns false when remote environment var is not defined' do allow(environment).to receive(:has_key?) { false } - expect(has_env.success?).to be false + expect(has_env.verify).to be false end end end diff --git a/spec/producer/core/tests/has_file_spec.rb b/spec/producer/core/tests/has_file_spec.rb index 4c2e73e..9347854 100644 --- a/spec/producer/core/tests/has_file_spec.rb +++ b/spec/producer/core/tests/has_file_spec.rb @@ -10,18 +10,18 @@ module Producer::Core expect(has_file).to be_a Test end - describe '#success?', :ssh do + describe '#verify', :ssh do before { sftp_story } it 'delegates the call on remote FS' do expect(env.remote.fs).to receive(:has_file?).with(filepath) - has_file.success? + has_file.verify end it 'returns the file existence' do existence = double('existence') allow(env.remote.fs).to receive(:has_file?) { existence } - expect(has_file.success?).to be existence + expect(has_file.verify).to be existence end end end diff --git a/spec/support/tests_helpers.rb b/spec/support/tests_helpers.rb index 61494b5..7e982d1 100644 --- a/spec/support/tests_helpers.rb +++ b/spec/support/tests_helpers.rb @@ -1,9 +1,9 @@ module TestsHelpers def test_ok - double('test', success?: true) + double('test', pass?: true) end def test_ko - double('test', success?: false) + double('test', pass?: false) end end