#--
# Copyright (c) 2007 Robert S. Thau, Smartleaf, Inc.
# 
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
module RestTestBoilerplate

  def model_name;       model_class.name.underscore;              end
  def resource_sing;    model_name.to_sym;                        end
  def resource_id;      (model_name + '_id').to_sym;              end
  def resource_pl;      model_name.pluralize.to_sym;              end
  def resource_path;    (model_name           + '_path').to_sym;  end
  def resources_path;   (model_name.pluralize + '_path').to_sym;  end

  def ids_for_update; [1];       end
  def enclosing_opts; return {}; end

  def setup
    @controller = controller_class.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new

    # Re-raise errors caught by the controller.
    controller_class.class_eval 'def rescue_action(e) raise e end'
  end

  def test_should_get_index
    get :index, enclosing_opts
    assert_response :success
    assert_not_nil assigns(resource_pl)
  end

  def test_should_get_new
    get :new, enclosing_opts
    assert_response :success
  end

  def test_should_create
    assert_difference("#{model_class.name}.count") do
      post :create, 
           enclosing_opts.merge( resource_sing => resource_create_inputs )
      assert_valid assigns(resource_sing)
    end

    assert_redirected_to( self.send( resource_path, 
                          enclosing_opts.merge(:id => assigns(resource_sing))))
  end

  def test_should_show
    ids_for_update.each do |id|
      get :show, enclosing_opts.merge( :id => id.to_s )
      assert_response :success
    end
  end

  def test_should_get_edit
    ids_for_update.each do |id|
      get :edit, enclosing_opts.merge( :id => id.to_s )
      assert_response :success
    end
  end

  def test_should_update
    ids_for_update.each do |id|
      put :update,
          enclosing_opts.merge( resource_sing => resource_edit_inputs,
                                :id => id )
      assert_valid assigns(resource_sing)
      assert_redirected_to( self.send( resource_path, 
                            enclosing_opts.merge(:id=>assigns(resource_sing))))
    end
  end

  def test_should_destroy
    ids_for_update.each do |id|
      assert_difference("#{model_class.name}.count", -1) do
        delete :destroy, enclosing_opts.merge( :id => id.to_s )
      end

      assert_redirected_to( self.send(  resources_path, enclosing_opts ))
    end
  end

end


