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

# Re-raise errors caught by the controller.
class TalkController; def rescue_action(e) raise e end; end

class AbstractTalkControllerTest < AbstractTestCase
  fixtures :comments, :topics, :users, :settings, :ratings
  
  def setup
    @controller = TalkController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    @request.session[:user] = users(:grace).id # grace is a participant
  end

end

class TalkControllerTest < AbstractTalkControllerTest
  
  def test_comment_not_explosive
    post :comment, :id => 1
    assert_response :redirect
  end
  
  def test_comment_requires_an_id
    post :comment
    assert_response :redirect
  end
  
  def test_comment_creates_a_comment
    assert_difference(Comment, :count, "Should have created a new comment") do
      post_comment
    end  
  end
  
  def test_created_comment_has_correct_user
    Comment.delete_all
    post_comment
    assert_equal users(:grace), Comment.find(:first).user
  end
  
  def test_comment_too_short
    assert_no_difference(Comment, :count, "Should not have created a new comment") do
      post_comment  :comment => {:body => ''}
    end
  end
  
  def cannot_comment_on_future_topic
    assert_no_difference(Comment, :count) { post_comment :topic_id => 3 }  
  end
  
  def cannot_comment_on_held_topic
    assert_no_difference(Comment, :count) { post_comment :topic_id => 2 }  
  end
  
  def test_reply_to_a_comment_adds_to_children_count
    t = topics(:direct_democracy)
    subject = comments(:first_reply)
    assert_difference(subject, :children_count) do
      post_comment :comment => {:parent_id => subject.id, :body => 'Hive Ban Walking Honor Roil Rut'}
      subject.reload # needed to clear the cache
    end
  end
  
  def test_reply_to_a_reply
    assert_difference(comments(:first_reply), :children_count) do
      post_comment :comment => {:parent_id => comments(:first_reply).id, :body => 'Hive Ban Walking Honor Roil Rut'}
      comments(:first_reply).reload
    end    
  end
  
  def test_guest_cannot_comment
    @request.session[:user] = users(:visitor1).id # guest
    assert_no_difference(Comment, :count) { post_comment }  
  end
  
  def test_comment_save
    params =  {
                "topic_id"=>"1", 
                "commit"=>"Preview", 
                "replace"=>"topic_comment", 
                "save"=>"1",
                "comment"=> {
                  "body"=>"first post\r\n"
                }
              }
    assert_difference(Comment, :count) { post :comment, params }  
  end
  
  private
  def post_comment(differences={})
    params =  { :topic_id => 1, 
                :save => 1,
                :comment => {
                  :body => "Hive Ban Walking Honor Roil Rut\r\n"
                }
              }.merge(differences)
    post :comment, params
  end
end

class TalkRatingNotReturnedControllerTest < AbstractTalkControllerTest
  
  def test_comment_on_base_when_already_rated
    post :get_comment_form, :topic_id => 1
    assert assigns(:subject_rating).nil?
  end
  
  def test_reply_on_comment_when_already_rated
    post :get_comment_form, :topic_id => 1, :parent_id => 2
    assert assigns(:subject_rating).nil?
  end
  
end

# TODO replying sends an email to original commenter

class TalkCommentRemovedControllerTest < AbstractTalkControllerTest

  def setup
    super
    login_as :laura   
    @request.env["HTTP_REFERER"] = "/" 
  end
  
  def test_remove_comment_sets_flag
    get :remove_comment, :id => 1
    assert Comment.find(1).removed?
  end
  
  # remove_comment redirects on GET
  def test_remove_redirects_on_get
    get :remove_comment, :id => 1
    assert_response :redirect
  end
  
  # remove_comment updates page on XHR
  def test_remove_comment_with_XHR
    xhr :post, :remove_comment, :id => 1
    assert_response :success
  end
  
  # Only admin can remove a comment
  def test_participant_cannot_remove_comment
    login_as :ernest
    get :remove_comment, :id => 1
    assert !Comment.find(1).removed?
  end
  
  def test_expert_cannot_remove_comment
    login_as :frank
    get :remove_comment, :id => 1
    assert !Comment.find(1).removed?    
  end
  
  # An email should be sent (to whom?) when the comment is removed
end

class MarkMessageTalkControllerTest < AbstractTalkControllerTest
  
  def test_marking_a_comment_creates_a_reading
    login_as :ernest
    assert_difference(Reading, :count) do
      xhr(:post, :mark, {:id => comments(:long_first_post).id}) 
    end
  end
  
end
