From 5cc16552ab4538dbcc2b9f7d6f60fa8d545928bb Mon Sep 17 00:00:00 2001 From: Artur Beljajev Date: Sat, 31 Mar 2018 22:42:54 +0300 Subject: [PATCH] Backport Rails 5 test assertions #799 --- test/support/rails5_assetions.rb | 94 ++++++++++++++++++++++++++++++++ test/test_helper.rb | 1 + 2 files changed, 95 insertions(+) create mode 100644 test/support/rails5_assetions.rb diff --git a/test/support/rails5_assetions.rb b/test/support/rails5_assetions.rb new file mode 100644 index 000000000..55a2e8dc6 --- /dev/null +++ b/test/support/rails5_assetions.rb @@ -0,0 +1,94 @@ +module ActiveSupport + module Testing + module Assertions + UNTRACKED = Object.new # :nodoc: + + # Assertion that the result of evaluating an expression is changed before + # and after invoking the passed in block. + # + # assert_changes 'Status.all_good?' do + # post :create, params: { status: { ok: false } } + # end + # + # You can pass the block as a string to be evaluated in the context of + # the block. A lambda can be passed for the block as well. + # + # assert_changes -> { Status.all_good? } do + # post :create, params: { status: { ok: false } } + # end + # + # The assertion is useful to test side effects. The passed block can be + # anything that can be converted to string with #to_s. + # + # assert_changes :@object do + # @object = 42 + # end + # + # The keyword arguments :from and :to can be given to specify the + # expected initial value and the expected value after the block was + # executed. + # + # assert_changes :@object, from: nil, to: :foo do + # @object = :foo + # end + # + # An error message can be specified. + # + # assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do + # post :create, params: { status: { incident: true } } + # end + def assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block) + exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) } + + before = exp.call + retval = yield + + unless from == UNTRACKED + error = "#{expression.inspect} isn't #{from.inspect}" + error = "#{message}.\n#{error}" if message + assert from === before, error + end + + after = exp.call + + if to == UNTRACKED + error = "#{expression.inspect} didn't changed" + error = "#{message}.\n#{error}" if message + assert_not_equal before, after, error + else + error = "#{expression.inspect} didn't change to #{to}" + error = "#{message}.\n#{error}" if message + assert to === after, error + end + + retval + end + + # Assertion that the result of evaluating an expression is changed before + # and after invoking the passed in block. + # + # assert_no_changes 'Status.all_good?' do + # post :create, params: { status: { ok: true } } + # end + # + # An error message can be specified. + # + # assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do + # post :create, params: { status: { ok: false } } + # end + def assert_no_changes(expression, message = nil, &block) + exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) } + + before = exp.call + retval = yield + after = exp.call + + error = "#{expression.inspect} did change to #{after}" + error = "#{message}.\n#{error}" if message + assert_equal before, after, error + + retval + end + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 7bde0991d..d85d5de73 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -11,6 +11,7 @@ require 'minitest/mock' require 'capybara/rails' require 'capybara/minitest' require 'webmock/minitest' +require 'support/rails5_assetions' # Remove once upgraded to Rails 5 Setting.address_processing = false