diff --git a/app/controllers/concerns/has_filters.rb b/app/controllers/concerns/has_filters.rb index eeca1745f..ea5397183 100644 --- a/app/controllers/concerns/has_filters.rb +++ b/app/controllers/concerns/has_filters.rb @@ -5,8 +5,7 @@ module HasFilters def has_filters(valid_filters, *args) before_action(*args) do @valid_filters = valid_filters - @current_filter = params[:filter] - @current_filter = @valid_filters.first unless @valid_filters.include?(@current_filter) + @current_filter = @valid_filters.include?(params[:filter]) ? params[:filter] : @valid_filters.first end end end diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index 5219c1308..68570dd70 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -82,8 +82,8 @@ class DebatesController < ApplicationController end def parse_order - @valid_orders = ['created_at', 'score', 'most_commented', 'random'] - @order = @valid_orders.include?(params[:order]) ? params[:order] : 'created_at' + @valid_orders = ['hot_score', 'created_at', 'score', 'most_commented', 'random'] + @order = @valid_orders.include?(params[:order]) ? params[:order] : @valid_orders.first end def parse_tag_filter diff --git a/app/controllers/moderation/comments_controller.rb b/app/controllers/moderation/comments_controller.rb index b53785e81..3d8d960aa 100644 --- a/app/controllers/moderation/comments_controller.rb +++ b/app/controllers/moderation/comments_controller.rb @@ -27,7 +27,7 @@ class Moderation::CommentsController < Moderation::BaseController private def load_comments - @comments = Comment.accessible_by(current_ability, :hide).flagged.sorted_for_moderation.includes(:commentable) + @comments = Comment.accessible_by(current_ability, :hide).flagged.sort_for_moderation.includes(:commentable) end end diff --git a/app/controllers/moderation/debates_controller.rb b/app/controllers/moderation/debates_controller.rb index 85441d3f2..ce970b082 100644 --- a/app/controllers/moderation/debates_controller.rb +++ b/app/controllers/moderation/debates_controller.rb @@ -26,7 +26,7 @@ class Moderation::DebatesController < Moderation::BaseController private def load_debates - @debates = Debate.accessible_by(current_ability, :hide).flagged.sorted_for_moderation + @debates = Debate.accessible_by(current_ability, :hide).flagged.sort_for_moderation end end diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index dbb31863e..ca3d04d68 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -2,8 +2,8 @@ class WelcomeController < ApplicationController skip_authorization_check def index - @featured_debates = Debate.includes(:tags).limit(3) + @featured_debates = Debate.sort_by_hot_score.limit(3).for_render set_debate_votes(@featured_debates) end -end \ No newline at end of file +end diff --git a/app/models/comment.rb b/app/models/comment.rb index 422d39f8d..8dd922714 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -17,13 +17,15 @@ class Comment < ActiveRecord::Base scope :recent, -> { order(id: :desc) } - scope :sorted_for_moderation, -> { order(flags_count: :desc, updated_at: :desc) } + scope :sort_for_moderation, -> { order(flags_count: :desc, updated_at: :desc) } scope :pending_flag_review, -> { where(ignored_flag_at: nil, hidden_at: nil) } scope :with_ignored_flag, -> { where("ignored_flag_at IS NOT NULL AND hidden_at IS NULL") } scope :flagged, -> { where("flags_count > 0") } scope :for_render, -> { with_hidden.includes(user: :organization) } + after_create :call_after_commented + def self.build(commentable, user, body, p_id=nil) new commentable: commentable, user_id: user.id, @@ -87,4 +89,8 @@ class Comment < ActiveRecord::Base !root? end + def call_after_commented + self.commentable.try(:after_commented) + end + end diff --git a/app/models/debate.rb b/app/models/debate.rb index 25ba8aca8..f8f57fa97 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -1,7 +1,5 @@ require 'numeric' class Debate < ActiveRecord::Base - default_scope { order(created_at: :desc) } - apply_simple_captcha TITLE_LENGTH = Debate.columns.find { |c| c.name == 'title' }.limit @@ -23,15 +21,18 @@ class Debate < ActiveRecord::Base before_validation :sanitize_description before_validation :sanitize_tag_list - scope :sorted_for_moderation, -> { order(flags_count: :desc, updated_at: :desc) } + before_save :calculate_hot_score + + scope :sort_for_moderation, -> { order(flags_count: :desc, updated_at: :desc) } scope :pending_flag_review, -> { where(ignored_flag_at: nil, hidden_at: nil) } scope :with_ignored_flag, -> { where("ignored_flag_at IS NOT NULL AND hidden_at IS NULL") } scope :flagged, -> { where("flags_count > 0") } scope :for_render, -> { includes(:tags) } - scope :sort_by_score , -> { reorder(cached_votes_score: :desc) } - scope :sort_by_created_at, -> { reorder(created_at: :desc) } - scope :sort_by_most_commented, -> { reorder(comments_count: :desc) } - scope :sort_by_random, -> { reorder("RANDOM()") } + scope :sort_by_hot_score , -> { order(hot_score: :desc) } + scope :sort_by_score , -> { order(cached_votes_score: :desc) } + scope :sort_by_created_at, -> { order(created_at: :desc) } + scope :sort_by_most_commented, -> { order(comments_count: :desc) } + scope :sort_by_random, -> { order("RANDOM()") } # Ahoy setup visitable # Ahoy will automatically assign visit_id on create @@ -103,6 +104,30 @@ class Debate < ActiveRecord::Base update(ignored_flag_at: Time.now) end + def after_commented + save # updates teh hot_score because there is a before_save + end + + def calculate_hot_score + z = 1.96 # Normal distribution with a confidence of 0.95 + time_unit = 1.0 * 12.hours + start = Time.new(2015, 6, 15) + comments_weight = 1.0/3 # 3 comments == 1 positive vote + + weighted_score = 0 + + n = cached_votes_total + comments_weight * comments_count + if n > 0 then + pos = cached_votes_up + comments_weight * comments_count + phat = 1.0 * pos / n + weighted_score = (phat + z*z/(2*n) - z * Math.sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n) + end + + age_in_units = 1.0 * ((created_at || Time.now) - start) / time_unit + + self.hot_score = (age_in_units**3 + weighted_score * 1000).round + end + protected def sanitize_description @@ -112,5 +137,4 @@ class Debate < ActiveRecord::Base def sanitize_tag_list self.tag_list = TagSanitizer.new.sanitize_tag_list(self.tag_list) end - end diff --git a/app/views/admin/organizations/index.html.erb b/app/views/admin/organizations/index.html.erb index 464168746..85f75cf34 100644 --- a/app/views/admin/organizations/index.html.erb +++ b/app/views/admin/organizations/index.html.erb @@ -19,7 +19,7 @@ <% @organizations.each do |organization| %> - + diff --git a/app/views/debates/_debate.html.erb b/app/views/debates/_debate.html.erb index 2d8ad2900..fd9304c3d 100644 --- a/app/views/debates/_debate.html.erb +++ b/app/views/debates/_debate.html.erb @@ -11,6 +11,8 @@

  <%= link_to t("debates.debate.comments", count: debate.comments_count), debate_path(debate, anchor: "comments") %> +  •  + <%= l debate.created_at.to_date %>

<%= link_to debate.description, debate %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 7a4be1323..7000a0150 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -69,6 +69,7 @@ en: select_order: Order by select_order_long: Order debates by orders: + hot_score: most active created_at: newest score: best rated most_commented: most commented diff --git a/config/locales/es.yml b/config/locales/es.yml index 10351fe3a..a556757fa 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -69,6 +69,7 @@ es: select_order: Ordenar por select_order_long: Estás viendo los debates orders: + hot_score: "más activos" created_at: "más nuevos" score: "mejor valorados" most_commented: "más comentados" diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb index 58a1da128..0fd7bbee1 100644 --- a/db/dev_seeds.rb +++ b/db/dev_seeds.rb @@ -59,6 +59,7 @@ tags = Faker::Lorem.words(25) description = "

#{Faker::Lorem.paragraphs.join('

')}

" debate = Debate.create!(author: author, title: Faker::Lorem.sentence(3), + created_at: rand((Time.now - 1.week) .. Time.now), description: description, tag_list: tags.sample(3).join(','), terms_of_service: "1") @@ -72,6 +73,7 @@ puts "Commenting Debates" author = User.reorder("RANDOM()").first debate = Debate.reorder("RANDOM()").first Comment.create!(user: author, + created_at: rand(debate.created_at .. Time.now), commentable: debate, body: Faker::Lorem.sentence) end @@ -82,7 +84,8 @@ puts "Commenting Comments" (1..100).each do |i| author = User.reorder("RANDOM()").first parent = Comment.reorder("RANDOM()").first - comment = Comment.create!(user: author, + Comment.create!(user: author, + created_at: rand(parent.created_at .. Time.now), commentable_id: parent.commentable_id, commentable_type: parent.commentable_type, body: Faker::Lorem.sentence, diff --git a/db/migrate/20150903171309_add_hot_score_to_debates.rb b/db/migrate/20150903171309_add_hot_score_to_debates.rb new file mode 100644 index 000000000..7e82d4c13 --- /dev/null +++ b/db/migrate/20150903171309_add_hot_score_to_debates.rb @@ -0,0 +1,5 @@ +class AddHotScoreToDebates < ActiveRecord::Migration + def change + add_column :debates, :hot_score, :bigint, default: 0 + end +end diff --git a/db/schema.rb b/db/schema.rb index 688f20838..13705eb14 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -101,6 +101,7 @@ ActiveRecord::Schema.define(version: 20150903200440) do t.datetime "confirmed_hide_at" t.integer "cached_anonymous_votes_total", default: 0 t.integer "cached_votes_score", default: 0 + t.integer "hot_score", limit: 8, default: 0 end add_index "debates", ["cached_votes_down"], name: "index_debates_on_cached_votes_down", using: :btree diff --git a/lib/tasks/debates.rake b/lib/tasks/debates.rake new file mode 100644 index 000000000..ce37e2743 --- /dev/null +++ b/lib/tasks/debates.rake @@ -0,0 +1,9 @@ +namespace :debates do + desc "Updates all debates by recalculating their hot_score" + task hot_score: :environment do + Debate.find_in_batches do |debates| + debates.each(&:save) + end + end + +end diff --git a/spec/factories.rb b/spec/factories.rb index 9f4345d4d..e541c1b20 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -71,6 +71,10 @@ FactoryGirl.define do Flag.flag(FactoryGirl.create(:user), debate) end end + + trait :with_hot_score do + before(:save) { |d| d.calculate_hot_score } + end end factory :vote do diff --git a/spec/features/admin/organizations_spec.rb b/spec/features/admin/organizations_spec.rb index f43c5d4dc..289b5cd1c 100644 --- a/spec/features/admin/organizations_spec.rb +++ b/spec/features/admin/organizations_spec.rb @@ -13,7 +13,7 @@ feature 'Admin::Organizations' do background do @user = create(:user, email: "marley@humanrights.com", phone_number: "6764440002") - organization = create(:organization, user: @user, name: "Get up, Stand up") + create(:organization, user: @user, name: "Get up, Stand up") end scenario "returns no results if search term is empty" do @@ -70,11 +70,13 @@ feature 'Admin::Organizations' do organization = create(:organization) visit admin_organizations_path - expect(current_path).to eq(admin_organizations_path) - expect(page).to have_link('Verify') - expect(page).to have_link('Reject') + within("#organization_#{organization.id}") do + expect(current_path).to eq(admin_organizations_path) + expect(page).to have_link('Verify') + expect(page).to have_link('Reject') - click_on 'Verify' + click_on 'Verify' + end expect(current_path).to eq(admin_organizations_path) expect(page).to have_content ('Verified') @@ -86,11 +88,13 @@ feature 'Admin::Organizations' do visit admin_organizations_path expect(current_path).to eq(admin_organizations_path) - expect(page).to have_content ('Verified') - expect(page).to_not have_link('Verify') - expect(page).to have_link('Reject') + within("#organization_#{organization.id}") do + expect(page).to have_content ('Verified') + expect(page).to_not have_link('Verify') + expect(page).to have_link('Reject') - click_on 'Reject' + click_on 'Reject' + end expect(current_path).to eq(admin_organizations_path) expect(page).to have_content ('Rejected') @@ -102,10 +106,12 @@ feature 'Admin::Organizations' do visit admin_organizations_path expect(current_path).to eq(admin_organizations_path) - expect(page).to have_link('Verify') - expect(page).to_not have_link('Reject', exact: true) + within("#organization_#{organization.id}") do + expect(page).to have_link('Verify') + expect(page).to_not have_link('Reject', exact: true) - click_on 'Verify' + click_on 'Verify' + end expect(current_path).to eq(admin_organizations_path) expect(page).to have_content ('Verified') diff --git a/spec/features/debates_spec.rb b/spec/features/debates_spec.rb index 3e2a0ea08..5c808a5ef 100644 --- a/spec/features/debates_spec.rb +++ b/spec/features/debates_spec.rb @@ -364,80 +364,87 @@ feature 'Debates' do expect(Flag.flagged?(user, debate)).to_not be end - feature 'Debate index order filters', :js do + feature 'Debate index order filters' do - before do - @most_commented_debate = create(:debate) - @most_score_debate = create(:debate) - @most_recent_debate = create(:debate) - create_list(:comment, 2, commentable: @most_commented_debate) - create_list(:vote, 2, votable: @most_score_debate) - create_list(:vote, 2, votable: @most_recent_debate, vote_flag: false) - create(:vote, votable: @most_recent_debate) - create(:comment, commentable: @most_recent_debate) - end + scenario 'Default order is hot_score', :js do + create(:debate, title: 'best').update_column(:hot_score, 10) + create(:debate, title: 'worst').update_column(:hot_score, 2) + create(:debate, title: 'medium').update_column(:hot_score, 5) - scenario 'Default order is created_at' do visit debates_path - expect(page).to have_select('order-selector', selected: 'newest') - expect(@most_recent_debate.title).to appear_before(@most_score_debate.title) - expect(@most_score_debate.title).to appear_before(@most_commented_debate.title) + expect(page).to have_select('order-selector', selected: 'most active') + expect('best').to appear_before('medium') + expect('medium').to appear_before('worst') end - scenario 'Debates are ordered by best rated' do - visit debates_path + scenario 'Debates are ordered by best rated', :js do + create(:debate, title: 'best', cached_votes_score: 10) + create(:debate, title: 'medium', cached_votes_score: 5) + create(:debate, title: 'worst', cached_votes_score: 2) + visit debates_path select 'best rated', from: 'order-selector' expect(page).to have_select('order-selector', selected: 'best rated') - expect(find("#debates .debate", match: :first)).to have_content(@most_score_debate.title) + + within '#debates' do + expect('best').to appear_before('medium') + expect('medium').to appear_before('worst') + end expect(current_url).to include('order=score') - expect(@most_score_debate.title).to appear_before(@most_commented_debate.title) - expect(@most_commented_debate.title).to appear_before(@most_recent_debate.title) end - scenario 'Debates are ordered by most commented' do - visit debates_path + scenario 'Debates are ordered by most commented', :js do + create(:debate, title: 'best', comments_count: 10) + create(:debate, title: 'medium', comments_count: 5) + create(:debate, title: 'worst', comments_count: 2) + visit debates_path select 'most commented', from: 'order-selector' expect(page).to have_select('order-selector', selected: 'most commented') - expect(find("#debates .debate", match: :first)).to have_content(@most_commented_debate.title) + + within '#debates' do + expect('best').to appear_before('medium') + expect('medium').to appear_before('worst') + end expect(current_url).to include('order=most_commented') - expect(@most_commented_debate.title).to appear_before(@most_recent_debate.title) - expect(@most_recent_debate.title).to appear_before(@most_score_debate.title) end - scenario 'Debates are ordered by newest' do + scenario 'Debates are ordered by newest', :js do + create(:debate, title: 'best', created_at: Time.now) + create(:debate, title: 'medium', created_at: Time.now - 1.hour) + create(:debate, title: 'worst', created_at: Time.now - 1.day) + visit debates_path - - select 'best rated', from: 'order-selector' - expect(find("#debates .debate", match: :first)).to have_content(@most_score_debate.title) - select 'newest', from: 'order-selector' expect(page).to have_select('order-selector', selected: 'newest') - expect(find("#debates .debate", match: :first)).to have_content(@most_recent_debate.title) + + within '#debates' do + expect('best').to appear_before('medium') + expect('medium').to appear_before('worst') + end expect(current_url).to include('order=created_at') - expect(@most_recent_debate.title).to appear_before(@most_score_debate.title) - expect(@most_score_debate.title).to appear_before(@most_commented_debate.title) end - scenario 'Debates are ordered randomly' do + scenario 'Debates are ordered randomly', :js do create_list(:debate, 12) visit debates_path select 'random', from: 'order-selector' expect(page).to have_select('order-selector', selected: 'random') + expect(page).to have_selector('#debates') debates_first_time = find("#debates").text select 'most commented', from: 'order-selector' expect(page).to have_select('order-selector', selected: 'most commented') - expect(find("#debates .debate", match: :first)).to have_content(@most_commented_debate.title) + expect(page).to have_selector('#debates') select 'random', from: 'order-selector' expect(page).to have_select('order-selector', selected: 'random') + expect(page).to have_selector('#debates') debates_second_time = find("#debates").text expect(debates_first_time).to_not eq(debates_second_time) diff --git a/spec/features/votes_spec.rb b/spec/features/votes_spec.rb index ea9761bde..1116d2985 100644 --- a/spec/features/votes_spec.rb +++ b/spec/features/votes_spec.rb @@ -2,17 +2,14 @@ require 'rails_helper' feature 'Votes' do + background do + @manuela = create(:user, verified_at: Time.now) + @pablo = create(:user) + + login_as(@manuela) + end + feature 'Debates' do - - background do - @manuela = create(:user, verified_at: Time.now) - @pablo = create(:user) - @debate = create(:debate) - - login_as(@manuela) - visit debate_path(@debate) - end - scenario "Home shows user votes on featured debates" do debate1 = create(:debate) debate2 = create(:debate) @@ -109,84 +106,86 @@ feature 'Votes' do end end - scenario 'Show no votes' do - visit debate_path(@debate) - - expect(page).to have_content "No votes" - - within('.in-favor') do - expect(page).to have_content "0%" - expect(page).to_not have_css("a.voted") - expect(page).to_not have_css("a.no-voted") + feature 'Single debate' do + background do + @debate = create(:debate) end - within('.against') do - expect(page).to have_content "0%" - expect(page).to_not have_css("a.voted") - expect(page).to_not have_css("a.no-voted") - end - end + scenario 'Show no votes' do + visit debate_path(@debate) - scenario 'Show' do - create(:vote, voter: @manuela, votable: @debate, vote_flag: true) - create(:vote, voter: @pablo, votable: @debate, vote_flag: false) - - visit debate_path(@debate) - - expect(page).to have_content "2 votes" - - within('.in-favor') do - expect(page).to have_content "50%" - expect(page).to have_css("a.voted") - end - - within('.against') do - expect(page).to have_content "50%" - expect(page).to have_css("a.no-voted") - end - end - - scenario 'Create from debate show', :js do - find('.in-favor a').click - - within('.in-favor') do - expect(page).to have_content "100%" - expect(page).to have_css("a.voted") - end - - within('.against') do - expect(page).to have_content "0%" - expect(page).to have_css("a.no-voted") - end - - expect(page).to have_content "1 vote" - end - - scenario 'Create from debate featured', :js do - visit root_path - - within("#featured-debates") do - find('.in-favor a').click + expect(page).to have_content "No votes" within('.in-favor') do - expect(page).to have_content "100%" - expect(page).to have_css("a.voted") + expect(page).to have_content "0%" + expect(page).to_not have_css("a.voted") + expect(page).to_not have_css("a.no-voted") end within('.against') do + expect(page).to have_content "0%" + expect(page).to_not have_css("a.voted") + expect(page).to_not have_css("a.no-voted") + end + end + + scenario 'Update', :js do + visit debate_path(@debate) + + find('.in-favor a').click + find('.against a').click + + within('.in-favor') do expect(page).to have_content "0%" expect(page).to have_css("a.no-voted") end + within('.against') do + expect(page).to have_content "100%" + expect(page).to have_css("a.voted") + end + expect(page).to have_content "1 vote" end - expect(URI.parse(current_url).path).to eq(root_path) - end - scenario 'Create from debate index', :js do - visit debates_path + scenario 'Trying to vote multiple times', :js do + visit debate_path(@debate) - within("#debates") do + find('.in-favor a').click + find('.in-favor a').click + + within('.in-favor') do + expect(page).to have_content "100%" + end + + within('.against') do + expect(page).to have_content "0%" + end + + expect(page).to have_content "1 vote" + end + + scenario 'Show' do + create(:vote, voter: @manuela, votable: @debate, vote_flag: true) + create(:vote, voter: @pablo, votable: @debate, vote_flag: false) + + visit debate_path(@debate) + + expect(page).to have_content "2 votes" + + within('.in-favor') do + expect(page).to have_content "50%" + expect(page).to have_css("a.voted") + end + + within('.against') do + expect(page).to have_content "50%" + expect(page).to have_css("a.no-voted") + end + end + + scenario 'Create from debate show', :js do + visit debate_path(@debate) find('.in-favor a').click @@ -202,51 +201,56 @@ feature 'Votes' do expect(page).to have_content "1 vote" end - expect(URI.parse(current_url).path).to eq(debates_path) - end - scenario 'Update', :js do - find('.in-favor a').click - find('.against a').click + scenario 'Create in featured', :js do + visit root_path - within('.in-favor') do - expect(page).to have_content "0%" - expect(page).to have_css("a.no-voted") + within("#featured-debates") do + find('.in-favor a').click + + within('.in-favor') do + expect(page).to have_content "100%" + expect(page).to have_css("a.voted") + end + + within('.against') do + expect(page).to have_content "0%" + expect(page).to have_css("a.no-voted") + end + + expect(page).to have_content "1 vote" + end + expect(URI.parse(current_url).path).to eq(root_path) end - within('.against') do - expect(page).to have_content "100%" - expect(page).to have_css("a.voted") + scenario 'Create in index', :js do + visit debates_path + + within("#debates") do + + find('.in-favor a').click + + within('.in-favor') do + expect(page).to have_content "100%" + expect(page).to have_css("a.voted") + end + + within('.against') do + expect(page).to have_content "0%" + expect(page).to have_css("a.no-voted") + end + + expect(page).to have_content "1 vote" + end + expect(URI.parse(current_url).path).to eq(debates_path) end - - expect(page).to have_content "1 vote" - end - - scenario 'Trying to vote multiple times', :js do - find('.in-favor a').click - find('.in-favor a').click - - within('.in-favor') do - expect(page).to have_content "100%" - end - - within('.against') do - expect(page).to have_content "0%" - end - - expect(page).to have_content "1 vote" end end feature 'Comments' do background do - @manuela = create(:user) - @pablo = create(:user) @debate = create(:debate) @comment = create(:comment, commentable: @debate) - - login_as(@manuela) - visit debate_path(@debate) end scenario 'Show' do @@ -269,6 +273,8 @@ feature 'Votes' do end scenario 'Create', :js do + visit debate_path(@debate) + within("#comment_#{@comment.id}_votes") do find(".in_favor a").click @@ -285,6 +291,8 @@ feature 'Votes' do end scenario 'Update', :js do + visit debate_path(@debate) + within("#comment_#{@comment.id}_votes") do find('.in_favor a').click find('.against a').click @@ -302,6 +310,8 @@ feature 'Votes' do end scenario 'Trying to vote multiple times', :js do + visit debate_path(@debate) + within("#comment_#{@comment.id}_votes") do find('.in_favor a').click find('.in_favor a').click @@ -317,6 +327,5 @@ feature 'Votes' do expect(page).to have_content "1 vote" end end - end end diff --git a/spec/models/debate_spec.rb b/spec/models/debate_spec.rb index fc4130354..537cc303c 100644 --- a/spec/models/debate_spec.rb +++ b/spec/models/debate_spec.rb @@ -174,15 +174,6 @@ describe Debate do end end - describe '#default_order' do - let!(:economy) { create(:debate) } - let!(:health) { create(:debate) } - - it "returns debates ordered by last one first" do - expect(Debate.all).to eq([health, economy]) - end - end - describe '#anonymous_votes_ratio' do it "returns the percentage of anonymous votes of the total votes" do debate = create(:debate, cached_anonymous_votes_total: 25, cached_votes_total: 100) @@ -190,4 +181,64 @@ describe Debate do end end + describe '#hot_score' do + let(:now) { Time.now } + + it "increases for newer debates" do + old = create(:debate, :with_hot_score, created_at: now - 1.day) + new = create(:debate, :with_hot_score, created_at: now) + expect(new.hot_score).to be > old.hot_score + end + + it "increases for debates with more comments" do + more_comments = create(:debate, :with_hot_score, created_at: now, comments_count: 10) + less_comments = create(:debate, :with_hot_score, created_at: now, comments_count: 1) + expect(more_comments.hot_score).to be > less_comments.hot_score + end + + it "increases for debates with more positive votes" do + more_likes = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 5) + less_likes = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 1) + expect(more_likes.hot_score).to be > less_likes.hot_score + end + + it "increases for debates with more confidence" do + more_confidence = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 1000, cached_votes_up: 700) + less_confidence = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 9) + expect(more_confidence.hot_score).to be > less_confidence.hot_score + end + + it "decays in older debates, even if they have more votes" do + older_more_voted = create(:debate, :with_hot_score, created_at: now - 2.days, cached_votes_total: 1000, cached_votes_up: 900) + new_less_voted = create(:debate, :with_hot_score, created_at: now, cached_votes_total: 10, cached_votes_up: 9) + expect(new_less_voted.hot_score).to be > older_more_voted.hot_score + end + + describe 'actions which affect it' do + let(:debate) { create(:debate, :with_hot_score) } + + it "increases with likes" do + previous = debate.hot_score + 5.times { debate.register_vote(create(:user), true) } + expect(previous).to be < debate.hot_score + end + + it "decreases with dislikes" do + debate.register_vote(create(:user), true) + previous = debate.hot_score + 3.times { debate.register_vote(create(:user), false) } + expect(previous).to be > debate.hot_score + end + + it "increases with comments" do + previous = debate.hot_score + Comment.create(user: create(:user), commentable: debate, body: 'foo') + expect(previous).to be < debate.hot_score + end + end + + end + + + end diff --git a/spec/support/matchers/appear_before.rb b/spec/support/matchers/appear_before.rb index bb1d65072..73df35139 100644 --- a/spec/support/matchers/appear_before.rb +++ b/spec/support/matchers/appear_before.rb @@ -1,6 +1,7 @@ RSpec::Matchers.define :appear_before do |later_content| match do |earlier_content| - page.body.index(earlier_content) < page.body.index(later_content) + text = page.text + text.index(earlier_content) < text.index(later_content) end end
<%= organization.name %> <%= organization.email %> <%= organization.phone_number %>