require 'shoulda/private_helpers' module Shoulda # :nodoc: module Macros # Deprecated. # # Macro that creates a test asserting a change between the return value # of a block that is run before and after the current setup block # is run. This is similar to Active Support's assert_difference # assertion, but supports more than just numeric values. See also # should_not_change. # # The passed description will be used when generating the test name and failure messages. # # Example: # # context "Creating a post" do # setup { Post.create } # should_change("the number of posts", :by => 1) { Post.count } # end # # As shown in this example, the :by option expects a numeric # difference between the before and after values of the expression. You # may also specify :from and :to options: # # should_change("the number of posts", :from => 0, :to => 1) { Post.count } # should_change("the post title", :from => "old", :to => "new") { @post.title } # # Combinations of :by, :from, and :to are allowed: # # # Assert the value changed in some way: # should_change("the post title") { @post.title } # # # Assert the value changed to anything other than "old:" # should_change("the post title", :from => "old") { @post.title } # # # Assert the value changed to "new:" # should_change("the post title", :to => "new") { @post.title } # # This macro was deprecated because these tests aren't as valuable as # alternative tests that explicitly test the final state. # # Consider an alternative: # # context "updating a post" do # setup do # @post = Post.create(:title => "old") # put :update, :post => {:title => "new"}, :id => @post.to_param # end # should "update the title" do # assert_equal "new", @post.reload.title # end # end def should_change(description, options = {}, &block) ::ActiveSupport::Deprecation.warn("Not considered a useful test. Instead, test the end state explicitly.") by, from, to = get_options!([options], :by, :from, :to) stmt = "change #{description}" stmt << " from #{from.inspect}" if from stmt << " to #{to.inspect}" if to stmt << " by #{by.inspect}" if by before = lambda { @_before_should_change = block.bind(self).call } should stmt, :before => before do old_value = @_before_should_change new_value = block.bind(self).call assert_operator from, :===, old_value, "#{description} did not originally match #{from.inspect}" if from assert_not_equal old_value, new_value, "#{description} did not change" unless by == 0 assert_operator to, :===, new_value, "#{description} was not changed to match #{to.inspect}" if to assert_equal old_value + by, new_value if by end end # Deprecated. # # Macro that creates a test asserting no change between the return value # of a block that is run before and after the current setup block # is run. This is the logical opposite of should_change. # # The passed description will be used when generating the test name and failure message. # # Example: # # context "Updating a post" do # setup { @post.update_attributes(:title => "new") } # should_not_change("the number of posts") { Post.count } # end # # This macro was deprecated because these tests aren't as valuable as # alternative tests that explicitly test the final state. # # Consider an alternative: # # context "updating a post" do # setup do # @post = Post.create(:title => "old") # put :update, :post => {:title => ""}, :id => @post.to_param # end # should "not update the title" do # assert_equal "old", @post.reload.title # end # end def should_not_change(description, &block) ::ActiveSupport::Deprecation.warn("Not considered a useful test. Instead, test the end state explicitly.") before = lambda { @_before_should_not_change = block.bind(self).call } should "not change #{description}", :before => before do new_value = block.bind(self).call assert_equal @_before_should_not_change, new_value, "#{description} changed" end end # Deprecated. # # Macro that creates a test asserting that a record of the given class was # created. # # Example: # # context "creating a post" do # setup { Post.create(post_attributes) } # should_create :post # end def should_create(class_name) ::ActiveSupport::Deprecation.warn should_change_record_count_of(class_name, 1, 'create') end # Deprecated. # # Macro that creates a test asserting that a record of the given class was # destroyed. # # Example: # # context "destroying a post" do # setup { Post.first.destroy } # should_destroy :post # end def should_destroy(class_name) ::ActiveSupport::Deprecation.warn should_change_record_count_of(class_name, -1, 'destroy') end private def should_change_record_count_of(class_name, amount, action) # :nodoc: klass = class_name.to_s.camelize.constantize before = lambda do @_before_change_record_count = klass.count end human_name = class_name.to_s.humanize.downcase should "#{action} a #{human_name}", :before => before do assert_equal @_before_change_record_count + amount, klass.count, "Expected to #{action} a #{human_name}" end end include Shoulda::Private end end