Fix vote counting
This commit is contained in:
parent
6c6f415cae
commit
ae067ee322
|
@ -1,12 +1,4 @@
|
||||||
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
|
||||||
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
|
||||||
# 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
|
||||||
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
|
||||||
# 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
|
||||||
|
|
|
@ -1,16 +1,4 @@
|
||||||
module Votes
|
module Votes
|
||||||
# Return the number of +1 comments (upvotes)
|
|
||||||
def upvotes
|
|
||||||
notes.select(&:upvote?).size
|
|
||||||
end
|
|
||||||
|
|
||||||
def upvotes_in_percent
|
|
||||||
if votes_count.zero?
|
|
||||||
0
|
|
||||||
else
|
|
||||||
100.0 / votes_count * upvotes
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return the number of -1 comments (downvotes)
|
# Return the number of -1 comments (downvotes)
|
||||||
def downvotes
|
def downvotes
|
||||||
|
@ -25,6 +13,19 @@ module Votes
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return the number of +1 comments (upvotes)
|
||||||
|
def upvotes
|
||||||
|
notes.select(&:upvote?).size
|
||||||
|
end
|
||||||
|
|
||||||
|
def upvotes_in_percent
|
||||||
|
if votes_count.zero?
|
||||||
|
0
|
||||||
|
else
|
||||||
|
100.0 / votes_count * upvotes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Return the total number of votes
|
# Return the total number of votes
|
||||||
def votes_count
|
def votes_count
|
||||||
upvotes + downvotes
|
upvotes + downvotes
|
||||||
|
|
|
@ -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
|
||||||
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
|
||||||
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
|
||||||
|
|
||||||
|
it "should not be votable" do
|
||||||
|
note.should_not be_votable
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Pre-line commit notes" do
|
describe "Commit diff line notes" do
|
||||||
before do
|
let!(:note) { create(:note_on_commit_line, note: "+1 from me") }
|
||||||
@note = create(:note,
|
let!(:commit) { note.noteable }
|
||||||
noteable_id: commit.id,
|
|
||||||
noteable_type: "Commit",
|
|
||||||
line_code: "0_16_1")
|
|
||||||
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.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
|
||||||
|
|
||||||
|
|
|
@ -1,132 +1,138 @@
|
||||||
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
|
||||||
|
|
Loading…
Reference in a new issue