Commit ae067ee3 authored by Riyad Preukschas's avatar Riyad Preukschas

Fix vote counting

parent 6c6f415c
module NotesHelper module NotesHelper
def loading_more_notes?
params[:loading_more].present?
end
def loading_new_notes?
params[:loading_new].present?
end
# Helps to distinguish e.g. commit notes in mr notes list # Helps to distinguish e.g. commit notes in mr notes list
def note_for_main_target?(note) def note_for_main_target?(note)
!@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?) !@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?)
...@@ -23,4 +15,12 @@ module NotesHelper ...@@ -23,4 +15,12 @@ module NotesHelper
link_to "#{note.diff_file_name}:L#{note.diff_new_line}", diffs_project_merge_request_path(note.project, note.noteable_id, anchor: note.line_code) link_to "#{note.diff_file_name}:L#{note.diff_new_line}", diffs_project_merge_request_path(note.project, note.noteable_id, anchor: note.line_code)
end end
end end
def loading_more_notes?
params[:loading_more].present?
end
def loading_new_notes?
params[:loading_new].present?
end
end end
...@@ -85,7 +85,9 @@ class Note < ActiveRecord::Base ...@@ -85,7 +85,9 @@ class Note < ActiveRecord::Base
# Returns true if this is a downvote note, # Returns true if this is a downvote note,
# otherwise false is returned # otherwise false is returned
def downvote? def downvote?
note.start_with?('-1') || note.start_with?(':-1:') votable? && (note.start_with?('-1') ||
note.start_with?(':-1:')
)
end end
def for_commit? def for_commit?
...@@ -100,6 +102,10 @@ class Note < ActiveRecord::Base ...@@ -100,6 +102,10 @@ class Note < ActiveRecord::Base
line_code.present? line_code.present?
end end
def for_issue?
noteable_type == "Issue"
end
def for_merge_request? def for_merge_request?
noteable_type == "MergeRequest" noteable_type == "MergeRequest"
end end
...@@ -150,6 +156,12 @@ class Note < ActiveRecord::Base ...@@ -150,6 +156,12 @@ class Note < ActiveRecord::Base
# Returns true if this is an upvote note, # Returns true if this is an upvote note,
# otherwise false is returned # otherwise false is returned
def upvote? def upvote?
note.start_with?('+1') || note.start_with?(':+1:') votable? && (note.start_with?('+1') ||
note.start_with?(':+1:')
)
end
def votable?
for_issue? || (for_merge_request? && !for_diff_line?)
end end
end end
module Votes module Votes
# Return the number of +1 comments (upvotes)
def upvotes # Return the number of -1 comments (downvotes)
notes.select(&:upvote?).size def downvotes
notes.select(&:downvote?).size
end end
def upvotes_in_percent def downvotes_in_percent
if votes_count.zero? if votes_count.zero?
0 0
else else
100.0 / votes_count * upvotes 100.0 - upvotes_in_percent
end end
end end
# Return the number of -1 comments (downvotes) # Return the number of +1 comments (upvotes)
def downvotes def upvotes
notes.select(&:downvote?).size notes.select(&:upvote?).size
end end
def downvotes_in_percent def upvotes_in_percent
if votes_count.zero? if votes_count.zero?
0 0
else else
100.0 - upvotes_in_percent 100.0 / votes_count * upvotes
end end
end end
......
...@@ -14,16 +14,14 @@ ...@@ -14,16 +14,14 @@
= time_ago_in_words(note.updated_at) = time_ago_in_words(note.updated_at)
ago ago
-# only show vote if it's a note for the main target - if note.upvote?
- if note_for_main_target?(note) %span.vote.upvote.label.label-success
- if note.upvote? %i.icon-thumbs-up
%span.vote.upvote.label.label-success \+1
%i.icon-thumbs-up - if note.downvote?
\+1 %span.vote.downvote.label.label-error
- if note.downvote? %i.icon-thumbs-down
%span.vote.downvote.label.label-error \-1
%i.icon-thumbs-down
\-1
.note-body .note-body
......
...@@ -91,6 +91,32 @@ FactoryGirl.define do ...@@ -91,6 +91,32 @@ FactoryGirl.define do
factory :note do factory :note do
project project
note "Note" note "Note"
author
factory :note_on_commit, traits: [:on_commit]
factory :note_on_commit_line, traits: [:on_commit, :on_line]
factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note]
factory :note_on_merge_request, traits: [:on_merge_request]
factory :note_on_merge_request_line, traits: [:on_merge_request, :on_line]
trait :on_commit do
noteable_id "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
noteable_type "Commit"
end
trait :on_line do
line_code "0_184_184"
end
trait :on_merge_request do
noteable_id 1
noteable_type "MergeRequest"
end
trait :on_issue do
noteable_id 1
noteable_type "Issue"
end
end end
factory :event do factory :event do
......
...@@ -43,79 +43,105 @@ describe Note do ...@@ -43,79 +43,105 @@ describe Note do
let(:project) { create(:project) } let(:project) { create(:project) }
it "recognizes a neutral note" do it "recognizes a neutral note" do
note = create(:note, note: "This is not a +1 note") note = create(:votable_note, note: "This is not a +1 note")
note.should_not be_upvote note.should_not be_upvote
note.should_not be_downvote note.should_not be_downvote
end end
it "recognizes a neutral emoji note" do it "recognizes a neutral emoji note" do
note = build(:note, note: "I would :+1: this, but I don't want to") note = build(:votable_note, note: "I would :+1: this, but I don't want to")
note.should_not be_upvote note.should_not be_upvote
note.should_not be_downvote note.should_not be_downvote
end end
it "recognizes a +1 note" do it "recognizes a +1 note" do
note = create(:note, note: "+1 for this") note = create(:votable_note, note: "+1 for this")
note.should be_upvote note.should be_upvote
end end
it "recognizes a +1 emoji as a vote" do it "recognizes a +1 emoji as a vote" do
note = build(:note, note: ":+1: for this") note = build(:votable_note, note: ":+1: for this")
note.should be_upvote note.should be_upvote
end end
it "recognizes a -1 note" do it "recognizes a -1 note" do
note = create(:note, note: "-1 for this") note = create(:votable_note, note: "-1 for this")
note.should be_downvote note.should be_downvote
end end
it "recognizes a -1 emoji as a vote" do it "recognizes a -1 emoji as a vote" do
note = build(:note, note: ":-1: for this") note = build(:votable_note, note: ":-1: for this")
note.should be_downvote note.should be_downvote
end end
end end
let(:project) { create(:project) }
let(:commit) { project.commit }
describe "Commit notes" do describe "Commit notes" do
before do let!(:note) { create(:note_on_commit, note: "+1 from me") }
@note = create(:note, let!(:commit) { note.noteable }
noteable_id: commit.id,
noteable_type: "Commit")
end
it "should be accessible through #noteable" do it "should be accessible through #noteable" do
@note.noteable_id.should == commit.id note.noteable_id.should == commit.id
@note.noteable.should be_a(Commit) note.noteable.should be_a(Commit)
@note.noteable.should == commit note.noteable.should == commit
end end
it "should save a valid note" do it "should save a valid note" do
@note.noteable_id.should == commit.id note.noteable_id.should == commit.id
@note.noteable == commit note.noteable == commit
end end
it "should be recognized by #for_commit?" do it "should be recognized by #for_commit?" do
@note.should be_for_commit note.should be_for_commit
end end
end
describe "Pre-line commit notes" do it "should not be votable" do
before do note.should_not be_votable
@note = create(:note,
noteable_id: commit.id,
noteable_type: "Commit",
line_code: "0_16_1")
end end
end
describe "Commit diff line notes" do
let!(:note) { create(:note_on_commit_line, note: "+1 from me") }
let!(:commit) { note.noteable }
it "should save a valid note" do it "should save a valid note" do
@note.noteable_id.should == commit.id note.noteable_id.should == commit.id
@note.noteable.id.should == commit.id note.noteable.id.should == commit.id
end end
it "should be recognized by #for_diff_line?" do it "should be recognized by #for_diff_line?" do
@note.should be_for_diff_line note.should be_for_diff_line
end
it "should be recognized by #for_commit_diff_line?" do
note.should be_for_commit_diff_line
end
it "should not be votable" do
note.should_not be_votable
end
end
describe "Issue notes" do
let!(:note) { create(:note_on_issue, note: "+1 from me") }
it "should not be votable" do
note.should be_votable
end
end
describe "Merge request notes" do
let!(:note) { create(:note_on_merge_request, note: "+1 from me") }
it "should not be votable" do
note.should be_votable
end
end
describe "Merge request diff line notes" do
let!(:note) { create(:note_on_merge_request_line, note: "+1 from me") }
it "should not be votable" do
note.should_not be_votable
end end
end end
......
require 'spec_helper' require 'spec_helper'
describe Issue do describe Issue do
let(:issue) { create(:issue) } it { should include_module(Votes) }
end
describe MergeRequest do
let(:merge_request) { FactoryGirl.create(:merge_request_with_diffs) }
it { should include_module(Votes) }
describe "#upvotes" do describe "#upvotes" do
it "with no notes has a 0/0 score" do it "with no notes has a 0/0 score" do
issue.upvotes.should == 0 merge_request.upvotes.should == 0
end end
it "should recognize non-+1 notes" do it "should recognize non-+1 notes" do
issue.notes << create(:note, note: "No +1 here") merge_request.notes << create(:note, note: "No +1 here")
issue.should have(1).note merge_request.should have(1).note
issue.notes.first.upvote?.should be_false merge_request.notes.first.upvote?.should be_false
issue.upvotes.should == 0 merge_request.upvotes.should == 0
end end
it "should recognize a single +1 note" do it "should recognize a single +1 note" do
issue.notes << create(:note, note: "+1 This is awesome") merge_request.notes << create(:note, note: "+1 This is awesome")
issue.upvotes.should == 1 merge_request.upvotes.should == 1
end end
it "should recognize multiple +1 notes" do it "should recognize multiple +1 notes" do
issue.notes << create(:note, note: "+1 This is awesome") merge_request.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this") merge_request.notes << create(:note, note: "+1 I want this")
issue.upvotes.should == 2 merge_request.upvotes.should == 2
end end
end end
describe "#downvotes" do describe "#downvotes" do
it "with no notes has a 0/0 score" do it "with no notes has a 0/0 score" do
issue.downvotes.should == 0 merge_request.downvotes.should == 0
end end
it "should recognize non--1 notes" do it "should recognize non--1 notes" do
issue.notes << create(:note, note: "Almost got a -1") merge_request.notes << create(:note, note: "Almost got a -1")
issue.should have(1).note merge_request.should have(1).note
issue.notes.first.downvote?.should be_false merge_request.notes.first.downvote?.should be_false
issue.downvotes.should == 0 merge_request.downvotes.should == 0
end end
it "should recognize a single -1 note" do it "should recognize a single -1 note" do
issue.notes << create(:note, note: "-1 This is bad") merge_request.notes << create(:note, note: "-1 This is bad")
issue.downvotes.should == 1 merge_request.downvotes.should == 1
end end
it "should recognize multiple -1 notes" do it "should recognize multiple -1 notes" do
issue.notes << create(:note, note: "-1 This is bad") merge_request.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "-1 Away with this") merge_request.notes << create(:note, note: "-1 Away with this")
issue.downvotes.should == 2 merge_request.downvotes.should == 2
end end
end end
describe "#votes_count" do describe "#votes_count" do
it "with no notes has a 0/0 score" do it "with no notes has a 0/0 score" do
issue.votes_count.should == 0 merge_request.votes_count.should == 0
end end
it "should recognize non notes" do it "should recognize non notes" do
issue.notes << create(:note, note: "No +1 here") merge_request.notes << create(:note, note: "No +1 here")
issue.should have(1).note merge_request.should have(1).note
issue.votes_count.should == 0 merge_request.votes_count.should == 0
end end
it "should recognize a single +1 note" do it "should recognize a single +1 note" do
issue.notes << create(:note, note: "+1 This is awesome") merge_request.notes << create(:note, note: "+1 This is awesome")
issue.votes_count.should == 1 merge_request.votes_count.should == 1
end end
it "should recognize a single -1 note" do it "should recognize a single -1 note" do
issue.notes << create(:note, note: "-1 This is bad") merge_request.notes << create(:note, note: "-1 This is bad")
issue.votes_count.should == 1 merge_request.votes_count.should == 1
end end
it "should recognize multiple notes" do it "should recognize multiple notes" do
issue.notes << create(:note, note: "+1 This is awesome") merge_request.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "-1 This is bad") merge_request.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "+1 I want this") merge_request.notes << create(:note, note: "+1 I want this")
issue.votes_count.should == 3 merge_request.votes_count.should == 3
end end
end end
describe "#upvotes_in_percent" do describe "#upvotes_in_percent" do
it "with no notes has a 0% score" do it "with no notes has a 0% score" do
issue.upvotes_in_percent.should == 0 merge_request.upvotes_in_percent.should == 0
end end
it "should count a single 1 note as 100%" do it "should count a single 1 note as 100%" do
issue.notes << create(:note, note: "+1 This is awesome") merge_request.notes << create(:note, note: "+1 This is awesome")
issue.upvotes_in_percent.should == 100 merge_request.upvotes_in_percent.should == 100
end end
it "should count multiple +1 notes as 100%" do it "should count multiple +1 notes as 100%" do
issue.notes << create(:note, note: "+1 This is awesome") merge_request.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this") merge_request.notes << create(:note, note: "+1 I want this")
issue.upvotes_in_percent.should == 100 merge_request.upvotes_in_percent.should == 100
end end
it "should count fractions for multiple +1 and -1 notes correctly" do it "should count fractions for multiple +1 and -1 notes correctly" do
issue.notes << create(:note, note: "+1 This is awesome") merge_request.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this") merge_request.notes << create(:note, note: "+1 I want this")
issue.notes << create(:note, note: "-1 This is bad") merge_request.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "+1 me too") merge_request.notes << create(:note, note: "+1 me too")
issue.upvotes_in_percent.should == 75 merge_request.upvotes_in_percent.should == 75
end end
end end
describe "#downvotes_in_percent" do describe "#downvotes_in_percent" do
it "with no notes has a 0% score" do it "with no notes has a 0% score" do
issue.downvotes_in_percent.should == 0 merge_request.downvotes_in_percent.should == 0
end end
it "should count a single -1 note as 100%" do it "should count a single -1 note as 100%" do
issue.notes << create(:note, note: "-1 This is bad") merge_request.notes << create(:note, note: "-1 This is bad")
issue.downvotes_in_percent.should == 100 merge_request.downvotes_in_percent.should == 100
end end
it "should count multiple -1 notes as 100%" do it "should count multiple -1 notes as 100%" do
issue.notes << create(:note, note: "-1 This is bad") merge_request.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "-1 Away with this") merge_request.notes << create(:note, note: "-1 Away with this")
issue.downvotes_in_percent.should == 100 merge_request.downvotes_in_percent.should == 100
end end
it "should count fractions for multiple +1 and -1 notes correctly" do it "should count fractions for multiple +1 and -1 notes correctly" do
issue.notes << create(:note, note: "+1 This is awesome") merge_request.notes << create(:note, note: "+1 This is awesome")
issue.notes << create(:note, note: "+1 I want this") merge_request.notes << create(:note, note: "+1 I want this")
issue.notes << create(:note, note: "-1 This is bad") merge_request.notes << create(:note, note: "-1 This is bad")
issue.notes << create(:note, note: "+1 me too") merge_request.notes << create(:note, note: "+1 me too")
issue.downvotes_in_percent.should == 25 merge_request.downvotes_in_percent.should == 25
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment