docbrown/spec/requests/notifications_spec.rb

432 lines
15 KiB
Ruby

require "rails_helper"
RSpec.describe "NotificationsIndex", type: :request do
include ActionView::Helpers::DateHelper
let(:dev_account) { create(:user) }
let(:user) { create(:user) }
before do
allow(User).to receive(:dev_account).and_return(dev_account)
end
def has_both_names(response_body)
response_body.include?(CGI.escapeHTML(User.last.name)) && response_body.include?(CGI.escapeHTML(User.second_to_last.name))
end
describe "GET /notifications" do
it "renders page with the proper heading" do
get "/notifications"
expect(response.body).to include("Notifications")
end
context "when signed out" do
it "renders the signup cue" do
get "/notifications"
expect(response.body).to include "Great to have you"
end
end
context "when signed in" do
it "does not render the signup cue" do
sign_in user
get "/notifications"
expect(response.body).not_to include "Create your account"
end
end
context "when a user has new follow notifications" do
before { sign_in user }
def mock_follow_notifications(amount)
create_list :user, amount
follow_instances = User.last(amount).map { |follower| follower.follow(user) }
follow_instances.each { |follow| Notification.send_new_follower_notification_without_delay(follow) }
end
it "renders the proper message for a single notification" do
mock_follow_notifications(1)
get "/notifications"
expect(response.body).to include CGI.escapeHTML(User.last.name)
end
it "renders the proper message for two notifications in the same day" do
mock_follow_notifications(2)
get "/notifications"
expect(has_both_names(response.body)).to be true
end
it "renders the proper message for three or more notifications in the same day" do
mock_follow_notifications(rand(3..10))
get "/notifications"
follow_message = "others followed you!"
expect(response.body).to include follow_message
end
it "does group notifications that occur on different days" do
mock_follow_notifications(2)
Notification.last.update(created_at: Notification.last.created_at - 1.day)
get "/notifications"
notifications = controller.instance_variable_get(:@notifications)
expect(notifications.count).to eq 1
end
end
context "when a user has new reaction notifications" do
let(:article1) { create(:article, user_id: user.id) }
let(:article2) { create(:article, user_id: user.id) }
let(:special_characters_article) { create(:article, user_id: user.id, title: "What's Become of Waring") }
before { sign_in user }
def mock_heart_reaction_notifications(amount, categories, reactable = article1)
create_list :user, amount
reactions = User.last(amount).map do |user|
create(
:reaction,
user_id: user.id,
reactable_id: reactable.id,
reactable_type: reactable.class.name,
category: categories.sample,
)
end
reactions.each { |reaction| Notification.send_reaction_notification_without_delay(reaction, reaction.reactable.user) }
end
it "renders the correct user for a single reaction" do
mock_heart_reaction_notifications(1, %w[like unicorn])
get "/notifications"
expect(response.body).to include CGI.escapeHTML(User.last.name)
end
it "renders the correct usernames for two or more reactions" do
mock_heart_reaction_notifications(2, %w[like unicorn])
get "/notifications"
expect(has_both_names(response.body)).to be true
end
it "renders the proper message for multiple reactions" do
random_amount = rand(3..10)
mock_heart_reaction_notifications(random_amount, %w[unicorn like])
get "/notifications"
expect(response.body).to include CGI.escapeHTML("and #{random_amount - 1} others")
end
it "does group notifications that are on different days but have the same reactable" do
mock_heart_reaction_notifications(2, %w[unicorn like readinglist])
Notification.last.update(created_at: Notification.last.created_at - 1.day)
get "/notifications"
notifications = controller.instance_variable_get(:@notifications)
expect(notifications.count).to eq 1
end
it "does not group notifications that are on the same day but have different reactables" do
mock_heart_reaction_notifications(1, %w[unicorn like readinglist], article1)
mock_heart_reaction_notifications(1, %w[unicorn like readinglist], article2)
get "/notifications"
notifications = controller.instance_variable_get(:@notifications)
expect(notifications.count).to eq 2
end
it "properly renders reactable titles" do
mock_heart_reaction_notifications(1, %w[unicorn like readinglist], special_characters_article)
get "/notifications"
expect(response.body).to include ERB::Util.html_escape(special_characters_article.title)
end
it "properly renders reactable titles for multiple reactions" do
amount = rand(3..10)
mock_heart_reaction_notifications(amount, %w[unicorn like readinglist], special_characters_article)
get "/notifications"
expect(response.body).to include ERB::Util.html_escape(special_characters_article.title)
end
end
context "when a user has a new comment notification" do
let(:user2) { create(:user) }
let(:article) { create(:article, :with_notification_subscription, user_id: user.id) }
let(:comment) { create(:comment, user_id: user2.id, commentable_id: article.id, commentable_type: "Article") }
before do
sign_in user
Notification.send_new_comment_notifications_without_delay(comment)
get "/notifications"
end
it "renders the correct message" do
expect(response.body).to include "commented on"
end
it "does not render incorrect message" do
expect(response.body).not_to include "replied to a thread in"
end
it "does not render the moderation message" do
expect(response.body).not_to include "As a trusted member"
end
it "renders the article's path" do
expect(response.body).to include article.path
end
it "renders the comment's processed HTML" do
expect(response.body).to include comment.processed_html
end
it "renders the reaction as previously reacted if it was reacted on" do
Reaction.create(user: user, reactable: comment, category: "like")
get "/notifications"
expect(response.body).to include "reaction-button reacted"
end
it "does not render the reaction as reacted if it was not reacted on" do
expect(response.body).not_to include "reaction-button reacted"
end
end
context "when a user has a new second level comment notification" do
let(:user2) { create(:user) }
let(:article) { create(:article, :with_notification_subscription, user_id: user.id) }
let(:comment) { create(:comment, user_id: user2.id, commentable_id: article.id, commentable_type: "Article") }
let(:second_comment) { create(:comment, user_id: user2.id, commentable_id: article.id, commentable_type: "Article", parent_id: comment.id) }
let(:third_comment) { create(:comment, user_id: user2.id, commentable_id: article.id, commentable_type: "Article", parent_id: second_comment.id) }
before do
sign_in user
Notification.send_new_comment_notifications_without_delay(comment)
Notification.send_new_comment_notifications_without_delay(second_comment)
Notification.send_new_comment_notifications_without_delay(third_comment)
get "/notifications"
end
it "contextualize comment notification text properly" do
expect(response.body).to include "replied to a thread in"
end
it "contextualize comment title properly" do
expect(response.body).to include CGI.escapeHTML("re: #{comment.title}")
end
end
context "when a user has a new moderation notification" do
let(:user2) { create(:user) }
let(:article) { create(:article, user_id: user.id) }
let(:comment) { create(:comment, user_id: user2.id, commentable_id: article.id, commentable_type: "Article") }
before do
user.add_role :trusted
sign_in user
sidekiq_perform_enqueued_jobs do
Notification.send_moderation_notification(comment)
end
get "/notifications"
end
it "renders the proper message" do
expect(response.body).to include "Since they are new to the community, could you leave a nice reply"
end
it "renders the article's path" do
expect(response.body).to include article.path
end
it "renders the comment's processed HTML" do
expect(response.body).to include comment.processed_html
end
end
context "when a user should not receive moderation notification" do
let(:user2) { create(:user) }
let(:article) { create(:article, user_id: user.id) }
let(:comment) { create(:comment, user_id: user2.id, commentable_id: article.id, commentable_type: "Article") }
before do
sign_in user
sidekiq_perform_enqueued_jobs do
Notification.send_moderation_notification(comment)
end
get "/notifications"
end
it "renders the proper message" do
expect(response.body).not_to include "Since they are new to the community, could you leave a nice reply"
end
it "renders the article's path" do
expect(response.body).not_to include article.path
end
it "renders the comment's processed HTML" do
expect(response.body).not_to include comment.processed_html
end
end
context "when a user has unsubscribed from mod roundrobin notifications" do
let(:user2) { create(:user) }
let(:article) { create(:article, user_id: user.id) }
let(:comment) { create(:comment, user_id: user2.id, commentable_id: article.id, commentable_type: "Article") }
before do
user.add_role :trusted
user.update(mod_roundrobin_notifications: false)
sign_in user
perform_enqueued_jobs do
Notification.send_moderation_notification(comment)
end
get "/notifications"
end
it "renders the proper message" do
expect(response.body).not_to include "Since they are new to the community, could you leave a nice reply"
end
it "renders the article's path" do
expect(response.body).not_to include article.path
end
it "renders the comment's processed HTML" do
expect(response.body).not_to include comment.processed_html
end
end
context "when a user has a new welcome notification" do
before do
sign_in user
end
it "renders the welcome notification" do
broadcast = create(:broadcast, :onboarding)
sidekiq_perform_enqueued_jobs do
Notification.send_welcome_notification(user.id)
end
get "/notifications"
expect(response.body).to include broadcast.processed_html
end
end
context "when a user has a new badge notification" do
before do
sign_in user
badge = create(:badge)
badge_achievement = create(:badge_achievement, user: user, badge: badge)
sidekiq_perform_enqueued_jobs do
Notification.send_new_badge_achievement_notification(badge_achievement)
end
get "/notifications"
end
it "renders the badge's title" do
expect(response.body).to include Badge.first.title
end
it "renders the rewarding context message" do
expect(response.body).to include user.badge_achievements.first.rewarding_context_message
end
it "renders the badge's description" do
expect(response.body).to include CGI.escapeHTML(Badge.first.description)
end
it "renders the CHECK YOUR PROFILE button" do
expect(response.body).to include "CHECK YOUR PROFILE"
end
end
context "when a user has a new mention notification" do
let(:user2) { create(:user) }
let(:article) { create(:article, user_id: user.id) }
let(:comment) do
create(
:comment,
user_id: user2.id,
commentable_id: article.id,
commentable_type: "Article",
body_markdown: "@#{user.username}",
)
end
let(:mention) { create(:mention, mentionable: comment, user: user) }
before do
sidekiq_perform_enqueued_jobs do
Notification.send_mention_notification(mention)
end
sign_in user
get "/notifications"
end
it "renders the proper message" do
expect(response.body).to include "mentioned you in a comment"
end
it "renders the processed HTML of the comment where they were mentioned" do
expect(response.body).to include comment.processed_html
end
end
context "when a user has a new article notification" do
let(:user2) { create(:user) }
let(:article) { create(:article, user_id: user.id) }
before do
user2.follow(user)
sidekiq_perform_enqueued_jobs do
Notification.send_to_followers(article, "Published")
end
sign_in user2
get "/notifications"
end
it "renders the proper message" do
expect(response.body).to include "made a new post:"
end
it "renders the article's path" do
expect(response.body).to include article.path
end
it "renders the author's name" do
expect(response.body).to include CGI.escapeHTML(article.user.name)
end
it "renders the reaction as previously reacted if it was reacted on" do
Reaction.create(user: user2, reactable: article, category: "like")
get "/notifications"
expect(response.body).to include "reaction-button reacted"
end
it "does not render the reaction as reacted if it was not reacted on" do
expect(response.body).not_to include "reaction-button reacted"
end
it "renders the article's published at" do
expect(response.body).to include time_ago_in_words(article.published_at)
end
end
context "when a user is an admin" do
let(:admin) { create(:user, :super_admin) }
let(:user2) { create(:user) }
let(:article) { create(:article, user_id: user.id) }
before do
user2.follow(user)
sidekiq_perform_enqueued_jobs do
Notification.send_to_followers(article, "Published")
end
sign_in admin
end
it "can view other people's notifications" do
get "/notifications?username=#{user2.username}"
expect(response.body).to include "made a new post:"
end
end
context "when filter is unknown" do
it "does not raise an error" do
sign_in user
expect { get "/notifications/feed" }.not_to raise_error
end
end
end
end