require File.dirname(__FILE__) + '/../test_helper'
require 'mocha'

class CommentMetricsTest < Test::Rails::TestCase
  fixtures :ratings, :comments, :users, :topics, :readings

  # Readings
  def test_list_for_readings_not_explosive
    assert_nothing_raised{Comment.list_for(:readings)}
  end
  
  def test_list_for_readings_returns_five_items
    assert_equal(5, Comment.list_for(:readings).length)
  end
  
  def test_list_for_readings_returns_array
    assert_kind_of(Array, Comment.list_for(:readings))
  end
  
  def test_list_for_readings_returns_array_of_pairs
    results = Comment.list_for(:readings)
    results.each {|row| assert_equal(2, row.length) }
    results.each do|comment, value|
       assert_kind_of(Integer, value)
       assert_kind_of(Comment, comment)
    end
  end
  
  def test_list_for_readings_returns_empty_array_when_nothing_found
    Comment.delete_all
    Reading.delete_all
    assert_kind_of(Array, Comment.list_for(:readings))
  end
  
  def test_list_for_readings_sorts_by_readings
    results = Comment.list_for(:readings)
    assert_equal(5, results.first[0].id)
    assert_equal(6, results.last[0].id)
  end
  
  def test_list_for_readings_has_correct_values
    results = Comment.list_for(:readings)
    results.each do |comment, value|
      assert_equal(comment.readings.count, value, "Comment #{comment.id} readings off")
    end
  end
  
  def test_list_for_readings_includes_removed_comments
    Comment.update(5, :removed => 1)
    assert_equal(5, Comment.list_for(:readings).first[0].id)
  end
  
  def test_list_for_readings_scopped_to_topic
    results = Comment.list_for(:readings, :topic => 1)
    assert(results.all?{|c, v|  c.topic_id == 1})
  end
  
  def test_list_for_readings_scopped_to_time
    results = Comment.list_for(:readings, :max_age => 24)
    assert(results.all? do |c, v|                   # each comment needs
      c.readings.any? do|r|                        # at least 1 
       r.created_at && r.created_at > 24.hours.ago # recent rating
    end
    end)
  end
  
  def test_list_for_readings_reverse
    results = Comment.list_for(:readings, :reverse => true)
    assert_equal(6, results.first[0].id)
    assert_equal(5, results.last[0].id)
  end

  # Rated
  def test_list_for_rated_not_explosive
    assert_nothing_raised{Comment.list_for(:rated)}
  end

  def test_list_for_rated_returns_five_items
    assert_equal(5, Comment.list_for(:rated).length)
  end
  
  def test_list_for_rated_returns_array
    assert_kind_of(Array, Comment.list_for(:rated))
  end
  
  def test_list_for_rated_returns_array_of_pairs
    results = Comment.list_for(:rated)
    results.each {|row| assert_equal(2, row.length) }
    results.each do|comment, value| 
       assert_kind_of(Integer, value)
       assert_kind_of(Comment, comment)
    end
  end
  
  def test_list_for_rated_returns_empty_array_when_nothing_found
    Comment.delete_all
    CommentRating.delete_all
    assert_kind_of(Array, Comment.list_for(:rated))
  end
  
  def test_list_for_rated_sorts_by_rated
    results = Comment.list_for(:rated)
    assert_equal(5, results.first[0].id)
    assert_equal(2, results.last[0].id)
  end
  
  def test_list_for_rated_has_correct_values
    results = Comment.list_for(:rated)
    results.each do |comment, value|
      assert_equal(comment.ratings.count, value, "Comment #{comment.id} rated count is off")
    end
  end
  
  def test_list_for_rated_includes_removed_comments
    Comment.update(5, :removed => 1)
    assert_equal(5, Comment.list_for(:rated).first[0].id)
  end
  
  def test_list_for_rated_scopped_to_topic
    results = Comment.list_for(:rated, :topic => 1)
    assert(results.all?{|c, v|  c.topic_id == 1})
  end
  
  def test_list_for_rated_scopped_to_time
    results = Comment.list_for(:rated, :max_age => 24)
    assert(results.all? do |c, v|                   # each comment needs
      c.ratings.any? do|r|                        # at least 1 
       r.created_on && r.created_on > 24.hours.ago # recent rating
    end
    end)
  end
  
  def test_list_for_rated_reverse
    results = Comment.list_for(:rated, :reverse => true)
    assert_equal(1, results.first[1]) # check value instead of ID because theres a tie
    assert_equal(3, results.last[1])
  end

  # Ratings
  def test_list_for_ratings_not_explosive
    assert_nothing_raised{Comment.list_for(:ratings)}
  end

  def test_list_for_ratings_returns_five_items
    assert_equal(5, Comment.list_for(:ratings).length)
  end
  
  def test_list_for_ratings_returns_array
    assert_kind_of(Array, Comment.list_for(:ratings))
  end
  
  def test_list_for_ratings_returns_array_of_pairs
    results = Comment.list_for(:ratings)
    results.each {|row| assert_equal(2, row.length) }
    results.each do|comment, value| 
       assert_kind_of(Float, value)
       assert_kind_of(Comment, comment)
    end
  end
  
  def test_list_for_ratings_returns_empty_array_when_nothing_found
    Comment.delete_all
    CommentRating.delete_all
    assert_kind_of(Array, Comment.list_for(:ratings))
  end
  
  def test_list_for_ratings_sorts_by_ratings
    results = Comment.list_for(:ratings)
    assert_equal(4, results.first[0].id)
    assert_equal(3, results.last[0].id)
  end
  
  def test_list_for_ratings_has_correct_values
    results = Comment.list_for(:ratings)
    results.each do |comment, value|
      assert_equal(comment.ratings.average(:value, :conditions => 'ratings.value != 77'), value, "Comment #{comment.id} ratings avg is off")
    end
  end
  
  def test_list_for_ratings_includes_removed_comments
    Comment.update(4, :removed => 1)
    assert_equal(4, Comment.list_for(:ratings).first[0].id)
  end
  
  def test_list_for_ratings_scopped_to_topic
    results = Comment.list_for(:ratings, :topic => 1)
    assert(results.all?{|c, v|  c.topic_id == 1})
  end
  
  def test_list_for_ratings_scopped_to_time
    results = Comment.list_for(:ratings, :max_age => 24)
    assert(results.all? do |c, v|                   # each comment needs
      c.ratings.any? do|r|                        # at least 1 
       r.created_on && r.created_on > 24.hours.ago # recent rating
    end
    end)
  end
  
  def test_list_for_ratings_reverse
    results = Comment.list_for(:ratings, :reverse => true)
    assert_equal(1, results.first[1]) # check value instead of ID because theres a tie
    assert_equal(5.0, results.last[1])
  end
  
  
  # direct_replies / comments_on
  def test_list_for_ratings_not_explosive
    assert_nothing_raised{Comment.list_for(:comments_on)}
  end

  # def test_list_for_comments_on_returns_five_items
  #   assert_equal(5, Comment.list_for(:comments_on).length)
  # end
  
  def test_list_for_comments_on_returns_array
    assert_kind_of(Array, Comment.list_for(:comments_on))
  end
  
  def test_list_for_comments_on_returns_array_of_pairs
    results = Comment.list_for(:comments_on)
    results.each {|row| assert_equal(2, row.length) }
    results.each do|comment, value| 
       assert_kind_of(Integer, value)
       assert_kind_of(Comment, comment)
    end
  end
  
  
  
  # word count
  def test_list_for_word_count_returns_array_of_pairs
    results = Comment.list_for(:word_count)
    results.each {|row| assert_equal(2, row.length) }
    results.each do|comment, value| 
       assert_kind_of(Integer, value)
       assert_kind_of(Comment, comment)
    end
  end
  
  def test_list_for_word_count_scopped_to_topic
    results = Comment.list_for(:word_count, :topic => 1)
    assert(results.all?{|c, v|  c.topic_id == 1})
  end
  
  def test_list_for_word_count_scopped_to_time
    results = Comment.list_for(:word_count, :max_age => 24)
    assert(results.all? do |c, v|  # each comment needs
       c.created_at > 24.hours.ago # to be recent
    end)
  end
  
end