require  File.dirname(__FILE__) + '/joinfix_test_helper'
require 'joinfix'

class NoJoinFixMigration < ActiveRecord::Migration
  def self.up
	create_table :no_join_fixes do |t|
		t.column :field, :string
	end	
	create_table :omap_no_join_fixes do |t|
		t.column :field, :string
	end	
  end

  def self.down
	drop_table :no_join_fixes
	drop_table :omap_no_join_fixes
  end
end

class NoJoinFix < ActiveRecord::Base
end

class OmapNoJoinFix < ActiveRecord::Base
end

class JoinFixTest < Test::Unit::TestCase
	fixtures :no_join_fixes, :omap_no_join_fixes
	
	attr_reader :joinfix, :parent, :child
	def setup
		@joinfix = JoinFix.new("joinfix")
		@parent = JoinFix.new("parent_entry", :name => "parent_name")
		@child =  JoinFix.new("child_entry", :name => "child_name")
	end
	
	def teardown
	end
	
	#
	# join tests
	#
	
	# Note that for all of these tests, the envisioned fixture looks like:
	# parent_entry:
	#  name: parent_name
	#  association:
	#    child_entry:
	#      name: child_name
	#
	# This template produces the parent and child entries.  The configurations may be derived from
	# reflection on the given association for the parent table ActiveRecord::Base class.
	#
	
	# join_belongs_to  tests
	def test_join_belongs_to
		assert_nil parent.join_belongs_to(child, :foreign_key => "foreign_key", :child_table => "child_table")
		
		assert_equal({:name => "parent_name", ["foreign_key", "child_table"] => "child_entry"}, parent)
		assert_equal({:name => "child_name"}, child)
	end

	def test_join_belongs_to_when_polymorphic
		assert_nil parent.join_belongs_to(child, 
			:polymorphic => true, 
			:associable => "associable", 
			:foreign_key => "associable", 
			:child_table => "child_table", 
			:child_class => "ChildTable" )
		
		assert_equal({
			:name => "parent_name", 
			["associable", "child_table"] => "child_entry",
			"associable_type" => "ChildTable"}, parent)
		assert_equal({:name => "child_name"}, child)
	end
	
	def test_join_belongs_to_validates_inclusion_of_required_configurations
		assert_raise(ArgumentError) { joinfix.join_belongs_to(nil, {}) }
		assert_raise(ArgumentError) { joinfix.join_has_one(nil, :child_table => "child_table") }
	end
	
	# join_has_one  tests
	def test_join_has_one
		assert_nil parent.join_has_one(child, 
			:foreign_key => "foreign_key", 
			:parent_table => "parent_table")
		
		assert_equal({:name => "parent_name"}, parent)
		assert_equal({:name => "child_name", ["foreign_key", "parent_table"] => "parent_entry"}, child)
	end
	
	def test_join_has_one_validates_inclusion_of_required_configurations
		assert_raise(ArgumentError) { joinfix.join_has_one(nil, {}) }
		assert_raise(ArgumentError) { joinfix.join_has_one(nil, :parent_table => "parent_table") }
	end
	
	# join_has_and_belongs_to_many tests
	def test_join_has_and_belongs_to_many	
		join = parent.join_has_and_belongs_to_many(child, 
				:foreign_key => "foreign_key", 
				:parent_table => "parent_table",
				:association_foreign_key => "association_foreign_key",
				:child_table => "child_table")
		
		assert_equal({:name => "parent_name"}, parent)
		assert_equal({:name => "child_name"}, child)
		assert_equal({["foreign_key", "parent_table"] => "parent_entry", ["association_foreign_key", "child_table"] => "child_entry"}, join)
	end
	
	def test_join_has_and_belongs_to_many_validates_inclusion_of_required_configurations
		assert_raise(ArgumentError) { joinfix.join_has_and_belongs_to_many(nil, {}) }
		assert_raise(ArgumentError) { joinfix.join_has_one(nil, :parent_table => "parent_table") }
	end
	
	# join_has_many test
	def test_join_has_many	
		assert_nil parent.join_has_many(child, 
			:foreign_key => "foreign_key", 
			:parent_table => "parent_table")
		
		assert_equal({:name => "parent_name"}, parent)
		assert_equal({:name => "child_name", ["foreign_key", "parent_table"] => "parent_entry"}, child)
	end
	
	def test_join_has_many_as
		assert_nil parent.join_has_many(child, 
			:as => "associable", 
			:foreign_key => "associable", 
			:parent_table => "parent_table", 
			:parent_class => "ParentTable")
		
		assert_equal({:name => "parent_name"}, parent)
		assert_equal({
			:name => "child_name", 
			["associable", "parent_table"] => "parent_entry",
			"associable_type" => "ParentTable"}, child)
	end
	
	def test_join_has_many_through
		join = parent.join_has_many(child, 
				:through => "some_join_table",
				:foreign_key => "foreign_key", 
				:parent_table => "parent_table",
				:association_foreign_key => "association_foreign_key", 
				:child_table => "child_table")
		
		assert_equal({:name => "parent_name"}, parent)
		assert_equal({:name => "child_name"}, child)
		assert_equal({["foreign_key", "parent_table"] => "parent_entry", ["association_foreign_key", "child_table"] => "child_entry"}, join)
	end
	
  def test_join_has_many_validates_inclusion_of_required_configurations
		assert_raise(ArgumentError) { joinfix.join_has_many(nil, {}) }
		assert_raise(ArgumentError) { joinfix.join_has_one(nil, :parent_table => "parent_table") }
	end
  
	#
	# test extract_if
	#
	
	def test_extract_if_with_no_inputs
		joinfix = JoinFix.new("extraction", :do_not_extract=> 'value')
		
		extracted = joinfix.extract_if 
		
		# in this case there are no keys, so no pairs are extracted
		assert_equal({}, extracted)
		assert_equal({:do_not_extract => 'value'}, joinfix)
	end
	
	def test_extract_if_using_allowed_keys
		joinfix = JoinFix.new("extraction", :do_not_extract => 'value', :extract => 'value')
		
		extracted = joinfix.extract_if :extract
		
		assert_equal({:extract=> 'value'}, extracted)
		assert_equal({:do_not_extract => 'value'}, joinfix)
	end
	
	def test_extract_if_using_block
		joinfix = JoinFix.new("extraction", :do_not_extract => 'value', :extract => 'value')
		
		extracted = joinfix.extract_if do |key, value|
			key == :extract
		end
		
		assert_equal({:extract => 'value'}, extracted)
		assert_equal({:do_not_extract => 'value'}, joinfix)
	end
	
	#
	#  test extract_unless
	#
	
	def test_extract_unless_with_no_inputs
		joinfix = JoinFix.new("extraction", :extract=> 'value')
		
		extracted = joinfix.extract_unless
		
		# in this case there are no allowed keys, so all pairs are extracted
		assert_equal({:extract => 'value'}, extracted)
		assert_equal({}, joinfix)
	end
	
	def test_extract_unless_using_allowed_keys
		joinfix = JoinFix.new("extraction", :do_not_extract => 'value', :extract => 'value')
		
		extracted = joinfix.extract_unless :do_not_extract
		
		assert_equal({:extract=> 'value'}, extracted)
		assert_equal({:do_not_extract => 'value'}, joinfix)
	end
	
	def test_extract_unless_using_block
		joinfix = JoinFix.new("extraction", :do_not_extract => 'value', :extract => 'value')
		
		extracted = joinfix.extract_unless do |key, value|
			key == :do_not_extract
		end
		
		assert_equal({:extract => 'value'}, extracted)
		assert_equal({:do_not_extract => 'value'}, joinfix)
	end
end