require File.join(File.dirname(__FILE__), '../test_helper')

class FacetedSearchTest < Test::Unit::TestCase
  
  fixtures :electronics
  
  # The tests below are for faceted search, but make sure you setup
  # the fields on your model you'd like to index as a facet field:
  # 
  # class Electronic < ActiveRecord::Base
  #   acts_as_solr :facets => [:category, :manufacturer]  
  # end
  # 
  # A basic faceted search using just one facet field
  def test_faceted_search_basic
    records = Electronic.find_by_solr "memory", :facets => {:fields =>[:category]}
    ipod_video = Electronic.find 1
    assert_equal 4, records.docs.size
    assert records.docs.include?(ipod_video)
    assert_equal({"category_facet" => [["Electronics", 1], ["Hard Drive", 1], ["Memory", 2]]}, 
                 records.facets['facet_fields'])
  end
  
  # Making sure the empty result returned what we expected
  def test_faceted_search_no_matches
    records = Electronic.find_by_solr "not found", :facets => { :fields => [:category]}
    assert_equal [], records.docs
    assert_equal [], records.facets['facet_fields']
  end
  
  # A basic faceted search using multiple facet fields
  def test_faceted_search_multiple_fields
    records = Electronic.find_by_solr "memory", :facets => {:fields =>[:category, :manufacturer]}
    assert_equal 4, records.docs.size
    assert_equal({"category_facet" => [["Electronics", 1], ["Hard Drive", 1], ["Memory", 2]],
                  "manufacturer_facet" => [["A-DATA Technology Inc.", 1],
                    ["Apple Computer Inc.", 1],
                    ["Corsair Microsystems Inc.", 1],
                    ["Dell, Inc", 0],
                    ["Samsung Electronics Co. Ltd.", 1]]}, records.facets['facet_fields'])
  end
  
  # A basic faceted search using facet queries to get counts. 
  # Here are the facets search query meaning:
  # "price:[* TO 200]" - Price up to 200
  # "price:[200 TO 500]" - Price from 200 to 500
  # "price:[500 TO *]" - Price higher than 500
  def test_facet_search_with_query
    records = Electronic.find_by_solr "memory", :facets => {:query => ["price:[* TO 200.00]",
                                                                          "price:[200.00 TO 500.00]",
                                                                          "price:[500.00 TO *]"]}
    assert_equal 4, records.docs.size
    assert_equal({"facet_queries" => {"price_rf:[* TO 200.00]"=>2,
                                      "price_rf:[200.00 TO 500.00]"=>1,
                                      "price_rf:[500.00 TO *]"=>1}, 
                   "facet_ranges" => {}, "facet_fields" => {}, "facet_dates" => {}}, records.facets)
  end
  
  # Faceted search specifying the query and fields
  def test_facet_search_with_query_and_field
    records = Electronic.find_by_solr "memory", :facets => {:query => ["price:[* TO 200.00]",
                                                                          "price:[200.00 TO 500.00]",
                                                                          "price:[500.00 TO *]"],
                                                               :fields => [:category, :manufacturer]}
    
    q = records.facets["facet_queries"]
    assert_equal 2, q["price_rf:[* TO 200.00]"]
    assert_equal 1, q["price_rf:[500.00 TO *]"]
    assert_equal 1, q["price_rf:[200.00 TO 500.00]"]
  
    f = records.facets["facet_fields"]
    f["category_facet"] = Hash[f["category_facet"]]
    assert_equal 1, f["category_facet"]["Electronics"]
    assert_equal 2, f["category_facet"]["Memory"]
    assert_equal 1, f["category_facet"]["Hard Drive"]
    f["manufacturer_facet"] = Hash[f["manufacturer_facet"]]
    assert_equal 1, f["manufacturer_facet"]["Samsung Electronics Co. Ltd."]
    assert_equal 1, f["manufacturer_facet"]["Corsair Microsystems Inc."]
    assert_equal 1, f["manufacturer_facet"]["A-DATA Technology Inc."]
    assert_equal 1, f["manufacturer_facet"]["Apple Computer Inc."]
  end
  
  # Faceted searches with :sort and :zeros options turned on/off
  def test_faceted_search_using_zero_and_sort
    records = Electronic.find_by_solr "memory", :facets => {:fields =>[:category]}
    assert_equal({"category_facet"=>[["Electronics", 1], ["Hard Drive", 1], ["Memory", 2]]}, records.facets['facet_fields'])
    
    records = Electronic.find_by_solr "memory", :facets => {:sort => true, :fields =>[:category]}
    assert_equal({"category_facet"=>[["Memory", 2], ["Electronics", 1], ["Hard Drive", 1]]}, records.facets['facet_fields'])
    
    records = Electronic.find_by_solr "memory", :facets => {:fields =>[:manufacturer]}
    assert_equal({"manufacturer_facet" => [["A-DATA Technology Inc.", 1],
                   ["Apple Computer Inc.", 1],
                   ["Corsair Microsystems Inc.", 1],
                   ["Dell, Inc", 0],
                   ["Samsung Electronics Co. Ltd.", 1]]}, records.facets['facet_fields'])
  
    records = Electronic.find_by_solr "memory", :facets => {:zeros => false, :fields =>[:manufacturer]}
    assert_equal({"manufacturer_facet" => [["A-DATA Technology Inc.", 1],
                   ["Apple Computer Inc.", 1],
                   ["Corsair Microsystems Inc.", 1],
                   ["Samsung Electronics Co. Ltd.", 1]]}, records.facets['facet_fields'])
  end
  
  # Faceted search with 'drill-down' option being passed.
  # The :browse option receives the argument in the format:
  # "facet_field:term". You can drill-down to as many
  # facet fields as you like
  def test_faceted_search_with_drill_down
    records = Electronic.find_by_solr "memory", :facets => {:fields =>[:category]}
    assert_equal 4, records.docs.size
    assert_equal({"category_facet"=>[["Electronics", 1], ["Hard Drive", 1], ["Memory", 2]]}, records.facets['facet_fields'])
    
    records = Electronic.find_by_solr "memory", :facets => {:fields =>[:category],
                                                               :browse => "category:Memory",
                                                               :zeros => false}
    assert_equal 2, records.docs.size
    assert_equal({"category_facet"=>[["Memory", 2]]}, records.facets['facet_fields'])
  end
  
  def test_faceted_search_with_dates
    records = Electronic.find_by_solr "memory", :facets => {:dates => {:fields => [:created_at, :updated_at],
      :start => (Date.today - 7.years).strftime("%Y-%m-%dT%H:%M:%SZ"), :end => Date.today.strftime("%Y-%m-%dT%H:%M:%SZ"), :gap => '+1YEAR', :other => :all}}

    assert_equal 4, records.docs.size
    
    assert_equal 0, records.facets["facet_dates"]["created_at_d"]["after"]
    assert_equal 1, records.facets["facet_dates"]["created_at_d"]["before"]
    assert_equal 3, records.facets["facet_dates"]["created_at_d"]["between"]
    
    assert_equal 0, records.facets["facet_dates"]["updated_at_d"]["after"]
    assert_equal 0, records.facets["facet_dates"]["updated_at_d"]["before"]
    assert_equal 4, records.facets["facet_dates"]["updated_at_d"]["between"]
  end
  
  def test_faceted_search_with_dates_filter
    records = Electronic.find_by_solr "memory", :facets => {:dates => {:filter => ["updated_at:[#{(Date.today - 3.months).strftime("%Y-%m-%dT%H:%M:%SZ")} TO NOW-1MONTH/DAY]"]}}
    
    assert_equal 2, records.docs.size
    
    records.docs.each { |r|
      assert r.updated_at >= (Date.today - 3.month)
      assert r.updated_at <= (Date.today - 1.month)
    }
  end
  
  def test_faceted_search_with_dates_filter_and_facets
    # this is a very contrived example but gives us data to validate
    records = Electronic.find_by_solr "memory", :facets => {:dates => {:filter => ["updated_at:[#{(Date.today - 3.months).strftime("%Y-%m-%dT%H:%M:%SZ")} TO NOW-1MONTH/DAY]"],
      :fields => [:created_at, :updated_at], :start => 'NOW-2MONTHS/DAY', :end => 'NOW-1MONTH/DAY', :gap => '+1MONTH', :other => :all}}
    
    assert_equal 2, records.docs.size
    
    assert_equal 0, records.facets["facet_dates"]["created_at_d"]["after"]
    assert_equal 2, records.facets["facet_dates"]["created_at_d"]["before"]
    assert_equal 0, records.facets["facet_dates"]["created_at_d"]["between"]
    
    assert_equal 0, records.facets["facet_dates"]["updated_at_d"]["after"]
    assert_equal 1, records.facets["facet_dates"]["updated_at_d"]["before"]
    assert_equal 1, records.facets["facet_dates"]["updated_at_d"]["between"]
  end
end
