require File.expand_path('./spec_helper', File.dirname(__FILE__))

describe 'A class that is commentable' do
  it 'can have many root comments' do
    expect(Commentable.new.comment_threads.respond_to?(:each)).to be true
  end

  describe 'when the commentable object is destroyed', skip: 'May actually be broken upstream!' do

    let(:user) {
      User.create!
    }

    let(:commentable) {
      Commentable.create!
    }

    let(:comment) {
      Comment.create!(commentator: user, commentable: commentable, body: 'blargh')
    }

    before(:each) do
      commentable.destroy
    end

    it 'also destroys its root comments' do
      expect(Comment.all).not_to include(comment)
    end

    context 'when there are nested comments' do

      let(:child) {
        Comment.create!(body: 'This is a child',
                        commentable: commentable,
                        commentator: user)
      }

      before(:each) do
        child.move_to_child_of(comment)
        commentable.destroy
      end

      it 'also destroys its nested comments' do
        expect(Comment.all).not_to include(comment)
        expect(Comment.all).not_to include(child)
      end
    end
  end

  describe 'special class finders' do

    let(:user) {
      User.create!
    }

    let(:commentable) {
      Commentable.create!
    }

    let(:other_commentable) {
      Commentable.create!
    }

    describe '#find_comments_for' do

      let(:comment) {
        Comment.create!(commentator: user,
                        commentable: commentable,
                        body: 'blargh')
      }

      let(:other_comment) {
        Comment.create!(commentator: user,
                        commentable: other_commentable,
                        body: 'hello')
      }

      let(:comments) {
        Commentable.find_comments_for(commentable)
      }

      it 'should return the comments for the passed commentable' do
        expect(comments).to include(comment)
      end

      it 'should not return the comments for other commentables' do
        expect(comments).not_to include(other_comment)
      end
    end

    describe '#find_comments_by_user' do

      let(:user2) {
        User.create!
      }

      let(:comment) {
        Comment.create!(commentator: user, commentable: commentable, body: 'blargh')
      }

      let(:other_comment) {
        Comment.create!(commentator: user2, commentable: other_commentable, body: 'hello')
      }

      let(:comments) {
        Commentable.find_comments_by_commentator(user)
      }

      it 'should return comments by the passed user' do
        expect(comments.all? { |c| c.commentator == user }).to eq(true)
      end

      it 'should not return comments by other users' do
        expect(comments.any? { |c| c.commentator != user }).to eq(false)
      end
    end
  end

  describe 'instance methods' do
    describe '#comments_ordered_by_submitted' do

      let(:user) {
        User.create!
      }

      let(:commentable) {
        Commentable.create!
      }

      let(:other_commentable) {
        Commentable.create!
      }

      let!(:comment) {
        Comment.create(commentator: user, commentable: commentable, body: 'sup')
      }

      let(:older_comment) {
        Comment.create(commentator: user, commentable: commentable, body: 'sup', created_at: 1.week.ago)
      }

      let(:oldest_comment) {
        Comment.create(commentator: user, commentable: commentable, body: 'sup', created_at: 2.years.ago)
      }

      let(:comments) {
        commentable.comments_ordered_by_submitted
      }

      it 'should return its own comments, ordered with the newest first' do
        expect(comments.all? do |c|
          c.commentable_type == commentable.class.to_s &&
              c.commentable_id == commentable.id
        end).to eq(true)
        comments.each_cons(2) do |c, c2|
          expect(c.created_at).to be > c2.created_at
        end
      end

      it 'should not include comments for other commentables' do
        expect(comments.any? do |c|
          c.commentable_type != commentable.class.to_s ||
              c.commentable_id != commentable.id
        end).to be false
      end
    end
  end
end
