require 'spec_helper'

describe Review do

  shared_examples_for :review do |target, target_type|
    before(:each) do
      Review.delete_all
      User.delete_all
      @user = FactoryGirl.create(:user)
    end

    after(:all) do
      Review.delete_all
      User.delete_all
    end

    context "validates review" do
      it "blank target" do
        review = Review.create({})
        review.valid?.should be_false
        review.errors[:target].should == ["can't be blank"]
      end

      it "no rating" do
        review = Review.create(target:target)
        review.valid?.should be_false
        review.errors[:rating].should include("can't be blank")
        review.errors[:rating].should include("is not a number")
      end

      it "no user" do
        review = Review.create(target:target, rating:3)
        review.valid?.should be_false
        review.errors[:user_id].should include("can't be blank")
      end

      it "complete" do
        review = Review.create(target:target, rating:3, user:@user)
        review.valid?.should be_true
      end

      it "unique" do
        review = Review.create(target:target, rating:3, user:@user)
        review.valid?.should be_true

        review2 = Review.create(target:target, rating:3, user:@user)
        review2.valid?.should be_false
      end

      it "reduces" do
        review = Review.create(target:target, rating:3, user:@user)
        review.valid?.should be_true

        review2 = Review.create(target:target, rating:5, user:FactoryGirl.create(:user))
        review2.valid?.should be_true
        Review.should have(2).items
        Review.index.should have(2).items

        # Reduce and check:
        ReviewSummary.should have(1).items
        ReviewSummary.first.avg_rating.should eq(4.0)

        ws_orig = ReviewSummary.first.wilson_score
        avg_orig = ReviewSummary.first.avg_rating

        # Create some more and verify:
        5.times {Review.create(target:target, rating:5, user:FactoryGirl.create(:user))}
        Review.index.should have(7).items
        ReviewSummary.should have(1).items

        ReviewSummary.first.wilson_score.should > ws_orig
        ReviewSummary.first.avg_rating.should > avg_orig

      end
    end # context

    context "validates review summary" do
      it "blank target" do
        review_summary = ReviewSummary.create()
        review_summary.valid?.should be_false
        review_summary.errors[:target_id].should == ["can't be blank"]
      end

      it "no rating" do
        review_summary = ReviewSummary.create(target:target)
        review_summary.valid?.should be_false
        review_summary.errors[:target].should be_empty
        review_summary.errors[:avg_rating].should include("can't be blank")
        review_summary.errors[:avg_rating].should include("is not a number")
      end

      it "no score" do
        review_summary = ReviewSummary.create(target:target, avg_rating:3.2)
        review_summary.valid?.should be_false
        review_summary.errors[:target].should be_empty
        review_summary.errors[:avg_rating].should be_empty
        review_summary.errors[:wilson_score].should include("can't be blank")
        review_summary.errors[:wilson_score].should include("is not a number")
      end

      it "no count" do
        review_summary = ReviewSummary.create(target:target, avg_rating:3.2, wilson_score:0.95)
        review_summary.valid?.should be_false
        review_summary.errors[:review_count].should include("can't be blank")
      end

      it "complete" do
        review_summary = ReviewSummary.create(target:target, avg_rating:3.2, wilson_score:0.95, review_count: 15)
        review_summary.valid?.should be_true
      end

      it "unique" do
        review = ReviewSummary.create(target:target, avg_rating:3, wilson_score:0.82, review_count:14)
        review.valid?.should be_true

        review2 = ReviewSummary.create(target:target, avg_rating:3.22, wilson_score:0.91, review_count:12)
        review2.valid?.should be_false
      end

      it "reduces and queries" do
        review = Review.create(target:target, rating:3, user:@user)
        review.valid?.should be_true
        review2 = Review.create(target:target, rating:5, user:FactoryGirl.create(:user))
        review2.valid?.should be_true
        Review.should have(2).items

        ReviewSummary.should have(1).items
        ReviewSummary.first.avg_rating.should eq(4.0)

        ws_orig = ReviewSummary.first.wilson_score
        avg_orig = ReviewSummary.first.avg_rating


        # Create some more and verify:
        5.times {Review.create(target:target, rating:5, user:FactoryGirl.create(:user))}
        ReviewSummary.should have(1).items
        ReviewSummary.first.wilson_score.should > ws_orig
        ReviewSummary.first.avg_rating.should > avg_orig


        # Create some more with a different target and verify:
        target2=FactoryGirl.create(:jam_track)
        5.times {Review.create(target:target2, rating:5, user:FactoryGirl.create(:user))}
        Review.index.should have(12).items
        Review.index(target_id: target2).should have(5).items
        summaries = ReviewSummary.index()
        summaries.should have(2).items
        summaries[0].wilson_score.should > summaries[1].wilson_score

        summaries = ReviewSummary.index(target_id: target2)
        summaries.should have(1).items
        summaries[0].target_id.should eq(target2.id)

        summaries = ReviewSummary.index(target_type: "JamRuby::JamTrack")
        summaries.should have(2).items

        summaries = ReviewSummary.index(minimum_reviews: 6)
        summaries.should have(1).items
      end
    end
  end

  describe "with a jamtrack" do
    @jam_track = FactoryGirl.create(:jam_track)
    it_behaves_like :review, @jam_track, "jam_track"
  end


end