mirror of
https://github.com/discourse/discourse.git
synced 2024-12-01 21:19:41 -06:00
b463a80cbf
When a group only has SMTP enabled and not IMAP, we do not want to enqueue the :group_smtp_email job because using the group's SMTP credentials for sending user_private_message emails is handled by the UserNotifications class. We do not want the :group_smtp_email job to be enqueued because that uses a reply key instead of the group.email_username for the reply-to address which is not what we want for SMTP only, and also creates an IncomingEmail record to prevent IMAP double syncing which we do not need either. There is an open question about what happens when IMAP is enabled after SMTP has been enabled for a while, and also questions around whether we could do away with :group_smtp_email altogether and handle everything via EmailLog and UserNotifications, adding additional columns to the former and modifying the Imap::Sync class to take this into account...a lot more further testing for IMAP needs to be done to answer those questions. For now, this fix should be sufficient to get the correct reply-to address for user_private_response messages sent in response to emails sent directly to the group's email_username SMTP address. Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
1414 lines
56 KiB
Ruby
1414 lines
56 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
RSpec::Matchers.define :add_notification do |user, notification_type|
|
|
match(notify_expectation_failures: true) do |actual|
|
|
notifications = user.notifications
|
|
before = notifications.count
|
|
|
|
actual.call
|
|
|
|
expect(notifications.count).to eq(before + 1), "expected 1 new notification, got #{notifications.count - before}"
|
|
|
|
last_notification_type = notifications.last.notification_type
|
|
expect(last_notification_type).to eq(Notification.types[notification_type]),
|
|
"expected notification type to be '#{notification_type}', got '#{Notification.types.key(last_notification_type)}'"
|
|
end
|
|
|
|
match_when_negated do |actual|
|
|
expect { actual.call }.to_not change { user.notifications.where(notification_type: Notification.types[notification_type]).count }
|
|
end
|
|
|
|
supports_block_expectations
|
|
end
|
|
|
|
RSpec::Matchers.define_negated_matcher :not_add_notification, :add_notification
|
|
|
|
describe PostAlerter do
|
|
|
|
fab!(:evil_trout) { Fabricate(:evil_trout) }
|
|
fab!(:user) { Fabricate(:user) }
|
|
|
|
def create_post_with_alerts(args = {})
|
|
post = Fabricate(:post, args)
|
|
PostAlerter.post_created(post)
|
|
end
|
|
|
|
context "private message" do
|
|
it "notifies for pms correctly" do
|
|
pm = Fabricate(:topic, archetype: 'private_message', category_id: nil)
|
|
op = Fabricate(:post, user: pm.user)
|
|
pm.allowed_users << pm.user
|
|
PostAlerter.post_created(op)
|
|
|
|
reply = Fabricate(:post, user: pm.user, topic: pm, reply_to_post_number: 1)
|
|
PostAlerter.post_created(reply)
|
|
|
|
reply2 = Fabricate(:post, topic: pm, reply_to_post_number: 1)
|
|
PostAlerter.post_created(reply2)
|
|
|
|
# we get a green notification for a reply
|
|
expect(Notification.where(user_id: pm.user_id).pluck_first(:notification_type)).to eq(Notification.types[:private_message])
|
|
|
|
TopicUser.change(pm.user_id, pm.id, notification_level: TopicUser.notification_levels[:tracking])
|
|
|
|
Notification.destroy_all
|
|
|
|
reply3 = Fabricate(:post, topic: pm)
|
|
PostAlerter.post_created(reply3)
|
|
|
|
# no notification cause we are tracking
|
|
expect(Notification.where(user_id: pm.user_id).count).to eq(0)
|
|
|
|
Notification.destroy_all
|
|
|
|
reply4 = Fabricate(:post, topic: pm, reply_to_post_number: 1)
|
|
PostAlerter.post_created(reply4)
|
|
|
|
# yes notification cause we were replied to
|
|
expect(Notification.where(user_id: pm.user_id).count).to eq(1)
|
|
|
|
end
|
|
|
|
context "group inboxes" do
|
|
fab!(:user1) { Fabricate(:user) }
|
|
fab!(:user2) { Fabricate(:user) }
|
|
fab!(:group) { Fabricate(:group, users: [user2], name: "TestGroup") }
|
|
fab!(:pm) { Fabricate(:topic, archetype: 'private_message', category_id: nil, allowed_groups: [group]) }
|
|
fab!(:op) { Fabricate(:post, user: pm.user, topic: pm) }
|
|
|
|
it "triggers :before_create_notifications_for_users" do
|
|
pm.allowed_users << user1
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.post_created(op)
|
|
end
|
|
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[user1], op])
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[user2], op])
|
|
|
|
end
|
|
|
|
it "triggers group summary notification" do
|
|
TopicUser.change(user2.id, pm.id, notification_level: TopicUser.notification_levels[:tracking])
|
|
|
|
PostAlerter.post_created(op)
|
|
group_summary_notification = Notification.where(user_id: user2.id)
|
|
|
|
expect(group_summary_notification.count).to eq(1)
|
|
expect(group_summary_notification.first.notification_type).to eq(Notification.types[:group_message_summary])
|
|
|
|
notification_payload = JSON.parse(group_summary_notification.first.data)
|
|
expect(notification_payload["group_name"]).to eq(group.name)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "unread" do
|
|
it "does not return whispers as unread posts" do
|
|
op = Fabricate(:post)
|
|
_whisper = Fabricate(:post, raw: 'this is a whisper post',
|
|
user: Fabricate(:admin),
|
|
topic: op.topic,
|
|
reply_to_post_number: op.post_number,
|
|
post_type: Post.types[:whisper])
|
|
|
|
expect(PostAlerter.new.first_unread_post(op.user, op.topic)).to be_blank
|
|
end
|
|
end
|
|
|
|
context 'edits' do
|
|
it 'notifies correctly on edits' do
|
|
Jobs.run_immediately!
|
|
PostActionNotifier.enable
|
|
|
|
post = Fabricate(:post, raw: 'I love waffles')
|
|
|
|
admin = Fabricate(:admin)
|
|
|
|
expect do
|
|
post.revise(admin, raw: 'I made a revision')
|
|
end.to add_notification(post.user, :edited)
|
|
|
|
# lets also like this post which should trigger a notification
|
|
expect do
|
|
PostActionCreator.new(
|
|
admin,
|
|
post,
|
|
PostActionType.types[:like]
|
|
).perform
|
|
end.to add_notification(post.user, :liked)
|
|
|
|
# skip this notification cause we already notified on an edit by the same user
|
|
# in the previous edit
|
|
freeze_time 2.hours.from_now
|
|
|
|
expect do
|
|
post.revise(admin, raw: 'I made another revision')
|
|
end.to_not change { Notification.count }
|
|
|
|
# this we do not skip cause 1 day has passed
|
|
freeze_time 23.hours.from_now
|
|
|
|
expect do
|
|
post.revise(admin, raw: 'I made another revision xyz')
|
|
end.to add_notification(post.user, :edited)
|
|
|
|
expect do
|
|
post.revise(Fabricate(:admin), raw: 'I made a revision')
|
|
end.to add_notification(post.user, :edited)
|
|
|
|
freeze_time 2.hours.from_now
|
|
|
|
expect do
|
|
post.revise(admin, raw: 'I made another revision')
|
|
end.to add_notification(post.user, :edited)
|
|
end
|
|
|
|
it 'notifies flaggers when flagged post gets unhidden by edit' do
|
|
post = create_post
|
|
walterwhite = Fabricate(:walter_white)
|
|
coding_horror = Fabricate(:coding_horror)
|
|
|
|
PostActionNotifier.enable
|
|
Reviewable.set_priorities(high: 4.0)
|
|
SiteSetting.hide_post_sensitivity = Reviewable.sensitivity[:low]
|
|
|
|
PostActionCreator.spam(evil_trout, post)
|
|
PostActionCreator.spam(walterwhite, post)
|
|
|
|
post.reload
|
|
expect(post.hidden).to eq(true)
|
|
|
|
expect {
|
|
post.revise(post.user, raw: post.raw + " ha I edited it ")
|
|
}.to add_notification(evil_trout, :edited)
|
|
.and add_notification(walterwhite, :edited)
|
|
|
|
post.reload
|
|
expect(post.hidden).to eq(false)
|
|
|
|
notification = walterwhite.notifications.last
|
|
expect(notification.topic_id).to eq(post.topic.id)
|
|
expect(notification.post_number).to eq(post.post_number)
|
|
expect(notification.data_hash["display_username"]).to eq(post.user.username)
|
|
|
|
PostActionCreator.create(coding_horror, post, :spam)
|
|
PostActionCreator.create(walterwhite, post, :off_topic)
|
|
|
|
post.reload
|
|
expect(post.hidden).to eq(true)
|
|
|
|
expect {
|
|
post.revise(post.user, raw: post.raw + " ha I edited it again ")
|
|
}.to not_add_notification(evil_trout, :edited)
|
|
.and not_add_notification(coding_horror, :edited)
|
|
.and not_add_notification(walterwhite, :edited)
|
|
end
|
|
end
|
|
|
|
context 'quotes' do
|
|
let(:category) { Fabricate(:category) }
|
|
let(:topic) { Fabricate(:topic, category: category) }
|
|
|
|
it 'does not notify for muted users' do
|
|
post = Fabricate(:post, raw: '[quote="EvilTrout, post:1"]whatup[/quote]', topic: topic)
|
|
MutedUser.create!(user_id: evil_trout.id, muted_user_id: post.user_id)
|
|
|
|
expect {
|
|
PostAlerter.post_created(post)
|
|
}.to change(evil_trout.notifications, :count).by(0)
|
|
end
|
|
|
|
it 'does not notify for ignored users' do
|
|
post = Fabricate(:post, raw: '[quote="EvilTrout, post:1"]whatup[/quote]', topic: topic)
|
|
Fabricate(:ignored_user, user: evil_trout, ignored_user: post.user)
|
|
|
|
expect {
|
|
PostAlerter.post_created(post)
|
|
}.to change(evil_trout.notifications, :count).by(0)
|
|
end
|
|
|
|
it 'does not notify for users with new reply notification' do
|
|
post = Fabricate(:post, raw: '[quote="EvilTrout, post:1"]whatup[/quote]', topic: topic)
|
|
notification = Notification.create!(topic: post.topic,
|
|
post_number: post.post_number,
|
|
read: false,
|
|
notification_type: Notification.types[:replied],
|
|
user: evil_trout,
|
|
data: { topic_title: "test topic" }.to_json
|
|
)
|
|
expect {
|
|
PostAlerter.post_edited(post)
|
|
}.to change(evil_trout.notifications, :count).by(0)
|
|
|
|
notification.destroy
|
|
expect {
|
|
PostAlerter.post_edited(post)
|
|
}.to change(evil_trout.notifications, :count).by(1)
|
|
end
|
|
|
|
it 'does not collapse quote notifications' do
|
|
expect {
|
|
2.times do
|
|
create_post_with_alerts(
|
|
raw: '[quote="EvilTrout, post:1"]whatup[/quote]',
|
|
topic: topic
|
|
)
|
|
end
|
|
}.to change(evil_trout.notifications, :count).by(2)
|
|
end
|
|
|
|
it "won't notify the user a second time on revision" do
|
|
p1 = create_post_with_alerts(raw: '[quote="Evil Trout, post:1"]whatup[/quote]')
|
|
expect {
|
|
p1.revise(p1.user, raw: '[quote="Evil Trout, post:1"]whatup now?[/quote]')
|
|
}.not_to change(evil_trout.notifications, :count)
|
|
end
|
|
|
|
it "doesn't notify the poster" do
|
|
topic = create_post_with_alerts.topic
|
|
expect {
|
|
Fabricate(:post, topic: topic, user: topic.user, raw: '[quote="Bruce Wayne, post:1"]whatup[/quote]')
|
|
}.not_to change(topic.user.notifications, :count)
|
|
end
|
|
|
|
it "triggers :before_create_notifications_for_users" do
|
|
post = Fabricate(:post, raw: '[quote="EvilTrout, post:1"]whatup[/quote]')
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.post_created(post)
|
|
end
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[evil_trout], post])
|
|
end
|
|
end
|
|
|
|
context 'linked' do
|
|
let(:post1) { create_post }
|
|
let(:user) { post1.user }
|
|
let(:linking_post) { create_post(raw: "my magic topic\n##{Discourse.base_url}#{post1.url}") }
|
|
|
|
before do
|
|
Jobs.run_immediately!
|
|
end
|
|
|
|
it "will notify correctly on linking" do
|
|
linking_post
|
|
|
|
expect(user.notifications.count).to eq(1)
|
|
|
|
topic = Fabricate(:topic)
|
|
|
|
watcher = Fabricate(:user)
|
|
TopicUser.create!(user_id: watcher.id, topic_id: topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
|
|
create_post(topic_id: topic.id, user: user, raw: "my magic topic\n##{Discourse.base_url}#{post1.url}")
|
|
|
|
user.reload
|
|
expect(user.notifications.where(notification_type: Notification.types[:linked]).count).to eq(1)
|
|
|
|
expect(watcher.notifications.count).to eq(1)
|
|
|
|
# don't notify on reflection
|
|
post1.reload
|
|
expect(PostAlerter.new.extract_linked_users(post1).length).to eq(0)
|
|
end
|
|
|
|
it "triggers :before_create_notifications_for_users" do
|
|
events = DiscourseEvent.track_events do
|
|
linking_post
|
|
end
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[user], linking_post])
|
|
end
|
|
|
|
it "doesn't notify the linked user if the user is staged and the category is restricted and allows strangers" do
|
|
staged_user = Fabricate(:staged)
|
|
group = Fabricate(:group)
|
|
group_member = Fabricate(:user)
|
|
group.add(group_member)
|
|
|
|
private_category = Fabricate(
|
|
:private_category, group: group,
|
|
email_in: 'test@test.com', email_in_allow_strangers: true
|
|
)
|
|
|
|
staged_user_post = create_post(user: staged_user, category: private_category)
|
|
|
|
linking = create_post(
|
|
user: group_member,
|
|
category: private_category,
|
|
raw: "my magic topic\n##{Discourse.base_url}#{staged_user_post.url}")
|
|
|
|
staged_user.reload
|
|
expect(staged_user.notifications.where(notification_type: Notification.types[:linked]).count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context '@group mentions' do
|
|
|
|
fab!(:group) { Fabricate(:group, name: 'group', mentionable_level: Group::ALIAS_LEVELS[:everyone]) }
|
|
let(:post) { create_post_with_alerts(raw: "Hello @group how are you?") }
|
|
before { group.add(evil_trout) }
|
|
|
|
it 'notifies users correctly' do
|
|
expect {
|
|
post
|
|
}.to change(evil_trout.notifications, :count).by(1)
|
|
|
|
expect(GroupMention.count).to eq(1)
|
|
|
|
Fabricate(:group, name: 'group-alt', mentionable_level: Group::ALIAS_LEVELS[:everyone])
|
|
|
|
expect {
|
|
create_post_with_alerts(raw: "Hello, @group-alt should not trigger a notification?")
|
|
}.to change(evil_trout.notifications, :count).by(0)
|
|
|
|
expect(GroupMention.count).to eq(2)
|
|
|
|
group.update_columns(mentionable_level: Group::ALIAS_LEVELS[:members_mods_and_admins])
|
|
expect {
|
|
create_post_with_alerts(raw: "Hello @group you are not mentionable")
|
|
}.to change(evil_trout.notifications, :count).by(0)
|
|
|
|
expect(GroupMention.count).to eq(3)
|
|
|
|
group.update_columns(mentionable_level: Group::ALIAS_LEVELS[:owners_mods_and_admins])
|
|
group.add_owner(user)
|
|
expect {
|
|
create_post_with_alerts(raw: "Hello @group the owner can mention you", user: user)
|
|
}.to change(evil_trout.notifications, :count).by(1)
|
|
|
|
expect(GroupMention.count).to eq(4)
|
|
end
|
|
|
|
it 'takes private mention as precedence' do
|
|
expect {
|
|
create_post_with_alerts(raw: "Hello @group and @eviltrout, nice to meet you")
|
|
}.to change(evil_trout.notifications, :count).by(1)
|
|
expect(evil_trout.notifications.last.notification_type).to eq(Notification.types[:mentioned])
|
|
end
|
|
|
|
it "triggers :before_create_notifications_for_users" do
|
|
events = DiscourseEvent.track_events do
|
|
post
|
|
end
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[evil_trout], post])
|
|
end
|
|
end
|
|
|
|
context '@mentions' do
|
|
|
|
let(:mention_post) { create_post_with_alerts(user: user, raw: 'Hello @eviltrout') }
|
|
let(:topic) { mention_post.topic }
|
|
|
|
before do
|
|
Jobs.run_immediately!
|
|
end
|
|
|
|
it 'notifies a user' do
|
|
expect {
|
|
mention_post
|
|
}.to change(evil_trout.notifications, :count).by(1)
|
|
end
|
|
|
|
it "won't notify the user a second time on revision" do
|
|
mention_post
|
|
expect {
|
|
mention_post.revise(mention_post.user, raw: "New raw content that still mentions @eviltrout")
|
|
}.not_to change(evil_trout.notifications, :count)
|
|
end
|
|
|
|
it "doesn't notify the user who created the topic in regular mode" do
|
|
topic.notify_regular!(user)
|
|
mention_post
|
|
expect {
|
|
create_post_with_alerts(user: user, raw: 'second post', topic: topic)
|
|
}.not_to change(user.notifications, :count)
|
|
end
|
|
|
|
it "triggers :before_create_notifications_for_users" do
|
|
events = DiscourseEvent.track_events do
|
|
mention_post
|
|
end
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[evil_trout], mention_post])
|
|
end
|
|
|
|
it "notification comes from editor if mention is added later" do
|
|
admin = Fabricate(:admin)
|
|
post = create_post_with_alerts(user: user, raw: 'No mention here.')
|
|
expect {
|
|
post.revise(admin, raw: "Mention @eviltrout in this edit.")
|
|
}.to change(evil_trout.notifications, :count)
|
|
n = evil_trout.notifications.last
|
|
expect(n.data_hash["original_username"]).to eq(admin.username)
|
|
end
|
|
|
|
it "doesn't notify the last post editor if they mention themselves" do
|
|
post = create_post_with_alerts(user: user, raw: 'Post without a mention.')
|
|
expect {
|
|
post.revise(evil_trout, raw: "O hai, @eviltrout!")
|
|
}.not_to change(evil_trout.notifications, :count)
|
|
end
|
|
|
|
fab!(:alice) { Fabricate(:user, username: 'alice') }
|
|
fab!(:bob) { Fabricate(:user, username: 'bob') }
|
|
fab!(:carol) { Fabricate(:admin, username: 'carol') }
|
|
fab!(:dave) { Fabricate(:user, username: 'dave') }
|
|
fab!(:eve) { Fabricate(:user, username: 'eve') }
|
|
fab!(:group) { Fabricate(:group, name: 'group', mentionable_level: Group::ALIAS_LEVELS[:everyone]) }
|
|
|
|
before do
|
|
group.bulk_add([alice.id, eve.id])
|
|
end
|
|
|
|
def create_post_with_alerts(args = {})
|
|
post = Fabricate(:post, args)
|
|
PostAlerter.post_created(post)
|
|
end
|
|
|
|
def set_topic_notification_level(user, topic, level_name)
|
|
TopicUser.change(user.id, topic.id, notification_level: TopicUser.notification_levels[level_name])
|
|
end
|
|
|
|
context "topic" do
|
|
fab!(:topic) { Fabricate(:topic, user: alice) }
|
|
|
|
[:watching, :tracking, :regular].each do |notification_level|
|
|
context "when notification level is '#{notification_level}'" do
|
|
before do
|
|
set_topic_notification_level(alice, topic, notification_level)
|
|
end
|
|
|
|
it "notifies about @username mention" do
|
|
args = { user: bob, topic: topic, raw: 'Hello @alice' }
|
|
expect { create_post_with_alerts(args) }.to add_notification(alice, :mentioned)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when notification level is 'muted'" do
|
|
before do
|
|
set_topic_notification_level(alice, topic, :muted)
|
|
end
|
|
|
|
it "does not notify about @username mention" do
|
|
args = { user: bob, topic: topic, raw: 'Hello @alice' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(alice, :mentioned)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "message to users" do
|
|
fab!(:pm_topic) do
|
|
Fabricate(:private_message_topic,
|
|
user: alice,
|
|
topic_allowed_users: [
|
|
Fabricate.build(:topic_allowed_user, user: alice),
|
|
Fabricate.build(:topic_allowed_user, user: bob),
|
|
Fabricate.build(:topic_allowed_user, user: Discourse.system_user)
|
|
]
|
|
)
|
|
end
|
|
|
|
context "when user is part of conversation" do
|
|
[:watching, :tracking, :regular].each do |notification_level|
|
|
context "when notification level is '#{notification_level}'" do
|
|
before do
|
|
set_topic_notification_level(alice, pm_topic, notification_level)
|
|
end
|
|
|
|
it "notifies about @username mention" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @alice' }
|
|
expect { create_post_with_alerts(args) }.to add_notification(alice, :mentioned)
|
|
end
|
|
|
|
it "notifies about @username mentions by non-human users" do
|
|
args = { user: Discourse.system_user, topic: pm_topic, raw: 'Hello @alice' }
|
|
expect { create_post_with_alerts(args) }.to add_notification(alice, :mentioned)
|
|
end
|
|
|
|
it "notifies about @group mention when allowed user is part of group" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @group' }
|
|
expect { create_post_with_alerts(args) }.to add_notification(alice, :group_mentioned)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when notification level is 'muted'" do
|
|
before do
|
|
set_topic_notification_level(alice, pm_topic, :muted)
|
|
end
|
|
|
|
it "does not notify about @username mention" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @alice' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(alice, :mentioned)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when user is not part of conversation" do
|
|
it "does not notify about @username mention even though mentioned user is an admin" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @carol' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(carol, :mentioned)
|
|
end
|
|
|
|
it "does not notify about @username mention by non-human user even though mentioned user is an admin" do
|
|
args = { user: Discourse.system_user, topic: pm_topic, raw: 'Hello @carol' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(carol, :mentioned)
|
|
end
|
|
|
|
it "does not notify about @username mention when mentioned user is not allowed to see message" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @dave' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(dave, :mentioned)
|
|
end
|
|
|
|
it "does not notify about @group mention when user is not an allowed user" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @group' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(eve, :group_mentioned)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "message to group" do
|
|
|
|
fab!(:some_group) { Fabricate(:group, name: 'some_group', mentionable_level: Group::ALIAS_LEVELS[:everyone]) }
|
|
fab!(:pm_topic) do
|
|
Fabricate(:private_message_topic,
|
|
user: alice,
|
|
topic_allowed_groups: [
|
|
Fabricate.build(:topic_allowed_group, group: group)
|
|
],
|
|
topic_allowed_users: [
|
|
Fabricate.build(:topic_allowed_user, user: Discourse.system_user)
|
|
]
|
|
)
|
|
end
|
|
|
|
before do
|
|
some_group.bulk_add([alice.id, carol.id])
|
|
end
|
|
|
|
context "when group is part of conversation" do
|
|
[:watching, :tracking, :regular].each do |notification_level|
|
|
context "when notification level is '#{notification_level}'" do
|
|
before do
|
|
set_topic_notification_level(alice, pm_topic, notification_level)
|
|
end
|
|
|
|
it "notifies about @group mention" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @group' }
|
|
expect { create_post_with_alerts(args) }.to add_notification(alice, :group_mentioned)
|
|
end
|
|
|
|
it "notifies about @group mentions by non-human users" do
|
|
args = { user: Discourse.system_user, topic: pm_topic, raw: 'Hello @group' }
|
|
expect { create_post_with_alerts(args) }.to add_notification(alice, :group_mentioned)
|
|
end
|
|
|
|
it "notifies about @username mention when user belongs to allowed group" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @alice' }
|
|
expect { create_post_with_alerts(args) }.to add_notification(alice, :mentioned)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when notification level is 'muted'" do
|
|
before do
|
|
set_topic_notification_level(alice, pm_topic, :muted)
|
|
end
|
|
|
|
it "does not notify about @group mention" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @group' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(alice, :group_mentioned)
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when group is not part of conversation" do
|
|
it "does not notify about @group mention even though mentioned user is an admin" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @some_group' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(carol, :group_mentioned)
|
|
end
|
|
|
|
it "does not notify about @group mention by non-human user even though mentioned user is an admin" do
|
|
args = { user: Discourse.system_user, topic: pm_topic, raw: 'Hello @some_group' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(carol, :group_mentioned)
|
|
end
|
|
|
|
it "does not notify about @username mention when user doesn't belong to allowed group" do
|
|
args = { user: bob, topic: pm_topic, raw: 'Hello @dave' }
|
|
expect { create_post_with_alerts(args) }.to_not add_notification(dave, :mentioned)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe ".create_notification" do
|
|
fab!(:topic) { Fabricate(:private_message_topic, user: user, created_at: 1.hour.ago) }
|
|
fab!(:post) { Fabricate(:post, topic: topic, created_at: 1.hour.ago) }
|
|
let(:type) { Notification.types[:private_message] }
|
|
|
|
it "creates a notification for PMs" do
|
|
post.revise(user, { raw: 'This is the revised post' }, revised_at: Time.zone.now)
|
|
|
|
expect {
|
|
PostAlerter.new.create_notification(user, type, post)
|
|
}.to change { user.notifications.count }.by(1)
|
|
|
|
expect(user.notifications.last.data_hash["topic_title"]).to eq(topic.title)
|
|
end
|
|
|
|
it "keeps the original title for PMs" do
|
|
original_title = topic.title
|
|
|
|
post.revise(user, { title: "This is the revised title" }, revised_at: Time.now)
|
|
|
|
expect {
|
|
PostAlerter.new.create_notification(user, type, post)
|
|
}.to change { user.notifications.count }.by(1)
|
|
|
|
expect(user.notifications.last.data_hash["topic_title"]).to eq(original_title)
|
|
end
|
|
|
|
it "triggers :pre_notification_alert" do
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.new.create_notification(user, type, post)
|
|
end
|
|
|
|
payload = {
|
|
notification_type: type,
|
|
post_number: post.post_number,
|
|
topic_title: post.topic.title,
|
|
topic_id: post.topic.id,
|
|
excerpt: post.excerpt(400, text_entities: true, strip_links: true, remap_emoji: true),
|
|
username: post.username,
|
|
post_url: post.url
|
|
}
|
|
|
|
expect(events).to include(event_name: :pre_notification_alert, params: [user, payload])
|
|
end
|
|
|
|
it "does not alert when revising and changing notification type" do
|
|
PostAlerter.new.create_notification(user, type, post)
|
|
|
|
post.revise(user, { raw: "Editing post to fake include a mention of @eviltrout" }, revised_at: Time.now)
|
|
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.new.create_notification(user, Notification.types[:mentioned], post)
|
|
end
|
|
|
|
payload = {
|
|
notification_type: type,
|
|
post_number: post.post_number,
|
|
topic_title: post.topic.title,
|
|
topic_id: post.topic.id,
|
|
excerpt: post.excerpt(400, text_entities: true, strip_links: true, remap_emoji: true),
|
|
username: post.username,
|
|
post_url: post.url
|
|
}
|
|
|
|
expect(events).not_to include(event_name: :pre_notification_alert, params: [user, payload])
|
|
end
|
|
|
|
it "triggers :before_create_notification" do
|
|
type = Notification.types[:private_message]
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.new.create_notification(user, type, post, {})
|
|
end
|
|
expect(events).to include(event_name: :before_create_notification, params: [user, type, post, {}])
|
|
end
|
|
end
|
|
|
|
describe "push_notification" do
|
|
let(:mention_post) { create_post_with_alerts(user: user, raw: 'Hello @eviltrout :heart:') }
|
|
let(:topic) { mention_post.topic }
|
|
|
|
it "pushes nothing to suspended users" do
|
|
SiteSetting.allowed_user_api_push_urls = "https://site.com/push|https://site2.com/push"
|
|
|
|
evil_trout.update_columns(suspended_till: 1.year.from_now)
|
|
|
|
2.times do |i|
|
|
UserApiKey.create!(user_id: evil_trout.id,
|
|
client_id: "xxx#{i}",
|
|
application_name: "iPhone#{i}",
|
|
scopes: ['notifications'].map { |name| UserApiKeyScope.new(name: name) },
|
|
push_url: "https://site2.com/push")
|
|
end
|
|
|
|
expect { mention_post }.to_not change { Jobs::PushNotification.jobs.count }
|
|
end
|
|
|
|
it "pushes nothing when the user is in 'do not disturb'" do
|
|
SiteSetting.allowed_user_api_push_urls = "https://site.com/push|https://site2.com/push"
|
|
2.times do |i|
|
|
UserApiKey.create!(user_id: evil_trout.id,
|
|
client_id: "xxx#{i}",
|
|
application_name: "iPhone#{i}",
|
|
scopes: ['notifications'].map { |name| UserApiKeyScope.new(name: name) },
|
|
push_url: "https://site2.com/push")
|
|
end
|
|
|
|
Fabricate(:do_not_disturb_timing, user: evil_trout, starts_at: Time.zone.now, ends_at: 1.day.from_now)
|
|
|
|
expect { mention_post }.to_not change { Jobs::PushNotification.jobs.count }
|
|
end
|
|
|
|
it "correctly pushes notifications if configured correctly" do
|
|
Jobs.run_immediately!
|
|
SiteSetting.allowed_user_api_push_urls = "https://site.com/push|https://site2.com/push"
|
|
|
|
2.times do |i|
|
|
UserApiKey.create!(user_id: evil_trout.id,
|
|
client_id: "xxx#{i}",
|
|
application_name: "iPhone#{i}",
|
|
scopes: ['notifications'].map { |name| UserApiKeyScope.new(name: name) },
|
|
push_url: "https://site2.com/push")
|
|
end
|
|
|
|
body = nil
|
|
headers = nil
|
|
|
|
stub_request(:post, "https://site2.com/push")
|
|
.to_return do |request|
|
|
body = request.body
|
|
headers = request.headers
|
|
{ status: 200, body: "OK" }
|
|
end
|
|
|
|
set_subfolder "/subpath"
|
|
payload = {
|
|
"secret_key" => SiteSetting.push_api_secret_key,
|
|
"url" => Discourse.base_url,
|
|
"title" => SiteSetting.title,
|
|
"description" => SiteSetting.site_description,
|
|
"notifications" => [
|
|
{
|
|
'notification_type' => 1,
|
|
'post_number' => 1,
|
|
'topic_title' => topic.title,
|
|
'topic_id' => topic.id,
|
|
'excerpt' => 'Hello @eviltrout ❤',
|
|
'username' => user.username,
|
|
'url' => UrlHelper.absolute(Discourse.base_path + mention_post.url),
|
|
'client_id' => 'xxx0'
|
|
},
|
|
{
|
|
'notification_type' => 1,
|
|
'post_number' => 1,
|
|
'topic_title' => topic.title,
|
|
'topic_id' => topic.id,
|
|
'excerpt' => 'Hello @eviltrout ❤',
|
|
'username' => user.username,
|
|
'url' => UrlHelper.absolute(Discourse.base_path + mention_post.url),
|
|
'client_id' => 'xxx1'
|
|
}
|
|
]
|
|
}
|
|
|
|
post = mention_post
|
|
|
|
expect(JSON.parse(body)).to eq(payload)
|
|
expect(headers["Content-Type"]).to eq('application/json')
|
|
|
|
TopicUser.change(evil_trout.id, topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
|
|
post = Fabricate(:post, topic: post.topic, user_id: evil_trout.id)
|
|
user2 = Fabricate(:user)
|
|
|
|
# if we collapse a reply notification we should get notified on the correct post
|
|
new_post = create_post_with_alerts(topic: post.topic, user_id: user.id, reply_to_post_number: post.post_number, raw: 'this is my first reply')
|
|
|
|
changes = {
|
|
"notification_type" => Notification.types[:posted],
|
|
"post_number" => new_post.post_number,
|
|
"username" => new_post.user.username,
|
|
"excerpt" => new_post.raw,
|
|
"url" => UrlHelper.absolute(Discourse.base_path + new_post.url)
|
|
}
|
|
|
|
payload["notifications"][0].merge! changes
|
|
payload["notifications"][1].merge! changes
|
|
|
|
expect(JSON.parse(body)).to eq(payload)
|
|
|
|
new_post = create_post_with_alerts(topic: post.topic, user_id: user2.id, reply_to_post_number: post.post_number, raw: 'this is my second reply')
|
|
|
|
changes = {
|
|
"post_number" => new_post.post_number,
|
|
"username" => new_post.user.username,
|
|
"excerpt" => new_post.raw,
|
|
"url" => UrlHelper.absolute(Discourse.base_path + new_post.url)
|
|
}
|
|
|
|
payload["notifications"][0].merge! changes
|
|
payload["notifications"][1].merge! changes
|
|
|
|
expect(JSON.parse(body)).to eq(payload)
|
|
|
|
end
|
|
end
|
|
|
|
describe "watching_first_post" do
|
|
fab!(:group) { Fabricate(:group) }
|
|
fab!(:user) { Fabricate(:user) }
|
|
fab!(:category) { Fabricate(:category) }
|
|
fab!(:tag) { Fabricate(:tag) }
|
|
fab!(:topic) { Fabricate(:topic, category: category, tags: [tag]) }
|
|
fab!(:post) { Fabricate(:post, topic: topic) }
|
|
|
|
it "doesn't notify people who aren't watching" do
|
|
PostAlerter.post_created(post)
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(0)
|
|
end
|
|
|
|
it "notifies the user who is following the first post category" do
|
|
level = CategoryUser.notification_levels[:watching_first_post]
|
|
CategoryUser.set_notification_level_for_category(user, level, category.id)
|
|
PostAlerter.new.after_save_post(post, true)
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(1)
|
|
end
|
|
|
|
it "doesn't notify when the record is not new" do
|
|
level = CategoryUser.notification_levels[:watching_first_post]
|
|
CategoryUser.set_notification_level_for_category(user, level, category.id)
|
|
PostAlerter.new.after_save_post(post, false)
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(0)
|
|
end
|
|
|
|
it "notifies the user who is following the first post tag" do
|
|
level = TagUser.notification_levels[:watching_first_post]
|
|
TagUser.change(user.id, tag.id, level)
|
|
PostAlerter.post_created(post)
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(1)
|
|
end
|
|
|
|
it "notifies the user who is following the first post group" do
|
|
GroupUser.create(group_id: group.id, user_id: user.id)
|
|
GroupUser.create(group_id: group.id, user_id: post.user.id)
|
|
topic.topic_allowed_groups.create(group_id: group.id)
|
|
|
|
level = GroupUser.notification_levels[:watching_first_post]
|
|
GroupUser.where(user_id: user.id, group_id: group.id).update_all(notification_level: level)
|
|
|
|
PostAlerter.post_created(post)
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(1)
|
|
end
|
|
|
|
it "triggers :before_create_notifications_for_users" do
|
|
level = CategoryUser.notification_levels[:watching_first_post]
|
|
CategoryUser.set_notification_level_for_category(user, level, category.id)
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.new.after_save_post(post, true)
|
|
end
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[user], post])
|
|
end
|
|
end
|
|
|
|
context "replies" do
|
|
it "triggers :before_create_notifications_for_users" do
|
|
user = Fabricate(:user)
|
|
topic = Fabricate(:topic)
|
|
_post = Fabricate(:post, user: user, topic: topic)
|
|
reply = Fabricate(:post, topic: topic, reply_to_post_number: 1)
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.post_created(reply)
|
|
end
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[user], reply])
|
|
end
|
|
|
|
it "notifies about regular reply" do
|
|
user = Fabricate(:user)
|
|
topic = Fabricate(:topic)
|
|
_post = Fabricate(:post, user: user, topic: topic)
|
|
|
|
reply = Fabricate(:post, topic: topic, reply_to_post_number: 1)
|
|
PostAlerter.post_created(reply)
|
|
|
|
expect(user.notifications.where(notification_type: Notification.types[:replied]).count).to eq(1)
|
|
end
|
|
|
|
it "doesn't notify regular user about whispered reply" do
|
|
user = Fabricate(:user)
|
|
admin = Fabricate(:admin)
|
|
|
|
topic = Fabricate(:topic)
|
|
_post = Fabricate(:post, user: user, topic: topic)
|
|
|
|
whispered_reply = Fabricate(:post, user: admin, topic: topic, post_type: Post.types[:whisper], reply_to_post_number: 1)
|
|
PostAlerter.post_created(whispered_reply)
|
|
|
|
expect(user.notifications.where(notification_type: Notification.types[:replied]).count).to eq(0)
|
|
end
|
|
|
|
it "notifies staff user about whispered reply" do
|
|
user = Fabricate(:user)
|
|
admin1 = Fabricate(:admin)
|
|
admin2 = Fabricate(:admin)
|
|
|
|
topic = Fabricate(:topic)
|
|
_post = Fabricate(:post, user: user, topic: topic)
|
|
|
|
whispered_reply1 = Fabricate(:post, user: admin1, topic: topic, post_type: Post.types[:whisper], reply_to_post_number: 1)
|
|
whispered_reply2 = Fabricate(:post, user: admin2, topic: topic, post_type: Post.types[:whisper], reply_to_post_number: 2)
|
|
PostAlerter.post_created(whispered_reply1)
|
|
PostAlerter.post_created(whispered_reply2)
|
|
|
|
expect(admin1.notifications.where(notification_type: Notification.types[:replied]).count).to eq(1)
|
|
|
|
TopicUser.change(admin1.id, topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
|
|
# this should change nothing cause the moderator post has an action code
|
|
# if we have an action code then we should never have notifications, this is rare but
|
|
# assign whispers are like this
|
|
whispered_reply3 = topic.add_moderator_post(admin2, "i am a reply", post_type: Post.types[:whisper], action_code: 'moderator_thing')
|
|
PostAlerter.post_created(whispered_reply3)
|
|
|
|
# if this whisper is not ignored like it should we would see a posted notification and no replied notifications
|
|
notifications = admin1.notifications.where(topic_id: topic.id).to_a
|
|
|
|
expect(notifications.first.notification_type).to eq(Notification.types[:replied])
|
|
expect(notifications.length).to eq(1)
|
|
expect(notifications.first.post_number).to eq(whispered_reply2.post_number)
|
|
end
|
|
|
|
it "sends email notifications only to users not on CC list of incoming email" do
|
|
alice = Fabricate(:user, username: "alice", email: "alice@example.com")
|
|
bob = Fabricate(:user, username: "bob", email: "bob@example.com")
|
|
carol = Fabricate(:user, username: "carol", email: "carol@example.com", staged: true)
|
|
dave = Fabricate(:user, username: "dave", email: "dave@example.com", staged: true)
|
|
erin = Fabricate(:user, username: "erin", email: "erin@example.com")
|
|
|
|
topic = Fabricate(:private_message_topic, topic_allowed_users: [
|
|
Fabricate.build(:topic_allowed_user, user: alice),
|
|
Fabricate.build(:topic_allowed_user, user: bob),
|
|
Fabricate.build(:topic_allowed_user, user: carol),
|
|
Fabricate.build(:topic_allowed_user, user: dave),
|
|
Fabricate.build(:topic_allowed_user, user: erin)
|
|
])
|
|
_post = Fabricate(:post, user: alice, topic: topic)
|
|
|
|
TopicUser.change(alice.id, topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
TopicUser.change(bob.id, topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
TopicUser.change(erin.id, topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
|
|
email = Fabricate(:incoming_email,
|
|
raw: <<~RAW,
|
|
Return-Path: <bob@example.com>
|
|
From: Bob <bob@example.com>
|
|
To: meta+1234@discoursemail.com, dave@example.com
|
|
CC: carol@example.com, erin@example.com
|
|
Subject: Hello world
|
|
Date: Fri, 15 Jan 2016 00:12:43 +0100
|
|
Message-ID: <12345@example.com>
|
|
Mime-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: quoted-printable
|
|
|
|
This post was created by email.
|
|
RAW
|
|
from_address: "bob@example.com",
|
|
to_addresses: "meta+1234@discoursemail.com;dave@example.com",
|
|
cc_addresses: "carol@example.com;erin@example.com")
|
|
reply = Fabricate(:post_via_email, user: bob, topic: topic, incoming_email: email, reply_to_post_number: 1)
|
|
|
|
NotificationEmailer.expects(:process_notification).with { |n| n.user_id == alice.id }.once
|
|
NotificationEmailer.expects(:process_notification).with { |n| n.user_id == bob.id }.never
|
|
NotificationEmailer.expects(:process_notification).with { |n| n.user_id == carol.id }.never
|
|
NotificationEmailer.expects(:process_notification).with { |n| n.user_id == dave.id }.never
|
|
NotificationEmailer.expects(:process_notification).with { |n| n.user_id == erin.id }.never
|
|
|
|
PostAlerter.post_created(reply)
|
|
|
|
expect(alice.notifications.count).to eq(1)
|
|
expect(bob.notifications.count).to eq(0)
|
|
expect(carol.notifications.count).to eq(1)
|
|
expect(dave.notifications.count).to eq(1)
|
|
expect(erin.notifications.count).to eq(1)
|
|
end
|
|
|
|
it "does not send email notifications to staged users when notification originates in mailinglist mirror category" do
|
|
category = Fabricate(:mailinglist_mirror_category)
|
|
topic = Fabricate(:topic, category: category)
|
|
user = Fabricate(:staged)
|
|
_post = Fabricate(:post, user: user, topic: topic)
|
|
reply = Fabricate(:post, topic: topic, reply_to_post_number: 1)
|
|
|
|
NotificationEmailer.expects(:process_notification).never
|
|
expect { PostAlerter.post_created(reply) }.to change(user.notifications, :count).by(0)
|
|
|
|
category.mailinglist_mirror = false
|
|
NotificationEmailer.expects(:process_notification).once
|
|
expect { PostAlerter.post_created(reply) }.to change(user.notifications, :count).by(1)
|
|
end
|
|
end
|
|
|
|
context "category" do
|
|
context "watching" do
|
|
it "triggers :before_create_notifications_for_users" do
|
|
user = Fabricate(:user)
|
|
category = Fabricate(:category)
|
|
topic = Fabricate(:topic, category: category)
|
|
post = Fabricate(:post, topic: topic)
|
|
level = CategoryUser.notification_levels[:watching]
|
|
CategoryUser.set_notification_level_for_category(user, level, category.id)
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.post_created(post)
|
|
end
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[user], post])
|
|
end
|
|
|
|
it "notifies staff about whispered post" do
|
|
category = Fabricate(:category)
|
|
topic = Fabricate(:topic, category: category)
|
|
admin = Fabricate(:admin)
|
|
user = Fabricate(:user)
|
|
level = CategoryUser.notification_levels[:watching]
|
|
CategoryUser.set_notification_level_for_category(admin, level, category.id)
|
|
CategoryUser.set_notification_level_for_category(user, level, category.id)
|
|
whispered_post = Fabricate(:post, user: Fabricate(:admin), topic: topic, post_type: Post.types[:whisper])
|
|
expect {
|
|
PostAlerter.post_created(whispered_post)
|
|
}.to add_notification(admin, :posted)
|
|
expect {
|
|
PostAlerter.post_created(whispered_post)
|
|
}.not_to add_notification(user, :posted)
|
|
end
|
|
|
|
it "notifies a staged user about a private post, but only if the user has access" do
|
|
staged_member = Fabricate(:staged)
|
|
staged_non_member = Fabricate(:staged)
|
|
group = Fabricate(:group)
|
|
group_member = Fabricate(:user)
|
|
|
|
group.add(group_member)
|
|
group.add(staged_member)
|
|
|
|
private_category = Fabricate(
|
|
:private_category, group: group,
|
|
email_in: 'test@test.com', email_in_allow_strangers: false
|
|
)
|
|
|
|
level = CategoryUser.notification_levels[:watching]
|
|
CategoryUser.set_notification_level_for_category(group_member, level, private_category.id)
|
|
CategoryUser.set_notification_level_for_category(staged_member, level, private_category.id)
|
|
CategoryUser.set_notification_level_for_category(staged_non_member, level, private_category.id)
|
|
|
|
topic = Fabricate(:topic, category: private_category, user: group_member)
|
|
post = Fabricate(:post, topic: topic)
|
|
|
|
expect {
|
|
PostAlerter.post_created(post)
|
|
}.to add_notification(staged_member, :posted)
|
|
.and not_add_notification(staged_non_member, :posted)
|
|
end
|
|
|
|
it "does not update existing unread notification" do
|
|
category = Fabricate(:category)
|
|
CategoryUser.set_notification_level_for_category(user, CategoryUser.notification_levels[:watching], category.id)
|
|
topic = Fabricate(:topic, category: category)
|
|
|
|
post = Fabricate(:post, topic: topic)
|
|
PostAlerter.post_created(post)
|
|
notification = Notification.last
|
|
expect(notification.topic_id).to eq(topic.id)
|
|
expect(notification.post_number).to eq(1)
|
|
|
|
post = Fabricate(:post, topic: topic)
|
|
PostAlerter.post_created(post)
|
|
notification = Notification.last
|
|
expect(notification.topic_id).to eq(topic.id)
|
|
expect(notification.post_number).to eq(1)
|
|
notification_data = JSON.parse(notification.data)
|
|
expect(notification_data["display_username"]).to eq(I18n.t("embed.replies", count: 2))
|
|
end
|
|
end
|
|
end
|
|
|
|
context "tags" do
|
|
context "watching" do
|
|
it "triggers :before_create_notifications_for_users" do
|
|
user = Fabricate(:user)
|
|
tag = Fabricate(:tag)
|
|
topic = Fabricate(:topic, tags: [tag])
|
|
post = Fabricate(:post, topic: topic)
|
|
level = TagUser.notification_levels[:watching]
|
|
TagUser.change(user.id, tag.id, level)
|
|
events = DiscourseEvent.track_events do
|
|
PostAlerter.post_created(post)
|
|
end
|
|
expect(events).to include(event_name: :before_create_notifications_for_users, params: [[user], post])
|
|
end
|
|
|
|
it "does not update existing unread notification" do
|
|
tag = Fabricate(:tag)
|
|
TagUser.change(user.id, tag.id, TagUser.notification_levels[:watching])
|
|
topic = Fabricate(:topic, tags: [tag])
|
|
|
|
post = Fabricate(:post, topic: topic)
|
|
PostAlerter.post_created(post)
|
|
notification = Notification.last
|
|
expect(notification.topic_id).to eq(topic.id)
|
|
expect(notification.post_number).to eq(1)
|
|
|
|
post = Fabricate(:post, topic: topic)
|
|
PostAlerter.post_created(post)
|
|
notification = Notification.last
|
|
expect(notification.topic_id).to eq(topic.id)
|
|
expect(notification.post_number).to eq(1)
|
|
notification_data = JSON.parse(notification.data)
|
|
expect(notification_data["display_username"]).to eq(I18n.t("embed.replies", count: 2))
|
|
end
|
|
end
|
|
|
|
context "on change" do
|
|
fab!(:user) { Fabricate(:user) }
|
|
fab!(:other_tag) { Fabricate(:tag) }
|
|
fab!(:watched_tag) { Fabricate(:tag) }
|
|
fab!(:post) { Fabricate(:post) }
|
|
|
|
before do
|
|
SiteSetting.tagging_enabled = true
|
|
Jobs.run_immediately!
|
|
TagUser.change(user.id, watched_tag.id, TagUser.notification_levels[:watching_first_post])
|
|
TopicUser.change(Fabricate(:user).id, post.topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
end
|
|
|
|
it "triggers a notification" do
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(0)
|
|
|
|
expect { PostRevisor.new(post).revise!(Fabricate(:user), tags: [other_tag.name, watched_tag.name]) }.to change { Notification.where(user_id: user.id).count }.by(1)
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(1)
|
|
|
|
expect { PostRevisor.new(post).revise!(Fabricate(:user), tags: [watched_tag.name, other_tag.name]) }.to change { Notification.count }.by(0)
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(1)
|
|
end
|
|
|
|
it "doesn't trigger a notification if topic is unlisted" do
|
|
post.topic.update_column(:visible, false)
|
|
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(0)
|
|
|
|
PostRevisor.new(post).revise!(Fabricate(:user), tags: [other_tag.name, watched_tag.name])
|
|
expect(user.notifications.where(notification_type: Notification.types[:watching_first_post]).count).to eq(0)
|
|
end
|
|
end
|
|
|
|
context "private message" do
|
|
fab!(:post) { Fabricate(:private_message_post) }
|
|
fab!(:other_tag) { Fabricate(:tag) }
|
|
fab!(:other_tag2) { Fabricate(:tag) }
|
|
fab!(:other_tag3) { Fabricate(:tag) }
|
|
fab!(:user) { Fabricate(:user) }
|
|
fab!(:staged) { Fabricate(:staged) }
|
|
fab!(:admin) { Fabricate(:admin) }
|
|
|
|
before do
|
|
SiteSetting.tagging_enabled = true
|
|
SiteSetting.allow_staff_to_tag_pms = true
|
|
Jobs.run_immediately!
|
|
TopicUser.change(user.id, post.topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
TopicUser.change(staged.id, post.topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
TopicUser.change(admin.id, post.topic.id, notification_level: TopicUser.notification_levels[:watching])
|
|
TagUser.change(staged.id, other_tag.id, TagUser.notification_levels[:watching])
|
|
TagUser.change(admin.id, other_tag3.id, TagUser.notification_levels[:watching])
|
|
post.topic.allowed_users << user
|
|
post.topic.allowed_users << staged
|
|
end
|
|
|
|
it "only notifies staff watching added tag" do
|
|
expect(PostRevisor.new(post).revise!(Fabricate(:admin), tags: [other_tag.name])).to be true
|
|
expect(Notification.where(user_id: staged.id).count).to eq(0)
|
|
expect(PostRevisor.new(post).revise!(Fabricate(:admin), tags: [other_tag2.name])).to be true
|
|
expect(Notification.where(user_id: admin.id).count).to eq(0)
|
|
expect(PostRevisor.new(post).revise!(Fabricate(:admin), tags: [other_tag3.name])).to be true
|
|
expect(Notification.where(user_id: admin.id).count).to eq(1)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe '#extract_linked_users' do
|
|
fab!(:topic) { Fabricate(:topic) }
|
|
fab!(:post) { Fabricate(:post, topic: topic) }
|
|
fab!(:post2) { Fabricate(:post) }
|
|
|
|
describe 'when linked post has been deleted' do
|
|
let(:topic_link) do
|
|
TopicLink.create!(
|
|
url: "/t/#{topic.id}",
|
|
topic_id: topic.id,
|
|
link_topic_id: post2.topic.id,
|
|
link_post_id: nil,
|
|
post_id: post.id,
|
|
user: user,
|
|
domain: 'test.com'
|
|
)
|
|
end
|
|
|
|
it 'should use the first post of the topic' do
|
|
topic_link
|
|
expect(PostAlerter.new.extract_linked_users(post.reload)).to eq([post2.user])
|
|
end
|
|
end
|
|
end
|
|
|
|
describe '#notify_post_users' do
|
|
fab!(:topic) { Fabricate(:topic) }
|
|
fab!(:post) { Fabricate(:post, topic: topic) }
|
|
fab!(:last_editor) { Fabricate(:user) }
|
|
fab!(:tag) { Fabricate(:tag) }
|
|
fab!(:category) { Fabricate(:category) }
|
|
|
|
it 'creates single edit notification when post is modified' do
|
|
TopicUser.create!(user_id: user.id, topic_id: topic.id, notification_level: TopicUser.notification_levels[:watching], highest_seen_post_number: post.post_number)
|
|
PostRevisor.new(post).revise!(last_editor, tags: [tag.name])
|
|
PostAlerter.new.notify_post_users(post, [])
|
|
expect(Notification.count).to eq(1)
|
|
expect(Notification.last.notification_type).to eq(Notification.types[:edited])
|
|
expect(JSON.parse(Notification.last.data)["display_username"]).to eq(last_editor.username)
|
|
|
|
PostAlerter.new.notify_post_users(post, [])
|
|
expect(Notification.count).to eq(1)
|
|
end
|
|
|
|
it 'creates posted notification when Sidekiq is slow' do
|
|
CategoryUser.set_notification_level_for_category(user, CategoryUser.notification_levels[:watching], category.id)
|
|
|
|
post = PostCreator.create!(
|
|
Fabricate(:user),
|
|
title: "one of my first topics",
|
|
raw: "one of my first posts",
|
|
category: category.id
|
|
)
|
|
|
|
TopicUser.change(user, post.topic_id, highest_seen_post_number: post.post_number)
|
|
|
|
# Manually run job after the user read the topic to simulate a slow
|
|
# Sidekiq.
|
|
job_args = Jobs::PostAlert.jobs[0]['args'][0]
|
|
expect { Jobs::PostAlert.new.execute(job_args.with_indifferent_access) }
|
|
.to change { Notification.count }.by(1)
|
|
|
|
expect(Notification.last.notification_type).to eq(Notification.types[:posted])
|
|
end
|
|
end
|
|
|
|
context "SMTP (group_smtp_email)" do
|
|
before do
|
|
SiteSetting.enable_smtp = true
|
|
SiteSetting.enable_imap = true
|
|
Jobs.run_immediately!
|
|
end
|
|
|
|
fab!(:group) do
|
|
Fabricate(
|
|
:group,
|
|
smtp_server: "smtp.gmail.com",
|
|
smtp_port: 587,
|
|
smtp_ssl: true,
|
|
imap_server: "imap.gmail.com",
|
|
imap_port: 993,
|
|
imap_ssl: true,
|
|
email_username: "discourse@example.com",
|
|
email_password: "password",
|
|
smtp_enabled: true,
|
|
imap_enabled: true
|
|
)
|
|
end
|
|
|
|
fab!(:topic) do
|
|
Fabricate(
|
|
:private_message_topic,
|
|
topic_allowed_groups: [
|
|
Fabricate.build(:topic_allowed_group, group: group)
|
|
]
|
|
)
|
|
end
|
|
|
|
def create_post_with_incoming
|
|
Fabricate(
|
|
:post,
|
|
topic: topic,
|
|
incoming_email:
|
|
Fabricate(
|
|
:incoming_email,
|
|
topic: topic,
|
|
from_address: "foo@discourse.org",
|
|
to_addresses: group.email_username,
|
|
cc_addresses: "bar@discourse.org"
|
|
)
|
|
)
|
|
end
|
|
|
|
it "does not send a group smtp email when the post already has an incoming email" do
|
|
post = create_post_with_incoming
|
|
|
|
expect { PostAlerter.new.after_save_post(post, true) }.to change { ActionMailer::Base.deliveries.size }.by(0)
|
|
end
|
|
|
|
it "sends a group smtp email when the post does not have an incoming email" do
|
|
create_post_with_incoming
|
|
post = Fabricate(:post, topic: topic)
|
|
expect { PostAlerter.new.after_save_post(post, true) }.to change { ActionMailer::Base.deliveries.size }.by(1)
|
|
email = ActionMailer::Base.deliveries.last
|
|
expect(email.from).to include(group.email_username)
|
|
expect(email.to).to contain_exactly("foo@discourse.org", "bar@discourse.org")
|
|
expect(email.subject).to eq("Re: #{topic.title}")
|
|
end
|
|
|
|
it "does not send a group smtp email if imap is not enabled for the group" do
|
|
group.update!(imap_enabled: false)
|
|
create_post_with_incoming
|
|
post = Fabricate(:post, topic: topic)
|
|
expect { PostAlerter.new.after_save_post(post, true) }.to change { ActionMailer::Base.deliveries.size }.by(0)
|
|
end
|
|
|
|
it "does not send a group smtp email if SiteSetting.enable_imap is false" do
|
|
SiteSetting.enable_imap = false
|
|
create_post_with_incoming
|
|
post = Fabricate(:post, topic: topic)
|
|
expect { PostAlerter.new.after_save_post(post, true) }.to change { ActionMailer::Base.deliveries.size }.by(0)
|
|
end
|
|
|
|
it "does not send a group smtp email if SiteSetting.enable_smtp is false" do
|
|
SiteSetting.enable_smtp = false
|
|
create_post_with_incoming
|
|
post = Fabricate(:post, topic: topic)
|
|
expect { PostAlerter.new.after_save_post(post, true) }.to change { ActionMailer::Base.deliveries.size }.by(0)
|
|
end
|
|
|
|
it "does not send group smtp emails for a whisper" do
|
|
create_post_with_incoming
|
|
post = Fabricate(:post, topic: topic, post_type: Post.types[:whisper])
|
|
expect { PostAlerter.new.after_save_post(post, true) }.to change { ActionMailer::Base.deliveries.size }.by(0)
|
|
end
|
|
|
|
it "does not send a notification email to the group when the post does not have an incoming email" do
|
|
PostAlerter.any_instance.expects(:create_notification).with(kind_of(User), Notification.types[:private_message], kind_of(Post), skip_send_email_to: ["discourse@example.com"]).at_least_once
|
|
post = create_post_with_incoming
|
|
staged_group_user = Fabricate(:staged, email: "discourse@example.com")
|
|
Fabricate(:topic_user, user: staged_group_user, topic: post.topic)
|
|
topic.allowed_users << staged_group_user
|
|
topic.save
|
|
expect { PostAlerter.new.after_save_post(post, true) }.to change { ActionMailer::Base.deliveries.size }.by(0)
|
|
end
|
|
|
|
it "skips sending a notification email to the group and all other incoming email addresses" do
|
|
|
|
create_post_with_incoming
|
|
PostAlerter.any_instance.expects(:create_notification).with(kind_of(User), Notification.types[:private_message], kind_of(Post), skip_send_email_to: ["foo@discourse.org", "bar@discourse.org", "discourse@example.com"]).at_least_once
|
|
|
|
post = Fabricate(:post, topic: topic.reload)
|
|
staged_group_user = Fabricate(:staged, email: "discourse@example.com")
|
|
Fabricate(:topic_user, user: staged_group_user, topic: post.topic)
|
|
topic.allowed_users << staged_group_user
|
|
topic.save
|
|
|
|
expect { PostAlerter.new.after_save_post(post, true) }.to change { ActionMailer::Base.deliveries.size }.by(1)
|
|
email = ActionMailer::Base.deliveries.last
|
|
expect(email.from).to eq([group.email_username])
|
|
expect(email.to).to contain_exactly("foo@discourse.org", "bar@discourse.org")
|
|
expect(email.subject).to eq("Re: #{topic.title}")
|
|
end
|
|
end
|
|
end
|