From 5ea16976f72ecc9f93348a3ee97efa6f4268767e Mon Sep 17 00:00:00 2001 From: taitus Date: Wed, 6 Sep 2017 12:34:38 +0200 Subject: [PATCH 1/8] Refactor communities controller. Add missing specs on topics order. --- app/controllers/communities_controller.rb | 12 +++++--- spec/features/communities_spec.rb | 37 +++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/app/controllers/communities_controller.rb b/app/controllers/communities_controller.rb index 3462c8425..ff74f208b 100644 --- a/app/controllers/communities_controller.rb +++ b/app/controllers/communities_controller.rb @@ -1,8 +1,8 @@ class CommunitiesController < ApplicationController + TOPIC_ORDERS = %w{newest most_commented oldest}.freeze + before_action :set_order, :set_community, :load_topics, :load_participants - before_action :set_order, :set_community, :load_topics, :load_participants, only: :show - - has_orders %w{newest most_commented oldest}, only: :show + has_orders TOPIC_ORDERS skip_authorization_check @@ -13,7 +13,7 @@ class CommunitiesController < ApplicationController private def set_order - @order = params[:order].present? ? params[:order] : "newest" + @order = valid_order? ? params[:order] : "newest" end def set_community @@ -27,4 +27,8 @@ class CommunitiesController < ApplicationController def load_participants @participants = @community.participants end + + def valid_order? + params[:order].present? && TOPIC_ORDERS.include?(params[:order]) + end end diff --git a/spec/features/communities_spec.rb b/spec/features/communities_spec.rb index b9d14c790..4772df24b 100644 --- a/spec/features/communities_spec.rb +++ b/spec/features/communities_spec.rb @@ -63,6 +63,43 @@ feature 'Communities' do end end + scenario "Topic order" do + proposal = create(:proposal) + community = proposal.community + topic1 = create(:topic, community: community) + topic2 = create(:topic, community: community) + topic2_comment = create(:comment, :with_confidence_score, commentable: topic2) + topic3 = create(:topic, community: community) + topic3_comment = create(:comment, :with_confidence_score, commentable: topic3) + topic3_comment = create(:comment, :with_confidence_score, commentable: topic3) + + visit community_path(community, order: :most_commented) + + expect(topic3.title).to appear_before(topic2.title) + expect(topic2.title).to appear_before(topic1.title) + + visit community_path(community, order: :oldest) + + expect(topic1.title).to appear_before(topic2.title) + expect(topic2.title).to appear_before(topic3.title) + + visit community_path(community, order: :newest) + + expect(topic3.title).to appear_before(topic2.title) + expect(topic2.title).to appear_before(topic1.title) + end + + scenario "Should order by newest when order param is invalid" do + proposal = create(:proposal) + community = proposal.community + topic1 = create(:topic, community: community) + topic2 = create(:topic, community: community) + + visit community_path(community, order: "invalid_param") + + expect(topic2.title).to appear_before(topic1.title) + end + scenario 'Should display topic edit button when author is logged' do proposal = create(:proposal) community = proposal.community From 64774b0d2db7a3d1403442ebc083a0f0fa51fbce Mon Sep 17 00:00:00 2001 From: taitus Date: Wed, 6 Sep 2017 13:30:12 +0200 Subject: [PATCH 2/8] Refactor topics controller. Add Common abilities. Add destroy action. --- app/controllers/topics_controller.rb | 11 +++-- app/models/abilities/common.rb | 3 ++ app/models/topic.rb | 2 - app/views/topics/_topics.html.erb | 5 ++- config/locales/en/community.yml | 1 + config/locales/en/responders.yml | 1 + config/locales/es/community.yml | 1 + config/locales/es/responders.yml | 1 + db/seeds.rb | 2 +- spec/features/topics_specs.rb | 62 +++++++++++++++++++++++++--- 10 files changed, 76 insertions(+), 13 deletions(-) diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index f0e57a383..0e63685bd 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -1,13 +1,13 @@ class TopicsController < ApplicationController include CommentableActions - include FlagActions before_action :load_community - before_action :load_topic, only: [:show, :edit, :update] + before_action :load_topic, only: [:show, :edit, :update, :destroy] has_orders %w{most_voted newest oldest}, only: :show - skip_authorization_check + skip_authorization_check only: :show + load_and_authorize_resource except: :show def new @topic = Topic.new @@ -39,6 +39,11 @@ class TopicsController < ApplicationController end end + def destroy + @topic.destroy + redirect_to community_path(@community), notice: I18n.t('flash.actions.destroy.topic') + end + private def topic_params diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb index 311b0dade..620cfb212 100644 --- a/app/models/abilities/common.rb +++ b/app/models/abilities/common.rb @@ -71,6 +71,9 @@ module Abilities can :create, Annotation can [:update, :destroy], Annotation, user_id: user.id + + can [:create], Topic + can [:update, :destroy], Topic, author_id: user.id end end end diff --git a/app/models/topic.rb b/app/models/topic.rb index 8c8f3f6c9..34abed0e3 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -1,6 +1,4 @@ class Topic < ActiveRecord::Base - include Flaggable - acts_as_paranoid column: :hidden_at include ActsAsParanoidAliases diff --git a/app/views/topics/_topics.html.erb b/app/views/topics/_topics.html.erb index f74fa573f..b5080a61f 100644 --- a/app/views/topics/_topics.html.erb +++ b/app/views/topics/_topics.html.erb @@ -9,7 +9,7 @@ <% topics.each do |topic| %>
-
+

<%= link_to topic.title, community_topic_path(@community, topic) %>

@@ -24,9 +24,10 @@
-
+
<% if topic.author == current_user %> <%= link_to t("community.show.topic.edit_button"), edit_community_topic_path(@community.id, topic), class: 'button small hollow' %> + <%= link_to t("community.show.topic.destroy_button"), community_topic_path(@community.id, topic), method: :delete, class: 'button hollow alert small' %> <% end %>
diff --git a/config/locales/en/community.yml b/config/locales/en/community.yml index 37b7ea74f..068c98998 100644 --- a/config/locales/en/community.yml +++ b/config/locales/en/community.yml @@ -26,6 +26,7 @@ en: disabled_info_title: You need to be logged to create a new topic topic: edit_button: Edit + destroy_button: Destroy comments: one: 1 comment other: "%{count} comments" diff --git a/config/locales/en/responders.yml b/config/locales/en/responders.yml index 17de27b74..203d5700e 100644 --- a/config/locales/en/responders.yml +++ b/config/locales/en/responders.yml @@ -29,3 +29,4 @@ en: spending_proposal: "Spending proposal deleted succesfully." budget_investment: "Investment project deleted succesfully." error: "Could not delete" + topic: "Topic deleted successfully." diff --git a/config/locales/es/community.yml b/config/locales/es/community.yml index 196cd4c50..8013c116c 100644 --- a/config/locales/es/community.yml +++ b/config/locales/es/community.yml @@ -26,6 +26,7 @@ es: disabled_info_title: Necesitas estar logueado para crear un nuevo tema topic: edit_button: Editar + destroy_button: Eliminar comments: one: 1 Comentario other: "%{count} Comentarios" diff --git a/config/locales/es/responders.yml b/config/locales/es/responders.yml index d3d4ff163..74e3ea20a 100644 --- a/config/locales/es/responders.yml +++ b/config/locales/es/responders.yml @@ -29,3 +29,4 @@ es: spending_proposal: "Propuesta de inversión eliminada." budget_investment: "Propuesta de inversión eliminada." error: "No se pudo borrar" + topic: "Tema eliminado." diff --git a/db/seeds.rb b/db/seeds.rb index 90665fdb8..41b995f8a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -79,7 +79,7 @@ Setting['feature.public_stats'] = true Setting['feature.budgets'] = true Setting['feature.signature_sheets'] = true Setting['feature.legislation'] = true -Setting['feature.community'] = nil +Setting['feature.community'] = true # Spending proposals feature flags Setting['feature.spending_proposal_features.voting_allowed'] = nil diff --git a/spec/features/topics_specs.rb b/spec/features/topics_specs.rb index 0d668d44b..9970e2339 100644 --- a/spec/features/topics_specs.rb +++ b/spec/features/topics_specs.rb @@ -13,7 +13,7 @@ feature 'Topics' do expect(page).to have_selector(".button.expanded.disabled") end - scenario 'Should can access to new topic page with user logged', :js do + scenario 'Can access to new topic page with user logged', :js do proposal = create(:proposal) community = proposal.community user = create(:user) @@ -47,10 +47,10 @@ feature 'Topics' do context 'Create' do - scenario 'Should can create a new topic', :js do + scenario 'Can create a new topic', :js do proposal = create(:proposal) community = proposal.community - user = create(:user) + user = create(:user) login_as(user) visit new_community_topic_path(community) @@ -62,11 +62,20 @@ feature 'Topics' do expect(current_path).to eq(community_path(community)) end + scenario 'Can not create a new topic when user not logged', :js do + proposal = create(:proposal) + community = proposal.community + + visit new_community_topic_path(community) + + expect(page).to have_content "You do not have permission to carry out the action 'new' on topic." + end + end context 'Edit' do - scenario 'Should can edit a topic' do + scenario 'Can edit a topic' do proposal = create(:proposal) community = proposal.community user = create(:user) @@ -82,11 +91,23 @@ feature 'Topics' do expect(current_path).to eq(community_path(community)) end + scenario 'Can not edit a topic when user logged is not an author' do + proposal = create(:proposal) + community = proposal.community + topic = create(:topic, community: community) + user = create(:user) + login_as(user) + + visit edit_community_topic_path(community, topic) + + expect(page).to have_content "You do not have permission to carry out the action 'edit' on topic." + end + end context 'Show' do - scenario 'Should can show topic' do + scenario 'Can show topic' do proposal = create(:proposal) community = proposal.community topic = create(:topic, community: community) @@ -99,4 +120,35 @@ feature 'Topics' do end + context 'Destroy' do + + scenario 'Can destroy a topic' do + proposal = create(:proposal) + community = proposal.community + user = create(:user) + topic = create(:topic, community: community, author: user) + login_as(user) + visit community_path(community) + + click_link "Destroy" + + expect(page).to have_content "Topic deleted successfully." + expect(page).not_to have_content topic.title + expect(current_path).to eq(community_path(community)) + end + + scenario 'Can not destroy a topic when user logged is not an author' do + proposal = create(:proposal) + community = proposal.community + topic = create(:topic, community: community) + user = create(:user) + login_as(user) + + visit community_path(community) + + expect(page).not_to have_link "Destroy" + end + + end + end From c5cb463a2ed0fdff47317990d0590086a9221bc5 Mon Sep 17 00:00:00 2001 From: taitus Date: Wed, 6 Sep 2017 13:47:29 +0200 Subject: [PATCH 3/8] Refactor helpers. --- app/helpers/comments_helper.rb | 4 ++-- app/helpers/communities_helper.rb | 13 +++---------- app/models/community.rb | 2 +- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb index 1ab6c9826..bdd2ccb68 100644 --- a/app/helpers/comments_helper.rb +++ b/app/helpers/comments_helper.rb @@ -42,7 +42,7 @@ module CommentsHelper def commentable_path(comment) commentable = comment.commentable - + case comment.commentable_type when "Budget::Investment" budget_investment_path(commentable.budget_id, commentable) @@ -51,7 +51,7 @@ module CommentsHelper when "Legislation::Annotation" legislation_process_draft_version_annotation_path(commentable.draft_version.process, commentable.draft_version, commentable) when "Topic" - community_topic_path(comment.commentable.community, comment.commentable) + community_topic_path(commentable.community, commentable) else commentable end diff --git a/app/helpers/communities_helper.rb b/app/helpers/communities_helper.rb index 1d50c5388..bb770a948 100644 --- a/app/helpers/communities_helper.rb +++ b/app/helpers/communities_helper.rb @@ -1,12 +1,7 @@ module CommunitiesHelper def community_title(community) - if community.from_proposal? - community.proposal.title - else - investment = Budget::Investment.where(community_id: community.id).first - investment.title - end + community.from_proposal? ? community.proposal.title : community.investment.title end def community_text(community) @@ -21,8 +16,7 @@ module CommunitiesHelper if community.from_proposal? community.proposal.author_id == participant.id else - investment = Budget::Investment.where(community_id: community.id).first - investment.author_id == participant.id + community.investment.author_id == participant.id end end @@ -30,8 +24,7 @@ module CommunitiesHelper if community.from_proposal? proposal_path(community.proposal) else - investment = Budget::Investment.where(community_id: community.id).first - budget_investment_path(investment.budget_id, investment) + budget_investment_path(community.investment.budget_id, community.investment) end end diff --git a/app/models/community.rb b/app/models/community.rb index 710982200..369c355ff 100644 --- a/app/models/community.rb +++ b/app/models/community.rb @@ -1,6 +1,6 @@ class Community < ActiveRecord::Base has_one :proposal - has_one :investment + has_one :investment, class_name: Budget::Investment has_many :topics def participants From 25560a27fc84e5c775d08fdf6ed54b535b39746b Mon Sep 17 00:00:00 2001 From: taitus Date: Wed, 6 Sep 2017 14:07:44 +0200 Subject: [PATCH 4/8] Refactor Community model. --- app/models/community.rb | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/app/models/community.rb b/app/models/community.rb index 369c355ff..3fa1cebaa 100644 --- a/app/models/community.rb +++ b/app/models/community.rb @@ -4,8 +4,8 @@ class Community < ActiveRecord::Base has_many :topics def participants - users_participants = users_who_commented_by + - users_who_topics_author_by + + users_participants = users_who_commented + + users_who_topics_author + author_from_community users_participants.uniq end @@ -16,24 +16,19 @@ class Community < ActiveRecord::Base private - def users_who_commented_by + def users_who_commented topics_ids = topics.pluck(:id) query = "comments.commentable_id IN (?)and comments.commentable_type = 'Topic'" User.by_comments(query, topics_ids) end - def users_who_topics_author_by + def users_who_topics_author author_ids = topics.pluck(:author_id) User.by_authors(author_ids) end def author_from_community - if from_proposal? - User.where(id: proposal.author_id) - else - investment = Budget::Investment.where(community_id: id).first - User.where(id: investment.author_id) - end + from_proposal? ? User.where(id: proposal.author_id) : User.where(id: investment.author_id) end end From 9b6b57a24cc010a5e5b1d8829f6f744074724f82 Mon Sep 17 00:00:00 2001 From: taitus Date: Wed, 6 Sep 2017 14:12:32 +0200 Subject: [PATCH 5/8] Remove all white spaces --- app/assets/javascripts/embed_video.js.coffee | 5 ++--- .../admin/budget_investment_milestones_controller.rb | 2 +- app/controllers/management/sessions_controller.rb | 2 +- app/models/concerns/communitable.rb | 4 ++-- .../admin/site_customization/pages/index.html.erb | 2 +- app/views/polls/_poll_group.html.erb | 2 +- db/seeds.rb | 4 ++-- lib/tasks/communities.rake | 4 ++-- spec/features/communities_spec.rb | 4 ++-- spec/features/topics_specs.rb | 12 ++++++------ spec/features/users_spec.rb | 2 +- spec/models/user_spec.rb | 4 ++-- vendor/assets/javascripts/annotator.js | 2 +- 13 files changed, 24 insertions(+), 25 deletions(-) diff --git a/app/assets/javascripts/embed_video.js.coffee b/app/assets/javascripts/embed_video.js.coffee index 85c18ac8e..0825d1b80 100644 --- a/app/assets/javascripts/embed_video.js.coffee +++ b/app/assets/javascripts/embed_video.js.coffee @@ -1,7 +1,6 @@ App.EmbedVideo = - + initialize: -> $('#js-embedded-video').each -> - code = $(this).data("video-code") + code = $(this).data("video-code") $('#js-embedded-video').html(code) - \ No newline at end of file diff --git a/app/controllers/admin/budget_investment_milestones_controller.rb b/app/controllers/admin/budget_investment_milestones_controller.rb index a4b8acc5d..fb5f42384 100644 --- a/app/controllers/admin/budget_investment_milestones_controller.rb +++ b/app/controllers/admin/budget_investment_milestones_controller.rb @@ -48,7 +48,7 @@ class Admin::BudgetInvestmentMilestonesController < Admin::BaseController end def load_budget_investment_milestone - @milestone = Budget::Investment::Milestone.find params[:id] + @milestone = Budget::Investment::Milestone.find params[:id] end diff --git a/app/controllers/management/sessions_controller.rb b/app/controllers/management/sessions_controller.rb index 85ed59eae..6db303a39 100644 --- a/app/controllers/management/sessions_controller.rb +++ b/app/controllers/management/sessions_controller.rb @@ -20,7 +20,7 @@ class Management::SessionsController < ActionController::Base def destroy_session session[:manager] = nil - session[:document_type] = nil + session[:document_type] = nil session[:document_number] = nil end diff --git a/app/models/concerns/communitable.rb b/app/models/concerns/communitable.rb index 6f0a10f43..415a7a3f0 100644 --- a/app/models/concerns/communitable.rb +++ b/app/models/concerns/communitable.rb @@ -7,8 +7,8 @@ module Communitable end def associate_community - community = Community.create - self.community_id = community.id + community = Community.create + self.community_id = community.id end end diff --git a/app/views/admin/site_customization/pages/index.html.erb b/app/views/admin/site_customization/pages/index.html.erb index dd9cfd3ad..897549caf 100644 --- a/app/views/admin/site_customization/pages/index.html.erb +++ b/app/views/admin/site_customization/pages/index.html.erb @@ -34,7 +34,7 @@ <% if page.status == "published" %> <%= link_to t("admin.site_customization.pages.index.see_page"), page.url, target: "_blank" %> <% else %> - <%= t("admin.site_customization.pages.index.see_page") %> + <%= t("admin.site_customization.pages.index.see_page") %> <% end %> diff --git a/app/views/polls/_poll_group.html.erb b/app/views/polls/_poll_group.html.erb index 6e0b85f16..e3e5c5976 100644 --- a/app/views/polls/_poll_group.html.erb +++ b/app/views/polls/_poll_group.html.erb @@ -64,7 +64,7 @@ <% if poll.expired? %> <%= t("polls.index.participate_button_expired") %> <% elsif poll.incoming? %> - <%= t("polls.index.participate_button_incoming") %> + <%= t("polls.index.participate_button_incoming") %> <% else %> <%= t("polls.index.participate_button") %> <% end %> diff --git a/db/seeds.rb b/db/seeds.rb index 41b995f8a..96916f29a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -39,10 +39,10 @@ Setting["months_to_archive_proposals"] = 12 Setting["email_domain_for_officials"] = '' # Code to be included at the top (inside ) of every page (useful for tracking) -Setting['per_page_code_head'] = '' +Setting['per_page_code_head'] = '' # Code to be included at the top (inside ) of every page -Setting['per_page_code_body'] = '' +Setting['per_page_code_body'] = '' # Social settings Setting["twitter_handle"] = nil diff --git a/lib/tasks/communities.rake b/lib/tasks/communities.rake index ad08e4bd9..261f4dbee 100644 --- a/lib/tasks/communities.rake +++ b/lib/tasks/communities.rake @@ -5,14 +5,14 @@ namespace :communities do Proposal.all.each do |proposal| if proposal.community.blank? - community = Community.create + community = Community.create proposal.update(community_id: community.id) end end Budget::Investment.all.each do |investment| if investment.community.blank? - community = Community.create + community = Community.create investment.update(community_id: community.id) end end diff --git a/spec/features/communities_spec.rb b/spec/features/communities_spec.rb index 4772df24b..2909f416e 100644 --- a/spec/features/communities_spec.rb +++ b/spec/features/communities_spec.rb @@ -15,7 +15,7 @@ feature 'Communities' do scenario 'Should display default content' do proposal = create(:proposal) community = proposal.community - user = create(:user) + user = create(:user) login_as(user) visit community_path(community) @@ -103,7 +103,7 @@ feature 'Communities' do scenario 'Should display topic edit button when author is logged' do proposal = create(:proposal) community = proposal.community - user = create(:user) + user = create(:user) topic1 = create(:topic, community: community, author: user) topic2 = create(:topic, community: community) login_as(user) diff --git a/spec/features/topics_specs.rb b/spec/features/topics_specs.rb index 9970e2339..0ba674844 100644 --- a/spec/features/topics_specs.rb +++ b/spec/features/topics_specs.rb @@ -16,7 +16,7 @@ feature 'Topics' do scenario 'Can access to new topic page with user logged', :js do proposal = create(:proposal) community = proposal.community - user = create(:user) + user = create(:user) login_as(user) visit community_path(community) @@ -28,7 +28,7 @@ feature 'Topics' do scenario 'Should have content on new topic page', :js do proposal = create(:proposal) community = proposal.community - user = create(:user) + user = create(:user) login_as(user) visit community_path(community) @@ -78,7 +78,7 @@ feature 'Topics' do scenario 'Can edit a topic' do proposal = create(:proposal) community = proposal.community - user = create(:user) + user = create(:user) topic = create(:topic, community: community, author: user) login_as(user) visit edit_community_topic_path(community, topic) @@ -95,7 +95,7 @@ feature 'Topics' do proposal = create(:proposal) community = proposal.community topic = create(:topic, community: community) - user = create(:user) + user = create(:user) login_as(user) visit edit_community_topic_path(community, topic) @@ -125,7 +125,7 @@ feature 'Topics' do scenario 'Can destroy a topic' do proposal = create(:proposal) community = proposal.community - user = create(:user) + user = create(:user) topic = create(:topic, community: community, author: user) login_as(user) visit community_path(community) @@ -141,7 +141,7 @@ feature 'Topics' do proposal = create(:proposal) community = proposal.community topic = create(:topic, community: community) - user = create(:user) + user = create(:user) login_as(user) visit community_path(community) diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index bd2aefa17..ae2bac6d1 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -235,7 +235,7 @@ feature 'Users' do end scenario 'Not display interests when proposal has been destroyed' do - proposal = create(:proposal, tag_list: "Sport") + proposal = create(:proposal, tag_list: "Sport") create(:follow, :followed_proposal, followable: proposal, user: @user) proposal.destroy diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 6db1a2a25..3d4217ea3 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -668,8 +668,8 @@ describe User do end it "should discard followed objects duplicated tags" do - proposal1 = create(:proposal, tag_list: "Sport") - proposal2 = create(:proposal, tag_list: "Sport") + proposal1 = create(:proposal, tag_list: "Sport") + proposal2 = create(:proposal, tag_list: "Sport") budget_investment = create(:budget_investment, tag_list: "Sport") create(:follow, followable: proposal1, user: user) diff --git a/vendor/assets/javascripts/annotator.js b/vendor/assets/javascripts/annotator.js index b9019a6b2..dfbc0a0bf 100644 --- a/vendor/assets/javascripts/annotator.js +++ b/vendor/assets/javascripts/annotator.js @@ -2054,7 +2054,7 @@ setDocument = Sizzle.setDocument = function( node ) { // getElementById is not reliable as a find shortcut delete Expr.find["ID"]; - Expr.filter["ID"] = function( id ) { + Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); From 79d4a82bfa58affd5a35604760aa80a830c37590 Mon Sep 17 00:00:00 2001 From: taitus Date: Wed, 6 Sep 2017 14:16:03 +0200 Subject: [PATCH 6/8] Fix specs --- spec/features/budgets/investments_spec.rb | 2 ++ spec/features/proposals_spec.rb | 2 ++ 2 files changed, 4 insertions(+) diff --git a/spec/features/budgets/investments_spec.rb b/spec/features/budgets/investments_spec.rb index ef2c1bf5b..4040717f1 100644 --- a/spec/features/budgets/investments_spec.rb +++ b/spec/features/budgets/investments_spec.rb @@ -340,6 +340,8 @@ feature 'Budget Investments' do end scenario 'Can not access the community' do + Setting['feature.community'] = false + investment = create(:budget_investment, heading: heading) visit budget_investment_path(budget_id: budget.id, id: investment.id) expect(page).not_to have_content "Access the community" diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb index 63050c43f..0c69eee3e 100644 --- a/spec/features/proposals_spec.rb +++ b/spec/features/proposals_spec.rb @@ -101,6 +101,8 @@ feature 'Proposals' do end scenario 'Can not access the community' do + Setting['feature.community'] = false + proposal = create(:proposal) visit proposal_path(proposal) expect(page).not_to have_content "Access the community" From f0667937fbdcdaceb9deb0e3e52c00ee9883dd47 Mon Sep 17 00:00:00 2001 From: taitus Date: Wed, 6 Sep 2017 14:41:58 +0200 Subject: [PATCH 7/8] Refactor and extract code to partials. --- app/views/communities/_participant.html.erb | 22 ++++++++++ app/views/communities/_participants.html.erb | 23 +--------- app/views/topics/_informative_text.html.erb | 11 +++++ app/views/topics/_topic.html.erb | 25 +++++++++++ app/views/topics/_topics.html.erb | 46 +++----------------- 5 files changed, 64 insertions(+), 63 deletions(-) create mode 100644 app/views/communities/_participant.html.erb create mode 100644 app/views/topics/_informative_text.html.erb create mode 100644 app/views/topics/_topic.html.erb diff --git a/app/views/communities/_participant.html.erb b/app/views/communities/_participant.html.erb new file mode 100644 index 000000000..5e4f02900 --- /dev/null +++ b/app/views/communities/_participant.html.erb @@ -0,0 +1,22 @@ +
+
+ + <%= avatar_image( participant, seed: participant.id, size: 32, class: 'author-photo') %> + +
+ + + <%= link_to participant.name, user_path(participant)%> + + + <% if is_author?(@community, participant) %> +  •  + + <%= t("comments.comment.author") %> + + <% end %> + +
+ +
+
diff --git a/app/views/communities/_participants.html.erb b/app/views/communities/_participants.html.erb index 931ebf105..a153ec624 100644 --- a/app/views/communities/_participants.html.erb +++ b/app/views/communities/_participants.html.erb @@ -14,28 +14,7 @@ <% @participants.each do |participant| %> -
-
- - <%= avatar_image( participant, seed: participant.id, size: 32, class: 'author-photo') %> - -
- - - <%= link_to participant.name, user_path(participant)%> - - - <% if is_author?(@community, participant) %> -  •  - - <%= t("comments.comment.author") %> - - <% end %> - -
- -
-
+ <%= render 'participant', participant: participant %> <% end %>
diff --git a/app/views/topics/_informative_text.html.erb b/app/views/topics/_informative_text.html.erb new file mode 100644 index 000000000..aeb5ad773 --- /dev/null +++ b/app/views/topics/_informative_text.html.erb @@ -0,0 +1,11 @@ +

<%= t("community.show.create_first_community_topic.first_theme") %>

+ +<% if user_signed_in? %> + <%= t("community.show.create_first_community_topic.first_theme_not_logged_in") %> +<% else %> +
+ <%= t("community.show.create_first_community_topic.sub_first_theme", + link: link_to(t("community.show.create_first_community_topic.sign_link", + org_name: setting['org_name']), new_user_session_path)).html_safe %> +
+<% end %> diff --git a/app/views/topics/_topic.html.erb b/app/views/topics/_topic.html.erb new file mode 100644 index 000000000..fe225d501 --- /dev/null +++ b/app/views/topics/_topic.html.erb @@ -0,0 +1,25 @@ +
+ +
+ +

<%= link_to topic.title, community_topic_path(@community, topic) %>

+ +

+   + <%= link_to t("community.show.topic.comments", count: topic.comments_count), community_topic_path(@community, topic, anchor: "comments") %> +  •  + <%= I18n.l topic.created_at.to_date %> +  •  + <%= topic.author.name %> +

+ +
+ +
+ <% if topic.author == current_user %> + <%= link_to t("community.show.topic.edit_button"), edit_community_topic_path(@community.id, topic), class: 'button small hollow' %> + <%= link_to t("community.show.topic.destroy_button"), community_topic_path(@community.id, topic), method: :delete, class: 'button hollow alert small' %> + <% end %> +
+ +
diff --git a/app/views/topics/_topics.html.erb b/app/views/topics/_topics.html.erb index b5080a61f..42fa4f319 100644 --- a/app/views/topics/_topics.html.erb +++ b/app/views/topics/_topics.html.erb @@ -1,49 +1,13 @@ <% if topics.any? %> -
<%= render 'shared/wide_order_selector', i18n_namespace: "comments" %>
- - <% topics.each do |topic| %> - -
-
- -

<%= link_to topic.title, community_topic_path(@community, topic) %>

- -

-   - <%= link_to t("community.show.topic.comments", count: topic.comments_count), community_topic_path(@community, topic, anchor: "comments") %> -  •  - <%= I18n.l topic.created_at.to_date %> -  •  - <%= topic.author.name %> -

- -
- -
- <% if topic.author == current_user %> - <%= link_to t("community.show.topic.edit_button"), edit_community_topic_path(@community.id, topic), class: 'button small hollow' %> - <%= link_to t("community.show.topic.destroy_button"), community_topic_path(@community.id, topic), method: :delete, class: 'button hollow alert small' %> - <% end %> -
- -
- - <% end %> - <% else %> -

<%= t("community.show.create_first_community_topic.first_theme") %>

- <% if user_signed_in? %> - <%= t("community.show.create_first_community_topic.first_theme_not_logged_in") %> - <% else %> -
- <%= t("community.show.create_first_community_topic.sub_first_theme", - link: link_to(t("community.show.create_first_community_topic.sign_link", - org_name: setting['org_name']), new_user_session_path)).html_safe %> -
- <% end %> + <%= render 'topics/informative_text', topics: topics %> +<% end %> + +<% topics.each do |topic| %> + <%= render 'topics/topic', topic: topic %> <% end %> From 748a54934c340756b64c69bfd12507778f817c34 Mon Sep 17 00:00:00 2001 From: taitus Date: Wed, 6 Sep 2017 15:01:39 +0200 Subject: [PATCH 8/8] Add missing specs on comments from topics --- spec/features/comments/topics_spec.rb | 554 +++++++++++++++++++++++++- 1 file changed, 552 insertions(+), 2 deletions(-) diff --git a/spec/features/comments/topics_spec.rb b/spec/features/comments/topics_spec.rb index c72e8028d..38971fcff 100644 --- a/spec/features/comments/topics_spec.rb +++ b/spec/features/comments/topics_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' include ActionView::Helpers::DateHelper -feature 'Commenting topics' do +feature 'Commenting topics from proposals' do let(:user) { create :user } let(:proposal) { create :proposal } @@ -319,7 +319,7 @@ feature 'Commenting topics' do page.find("#flag-expand-comment-#{comment.id}").click expect(page).to have_selector("#flag-comment-#{comment.id}") end - + Setting['feature.community'] = nil end @@ -550,3 +550,553 @@ feature 'Commenting topics' do end end + +feature 'Commenting topics from budget investments' do + let(:user) { create :user } + let(:investment) { create :budget_investment } + + scenario 'Index', :js do + + community = investment.community + topic = create(:topic, community: community) + 3.times { create(:comment, commentable: topic) } + + visit community_topic_path(community, topic) + + expect(page).to have_css('.comment', count: 3) + + comment = Comment.last + within first('.comment') do + expect(page).to have_content comment.user.name + expect(page).to have_content I18n.l(comment.created_at, format: :datetime) + expect(page).to have_content comment.body + end + end + + scenario 'Show', :js do + community = investment.community + topic = create(:topic, community: community) + parent_comment = create(:comment, commentable: topic) + first_child = create(:comment, commentable: topic, parent: parent_comment) + second_child = create(:comment, commentable: topic, parent: parent_comment) + + visit comment_path(parent_comment) + + expect(page).to have_css(".comment", count: 3) + expect(page).to have_content parent_comment.body + expect(page).to have_content first_child.body + expect(page).to have_content second_child.body + + expect(page).to have_link "Go back to #{topic.title}", href: community_topic_path(community, topic) + end + + scenario 'Collapsable comments', :js do + community = investment.community + topic = create(:topic, community: community) + parent_comment = create(:comment, body: "Main comment", commentable: topic) + child_comment = create(:comment, body: "First subcomment", commentable: topic, parent: parent_comment) + grandchild_comment = create(:comment, body: "Last subcomment", commentable: topic, parent: child_comment) + + visit community_topic_path(community, topic) + + expect(page).to have_css('.comment', count: 3) + + find("#comment_#{child_comment.id}_children_arrow").trigger('click') + + expect(page).to have_css('.comment', count: 2) + expect(page).to_not have_content grandchild_comment.body + + find("#comment_#{child_comment.id}_children_arrow").trigger('click') + + expect(page).to have_css('.comment', count: 3) + expect(page).to have_content grandchild_comment.body + + find("#comment_#{parent_comment.id}_children_arrow").trigger('click') + + expect(page).to have_css('.comment', count: 1) + expect(page).to_not have_content child_comment.body + expect(page).to_not have_content grandchild_comment.body + end + + scenario 'Comment order' do + community = investment.community + topic = create(:topic, community: community) + c1 = create(:comment, :with_confidence_score, commentable: topic, cached_votes_up: 100, + cached_votes_total: 120, created_at: Time.current - 2) + c2 = create(:comment, :with_confidence_score, commentable: topic, cached_votes_up: 10, + cached_votes_total: 12, created_at: Time.current - 1) + c3 = create(:comment, :with_confidence_score, commentable: topic, cached_votes_up: 1, + cached_votes_total: 2, created_at: Time.current) + + visit community_topic_path(community, topic, order: :most_voted) + + expect(c1.body).to appear_before(c2.body) + expect(c2.body).to appear_before(c3.body) + + visit community_topic_path(community, topic, order: :newest) + + expect(c3.body).to appear_before(c2.body) + expect(c2.body).to appear_before(c1.body) + + visit community_topic_path(community, topic, order: :oldest) + + expect(c1.body).to appear_before(c2.body) + expect(c2.body).to appear_before(c3.body) + end + + scenario 'Creation date works differently in roots and in child comments, when sorting by confidence_score' do + community = investment.community + topic = create(:topic, community: community) + old_root = create(:comment, commentable: topic, created_at: Time.current - 10) + new_root = create(:comment, commentable: topic, created_at: Time.current) + old_child = create(:comment, commentable: topic, parent_id: new_root.id, created_at: Time.current - 10) + new_child = create(:comment, commentable: topic, parent_id: new_root.id, created_at: Time.current) + + visit community_topic_path(community, topic, order: :most_voted) + + expect(new_root.body).to appear_before(old_root.body) + expect(old_child.body).to appear_before(new_child.body) + + visit community_topic_path(community, topic, order: :newest) + + expect(new_root.body).to appear_before(old_root.body) + expect(new_child.body).to appear_before(old_child.body) + + visit community_topic_path(community, topic, order: :oldest) + + expect(old_root.body).to appear_before(new_root.body) + expect(old_child.body).to appear_before(new_child.body) + end + + scenario 'Turns links into html links' do + community = investment.community + topic = create(:topic, community: community) + create :comment, commentable: topic, body: 'Built with http://rubyonrails.org/' + + visit community_topic_path(community, topic) + + within first('.comment') do + expect(page).to have_content 'Built with http://rubyonrails.org/' + expect(page).to have_link('http://rubyonrails.org/', href: 'http://rubyonrails.org/') + expect(find_link('http://rubyonrails.org/')[:rel]).to eq('nofollow') + expect(find_link('http://rubyonrails.org/')[:target]).to eq('_blank') + end + end + + scenario 'Sanitizes comment body for security' do + community = investment.community + topic = create(:topic, community: community) + create :comment, commentable: topic, + body: " click me http://www.url.com" + + visit community_topic_path(community, topic) + + within first('.comment') do + expect(page).to have_content "click me http://www.url.com" + expect(page).to have_link('http://www.url.com', href: 'http://www.url.com') + expect(page).not_to have_link('click me') + end + end + + scenario 'Paginated comments' do + community = investment.community + topic = create(:topic, community: community) + per_page = 10 + (per_page + 2).times { create(:comment, commentable: topic)} + + visit community_topic_path(community, topic) + + expect(page).to have_css('.comment', count: per_page) + within("ul.pagination") do + expect(page).to have_content("1") + expect(page).to have_content("2") + expect(page).to_not have_content("3") + click_link "Next", exact: false + end + + expect(page).to have_css('.comment', count: 2) + end + + feature 'Not logged user' do + scenario 'can not see comments forms' do + community = investment.community + topic = create(:topic, community: community) + create(:comment, commentable: topic) + + visit community_topic_path(community, topic) + + expect(page).to have_content 'You must Sign in or Sign up to leave a comment' + within('#comments') do + expect(page).to_not have_content 'Write a comment' + expect(page).to_not have_content 'Reply' + end + end + end + + scenario 'Create', :js do + login_as(user) + community = investment.community + topic = create(:topic, community: community) + visit community_topic_path(community, topic) + + fill_in "comment-body-topic_#{topic.id}", with: 'Have you thought about...?' + click_button 'Publish comment' + + within "#comments" do + expect(page).to have_content 'Have you thought about...?' + end + + within "#tab-comments-label" do + expect(page).to have_content 'Comments (1)' + end + end + + scenario 'Errors on create', :js do + login_as(user) + community = investment.community + topic = create(:topic, community: community) + visit community_topic_path(community, topic) + + click_button 'Publish comment' + + expect(page).to have_content "Can't be blank" + end + + scenario 'Reply', :js do + community = investment.community + topic = create(:topic, community: community) + citizen = create(:user, username: 'Ana') + manuela = create(:user, username: 'Manuela') + comment = create(:comment, commentable: topic, user: citizen) + + login_as(manuela) + visit community_topic_path(community, topic) + + click_link "Reply" + + within "#js-comment-form-comment_#{comment.id}" do + fill_in "comment-body-comment_#{comment.id}", with: 'It will be done next week.' + click_button 'Publish reply' + end + + within "#comment_#{comment.id}" do + expect(page).to have_content 'It will be done next week.' + end + + expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true) + end + + scenario 'Errors on reply', :js do + community = investment.community + topic = create(:topic, community: community) + comment = create(:comment, commentable: topic, user: user) + + login_as(user) + visit community_topic_path(community, topic) + + click_link "Reply" + + within "#js-comment-form-comment_#{comment.id}" do + click_button 'Publish reply' + expect(page).to have_content "Can't be blank" + end + + end + + scenario "N replies", :js do + community = investment.community + topic = create(:topic, community: community) + parent = create(:comment, commentable: topic) + + 7.times do + create(:comment, commentable: topic, parent: parent) + parent = parent.children.first + end + + visit community_topic_path(community, topic) + expect(page).to have_css(".comment.comment.comment.comment.comment.comment.comment.comment") + end + + scenario "Flagging as inappropriate", :js do + community = investment.community + topic = create(:topic, community: community) + comment = create(:comment, commentable: topic) + + login_as(user) + visit community_topic_path(community, topic) + + within "#comment_#{comment.id}" do + page.find("#flag-expand-comment-#{comment.id}").click + page.find("#flag-comment-#{comment.id}").click + + expect(page).to have_css("#unflag-expand-comment-#{comment.id}") + end + + expect(Flag.flagged?(user, comment)).to be + end + + scenario "Undoing flagging as inappropriate", :js do + community = investment.community + topic = create(:topic, community: community) + comment = create(:comment, commentable: topic) + Flag.flag(user, comment) + + login_as(user) + visit community_topic_path(community, topic) + + within "#comment_#{comment.id}" do + page.find("#unflag-expand-comment-#{comment.id}").click + page.find("#unflag-comment-#{comment.id}").click + + expect(page).to have_css("#flag-expand-comment-#{comment.id}") + end + + expect(Flag.flagged?(user, comment)).to_not be + end + + scenario "Flagging turbolinks sanity check", :js do + Setting['feature.community'] = true + + community = investment.community + topic = create(:topic, community: community, title: "Should we change the world?") + comment = create(:comment, commentable: topic) + + login_as(user) + visit community_path(community) + click_link "Should we change the world?" + + within "#comment_#{comment.id}" do + page.find("#flag-expand-comment-#{comment.id}").click + expect(page).to have_selector("#flag-comment-#{comment.id}") + end + + Setting['feature.community'] = nil + end + + scenario "Erasing a comment's author" do + community = investment.community + topic = create(:topic, community: community) + comment = create(:comment, commentable: topic, body: "this should be visible") + comment.user.erase + + visit community_topic_path(community, topic) + + within "#comment_#{comment.id}" do + expect(page).to have_content('User deleted') + expect(page).to have_content('this should be visible') + end + end + + feature "Moderators" do + scenario "can create comment as a moderator", :js do + community = investment.community + topic = create(:topic, community: community) + moderator = create(:moderator) + + login_as(moderator.user) + visit community_topic_path(community, topic) + + fill_in "comment-body-topic_#{topic.id}", with: "I am moderating!" + check "comment-as-moderator-topic_#{topic.id}" + click_button "Publish comment" + + within "#comments" do + expect(page).to have_content "I am moderating!" + expect(page).to have_content "Moderator ##{moderator.id}" + expect(page).to have_css "div.is-moderator" + expect(page).to have_css "img.moderator-avatar" + end + end + + scenario "can create reply as a moderator", :js do + community = investment.community + topic = create(:topic, community: community) + citizen = create(:user, username: "Ana") + manuela = create(:user, username: "Manuela") + moderator = create(:moderator, user: manuela) + comment = create(:comment, commentable: topic, user: citizen) + + login_as(manuela) + visit community_topic_path(community, topic) + + click_link "Reply" + + within "#js-comment-form-comment_#{comment.id}" do + fill_in "comment-body-comment_#{comment.id}", with: "I am moderating!" + check "comment-as-moderator-comment_#{comment.id}" + click_button 'Publish reply' + end + + within "#comment_#{comment.id}" do + expect(page).to have_content "I am moderating!" + expect(page).to have_content "Moderator ##{moderator.id}" + expect(page).to have_css "div.is-moderator" + expect(page).to have_css "img.moderator-avatar" + end + + expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true) + end + + scenario "can not comment as an administrator" do + community = investment.community + topic = create(:topic, community: community) + moderator = create(:moderator) + + login_as(moderator.user) + visit community_topic_path(community, topic) + + expect(page).to_not have_content "Comment as administrator" + end + end + + feature "Administrators" do + scenario "can create comment as an administrator", :js do + community = investment.community + topic = create(:topic, community: community) + admin = create(:administrator) + + login_as(admin.user) + visit community_topic_path(community, topic) + + fill_in "comment-body-topic_#{topic.id}", with: "I am your Admin!" + check "comment-as-administrator-topic_#{topic.id}" + click_button "Publish comment" + + within "#comments" do + expect(page).to have_content "I am your Admin!" + expect(page).to have_content "Administrator ##{admin.id}" + expect(page).to have_css "div.is-admin" + expect(page).to have_css "img.admin-avatar" + end + end + + scenario "can create reply as an administrator", :js do + community = investment.community + topic = create(:topic, community: community) + citizen = create(:user, username: "Ana") + manuela = create(:user, username: "Manuela") + admin = create(:administrator, user: manuela) + comment = create(:comment, commentable: topic, user: citizen) + + login_as(manuela) + visit community_topic_path(community, topic) + + click_link "Reply" + + within "#js-comment-form-comment_#{comment.id}" do + fill_in "comment-body-comment_#{comment.id}", with: "Top of the world!" + check "comment-as-administrator-comment_#{comment.id}" + click_button 'Publish reply' + end + + within "#comment_#{comment.id}" do + expect(page).to have_content "Top of the world!" + expect(page).to have_content "Administrator ##{admin.id}" + expect(page).to have_css "div.is-admin" + expect(page).to have_css "img.admin-avatar" + end + + expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true) + end + + scenario "can not comment as a moderator" do + community = investment.community + topic = create(:topic, community: community) + admin = create(:administrator) + + login_as(admin.user) + visit community_topic_path(community, topic) + + expect(page).to_not have_content "Comment as moderator" + end + end + + feature 'Voting comments' do + + background do + @manuela = create(:user, verified_at: Time.current) + @pablo = create(:user) + @investment = create(:budget_investment) + @topic = create(:topic, community: @investment.community) + @comment = create(:comment, commentable: @topic) + + login_as(@manuela) + end + + scenario 'Show' do + create(:vote, voter: @manuela, votable: @comment, vote_flag: true) + create(:vote, voter: @pablo, votable: @comment, vote_flag: false) + + visit community_topic_path(@investment.community, @topic) + + within("#comment_#{@comment.id}_votes") do + within(".in_favor") do + expect(page).to have_content "1" + end + + within(".against") do + expect(page).to have_content "1" + end + + expect(page).to have_content "2 votes" + end + end + + scenario 'Create', :js do + visit community_topic_path(@investment.community, @topic) + + within("#comment_#{@comment.id}_votes") do + find(".in_favor a").click + + within(".in_favor") do + expect(page).to have_content "1" + end + + within(".against") do + expect(page).to have_content "0" + end + + expect(page).to have_content "1 vote" + end + end + + scenario 'Update', :js do + visit community_topic_path(@investment.community, @topic) + + within("#comment_#{@comment.id}_votes") do + find('.in_favor a').click + find('.against a').click + + within('.in_favor') do + expect(page).to have_content "0" + end + + within('.against') do + expect(page).to have_content "1" + end + + expect(page).to have_content "1 vote" + end + end + + scenario 'Trying to vote multiple times', :js do + visit community_topic_path(@investment.community, @topic) + + within("#comment_#{@comment.id}_votes") do + find('.in_favor a').click + find('.in_favor a').click + + within('.in_favor') do + expect(page).to have_content "1" + end + + within('.against') do + expect(page).to have_content "0" + end + + expect(page).to have_content "1 vote" + end + end + end + +end