Merge pull request #2206 from consul/related-contents-score

Related contents score
This commit is contained in:
BertoCQ
2017-12-20 15:13:12 +01:00
committed by GitHub
25 changed files with 267 additions and 123 deletions

View File

@@ -2424,11 +2424,28 @@ table {
li { li {
border-bottom: 1px solid $border; border-bottom: 1px solid $border;
padding: $line-height / 4; margin-bottom: 0 !important;
padding: $line-height / 2;
&:first-child { &:first-child {
border-top: 1px solid $border; border-top: 1px solid $border;
} }
@include breakpoint(medium) {
.score-actions {
display: none;
float: right;
}
}
&:hover {
background: #f9f9f9;
.score-actions {
display: block;
}
}
} }
h3 { h3 {
@@ -2436,7 +2453,7 @@ table {
font-weight: normal; font-weight: normal;
} }
span:not(.icon-flag) { .related-content-title {
color: #4f4f4f; color: #4f4f4f;
font-size: rem-calc(12); font-size: rem-calc(12);
text-transform: uppercase; text-transform: uppercase;
@@ -2447,6 +2464,47 @@ table {
} }
} }
.relate-content-score {
display: block;
@include breakpoint(medium) {
text-align: center;
}
a {
font-weight: bold;
margin-right: $line-height;
padding-left: rem-calc(20);
position: relative;
text-decoration: none;
&.score-positive:before,
&.score-negative:before {
font-family: 'icons';
left: 0;
position: absolute;
}
&.score-positive {
color: $color-success;
&:before {
color: $color-success;
content: '\6c';
}
}
&.score-negative {
color: $color-alert;
&:before {
color: $color-alert;
content: '\76';
}
}
}
}
// 22. Images // 22. Images
// ----------------- // -----------------

View File

@@ -1,13 +1,11 @@
class RelatedContentsController < ApplicationController class RelatedContentsController < ApplicationController
VALID_URL = /#{Setting['url']}\/.*\/.*/
skip_authorization_check skip_authorization_check
respond_to :html, :js respond_to :html, :js
def create def create
if relationable_object && related_object if relationable_object && related_object
@relationable.relate_content(@related) RelatedContent.create(parent_relationable: @relationable, child_relationable: @related, author: current_user)
flash[:success] = t('related_content.success') flash[:success] = t('related_content.success')
else else
@@ -17,28 +15,25 @@ class RelatedContentsController < ApplicationController
redirect_to @relationable redirect_to @relationable
end end
def flag def score_positive
@related = RelatedContent.find_by(id: params[:id]) score(:positive)
Flag.flag(current_user, @related)
Flag.flag(current_user, @related.opposite_related_content)
render template: 'relationable/_refresh_flag_actions'
end end
def unflag def score_negative
@related = RelatedContent.find_by(id: params[:id]) score(:negative)
Flag.unflag(current_user, @related)
Flag.unflag(current_user, @related.opposite_related_content)
render template: 'relationable/_refresh_flag_actions'
end end
private private
def score(action)
@related = RelatedContent.find_by(id: params[:id])
@related.send("score_#{action}", current_user)
render template: 'relationable/_refresh_score_actions'
end
def valid_url? def valid_url?
params[:url].match(VALID_URL) params[:url].start_with?(Setting['url'])
end end
def relationable_object def relationable_object

View File

@@ -21,8 +21,6 @@ module FlagsHelper
def own_flaggable?(flaggable) def own_flaggable?(flaggable)
if flaggable.is_a? Comment if flaggable.is_a? Comment
flaggable.user_id == current_user.id flaggable.user_id == current_user.id
elsif flaggable.is_a? RelatedContent
false
else else
flaggable.author_id == current_user.id flaggable.author_id == current_user.id
end end

View File

@@ -5,19 +5,11 @@ module Relationable
has_many :related_contents, as: :parent_relationable, dependent: :destroy has_many :related_contents, as: :parent_relationable, dependent: :destroy
end end
def relate_content(relationable) def find_related_content(relationable)
RelatedContent.find_or_create_by(parent_relationable: self, child_relationable: relationable) RelatedContent.where(parent_relationable: self, child_relationable: relationable).first
end end
def relationed_contents def relationed_contents
related_contents.not_hidden.map { |related_content| related_content.child_relationable } related_contents.not_hidden.map { |related_content| related_content.child_relationable }
end end
def report_related_content(relationable)
related_content = related_contents.find_by(child_relationable: relationable)
if related_content.present?
related_content.increment!(:flags_count)
related_content.opposite_related_content.increment!(:flags_count)
end
end
end end

View File

@@ -1,12 +1,15 @@
class RelatedContent < ActiveRecord::Base class RelatedContent < ActiveRecord::Base
include Flaggable RELATED_CONTENT_SCORE_THRESHOLD = Setting['related_content_score_threshold'].to_f
RELATED_CONTENTS_REPORT_THRESHOLD = Setting['related_contents_report_threshold'].to_i
RELATIONABLE_MODELS = %w{proposals debates}.freeze RELATIONABLE_MODELS = %w{proposals debates}.freeze
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
belongs_to :author, class_name: 'User', foreign_key: 'author_id'
belongs_to :parent_relationable, polymorphic: true, touch: true belongs_to :parent_relationable, polymorphic: true, touch: true
belongs_to :child_relationable, polymorphic: true, touch: true belongs_to :child_relationable, polymorphic: true, touch: true
has_one :opposite_related_content, class_name: 'RelatedContent', foreign_key: :related_content_id has_one :opposite_related_content, class_name: 'RelatedContent', foreign_key: :related_content_id
has_many :related_content_scores
validates :parent_relationable_id, presence: true validates :parent_relationable_id, presence: true
validates :parent_relationable_type, presence: true validates :parent_relationable_type, presence: true
@@ -15,22 +18,46 @@ class RelatedContent < ActiveRecord::Base
validates :parent_relationable_id, uniqueness: { scope: [:parent_relationable_type, :child_relationable_id, :child_relationable_type] } validates :parent_relationable_id, uniqueness: { scope: [:parent_relationable_type, :child_relationable_id, :child_relationable_type] }
after_create :create_opposite_related_content, unless: proc { opposite_related_content.present? } after_create :create_opposite_related_content, unless: proc { opposite_related_content.present? }
after_destroy :destroy_opposite_related_content, if: proc { opposite_related_content.present? } after_create :create_author_score
scope :not_hidden, -> { where('flags_count <= ?', RELATED_CONTENTS_REPORT_THRESHOLD) } scope :not_hidden, -> { where(hidden_at: nil) }
def hidden_by_reports? def score_positive(user)
flags_count > RELATED_CONTENTS_REPORT_THRESHOLD score(RelatedContentScore::SCORES[:POSITIVE], user)
end
def score_negative(user)
score(RelatedContentScore::SCORES[:NEGATIVE], user)
end
def scored_by_user?(user)
related_content_scores.exists?(user: user)
end end
private private
def create_opposite_related_content def create_opposite_related_content
related_content = RelatedContent.create!(opposite_related_content: self, parent_relationable: child_relationable, child_relationable: parent_relationable) related_content = RelatedContent.create!(opposite_related_content: self, parent_relationable: child_relationable,
child_relationable: parent_relationable, author: author)
self.opposite_related_content = related_content self.opposite_related_content = related_content
end end
def destroy_opposite_related_content def score(value, user)
opposite_related_content.destroy score_with_opposite(value, user)
hide_with_opposite if (related_content_scores.sum(:value) / related_content_scores_count) < RELATED_CONTENT_SCORE_THRESHOLD
end
def hide_with_opposite
hide
opposite_related_content.hide
end
def create_author_score
score_positive(author)
end
def score_with_opposite(value, user)
RelatedContentScore.create(user: user, related_content: self, value: value)
RelatedContentScore.create(user: user, related_content: opposite_related_content, value: value)
end end
end end

View File

@@ -0,0 +1,13 @@
class RelatedContentScore < ActiveRecord::Base
SCORES = {
POSITIVE: 1,
NEGATIVE: -1
}.freeze
belongs_to :related_content, touch: true, counter_cache: :related_content_scores_count
belongs_to :user
validates :user, presence: true
validates :related_content, presence: true
validates :related_content_id, uniqueness: { scope: [:user_id] }
end

View File

@@ -1,19 +0,0 @@
<span class="flag-content">
<% if show_flag_action? related %>
<a id="flag-expand-related-<%= related.id %>" data-toggle="flag-drop-related-<%= related.id %>" title="<%= t('shared.flag') %>" class="float-right flag">
<span class="icon-flag flag-disable"></span>
</a>
<span class="dropdown-pane" id="flag-drop-related-<%= related.id %>" data-dropdown data-auto-focus="true">
<%= link_to t('shared.flag'), flag_related_content_path(related), method: :put, remote: true, id: "flag-related-#{ related.id }" %>
</span>
<% end %>
<% if show_unflag_action? related %>
<a id="unflag-expand-related-<%= related.id %>" data-toggle="unflag-drop-related-<%= related.id %>" title="<%= t('shared.unflag') %>" class="float-right flag">
<span class="icon-flag flag-active"></span>
</a>
<span class="dropdown-pane" id="unflag-drop-related-<%= related.id %>" data-dropdown data-auto-focus="true">
<%= link_to t('shared.unflag'), unflag_related_content_path(related), method: :put, remote: true, id: "unflag-related-#{ related.id }" %>
</span>
<% end %>
</span>

View File

@@ -1 +0,0 @@
$("#<%= dom_id(@related) %>.js-flag-actions").html('<%= j render("relationable/flag_actions", related: @related) %>');

View File

@@ -0,0 +1 @@
$("#<%= dom_id(@related) %>.js-score-actions").html('');

View File

@@ -4,11 +4,13 @@
<h2 class="inline-block"> <h2 class="inline-block">
<%= t("related_content.title") %>&nbsp;<span>(<%= relationable.relationed_contents.count %>)</span> <%= t("related_content.title") %>&nbsp;<span>(<%= relationable.relationed_contents.count %>)</span>
</h2> </h2>
<a> <% if current_user %>
<button type="button" data-toggle="related_content" class="add-related-content" id="add-related-content"> <a>
<%= t("related_content.add") %> <button type="button" data-toggle="related_content" class="add-related-content" id="add-related-content">
</button> <%= t("related_content.add") %>
</a> </button>
</a>
<% end %>
</div> </div>
<%= render 'relationable/form', relationable: relationable %> <%= render 'relationable/form', relationable: relationable %>

View File

@@ -1,11 +1,14 @@
<ul class="related-content-list" id="related-content-list"> <ul class="related-content-list" id="related-content-list">
<% @related_contents.each do |related| %> <% @related_contents.each do |related| %>
<li> <li id="related-content-<%= related.find_related_content(relationable).id %>">
<span id="<%= dom_id(related.relate_content(relationable)) %>" class="js-flag-actions"> <% related_content = related.find_related_content(relationable) %>
<%= render 'relationable/flag_actions', related: related.relate_content(relationable) %> <% if current_user && related_content.author != current_user && !related_content.scored_by_user?(current_user)%>
</span> <span id="<%= dom_id(related.find_related_content(relationable)) %>" class="js-score-actions score-actions">
<%= render 'relationable/score', related: related_content %>
</span>
<% end %>
<span><%= t("related_content.content_title.#{related.class.name.downcase}") %></span><br> <span class="related-content-title"><%= t("related_content.content_title.#{related.class.name.downcase}") %></span><br>
<h3 class="inline-block"> <h3 class="inline-block">
<%= link_to related.title, eval("#{related.class.name.downcase}_path(related)") %> <%= link_to related.title, eval("#{related.class.name.downcase}_path(related)") %>
</h3> </h3>

View File

@@ -0,0 +1,17 @@
<small><%= t("related_content.is_related") %></small>
<span class="relate-content-score">
<%= link_to t("related_content.score_positive"),
score_positive_related_content_path(related),
method: :put,
remote: true,
id: "score-positive-related-#{ related.id }",
class: "score-positive" %>
<%= link_to t("related_content.score_negative"),
score_negative_related_content_path(related),
method: :put,
remote: true,
id: "score-negative-related-#{ related.id }",
class: "score-negative" %>
</span>

View File

@@ -820,6 +820,9 @@ en:
submit: "Add" submit: "Add"
error: "Link not valid. Remember to start with %{url}." error: "Link not valid. Remember to start with %{url}."
success: "You added a new related content" success: "You added a new related content"
is_related: "¿Is it related content?"
score_positive: "Yes"
score_negative: "No"
content_title: content_title:
proposal: "Proposal" proposal: "Proposal"
debate: "Debate" debate: "Debate"

View File

@@ -819,6 +819,9 @@ es:
submit: "Añadir" submit: "Añadir"
error: "Enlace no válido. Recuerda que debe empezar por %{url}." error: "Enlace no válido. Recuerda que debe empezar por %{url}."
success: "Has añadido un nuevo contenido relacionado" success: "Has añadido un nuevo contenido relacionado"
is_related: "¿Es contenido relacionado?"
score_positive: "Sí"
score_negative: "No"
content_title: content_title:
proposal: "Propuesta" proposal: "Propuesta"
debate: "Debate" debate: "Debate"

View File

@@ -464,8 +464,8 @@ Rails.application.routes.draw do
resources :related_contents, only: [:create] do resources :related_contents, only: [:create] do
member do member do
put :flag put :score_positive
put :unflag put :score_negative
end end
end end

View File

@@ -67,7 +67,7 @@ section "Creating Settings" do
Setting.create(key: 'map_latitude', value: 51.48) Setting.create(key: 'map_latitude', value: 51.48)
Setting.create(key: 'map_longitude', value: 0.0) Setting.create(key: 'map_longitude', value: 0.0)
Setting.create(key: 'map_zoom', value: 10) Setting.create(key: 'map_zoom', value: 10)
Setting.create(key: 'related_contents_report_threshold', value: 2) Setting.create(key: 'related_content_score_threshold', value: -0.3)
end end
section "Creating Geozones" do section "Creating Geozones" do

View File

@@ -0,0 +1,5 @@
class RemoveRelatedContentsFlagsCount < ActiveRecord::Migration
def change
remove_column :related_contents, :flags_count
end
end

View File

@@ -0,0 +1,11 @@
class CreateRelatedContentScores < ActiveRecord::Migration
def change
create_table :related_content_scores do |t|
t.references :user, index: true, foreign_key: true
t.references :related_content, index: true, foreign_key: true
t.integer :value
end
add_index :related_content_scores, [:user_id, :related_content_id], name: "unique_user_related_content_scoring", unique: true, using: :btree
end
end

View File

@@ -0,0 +1,6 @@
class AddHiddenAtToRelatedContents < ActiveRecord::Migration
def change
add_column :related_contents, :hidden_at, :datetime
add_index :related_contents, :hidden_at
end
end

View File

@@ -0,0 +1,5 @@
class AddRelatedContentScoresCounterToRelatedContent < ActiveRecord::Migration
def change
add_column :related_contents, :related_content_scores_count, :integer, default: 0
end
end

View File

@@ -0,0 +1,5 @@
class AddAuthorToRelatedContent < ActiveRecord::Migration
def change
add_column :related_contents, :author_id, :integer
end
end

View File

@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20171215152244) do ActiveRecord::Schema.define(version: 20171220010000) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -854,6 +854,16 @@ ActiveRecord::Schema.define(version: 20171215152244) do
add_index "proposals", ["title"], name: "index_proposals_on_title", using: :btree add_index "proposals", ["title"], name: "index_proposals_on_title", using: :btree
add_index "proposals", ["tsv"], name: "index_proposals_on_tsv", using: :gin add_index "proposals", ["tsv"], name: "index_proposals_on_tsv", using: :gin
create_table "related_content_scores", force: :cascade do |t|
t.integer "user_id"
t.integer "related_content_id"
t.integer "value"
end
add_index "related_content_scores", ["related_content_id"], name: "index_related_content_scores_on_related_content_id", using: :btree
add_index "related_content_scores", ["user_id", "related_content_id"], name: "unique_user_related_content_scoring", unique: true, using: :btree
add_index "related_content_scores", ["user_id"], name: "index_related_content_scores_on_user_id", using: :btree
create_table "related_contents", force: :cascade do |t| create_table "related_contents", force: :cascade do |t|
t.integer "parent_relationable_id" t.integer "parent_relationable_id"
t.string "parent_relationable_type" t.string "parent_relationable_type"
@@ -862,10 +872,13 @@ ActiveRecord::Schema.define(version: 20171215152244) do
t.integer "related_content_id" t.integer "related_content_id"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.integer "flags_count", default: 0 t.datetime "hidden_at"
t.integer "related_content_scores_count", default: 0
t.integer "author_id"
end end
add_index "related_contents", ["child_relationable_type", "child_relationable_id"], name: "index_related_contents_on_child_relationable", using: :btree add_index "related_contents", ["child_relationable_type", "child_relationable_id"], name: "index_related_contents_on_child_relationable", using: :btree
add_index "related_contents", ["hidden_at"], name: "index_related_contents_on_hidden_at", using: :btree
add_index "related_contents", ["parent_relationable_id", "parent_relationable_type", "child_relationable_id", "child_relationable_type"], name: "unique_parent_child_related_content", unique: true, using: :btree add_index "related_contents", ["parent_relationable_id", "parent_relationable_type", "child_relationable_id", "child_relationable_type"], name: "unique_parent_child_related_content", unique: true, using: :btree
add_index "related_contents", ["parent_relationable_type", "parent_relationable_id"], name: "index_related_contents_on_parent_relationable", using: :btree add_index "related_contents", ["parent_relationable_type", "parent_relationable_id"], name: "index_related_contents_on_parent_relationable", using: :btree
add_index "related_contents", ["related_content_id"], name: "opposite_related_content", using: :btree add_index "related_contents", ["related_content_id"], name: "opposite_related_content", using: :btree
@@ -1189,6 +1202,8 @@ ActiveRecord::Schema.define(version: 20171215152244) do
add_foreign_key "poll_recounts", "poll_officer_assignments", column: "officer_assignment_id" add_foreign_key "poll_recounts", "poll_officer_assignments", column: "officer_assignment_id"
add_foreign_key "poll_voters", "polls" add_foreign_key "poll_voters", "polls"
add_foreign_key "proposals", "communities" add_foreign_key "proposals", "communities"
add_foreign_key "related_content_scores", "related_contents"
add_foreign_key "related_content_scores", "users"
add_foreign_key "users", "geozones" add_foreign_key "users", "geozones"
add_foreign_key "valuators", "users" add_foreign_key "valuators", "users"
end end

View File

@@ -120,4 +120,4 @@ Setting['map_longitude'] = 0.0
Setting['map_zoom'] = 10 Setting['map_zoom'] = 10
# Related content # Related content
Setting['related_contents_report_threshold'] = 5 Setting['related_content_score_threshold'] = -0.3

View File

@@ -18,7 +18,7 @@ describe RelatedContent do
end end
it "should not allow repeated related contents" do it "should not allow repeated related contents" do
related_content = create(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable) related_content = create(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable, author: build(:user))
new_related_content = build(:related_content, parent_relationable: related_content.parent_relationable, child_relationable: related_content.child_relationable) new_related_content = build(:related_content, parent_relationable: related_content.parent_relationable, child_relationable: related_content.child_relationable)
expect(new_related_content).not_to be_valid expect(new_related_content).not_to be_valid
end end
@@ -26,7 +26,7 @@ describe RelatedContent do
describe 'create_opposite_related_content' do describe 'create_opposite_related_content' do
let(:parent_relationable) { create(:proposal) } let(:parent_relationable) { create(:proposal) }
let(:child_relationable) { create(:debate) } let(:child_relationable) { create(:debate) }
let(:related_content) { build(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable) } let(:related_content) { build(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable, author: build(:user)) }
it 'creates an opposite related_content' do it 'creates an opposite related_content' do
expect { related_content.save }.to change { RelatedContent.count }.by(2) expect { related_content.save }.to change { RelatedContent.count }.by(2)
@@ -38,32 +38,18 @@ describe RelatedContent do
end end
end end
describe 'relationable destroy' do
let(:parent_relationable) { create(:proposal) }
let(:child_relationable) { create(:debate) }
it 'destroys both related contents involved' do
related_content = create(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable)
expect { related_content.parent_relationable.destroy }.to change { RelatedContent.all.count }.by(-2)
expect(child_relationable.related_contents).to be_empty
end
end
# TODO: Move this into a Relationable shared context
describe '#report_related_content' do
it 'increments both relation and opposite relation flags_count counters' do
related_content = create(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable)
parent_relationable.report_related_content(child_relationable)
expect(related_content.reload.flags_count).to eq(1)
expect(related_content.reload.opposite_related_content.flags_count).to eq(1)
end
end
describe '#relationed_contents' do describe '#relationed_contents' do
before do before do
create(:related_content, parent_relationable: parent_relationable, child_relationable: create(:proposal), flags_count: 6) related_content = create(:related_content, parent_relationable: parent_relationable, child_relationable: create(:proposal), author: build(:user))
create(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable) create(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable, author: build(:user))
2.times do
related_content.send("score_positive", build(:user))
end
6.times do
related_content.send("score_negative", build(:user))
end
end end
it 'returns not hidden by reports related contents' do it 'returns not hidden by reports related contents' do

View File

@@ -6,7 +6,7 @@ shared_examples "relationable" do |relationable_model_name|
let(:user) { create(:user) } let(:user) { create(:user) }
scenario 'related contents are listed' do scenario 'related contents are listed' do
related_content = create(:related_content, parent_relationable: relationable, child_relationable: related1) related_content = create(:related_content, parent_relationable: relationable, child_relationable: related1, author: build(:user))
visit eval("#{relationable.class.name.downcase}_path(relationable)") visit eval("#{relationable.class.name.downcase}_path(relationable)")
within("#related-content-list") do within("#related-content-list") do
@@ -25,6 +25,7 @@ shared_examples "relationable" do |relationable_model_name|
end end
scenario 'related contents can be added' do scenario 'related contents can be added' do
login_as(user)
visit eval("#{relationable.class.name.downcase}_path(relationable)") visit eval("#{relationable.class.name.downcase}_path(relationable)")
expect(page).to have_selector('#related_content', visible: false) expect(page).to have_selector('#related_content', visible: false)
@@ -57,6 +58,7 @@ shared_examples "relationable" do |relationable_model_name|
end end
scenario 'if related content URL is invalid returns error' do scenario 'if related content URL is invalid returns error' do
login_as(user)
visit eval("#{relationable.class.name.downcase}_path(relationable)") visit eval("#{relationable.class.name.downcase}_path(relationable)")
click_on("Add related content") click_on("Add related content")
@@ -69,37 +71,54 @@ shared_examples "relationable" do |relationable_model_name|
expect(page).to have_content("Link not valid. Remember to start with #{Setting[:url]}.") expect(page).to have_content("Link not valid. Remember to start with #{Setting[:url]}.")
end end
scenario 'related content can be flagged', :js do scenario 'related content can be scored positively', :js do
related_content = create(:related_content, parent_relationable: relationable, child_relationable: related1) related_content = create(:related_content, parent_relationable: relationable, child_relationable: related1, author: build(:user))
login_as(user) login_as(user)
visit eval("#{relationable.class.name.downcase}_path(relationable)") visit eval("#{relationable.class.name.downcase}_path(relationable)")
within("#related-content-list") do within("#related-content-list") do
expect(page).to have_css("#flag-expand-related-#{related_content.opposite_related_content.id}") find("#related-content-#{related_content.opposite_related_content.id}").hover
find("#flag-expand-related-#{related_content.opposite_related_content.id}").click find("#score-positive-related-#{related_content.opposite_related_content.id}").click
expect(page).to have_css("#flag-drop-related-#{related_content.opposite_related_content.id}", visible: true) expect(page).to_not have_css("#score-positive-related-#{related_content.opposite_related_content.id}")
click_link("flag-related-#{related_content.opposite_related_content.id}")
expect(page).to have_css("#unflag-expand-related-#{related_content.opposite_related_content.id}")
end end
expect(related_content.reload.flags_count).to eq(1) expect(related_content.related_content_scores.find_by(user_id: user.id, related_content_id: related_content.id).value).to eq(1)
expect(related_content.opposite_related_content.flags_count).to eq(1) expect(related_content.opposite_related_content.related_content_scores.find_by(user_id: user.id, related_content_id: related_content.opposite_related_content.id).value).to eq(1)
end end
scenario 'if related content has been flagged more than 5 times it will be hidden', :js do scenario 'related content can be scored negatively', :js do
related_content = create(:related_content, parent_relationable: relationable, child_relationable: related1) related_content = create(:related_content, parent_relationable: relationable, child_relationable: related1, author: build(:user))
related_content.flags_count = Setting['related_contents_report_threshold'].to_i + 1
related_content.opposite_related_content.flags_count = related_content.flags_count
related_content.save
related_content.opposite_related_content.save
login_as(user) login_as(user)
visit eval("#{relationable.class.name.downcase}_path(relationable)") visit eval("#{relationable.class.name.downcase}_path(relationable)")
within("#related-content-list") do
find("#related-content-#{related_content.opposite_related_content.id}").hover
find("#score-negative-related-#{related_content.opposite_related_content.id}").click
expect(page).to_not have_css("#score-negative-related-#{related_content.opposite_related_content.id}")
end
expect(related_content.related_content_scores.find_by(user_id: user.id, related_content_id: related_content.id).value).to eq(-1)
expect(related_content.opposite_related_content.related_content_scores.find_by(user_id: user.id, related_content_id: related_content.opposite_related_content.id).value).to eq(-1)
end
scenario 'if related content has negative score it will be hidden' do
related_content = create(:related_content, parent_relationable: relationable, child_relationable: related1, author: build(:user))
2.times do
related_content.send("score_positive", build(:user))
end
6.times do
related_content.send("score_negative", build(:user))
end
login_as(user)
visit eval("#{relationable.class.name.downcase}_path(relationable)")
expect(page).to_not have_css("#related-content-list") expect(page).to_not have_css("#related-content-list")
end end
end end