diff --git a/spec/factories.rb b/spec/factories.rb index 3aeaef9e2..50dd0dec8 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -749,6 +749,23 @@ FactoryBot.define do sequence(:title) { |n| "Thank you for supporting my proposal #{n}" } sequence(:body) { |n| "Please let others know so we can make it happen #{n}" } proposal + association :author, factory: :user + + trait :moderated do + moderated true + end + + trait :ignored do + ignored_at Date.current + end + + trait :hidden do + hidden_at Date.current + end + + trait :with_confirmed_hide do + confirmed_hide_at Time.current + end end factory :direct_message do diff --git a/spec/features/admin/proposal_notifications_spec.rb b/spec/features/admin/proposal_notifications_spec.rb new file mode 100644 index 000000000..9186e228f --- /dev/null +++ b/spec/features/admin/proposal_notifications_spec.rb @@ -0,0 +1,94 @@ +require 'rails_helper' + +feature 'Admin proposal notifications' do + + background do + admin = create(:administrator) + login_as(admin.user) + end + + scenario 'List shows all relevant info' do + proposal_notification = create(:proposal_notification, :hidden) + visit admin_proposal_notifications_path + + expect(page).to have_content(proposal_notification.title) + expect(page).to have_content(proposal_notification.body) + end + + scenario 'Restore' do + proposal_notification = create(:proposal_notification, :hidden, created_at: Date.current - 5.days) + visit admin_proposal_notifications_path + + click_link 'Restore' + + expect(page).not_to have_content(proposal_notification.title) + + expect(proposal_notification.reload).not_to be_hidden + expect(proposal_notification).to be_ignored + end + + scenario 'Confirm hide' do + proposal_notification = create(:proposal_notification, :hidden, created_at: Date.current - 5.days) + visit admin_proposal_notifications_path + + click_link 'Confirm moderation' + + expect(page).not_to have_content(proposal_notification.title) + click_link('Confirmed') + expect(page).to have_content(proposal_notification.title) + + expect(proposal_notification.reload).to be_confirmed_hide + end + + scenario "Current filter is properly highlighted" do + visit admin_proposal_notifications_path + expect(page).not_to have_link('Pending') + expect(page).to have_link('All') + expect(page).to have_link('Confirmed') + + visit admin_proposal_notifications_path(filter: 'Pending') + expect(page).not_to have_link('Pending') + expect(page).to have_link('All') + expect(page).to have_link('Confirmed') + + visit admin_proposal_notifications_path(filter: 'all') + expect(page).to have_link('Pending') + expect(page).not_to have_link('All') + expect(page).to have_link('Confirmed') + + visit admin_proposal_notifications_path(filter: 'with_confirmed_hide') + expect(page).to have_link('All') + expect(page).to have_link('Pending') + expect(page).not_to have_link('Confirmed') + end + + scenario "Filtering proposals" do + create(:proposal_notification, :hidden, title: "Unconfirmed notification") + create(:proposal_notification, :hidden, :with_confirmed_hide, title: "Confirmed notification") + + visit admin_proposal_notifications_path(filter: 'pending') + expect(page).to have_content('Unconfirmed notification') + expect(page).not_to have_content('Confirmed notification') + + visit admin_proposal_notifications_path(filter: 'all') + expect(page).to have_content('Unconfirmed notification') + expect(page).to have_content('Confirmed notification') + + visit admin_proposal_notifications_path(filter: 'with_confirmed_hide') + expect(page).not_to have_content('Unconfirmed notification') + expect(page).to have_content('Confirmed notification') + end + + scenario "Action links remember the pagination setting and the filter" do + per_page = Kaminari.config.default_per_page + (per_page + 2).times { create(:proposal_notification, :hidden, :with_confirmed_hide) } + + visit admin_proposal_notifications_path(filter: 'with_confirmed_hide', page: 2) + + click_on('Restore', match: :first, exact: true) + + expect(current_url).to include('filter=with_confirmed_hide') + expect(current_url).to include('page=2') + end + +end diff --git a/spec/features/moderation/proposal_notifications_spec.rb b/spec/features/moderation/proposal_notifications_spec.rb new file mode 100644 index 000000000..4af3a815d --- /dev/null +++ b/spec/features/moderation/proposal_notifications_spec.rb @@ -0,0 +1,189 @@ +require 'rails_helper' + +feature 'Moderate proposal notifications' do + + scenario 'Hide', :js do + citizen = create(:user) + proposal = create(:proposal) + proposal_notification = create(:proposal_notification, proposal: proposal, created_at: Date.current - 4.days) + moderator = create(:moderator) + + login_as(moderator.user) + visit proposal_path(proposal) + click_link "Notifications (1)" + + within("#proposal_notification_#{proposal_notification.id}") do + accept_confirm { click_link 'Hide' } + end + + expect(page).to have_css("#proposal_notification_#{proposal.id}.faded") + + logout + login_as(citizen) + visit proposal_path(proposal) + + expect(page).to have_content "Notifications (0)" + end + + scenario 'Can not hide own proposal notification' do + moderator = create(:moderator) + proposal = create(:proposal, author: moderator.user) + proposal_notification = create(:proposal_notification, proposal: proposal, created_at: Date.current - 4.days) + + login_as(moderator.user) + visit proposal_path(proposal) + + within("#proposal_notification_#{proposal_notification.id}") do + expect(page).not_to have_link('Hide') + expect(page).not_to have_link('Block author') + end + end + + feature '/moderation/ screen' do + + background do + moderator = create(:moderator) + login_as(moderator.user) + end + + feature 'moderate in bulk' do + feature "When a proposal has been selected for moderation" do + background do + proposal = create(:proposal) + @proposal_notification = create(:proposal_notification, proposal: proposal, created_at: Date.current - 4.days) + visit moderation_proposal_notifications_path + within('.menu.simple') do + click_link "All" + end + + within("#proposal_notification_#{@proposal_notification.id}") do + check "proposal_notification_#{@proposal_notification.id}_check" + end + end + + scenario 'Hide the proposal' do + click_on "Hide proposals" + expect(page).not_to have_css("#proposal_notification_#{@proposal_notification.id}") + expect(@proposal_notification.reload).to be_hidden + expect(@proposal_notification.author).not_to be_hidden + end + + scenario 'Block the author' do + author = create(:user) + @proposal_notification.update(author: author) + click_on "Block authors" + expect(page).not_to have_css("#proposal_notification_#{@proposal_notification.id}") + expect(@proposal_notification.reload).to be_hidden + expect(author.reload).to be_hidden + end + + scenario 'Ignore the proposal' do + click_button "Mark as viewed" + + expect(@proposal_notification.reload).to be_ignored + expect(@proposal_notification.reload).not_to be_hidden + expect(@proposal_notification.author).not_to be_hidden + end + end + + scenario "select all/none", :js do + create_list(:proposal_notification, 2) + + visit moderation_proposal_notifications_path + + within('.js-check') { click_on 'All' } + + expect(all('input[type=checkbox]')).to all(be_checked) + + within('.js-check') { click_on 'None' } + + all('input[type=checkbox]').each do |checkbox| + expect(checkbox).not_to be_checked + end + end + + scenario "remembering page, filter and order" do + create_list(:proposal, 52) + + visit moderation_proposal_notifications_path(filter: 'all', page: '2', order: 'created_at') + + click_button "Mark as viewed" + + expect(page).to have_selector('.js-order-selector[data-order="created_at"]') + + expect(current_url).to include('filter=all') + expect(current_url).to include('page=2') + expect(current_url).to include('order=created_at') + end + end + + scenario "Current filter is properly highlighted" do + visit moderation_proposal_notifications_path + expect(page).not_to have_link('Pending review') + expect(page).to have_link('All') + expect(page).to have_link('Mark as viewed') + + visit moderation_proposal_notifications_path(filter: 'all') + within('.menu.simple') do + expect(page).not_to have_link('All') + expect(page).to have_link('Pending review') + expect(page).to have_link('Mark as viewed') + end + + visit moderation_proposal_notifications_path(filter: 'pending_review') + within('.menu.simple') do + expect(page).to have_link('All') + expect(page).not_to have_link('Pending review') + expect(page).to have_link('Mark as viewed') + end + + visit moderation_proposal_notifications_path(filter: 'ignored') + within('.menu.simple') do + expect(page).to have_link('All') + expect(page).to have_link('Pending review') + expect(page).not_to have_link('Marked as viewed') + end + end + + scenario "Filtering proposals" do + proposal = create(:proposal) + create(:proposal_notification, title: "Regular proposal", proposal: proposal) + create(:proposal_notification, :moderated, title: "Pending proposal", proposal: proposal) + create(:proposal_notification, :hidden, title: "Hidden proposal", proposal: proposal) + create(:proposal_notification, :moderated, :ignored, title: "Ignored proposal", proposal: proposal) + + visit moderation_proposal_notifications_path(filter: 'all') + expect(page).to have_content('Regular proposal') + expect(page).to have_content('Pending proposal') + expect(page).not_to have_content('Hidden proposal') + expect(page).to have_content('Ignored proposal') + + visit moderation_proposal_notifications_path(filter: 'pending_review') + expect(page).not_to have_content('Regular proposal') + expect(page).to have_content('Pending proposal') + expect(page).not_to have_content('Hidden proposal') + expect(page).not_to have_content('Ignored proposal') + + visit moderation_proposal_notifications_path(filter: 'ignored') + expect(page).not_to have_content('Regular proposal') + expect(page).not_to have_content('Pending proposal') + expect(page).not_to have_content('Hidden proposal') + expect(page).to have_content('Ignored proposal') + end + + scenario "sorting proposal notifications" do + moderated_notification = create(:proposal_notification, :moderated, title: "Moderated notification", created_at: Time.current - 1.day) + moderated_new_notification = create(:proposal_notification, :moderated, title: "Moderated new notification", created_at: Time.current - 12.hours) + newer_notification = create(:proposal_notification, title: "Newer notification", created_at: Time.current) + old_moderated_notification = create(:proposal_notification, :moderated, title: "Older notification", created_at: Time.current - 2.days) + + visit moderation_proposal_notifications_path(filter: 'all', order: 'created_at') + + expect(moderated_new_notification.title).to appear_before(moderated_notification.title) + + visit moderation_proposal_notifications_path(filter: 'all', order: 'moderated') + + expect(old_moderated_notification.title).to appear_before(newer_notification.title) + end + end +end