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

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

class BlogControllerTest < Test::Unit::TestCase
  fixtures :entries

  def setup
    @controller = BlogController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
  end

  def assert_posts_and_comments(posts, comments)
    # account for div="comment" inside the comment form
    comments += 1 if posts == 1

    # assert the number of posts
    assert_tag :tag=>'div', :attributes => {:class => 'content'},
      :children => {:count => posts, :only => {
        :tag=>'div', :attributes => {:class => 'blogbody'} } }

    # assert the number of comments
    assert_tag :tag=>'div', :attributes => {:class => 'content'},
      :children => {:count => comments, :only => {
        :tag=>'div', :attributes => {:class => 'comment'} } }
  end

  def test_index
    get :posts, :path=>['index.html']
    assert_response :success
    assert_template 'html'

    # only two posts have titles
    assert_tag :tag=>'div', :attributes => {:class => 'content'},
      :children => {:count => 2, :only => {:child => {:tag => 'h3'} } }
    assert_tag :tag=>'h3', :content => @red_post.title
    assert_tag :tag=>'h3', :content => @blue_post.title

    # four posts, two with one child each
    assert_posts_and_comments 4, 0
    assert_tag :tag=>'div', :attributes => {:class => 'content'},
      :children => {:count => 2, :only => {
        :tag=>'div', :content => /Comments \(1\)/ } }
  end

  def test_comments
    get :comments, :path=>'comments.html'
    assert_response :success
    assert_template 'post'

    assert_posts_and_comments 0, 2
  end

  def test_query_multiple
    get :posts, :path=>['index.html'], :q=>"query"
    assert_response :success
    assert_template 'html'

    assert_posts_and_comments 2, 0
  end

  def test_query_redirect
    get :posts, :path=>['index.html'], :q=>"blue"
    assert_response :redirect
    assert_redirected_to :path=>@blue_post.by_date[:path][-1]
  end

  def test_query_redirect
    get :posts, :path=>['index.html'], :q=>"ziltch"
    assert_response 404
    assert_template '404.html'
  end

  def test_date_redirect
    get :by_date, @red_post.by_date.dup.update(:path=>[])
    assert_response :redirect
    assert_redirected_to :path=>@red_post.by_date[:path][-1]
  end

  def test_month_range
    get :by_date, @red_post.by_date.update(:day=>nil, :path=>[])
    assert_response :success
    assert_template 'html'
    assert_posts_and_comments 2, 0
  end

  def test_year_range
    get :by_date, @red_post.by_date.update(:month=>nil, :day=>nil, :path=>[])
    assert_response :success
    assert_template 'html'
    assert_posts_and_comments 2, 0
  end

  def test_archive
    get :archive, @red_post.by_date.dup.update(:day=>nil)
    assert_response :success
    assert_template 'archive'

    assert_tag :tag=>'a', :attributes => {:class => 'entry'},
      :content => @red_post.title

    assert_tag :tag=>'a', :attributes => {:class => 'entry'},
      :content => @blue_post.title
  end

  def test_atom_feed
    get :posts, :path=>['index.atom']
    assert_response :success
    assert_template 'atom'

    assert_tag :tag=>'feed',
      :children => {:count => 4, :only => { :tag=>'entry' } }
  end

  def test_get_by_id
    get :by_id, @one_post.by_id
    assert_response :success
    assert_template 'post'

    # single post, no comments
    assert_posts_and_comments 1, 0

    # assert content matches the entry
    assert_tag :tag=>'div', :attributes => {:class => 'blogbody'},
      :content => /#{@one_post.content}/
  end

  def test_get_by_id_with_flav
    uri = @one_post.by_id
    uri[:path][-1] += ".html"

    get :by_id, uri
    assert_response :success
    assert_template 'post'

    # single post, no comments
    assert_posts_and_comments 1, 0

    # assert content matches the entry
    assert_tag :tag=>'div', :attributes => {:class => 'blogbody'},
      :content => /#{@one_post.content}/
  end

  def test_get_by_date
    get :by_date, @red_post.by_date
    assert_response :success
    assert_template 'post'

    # assert one post, with one comment
    assert_posts_and_comments 1, 1
  end

  def test_post_comment
    post :by_date, @red_post.by_date.merge(:comment => "red reeks!")

    assert_response :redirect
    assert_redirected_to :action => 'posts'

    get :by_date, @red_post.by_date

    # assert one post, with two comments
    assert_posts_and_comments 1, 2

    # assert content matches the comment
    assert_tag :tag=>'div', :content => /red reeks/
  end

  def test_id_not_found
    get :by_id, {:path => "3000"}
    assert_response 404
    assert_template '404.html'
  end

  def test_stray_post
    post :posts, :path=>['index.html']
    assert_response 405
    assert_template '405.html'
  end

  def test_stray_post_archive
    post :archive, @red_post.by_date.dup.update(:day=>nil)
    assert_response 405
    assert_template '405.html'
  end
end
