ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'test/rails' # from ZenTest, see http://zentest.rubyforge.org/
require 'test_help'

# for sphincter
require 'sphincter/search_stub'
ActiveRecord::Base.extend Sphincter::SearchStub

module TestHelpers
  
  # Add more helper methods to be used by all tests here...
  def sanity_check(message, condition)
    assert condition, "Sanity check failed: #{message}"
  end
  
  def assert_saves_okay(record)
    assert record.save, "save failed: #{record.errors.full_messages}"
  end
    
  # http://project.ioni.st/post/217#post-217
  #
  #  def test_new_publication
  #    assert_difference(Publication, :count) do
  #      post :create, :publication => {...}
  #      # ...
  #    end
  #  end
  # 
  def assert_difference(object, method = nil, message = nil, difference = 1)
    initial_value = object.send(method)
    yield
    assert_equal initial_value + difference,
      object.send(method), 
      message
  end
  
  def assert_no_difference(object, method, message = nil, &block)
    initial_value = object.send(method)
    yield
    assert_equal initial_value,
      object.send(method), 
      message
  end
  
  def assert_record_not_found(model, id)
    assert_raises(ActiveRecord::RecordNotFound){ model.find(id) }
  end
  
  # from http://blog.caboo.se/articles/2006/06/24/easier-model-validation-through-better-helper-methods
  def assert_invalid(model, attribute, *values)
    if values.empty?
      assert ! model.valid?, "Object is valid with #{attribute} value: #{model.send(attribute)}"
      assert ! model.save, "Object saved."
      assert model.errors.invalid?(attribute.to_s), "#{attribute} has no attached error"
    else
      values.flatten.each do |value|
        obj = model.dup
        obj.send("#{attribute}=", value)
        assert_invalid obj, attribute
      end
    end
  end

  def assert_valid(model, attribute=nil, *values)
    if values.empty?
      unless attribute.nil?
        assert model.valid?, "Object is not valid with #{attribute} value: #{model.send(attribute)}"
      else
        assert model.valid?, model.errors.full_messages
      end
      assert model.errors.empty?, model.errors.full_messages
    else
      m = model.dup # the recursion was confusing mysql
      values.flatten.each do |value|
        obj = m.dup
        obj.send("#{attribute}=", value)
        assert_valid(obj, attribute)
      end
    end
  end
  
  def assert_radio_button_is_checked(id)
    assert_tag :tag => "input", :attributes => {:id => id, :checked => "checked"}    
  end
  
  # http://blog.caboo.se/articles/2006/11/04/automatically-test-your-associations
  def check_associations(m)
    @m = m.new
    m.reflect_on_all_associations.each do |assoc|
      assert_nothing_raised("#{m}.#{assoc.name} caused an error") do
        @m.send(assoc.name, true)
      end
    end
    true
  end
  
end

class Test::Rails::TestCase
  
  # use convenince methods like login_as, assert_requires_login and assert_accepts_login
  include AuthenticatedTestHelper
  include TestHelpers

  # Transactional fixtures accelerate your tests by wrapping each test method
  # in a transaction that's rolled back on completion.  This ensures that the
  # test database remains unchanged so your fixtures don't have to be reloaded
  # between every test method.  Fewer database queries means faster tests.
  #
  # Read Mike Clark's excellent walkthrough at
  #   http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
  #
  # Every Active Record database supports transactions except MyISAM tables
  # in MySQL.  Turn off transactional fixtures in this case; however, if you
  # don't care one way or the other, switching from MyISAM to InnoDB tables
  # is recommended.
  self.use_transactional_fixtures = true

  # Instantiated fixtures are slow, but give you @david where otherwise you
  # would need people(:david).  If you don't want to migrate your existing
  # test cases which use the @david style and don't mind the speed hit (each
  # instantiated fixtures translates to a database query per test method),
  # then set this back to true.
  self.use_instantiated_fixtures  = false  
end

class AbstractTestCase < Test::Rails::TestCase
 def run(*args)
   return if @method_name == :default_test
   super 
 end
end

class ActionController::IntegrationTest
  include AuthenticatedTestHelper
  include TestHelpers
end 

# http://nubyonrails.com/articles/2006/04/07/test-your-helpers
require File.expand_path(File.dirname(__FILE__) + '/helper_testcase')
