module ThoughtBot::Shoulda::Controller::XML::ClassMethods

def make_create_xml_tests(res) # :nodoc:

:nodoc:
def make_create_xml_tests(res) # :nodoc:
  context "on POST to #{controller_name_from_class}#create as xml" do
    setup do
      request_xml
      parent_params = make_parent_params(res)
      @count = res.klass.count
      post :create, parent_params.merge(res.object => res.create.params)
    end
    if res.denied.actions.include?(:create)
      should_respond_with 401
      should_not_assign_to res.object

      should "not create new record" do
        assert_equal @count, res.klass.count
      end          
    else
      should_assign_to res.object
      should "not have errors on @#{res.object}" do
        assert_equal [], pretty_error_messages(assigns(res.object)), "@#{res.object} has errors:"            
      end
    end      
  end
end

def make_destroy_xml_tests(res) # :nodoc:

:nodoc:
def make_destroy_xml_tests(res) # :nodoc:
  context "on DELETE to #{controller_name_from_class}#destroy as xml" do
    setup do
      request_xml
      @record = get_existing_record(res)
      parent_params = make_parent_params(res, @record)
      delete :destroy, parent_params.merge({ res.identifier => @record.to_param })
    end
    if res.denied.actions.include?(:destroy)
      should_respond_with 401

      should "not destroy record" do
        assert @record.reload
      end
    else
      should "destroy record" do
        assert_raises(::ActiveRecord::RecordNotFound, "@#{res.object} was not destroyed.") do
          @record.reload
        end
      end
    end
  end
end

def make_edit_xml_tests(res) # :nodoc:

:nodoc:
def make_edit_xml_tests(res) # :nodoc:
  # XML doesn't need an :edit action
end

def make_index_xml_tests(res) # :nodoc:

:nodoc:
def make_index_xml_tests(res) # :nodoc:
  context "on GET to #{controller_name_from_class}#index as xml" do
    setup do
      request_xml
      parent_params = make_parent_params(res)
      get(:index, parent_params)          
    end
    if res.denied.actions.include?(:index)
      should_not_assign_to res.object.to_s.pluralize
      should_respond_with 401          
    else
      should_respond_with :success
      should_respond_with_xml_for res.object.to_s.pluralize
      should_assign_to res.object.to_s.pluralize
    end
  end
end

def make_new_xml_tests(res) # :nodoc:

:nodoc:
def make_new_xml_tests(res) # :nodoc:
  # XML doesn't need a :new action
end

def make_show_xml_tests(res) # :nodoc:

:nodoc:
def make_show_xml_tests(res) # :nodoc:
  context "on GET to #{controller_name_from_class}#show as xml" do
    setup do
      request_xml
      record = get_existing_record(res)
      parent_params = make_parent_params(res, record)
      get :show, parent_params.merge({ res.identifier => record.to_param })          
    end
    if res.denied.actions.include?(:show)
      should_not_assign_to res.object
      should_respond_with 401
    else
      should_assign_to res.object          
      should_respond_with :success
      should_respond_with_xml_for res.object
    end
  end
end

def make_update_xml_tests(res) # :nodoc:

:nodoc:
def make_update_xml_tests(res) # :nodoc:
  context "on PUT to #{controller_name_from_class}#update as xml" do
    setup do
      request_xml
      @record = get_existing_record(res)
      parent_params = make_parent_params(res, @record)
      put :update, parent_params.merge(res.identifier => @record.to_param, res.object => res.update.params)
    end
    if res.denied.actions.include?(:update)
      should_not_assign_to res.object
      should_respond_with 401
    else
      should_assign_to res.object
      should "not have errors on @#{res.object}" do
        assert_equal [], assigns(res.object).errors.full_messages, "@#{res.object} has errors:"
      end
    end
  end
end

def should_respond_with_xml_for(name = nil)

and that the XML contains ++ as the root element.
Macro that creates a test asserting that the controller responded with an XML content-type
def should_respond_with_xml_for(name = nil)
  should "have ContentType set to 'application/xml'" do
    assert_xml_response
  end
  
  if name
    should "return <#{name}/> as the root element" do
      body = @response.body.first(100).map {|l| "  #{l}"}
      assert_select name.to_s.dasherize, 1, "Body:\n#{body}...\nDoes not have <#{name}/> as the root element."
    end
  end
end