Commit ae067ee322e6702fb5ef0fd4f0cc4d4d5106cbde

Authored by Riyad Preukschas
1 parent 6c6f415c

Fix vote counting

app/helpers/notes_helper.rb
1 1 module NotesHelper
2   - def loading_more_notes?
3   - params[:loading_more].present?
4   - end
5   -
6   - def loading_new_notes?
7   - params[:loading_new].present?
8   - end
9   -
10 2 # Helps to distinguish e.g. commit notes in mr notes list
11 3 def note_for_main_target?(note)
12 4 !@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?)
... ... @@ -23,4 +15,12 @@ module NotesHelper
23 15 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)
24 16 end
25 17 end
  18 +
  19 + def loading_more_notes?
  20 + params[:loading_more].present?
  21 + end
  22 +
  23 + def loading_new_notes?
  24 + params[:loading_new].present?
  25 + end
26 26 end
... ...
app/models/note.rb
... ... @@ -85,7 +85,9 @@ class Note < ActiveRecord::Base
85 85 # Returns true if this is a downvote note,
86 86 # otherwise false is returned
87 87 def downvote?
88   - note.start_with?('-1') || note.start_with?(':-1:')
  88 + votable? && (note.start_with?('-1') ||
  89 + note.start_with?(':-1:')
  90 + )
89 91 end
90 92  
91 93 def for_commit?
... ... @@ -100,6 +102,10 @@ class Note < ActiveRecord::Base
100 102 line_code.present?
101 103 end
102 104  
  105 + def for_issue?
  106 + noteable_type == "Issue"
  107 + end
  108 +
103 109 def for_merge_request?
104 110 noteable_type == "MergeRequest"
105 111 end
... ... @@ -150,6 +156,12 @@ class Note < ActiveRecord::Base
150 156 # Returns true if this is an upvote note,
151 157 # otherwise false is returned
152 158 def upvote?
153   - note.start_with?('+1') || note.start_with?(':+1:')
  159 + votable? && (note.start_with?('+1') ||
  160 + note.start_with?(':+1:')
  161 + )
  162 + end
  163 +
  164 + def votable?
  165 + for_issue? || (for_merge_request? && !for_diff_line?)
154 166 end
155 167 end
... ...
app/roles/votes.rb
1 1 module Votes
2   - # Return the number of +1 comments (upvotes)
3   - def upvotes
4   - notes.select(&:upvote?).size
  2 +
  3 + # Return the number of -1 comments (downvotes)
  4 + def downvotes
  5 + notes.select(&:downvote?).size
5 6 end
6 7  
7   - def upvotes_in_percent
  8 + def downvotes_in_percent
8 9 if votes_count.zero?
9 10 0
10 11 else
11   - 100.0 / votes_count * upvotes
  12 + 100.0 - upvotes_in_percent
12 13 end
13 14 end
14 15  
15   - # Return the number of -1 comments (downvotes)
16   - def downvotes
17   - notes.select(&:downvote?).size
  16 + # Return the number of +1 comments (upvotes)
  17 + def upvotes
  18 + notes.select(&:upvote?).size
18 19 end
19 20  
20   - def downvotes_in_percent
  21 + def upvotes_in_percent
21 22 if votes_count.zero?
22 23 0
23 24 else
24   - 100.0 - upvotes_in_percent
  25 + 100.0 / votes_count * upvotes
25 26 end
26 27 end
27 28  
... ...
app/views/notes/_note.html.haml
... ... @@ -14,16 +14,14 @@
14 14 = time_ago_in_words(note.updated_at)
15 15 ago
16 16  
17   - -# only show vote if it's a note for the main target
18   - - if note_for_main_target?(note)
19   - - if note.upvote?
20   - %span.vote.upvote.label.label-success
21   - %i.icon-thumbs-up
22   - \+1
23   - - if note.downvote?
24   - %span.vote.downvote.label.label-error
25   - %i.icon-thumbs-down
26   - \-1
  17 + - if note.upvote?
  18 + %span.vote.upvote.label.label-success
  19 + %i.icon-thumbs-up
  20 + \+1
  21 + - if note.downvote?
  22 + %span.vote.downvote.label.label-error
  23 + %i.icon-thumbs-down
  24 + \-1
27 25  
28 26  
29 27 .note-body
... ...
spec/factories.rb
... ... @@ -91,6 +91,32 @@ FactoryGirl.define do
91 91 factory :note do
92 92 project
93 93 note "Note"
  94 + author
  95 +
  96 + factory :note_on_commit, traits: [:on_commit]
  97 + factory :note_on_commit_line, traits: [:on_commit, :on_line]
  98 + factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note]
  99 + factory :note_on_merge_request, traits: [:on_merge_request]
  100 + factory :note_on_merge_request_line, traits: [:on_merge_request, :on_line]
  101 +
  102 + trait :on_commit do
  103 + noteable_id "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
  104 + noteable_type "Commit"
  105 + end
  106 +
  107 + trait :on_line do
  108 + line_code "0_184_184"
  109 + end
  110 +
  111 + trait :on_merge_request do
  112 + noteable_id 1
  113 + noteable_type "MergeRequest"
  114 + end
  115 +
  116 + trait :on_issue do
  117 + noteable_id 1
  118 + noteable_type "Issue"
  119 + end
94 120 end
95 121  
96 122 factory :event do
... ...
spec/models/note_spec.rb
... ... @@ -43,79 +43,105 @@ describe Note do
43 43 let(:project) { create(:project) }
44 44  
45 45 it "recognizes a neutral note" do
46   - note = create(:note, note: "This is not a +1 note")
  46 + note = create(:votable_note, note: "This is not a +1 note")
47 47 note.should_not be_upvote
48 48 note.should_not be_downvote
49 49 end
50 50  
51 51 it "recognizes a neutral emoji note" do
52   - note = build(:note, note: "I would :+1: this, but I don't want to")
  52 + note = build(:votable_note, note: "I would :+1: this, but I don't want to")
53 53 note.should_not be_upvote
54 54 note.should_not be_downvote
55 55 end
56 56  
57 57 it "recognizes a +1 note" do
58   - note = create(:note, note: "+1 for this")
  58 + note = create(:votable_note, note: "+1 for this")
59 59 note.should be_upvote
60 60 end
61 61  
62 62 it "recognizes a +1 emoji as a vote" do
63   - note = build(:note, note: ":+1: for this")
  63 + note = build(:votable_note, note: ":+1: for this")
64 64 note.should be_upvote
65 65 end
66 66  
67 67 it "recognizes a -1 note" do
68   - note = create(:note, note: "-1 for this")
  68 + note = create(:votable_note, note: "-1 for this")
69 69 note.should be_downvote
70 70 end
71 71  
72 72 it "recognizes a -1 emoji as a vote" do
73   - note = build(:note, note: ":-1: for this")
  73 + note = build(:votable_note, note: ":-1: for this")
74 74 note.should be_downvote
75 75 end
76 76 end
77 77  
78   - let(:project) { create(:project) }
79   - let(:commit) { project.commit }
80   -
81 78 describe "Commit notes" do
82   - before do
83   - @note = create(:note,
84   - noteable_id: commit.id,
85   - noteable_type: "Commit")
86   - end
  79 + let!(:note) { create(:note_on_commit, note: "+1 from me") }
  80 + let!(:commit) { note.noteable }
87 81  
88 82 it "should be accessible through #noteable" do
89   - @note.noteable_id.should == commit.id
90   - @note.noteable.should be_a(Commit)
91   - @note.noteable.should == commit
  83 + note.noteable_id.should == commit.id
  84 + note.noteable.should be_a(Commit)
  85 + note.noteable.should == commit
92 86 end
93 87  
94 88 it "should save a valid note" do
95   - @note.noteable_id.should == commit.id
96   - @note.noteable == commit
  89 + note.noteable_id.should == commit.id
  90 + note.noteable == commit
97 91 end
98 92  
99 93 it "should be recognized by #for_commit?" do
100   - @note.should be_for_commit
  94 + note.should be_for_commit
101 95 end
102   - end
103 96  
104   - describe "Pre-line commit notes" do
105   - before do
106   - @note = create(:note,
107   - noteable_id: commit.id,
108   - noteable_type: "Commit",
109   - line_code: "0_16_1")
  97 + it "should not be votable" do
  98 + note.should_not be_votable
110 99 end
  100 + end
  101 +
  102 + describe "Commit diff line notes" do
  103 + let!(:note) { create(:note_on_commit_line, note: "+1 from me") }
  104 + let!(:commit) { note.noteable }
111 105  
112 106 it "should save a valid note" do
113   - @note.noteable_id.should == commit.id
114   - @note.noteable.id.should == commit.id
  107 + note.noteable_id.should == commit.id
  108 + note.noteable.id.should == commit.id
115 109 end
116 110  
117 111 it "should be recognized by #for_diff_line?" do
118   - @note.should be_for_diff_line
  112 + note.should be_for_diff_line
  113 + end
  114 +
  115 + it "should be recognized by #for_commit_diff_line?" do
  116 + note.should be_for_commit_diff_line
  117 + end
  118 +
  119 + it "should not be votable" do
  120 + note.should_not be_votable
  121 + end
  122 + end
  123 +
  124 + describe "Issue notes" do
  125 + let!(:note) { create(:note_on_issue, note: "+1 from me") }
  126 +
  127 + it "should not be votable" do
  128 + note.should be_votable
  129 + end
  130 + end
  131 +
  132 + describe "Merge request notes" do
  133 + let!(:note) { create(:note_on_merge_request, note: "+1 from me") }
  134 +
  135 + it "should not be votable" do
  136 + note.should be_votable
  137 + end
  138 + end
  139 +
  140 + describe "Merge request diff line notes" do
  141 + let!(:note) { create(:note_on_merge_request_line, note: "+1 from me") }
  142 +
  143 + it "should not be votable" do
  144 + note.should_not be_votable
119 145 end
120 146 end
121 147  
... ...
spec/roles/votes_spec.rb
1 1 require 'spec_helper'
2 2  
3 3 describe Issue do
4   - let(:issue) { create(:issue) }
  4 + it { should include_module(Votes) }
  5 +end
  6 +
  7 +describe MergeRequest do
  8 + let(:merge_request) { FactoryGirl.create(:merge_request_with_diffs) }
  9 +
  10 + it { should include_module(Votes) }
5 11  
6 12 describe "#upvotes" do
7 13 it "with no notes has a 0/0 score" do
8   - issue.upvotes.should == 0
  14 + merge_request.upvotes.should == 0
9 15 end
10 16  
11 17 it "should recognize non-+1 notes" do
12   - issue.notes << create(:note, note: "No +1 here")
13   - issue.should have(1).note
14   - issue.notes.first.upvote?.should be_false
15   - issue.upvotes.should == 0
  18 + merge_request.notes << create(:note, note: "No +1 here")
  19 + merge_request.should have(1).note
  20 + merge_request.notes.first.upvote?.should be_false
  21 + merge_request.upvotes.should == 0
16 22 end
17 23  
18 24 it "should recognize a single +1 note" do
19   - issue.notes << create(:note, note: "+1 This is awesome")
20   - issue.upvotes.should == 1
  25 + merge_request.notes << create(:note, note: "+1 This is awesome")
  26 + merge_request.upvotes.should == 1
21 27 end
22 28  
23 29 it "should recognize multiple +1 notes" do
24   - issue.notes << create(:note, note: "+1 This is awesome")
25   - issue.notes << create(:note, note: "+1 I want this")
26   - issue.upvotes.should == 2
  30 + merge_request.notes << create(:note, note: "+1 This is awesome")
  31 + merge_request.notes << create(:note, note: "+1 I want this")
  32 + merge_request.upvotes.should == 2
27 33 end
28 34 end
29 35  
30 36 describe "#downvotes" do
31 37 it "with no notes has a 0/0 score" do
32   - issue.downvotes.should == 0
  38 + merge_request.downvotes.should == 0
33 39 end
34 40  
35 41 it "should recognize non--1 notes" do
36   - issue.notes << create(:note, note: "Almost got a -1")
37   - issue.should have(1).note
38   - issue.notes.first.downvote?.should be_false
39   - issue.downvotes.should == 0
  42 + merge_request.notes << create(:note, note: "Almost got a -1")
  43 + merge_request.should have(1).note
  44 + merge_request.notes.first.downvote?.should be_false
  45 + merge_request.downvotes.should == 0
40 46 end
41 47  
42 48 it "should recognize a single -1 note" do
43   - issue.notes << create(:note, note: "-1 This is bad")
44   - issue.downvotes.should == 1
  49 + merge_request.notes << create(:note, note: "-1 This is bad")
  50 + merge_request.downvotes.should == 1
45 51 end
46 52  
47 53 it "should recognize multiple -1 notes" do
48   - issue.notes << create(:note, note: "-1 This is bad")
49   - issue.notes << create(:note, note: "-1 Away with this")
50   - issue.downvotes.should == 2
  54 + merge_request.notes << create(:note, note: "-1 This is bad")
  55 + merge_request.notes << create(:note, note: "-1 Away with this")
  56 + merge_request.downvotes.should == 2
51 57 end
52 58 end
53 59  
54 60 describe "#votes_count" do
55 61 it "with no notes has a 0/0 score" do
56   - issue.votes_count.should == 0
  62 + merge_request.votes_count.should == 0
57 63 end
58 64  
59 65 it "should recognize non notes" do
60   - issue.notes << create(:note, note: "No +1 here")
61   - issue.should have(1).note
62   - issue.votes_count.should == 0
  66 + merge_request.notes << create(:note, note: "No +1 here")
  67 + merge_request.should have(1).note
  68 + merge_request.votes_count.should == 0
63 69 end
64 70  
65 71 it "should recognize a single +1 note" do
66   - issue.notes << create(:note, note: "+1 This is awesome")
67   - issue.votes_count.should == 1
  72 + merge_request.notes << create(:note, note: "+1 This is awesome")
  73 + merge_request.votes_count.should == 1
68 74 end
69 75  
70 76 it "should recognize a single -1 note" do
71   - issue.notes << create(:note, note: "-1 This is bad")
72   - issue.votes_count.should == 1
  77 + merge_request.notes << create(:note, note: "-1 This is bad")
  78 + merge_request.votes_count.should == 1
73 79 end
74 80  
75 81 it "should recognize multiple notes" do
76   - issue.notes << create(:note, note: "+1 This is awesome")
77   - issue.notes << create(:note, note: "-1 This is bad")
78   - issue.notes << create(:note, note: "+1 I want this")
79   - issue.votes_count.should == 3
  82 + merge_request.notes << create(:note, note: "+1 This is awesome")
  83 + merge_request.notes << create(:note, note: "-1 This is bad")
  84 + merge_request.notes << create(:note, note: "+1 I want this")
  85 + merge_request.votes_count.should == 3
80 86 end
81 87 end
82 88  
83 89 describe "#upvotes_in_percent" do
84 90 it "with no notes has a 0% score" do
85   - issue.upvotes_in_percent.should == 0
  91 + merge_request.upvotes_in_percent.should == 0
86 92 end
87 93  
88 94 it "should count a single 1 note as 100%" do
89   - issue.notes << create(:note, note: "+1 This is awesome")
90   - issue.upvotes_in_percent.should == 100
  95 + merge_request.notes << create(:note, note: "+1 This is awesome")
  96 + merge_request.upvotes_in_percent.should == 100
91 97 end
92 98  
93 99 it "should count multiple +1 notes as 100%" do
94   - issue.notes << create(:note, note: "+1 This is awesome")
95   - issue.notes << create(:note, note: "+1 I want this")
96   - issue.upvotes_in_percent.should == 100
  100 + merge_request.notes << create(:note, note: "+1 This is awesome")
  101 + merge_request.notes << create(:note, note: "+1 I want this")
  102 + merge_request.upvotes_in_percent.should == 100
97 103 end
98 104  
99 105 it "should count fractions for multiple +1 and -1 notes correctly" do
100   - issue.notes << create(:note, note: "+1 This is awesome")
101   - issue.notes << create(:note, note: "+1 I want this")
102   - issue.notes << create(:note, note: "-1 This is bad")
103   - issue.notes << create(:note, note: "+1 me too")
104   - issue.upvotes_in_percent.should == 75
  106 + merge_request.notes << create(:note, note: "+1 This is awesome")
  107 + merge_request.notes << create(:note, note: "+1 I want this")
  108 + merge_request.notes << create(:note, note: "-1 This is bad")
  109 + merge_request.notes << create(:note, note: "+1 me too")
  110 + merge_request.upvotes_in_percent.should == 75
105 111 end
106 112 end
107 113  
108 114 describe "#downvotes_in_percent" do
109 115 it "with no notes has a 0% score" do
110   - issue.downvotes_in_percent.should == 0
  116 + merge_request.downvotes_in_percent.should == 0
111 117 end
112 118  
113 119 it "should count a single -1 note as 100%" do
114   - issue.notes << create(:note, note: "-1 This is bad")
115   - issue.downvotes_in_percent.should == 100
  120 + merge_request.notes << create(:note, note: "-1 This is bad")
  121 + merge_request.downvotes_in_percent.should == 100
116 122 end
117 123  
118 124 it "should count multiple -1 notes as 100%" do
119   - issue.notes << create(:note, note: "-1 This is bad")
120   - issue.notes << create(:note, note: "-1 Away with this")
121   - issue.downvotes_in_percent.should == 100
  125 + merge_request.notes << create(:note, note: "-1 This is bad")
  126 + merge_request.notes << create(:note, note: "-1 Away with this")
  127 + merge_request.downvotes_in_percent.should == 100
122 128 end
123 129  
124 130 it "should count fractions for multiple +1 and -1 notes correctly" do
125   - issue.notes << create(:note, note: "+1 This is awesome")
126   - issue.notes << create(:note, note: "+1 I want this")
127   - issue.notes << create(:note, note: "-1 This is bad")
128   - issue.notes << create(:note, note: "+1 me too")
129   - issue.downvotes_in_percent.should == 25
  131 + merge_request.notes << create(:note, note: "+1 This is awesome")
  132 + merge_request.notes << create(:note, note: "+1 I want this")
  133 + merge_request.notes << create(:note, note: "-1 This is bad")
  134 + merge_request.notes << create(:note, note: "+1 me too")
  135 + merge_request.downvotes_in_percent.should == 25
130 136 end
131 137 end
132 138 end
... ...