mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 10:24:49 +08:00
6e161d3e75
The most common thing that we do with fab! is: fab!(:thing) { Fabricate(:thing) } This commit adds a shorthand for this which is just simply: fab!(:thing) i.e. If you omit the block, then, by default, you'll get a `Fabricate`d object using the fabricator of the same name.
1506 lines
50 KiB
Ruby
1506 lines
50 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe UserNotifications do
|
|
let(:user) { Fabricate(:admin) }
|
|
|
|
describe "#get_context_posts" do
|
|
it "does not include hidden/deleted/user_deleted posts in context" do
|
|
post1 = create_post
|
|
_post2 = Fabricate(:post, topic: post1.topic, deleted_at: 1.day.ago)
|
|
_post3 = Fabricate(:post, topic: post1.topic, user_deleted: true)
|
|
_post4 = Fabricate(:post, topic: post1.topic, hidden: true)
|
|
_post5 = Fabricate(:post, topic: post1.topic, post_type: Post.types[:moderator_action])
|
|
_post6 = Fabricate(:post, topic: post1.topic, post_type: Post.types[:small_action])
|
|
_post7 = Fabricate(:post, topic: post1.topic, post_type: Post.types[:whisper])
|
|
last = Fabricate(:post, topic: post1.topic)
|
|
|
|
post1.user.user_option.email_previous_replies = UserOption.previous_replies_type[:always]
|
|
|
|
# default is only post #1
|
|
expect(UserNotifications.get_context_posts(last, nil, post1.user).count).to eq(1)
|
|
# staff members can also see the whisper
|
|
moderator = build(:moderator)
|
|
moderator.user_option = UserOption.new
|
|
moderator.user_option.email_previous_replies = UserOption.previous_replies_type[:always]
|
|
tu = TopicUser.new(topic: post1.topic, user: moderator)
|
|
expect(UserNotifications.get_context_posts(last, tu, tu.user).count).to eq(2)
|
|
end
|
|
|
|
it "allows users to control context" do
|
|
post1 = create_post
|
|
_post2 = Fabricate(:post, topic: post1.topic)
|
|
post3 = Fabricate(:post, topic: post1.topic)
|
|
|
|
user = Fabricate(:user)
|
|
TopicUser.change(user.id, post1.topic_id, last_emailed_post_number: 1)
|
|
topic_user = TopicUser.find_by(user_id: user.id, topic_id: post1.topic_id)
|
|
# to avoid reloads after update_columns
|
|
user = topic_user.user
|
|
user.user_option.update_columns(
|
|
email_previous_replies: UserOption.previous_replies_type[:unless_emailed],
|
|
)
|
|
|
|
expect(UserNotifications.get_context_posts(post3, topic_user, user).count).to eq(1)
|
|
|
|
user.user_option.update_columns(
|
|
email_previous_replies: UserOption.previous_replies_type[:never],
|
|
)
|
|
expect(UserNotifications.get_context_posts(post3, topic_user, user).count).to eq(0)
|
|
|
|
user.user_option.update_columns(
|
|
email_previous_replies: UserOption.previous_replies_type[:always],
|
|
)
|
|
expect(UserNotifications.get_context_posts(post3, topic_user, user).count).to eq(2)
|
|
|
|
SiteSetting.private_email = true
|
|
expect(UserNotifications.get_context_posts(post3, topic_user, user).count).to eq(0)
|
|
end
|
|
end
|
|
|
|
describe ".signup" do
|
|
subject(:email) { UserNotifications.signup(user) }
|
|
|
|
it "works" do
|
|
expect(email.to).to eq([user.email])
|
|
expect(email.subject).to be_present
|
|
expect(email.from).to eq([SiteSetting.notification_email])
|
|
expect(email.body).to be_present
|
|
end
|
|
end
|
|
|
|
describe ".forgot_password" do
|
|
subject(:email) { UserNotifications.forgot_password(user) }
|
|
|
|
it "works" do
|
|
expect(email.to).to eq([user.email])
|
|
expect(email.subject).to be_present
|
|
expect(email.from).to eq([SiteSetting.notification_email])
|
|
expect(email.body).to be_present
|
|
end
|
|
end
|
|
|
|
describe ".post_approved" do
|
|
fab!(:post)
|
|
|
|
it "works" do
|
|
subject =
|
|
UserNotifications.post_approved(user, { notification_data_hash: { post_url: post.url } })
|
|
|
|
expect(subject.to).to eq([user.email])
|
|
expect(subject.subject).to be_present
|
|
expect(subject.from).to eq([SiteSetting.notification_email])
|
|
expect(subject.body).to be_present
|
|
end
|
|
end
|
|
|
|
describe ".confirm_new_email" do
|
|
let(:opts) { { requested_by_admin: requested_by_admin, email_token: token } }
|
|
let(:token) { "test123" }
|
|
|
|
context "when requested by admin" do
|
|
let(:requested_by_admin) { true }
|
|
|
|
it "uses the requested by admin template" do
|
|
expect(UserNotifications.confirm_new_email(user, opts).body).to include(
|
|
"This email change was requested by a site admin.",
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when not requested by admin" do
|
|
let(:requested_by_admin) { false }
|
|
|
|
it "uses the normal template" do
|
|
expect(UserNotifications.confirm_new_email(user, opts).body).not_to include(
|
|
"This email change was requested by a site admin.",
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe ".email_login" do
|
|
subject(:email) { UserNotifications.email_login(user, email_token: email_token) }
|
|
|
|
let(:email_token) do
|
|
Fabricate(:email_token, user: user, scope: EmailToken.scopes[:email_login]).token
|
|
end
|
|
|
|
it "generates the right email" do
|
|
expect(email.to).to eq([user.email])
|
|
expect(email.from).to eq([SiteSetting.notification_email])
|
|
|
|
expect(email.subject).to eq(
|
|
I18n.t("user_notifications.email_login.subject_template", email_prefix: SiteSetting.title),
|
|
)
|
|
|
|
expect(email.body.to_s).to match(
|
|
I18n.t(
|
|
"user_notifications.email_login.text_body_template",
|
|
site_name: SiteSetting.title,
|
|
base_url: Discourse.base_url,
|
|
email_token: email_token,
|
|
),
|
|
)
|
|
end
|
|
end
|
|
|
|
describe ".digest" do
|
|
subject(:email) { UserNotifications.digest(user) }
|
|
|
|
after { Discourse.redis.keys("summary-new-users:*").each { |key| Discourse.redis.del(key) } }
|
|
|
|
context "without new topics" do
|
|
it "doesn't send the email" do
|
|
expect(email.to).to be_blank
|
|
end
|
|
end
|
|
|
|
context "with topics only from new users" do
|
|
let!(:new_today) do
|
|
Fabricate(
|
|
:topic,
|
|
user: Fabricate(:user, trust_level: TrustLevel[0], created_at: 10.minutes.ago),
|
|
title: "Hey everyone look at me",
|
|
)
|
|
end
|
|
let!(:new_yesterday) do
|
|
Fabricate(
|
|
:topic,
|
|
user: Fabricate(:user, trust_level: TrustLevel[0], created_at: 25.hours.ago),
|
|
created_at: 25.hours.ago,
|
|
title: "This topic is of interest to you",
|
|
)
|
|
end
|
|
|
|
it "returns topics from new users if they're more than 24 hours old" do
|
|
expect(email.to).to eq([user.email])
|
|
html = email.html_part.body.to_s
|
|
expect(html).to include(new_yesterday.title)
|
|
expect(html).to_not include(new_today.title)
|
|
end
|
|
end
|
|
|
|
context "with new topics" do
|
|
let!(:popular_topic) do
|
|
Fabricate(:topic, user: Fabricate(:coding_horror), created_at: 1.hour.ago)
|
|
end
|
|
|
|
it "works" do
|
|
expect(email.to).to eq([user.email])
|
|
expect(email.subject).to be_present
|
|
expect(email.from).to eq([SiteSetting.notification_email])
|
|
expect(email.html_part.body.to_s).to be_present
|
|
expect(email.text_part.body.to_s).to be_present
|
|
expect(email.header["List-Unsubscribe"].to_s).to match(/\/email\/unsubscribe\/\h{64}/)
|
|
expect(email.html_part.body.to_s).to include("New Users")
|
|
end
|
|
|
|
it "doesn't include new user count if digest_after_minutes is low" do
|
|
user.user_option.digest_after_minutes = 60
|
|
expect(email.html_part.body.to_s).to_not include("New Users")
|
|
end
|
|
|
|
it "works with min_date string" do
|
|
digest = UserNotifications.digest(user, since: 1.month.ago.to_date.to_s)
|
|
expect(digest.html_part.body.to_s).to be_present
|
|
expect(digest.text_part.body.to_s).to be_present
|
|
expect(digest.html_part.body.to_s).to include("New Users")
|
|
end
|
|
|
|
it "includes email_prefix in email subject instead of site title" do
|
|
SiteSetting.email_prefix = "Try Discourse"
|
|
SiteSetting.title = "Discourse Meta"
|
|
|
|
expect(email.subject).to match(/Try Discourse/)
|
|
expect(email.subject).not_to match(/Discourse Meta/)
|
|
end
|
|
|
|
it "includes unread likes received count within the since date" do
|
|
Fabricate(
|
|
:notification,
|
|
user: user,
|
|
notification_type: Notification.types[:liked],
|
|
created_at: 2.months.ago,
|
|
)
|
|
Fabricate(
|
|
:notification,
|
|
user: user,
|
|
notification_type: Notification.types[:liked],
|
|
read: true,
|
|
)
|
|
Fabricate(:notification, user: user, notification_type: Notification.types[:liked])
|
|
Fabricate(:notification, user: user, notification_type: Notification.types[:liked])
|
|
digest = UserNotifications.digest(user, since: 1.month.ago.to_date.to_s)
|
|
parsed_html = Nokogiri::HTML5.fragment(digest.html_part.body.to_s)
|
|
expect(parsed_html.css(".header-stat-count #likes_received_stat_count strong").text).to eq(
|
|
"2",
|
|
)
|
|
expect(
|
|
parsed_html.css(".header-stat-description #likes_received_stat_description strong").text,
|
|
).to eq("Likes Received")
|
|
end
|
|
|
|
it "excludes deleted topics and their posts" do
|
|
deleted =
|
|
Fabricate(
|
|
:topic,
|
|
user: Fabricate(:user),
|
|
title: "Delete this topic plz",
|
|
created_at: 1.hour.ago,
|
|
)
|
|
post =
|
|
Fabricate(
|
|
:post,
|
|
topic: deleted,
|
|
score: 100.0,
|
|
post_number: 2,
|
|
raw: "Your wish is my command",
|
|
created_at: 1.hour.ago,
|
|
)
|
|
deleted.trash!
|
|
html = email.html_part.body.to_s
|
|
expect(html).to_not include deleted.title
|
|
expect(html).to_not include post.raw
|
|
end
|
|
|
|
it "excludes shared drafts" do
|
|
cat = Fabricate(:category)
|
|
SiteSetting.shared_drafts_category = cat.id
|
|
topic =
|
|
Fabricate(:topic, title: "This is a draft", category_id: cat.id, created_at: 1.hour.ago)
|
|
post =
|
|
Fabricate(
|
|
:post,
|
|
topic: topic,
|
|
score: 100.0,
|
|
post_number: 2,
|
|
raw: "secret draft content",
|
|
created_at: 1.hour.ago,
|
|
)
|
|
html = email.html_part.body.to_s
|
|
expect(html).to_not include topic.title
|
|
expect(html).to_not include post.raw
|
|
end
|
|
|
|
it "excludes whispers and other post types that don't belong" do
|
|
t =
|
|
Fabricate(
|
|
:topic,
|
|
user: Fabricate(:user),
|
|
title: "Who likes the same stuff I like?",
|
|
created_at: 1.hour.ago,
|
|
)
|
|
whisper =
|
|
Fabricate(
|
|
:post,
|
|
topic: t,
|
|
score: 100.0,
|
|
post_number: 2,
|
|
raw: "You like weird stuff",
|
|
post_type: Post.types[:whisper],
|
|
created_at: 1.hour.ago,
|
|
)
|
|
mod_action =
|
|
Fabricate(
|
|
:post,
|
|
topic: t,
|
|
score: 100.0,
|
|
post_number: 3,
|
|
raw: "This topic unlisted",
|
|
post_type: Post.types[:moderator_action],
|
|
created_at: 1.hour.ago,
|
|
)
|
|
small_action =
|
|
Fabricate(
|
|
:post,
|
|
topic: t,
|
|
score: 100.0,
|
|
post_number: 4,
|
|
raw: "A small action",
|
|
post_type: Post.types[:small_action],
|
|
created_at: 1.hour.ago,
|
|
)
|
|
html = email.html_part.body.to_s
|
|
expect(html).to_not include whisper.raw
|
|
expect(html).to_not include mod_action.raw
|
|
expect(html).to_not include small_action.raw
|
|
end
|
|
|
|
it "excludes deleted and hidden posts" do
|
|
t =
|
|
Fabricate(
|
|
:topic,
|
|
user: Fabricate(:user),
|
|
title: "Post objectionable stuff here",
|
|
created_at: 1.hour.ago,
|
|
)
|
|
deleted =
|
|
Fabricate(
|
|
:post,
|
|
topic: t,
|
|
score: 100.0,
|
|
post_number: 2,
|
|
raw: "This post is uncalled for",
|
|
deleted_at: 5.minutes.ago,
|
|
created_at: 1.hour.ago,
|
|
)
|
|
hidden =
|
|
Fabricate(
|
|
:post,
|
|
topic: t,
|
|
score: 100.0,
|
|
post_number: 3,
|
|
raw: "Try to find this post",
|
|
hidden: true,
|
|
hidden_at: 5.minutes.ago,
|
|
hidden_reason_id: Post.hidden_reasons[:flagged_by_tl3_user],
|
|
created_at: 1.hour.ago,
|
|
)
|
|
user_deleted =
|
|
Fabricate(
|
|
:post,
|
|
topic: t,
|
|
score: 100.0,
|
|
post_number: 4,
|
|
raw: "I regret this post",
|
|
user_deleted: true,
|
|
created_at: 1.hour.ago,
|
|
)
|
|
html = email.html_part.body.to_s
|
|
expect(html).to_not include deleted.raw
|
|
expect(html).to_not include hidden.raw
|
|
expect(html).to_not include user_deleted.raw
|
|
end
|
|
|
|
it "excludes posts that are newer than editing grace period" do
|
|
SiteSetting.editing_grace_period = 5.minutes
|
|
too_new =
|
|
Fabricate(
|
|
:topic,
|
|
user: Fabricate(:user),
|
|
title: "Oops I need to edit this",
|
|
created_at: 1.minute.ago,
|
|
)
|
|
_too_new_post =
|
|
Fabricate(
|
|
:post,
|
|
user: too_new.user,
|
|
topic: too_new,
|
|
score: 100.0,
|
|
post_number: 1,
|
|
created_at: 1.minute.ago,
|
|
)
|
|
html = email.html_part.body.to_s
|
|
expect(html).to_not include too_new.title
|
|
end
|
|
|
|
it "uses theme color" do
|
|
cs =
|
|
Fabricate(
|
|
:color_scheme,
|
|
name: "Fancy",
|
|
color_scheme_colors: [
|
|
Fabricate(:color_scheme_color, name: "header_primary", hex: "F0F0F0"),
|
|
Fabricate(:color_scheme_color, name: "header_background", hex: "1E1E1E"),
|
|
],
|
|
)
|
|
theme =
|
|
Fabricate(:theme, user_selectable: true, user: Fabricate(:admin), color_scheme_id: cs.id)
|
|
|
|
theme.set_default!
|
|
|
|
html = email.html_part.body.to_s
|
|
expect(html).to include "F0F0F0"
|
|
expect(html).to include "1E1E1E"
|
|
end
|
|
|
|
it "supports subfolder" do
|
|
set_subfolder "/forum"
|
|
html = email.html_part.body.to_s
|
|
text = email.text_part.body.to_s
|
|
expect(html).to be_present
|
|
expect(text).to be_present
|
|
expect(html).to_not include("/forum/forum")
|
|
expect(text).to_not include("/forum/forum")
|
|
expect(email.header["List-Unsubscribe"].to_s).to match(
|
|
/http:\/\/test.localhost\/forum\/email\/unsubscribe\/\h{64}/,
|
|
)
|
|
|
|
topic_url = "http://test.localhost/forum/t/#{popular_topic.slug}/#{popular_topic.id}"
|
|
expect(html).to include(topic_url)
|
|
expect(text).to include(topic_url)
|
|
end
|
|
|
|
it "applies lang/xml:lang html attributes" do
|
|
SiteSetting.default_locale = "pl_PL"
|
|
html = email.html_part.to_s
|
|
|
|
expect(html).to match(' lang="pl-PL"')
|
|
expect(html).to match(' xml:lang="pl-PL"')
|
|
end
|
|
end
|
|
end
|
|
|
|
describe ".user_replied" do
|
|
let(:response_by_user) { Fabricate(:user, name: "John Doe") }
|
|
let(:category) { Fabricate(:category, name: "India") }
|
|
let(:tag1) { Fabricate(:tag, name: "Taggo", public_topic_count: 1) }
|
|
let(:tag2) { Fabricate(:tag, name: "Taggie", public_topic_count: 3) }
|
|
let(:tag3) { Fabricate(:tag, name: "Teggo", public_topic_count: 2) }
|
|
|
|
let(:hidden_tag) { Fabricate(:tag, name: "hidden") }
|
|
let!(:hidden_tag_group) do
|
|
Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: [hidden_tag.name])
|
|
end
|
|
|
|
let(:topic) do
|
|
Fabricate(
|
|
:topic,
|
|
category: category,
|
|
tags: [tag1, tag2, tag3, hidden_tag],
|
|
title: "Super cool topic",
|
|
)
|
|
end
|
|
let(:post) { Fabricate(:post, topic: topic, raw: "This is My super duper cool topic") }
|
|
let(:response) { Fabricate(:basic_reply, topic: post.topic, user: response_by_user) }
|
|
let(:user) { Fabricate(:user) }
|
|
let(:notification) { Fabricate(:replied_notification, user: user, post: response) }
|
|
|
|
it "generates a correct email" do
|
|
SiteSetting.default_email_in_reply_to = true
|
|
|
|
# Fabricator is not fabricating this ...
|
|
SiteSetting.email_subject =
|
|
"[%{site_name}] %{optional_pm}%{optional_cat}%{optional_tags}%{topic_title}"
|
|
SiteSetting.enable_names = true
|
|
SiteSetting.display_name_on_posts = true
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
# from should include full user name
|
|
expect(mail[:from].display_names).to eql(["John Doe via Discourse"])
|
|
|
|
# subject should include category name
|
|
expect(mail.subject).to match(/India/)
|
|
|
|
# subject should include tag names
|
|
expect(mail.subject).to match(/Taggo/)
|
|
expect(mail.subject).to match(/Taggie/)
|
|
|
|
mail_html = mail.html_part.body.to_s
|
|
|
|
expect(mail_html.scan(/My super duper cool topic/).count).to eq(1)
|
|
expect(mail_html.scan(/In Reply To/).count).to eq(1)
|
|
|
|
# 2 "visit topic" link
|
|
expect(mail_html.scan(/Visit Topic/).count).to eq(2)
|
|
|
|
# 2 respond to links cause we have 1 context post
|
|
expect(mail_html.scan(/to respond/).count).to eq(2)
|
|
|
|
# 1 unsubscribe
|
|
expect(mail_html.scan(/To unsubscribe/).count).to eq(1)
|
|
|
|
# side effect, topic user is updated with post number
|
|
tu = TopicUser.get(post.topic_id, user)
|
|
expect(tu.last_emailed_post_number).to eq(response.post_number)
|
|
|
|
# no In Reply To if user opts out
|
|
user.user_option.email_in_reply_to = false
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
expect(mail.html_part.body.to_s.scan(/In Reply To/).count).to eq(0)
|
|
|
|
SiteSetting.enable_names = true
|
|
SiteSetting.display_name_on_posts = true
|
|
SiteSetting.prioritize_username_in_ux = false
|
|
|
|
response.user.username = "bobmarley"
|
|
response.user.name = "Bob Marley"
|
|
response.user.save
|
|
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
mail_html = mail.html_part.body.to_s
|
|
expect(mail_html.scan(/>Bob Marley/).count).to eq(1)
|
|
expect(mail_html.scan(/>bobmarley/).count).to eq(0)
|
|
|
|
expect(mail.subject.scan(/#{tag1.name}/).count).to eq(1)
|
|
expect(mail.subject.scan(/#{hidden_tag.name}/).count).to eq(0)
|
|
|
|
SiteSetting.prioritize_username_in_ux = true
|
|
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
mail_html = mail.html_part.body.to_s
|
|
expect(mail_html.scan(/>Bob Marley/).count).to eq(0)
|
|
expect(mail_html.scan(/>bobmarley/).count).to eq(1)
|
|
end
|
|
|
|
describe "number of tags shown in subject line" do
|
|
describe "max_tags_per_email_subject siteSetting enabled" do
|
|
before { SiteSetting.enable_max_tags_per_email_subject = true }
|
|
|
|
it "should match max_tags_per_email_subject" do
|
|
SiteSetting.email_subject =
|
|
"[%{site_name}] %{optional_pm}%{optional_cat}%{optional_tags}%{topic_title}"
|
|
SiteSetting.max_tags_per_topic = 1
|
|
SiteSetting.max_tags_per_email_subject = 2
|
|
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
expect(mail.subject).to eq(
|
|
"[Discourse] [#{category.name}] #{tag2.name} #{tag3.name} #{topic.title}",
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "max_tags_per_email_subject siteSetting disabled" do
|
|
before { SiteSetting.enable_max_tags_per_email_subject = false }
|
|
|
|
it "should match max_tags_per_topic" do
|
|
SiteSetting.email_subject =
|
|
"[%{site_name}] %{optional_pm}%{optional_cat}%{optional_tags}%{topic_title}"
|
|
SiteSetting.max_tags_per_topic = 2
|
|
SiteSetting.max_tags_per_email_subject = 1
|
|
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
expect(mail.subject).to eq(
|
|
"[Discourse] [#{category.name}] #{tag2.name} #{tag3.name} #{topic.title}",
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
it "doesn't include details when private_email is enabled" do
|
|
SiteSetting.private_email = true
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
expect(mail.html_part.body.to_s).to_not include(response.raw)
|
|
expect(mail.html_part.body.to_s).to_not include(topic.url)
|
|
expect(mail.text_part.to_s).to_not include(response.raw)
|
|
expect(mail.text_part.to_s).to_not include(topic.url)
|
|
end
|
|
|
|
it "includes excerpt when post_excerpts_in_emails is enabled" do
|
|
paragraphs = [
|
|
"This is the first paragraph, but you should read more.",
|
|
"And here is its friend, the second paragraph.",
|
|
]
|
|
SiteSetting.post_excerpts_in_emails = true
|
|
SiteSetting.post_excerpt_maxlength = paragraphs.first.length
|
|
response.update!(raw: paragraphs.join("\n\n"))
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
mail_html = mail.html_part.body.to_s
|
|
expect(mail_html.scan(/#{paragraphs[0]}/).count).to eq(1)
|
|
expect(mail_html.scan(/#{paragraphs[1]}/).count).to eq(0)
|
|
end
|
|
end
|
|
|
|
describe ".user_posted" do
|
|
let(:response_by_user) { Fabricate(:user, name: "John Doe", username: "john") }
|
|
let(:topic) { Fabricate(:topic, title: "Super cool topic") }
|
|
let(:post) { Fabricate(:post, topic: topic) }
|
|
let(:response) { Fabricate(:post, topic: topic, user: response_by_user) }
|
|
let(:user) { Fabricate(:user) }
|
|
let(:notification) { Fabricate(:posted_notification, user: user, post: response) }
|
|
|
|
it "generates a correct email" do
|
|
SiteSetting.enable_names = false
|
|
mail =
|
|
UserNotifications.user_posted(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
# from should not include full user name if "show user full names" is disabled
|
|
expect(mail[:from].display_names).to_not eql(["John Doe"])
|
|
|
|
# from should include username if "show user full names" is disabled
|
|
expect(mail[:from].display_names).to eql(["john via Discourse"])
|
|
|
|
# subject should not include category name
|
|
expect(mail.subject).not_to match(/Uncategorized/)
|
|
|
|
# 1 respond to links as no context by default
|
|
expect(mail.html_part.body.to_s.scan(/to respond/).count).to eq(1)
|
|
|
|
# 1 unsubscribe link
|
|
expect(mail.html_part.body.to_s.scan(/To unsubscribe/).count).to eq(1)
|
|
|
|
# side effect, topic user is updated with post number
|
|
tu = TopicUser.get(post.topic_id, user)
|
|
expect(tu.last_emailed_post_number).to eq(response.post_number)
|
|
end
|
|
|
|
it "doesn't include details when private_email is enabled" do
|
|
SiteSetting.private_email = true
|
|
mail =
|
|
UserNotifications.user_posted(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
expect(mail.html_part.body.to_s).to_not include(response.raw)
|
|
expect(mail.text_part.to_s).to_not include(response.raw)
|
|
end
|
|
|
|
it "uses the original subject for staged users" do
|
|
incoming_email =
|
|
Fabricate(
|
|
:incoming_email,
|
|
subject: "Original Subject",
|
|
post: post,
|
|
topic: post.topic,
|
|
user: user,
|
|
)
|
|
|
|
mail =
|
|
UserNotifications.user_posted(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
expect(mail.subject).to match(/Super cool topic/)
|
|
|
|
user.update!(staged: true)
|
|
mail =
|
|
UserNotifications.user_posted(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
expect(mail.subject).to eq("Re: Original Subject")
|
|
|
|
another_post = Fabricate(:post, topic: topic)
|
|
incoming_email.update!(post_id: another_post.id)
|
|
|
|
mail =
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
expect(mail.subject).to match(/Super cool topic/)
|
|
end
|
|
end
|
|
|
|
describe ".user_private_message" do
|
|
let(:response_by_user) { Fabricate(:user, name: "", username: "john") }
|
|
let(:topic) { Fabricate(:private_message_topic, title: "Super cool topic") }
|
|
let(:post) { Fabricate(:post, topic: topic) }
|
|
let(:response) { Fabricate(:post, topic: topic, user: response_by_user) }
|
|
let(:user) { Fabricate(:user) }
|
|
let(:notification) { Fabricate(:private_message_notification, user: user, post: response) }
|
|
|
|
it "generates a correct email" do
|
|
SiteSetting.enable_names = true
|
|
mail =
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
# from should include username if full user name is not provided
|
|
expect(mail[:from].display_names).to eql(["john via Discourse"])
|
|
|
|
# subject should include "[PM]"
|
|
expect(mail.subject).to include("[PM] ")
|
|
|
|
# 1 "visit message" link
|
|
expect(mail.html_part.body.to_s.scan(/Visit Message/).count).to eq(1)
|
|
|
|
# 1 respond to link
|
|
expect(mail.html_part.body.to_s.scan(/to respond/).count).to eq(1)
|
|
|
|
# 1 unsubscribe link
|
|
expect(mail.html_part.body.to_s.scan(/To unsubscribe/).count).to eq(1)
|
|
|
|
# side effect, topic user is updated with post number
|
|
tu = TopicUser.get(topic.id, user)
|
|
expect(tu.last_emailed_post_number).to eq(response.post_number)
|
|
end
|
|
|
|
it "doesn't include details when private_email is enabled" do
|
|
SiteSetting.private_email = true
|
|
mail =
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
expect(mail.html_part.body.to_s).to_not include(response.raw)
|
|
expect(mail.html_part.body.to_s).to_not include(topic.url)
|
|
expect(mail.text_part.to_s).to_not include(response.raw)
|
|
expect(mail.text_part.to_s).to_not include(topic.url)
|
|
end
|
|
|
|
it "doesn't include group name in subject" do
|
|
group = Fabricate(:group)
|
|
topic.allowed_groups = [group]
|
|
mail =
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
expect(mail.subject).to include("[PM] ")
|
|
end
|
|
|
|
it "includes a list of participants (except for the destination user), groups first with member lists" do
|
|
group1 = Fabricate(:group, name: "group1")
|
|
group2 = Fabricate(:group, name: "group2")
|
|
|
|
user1 = Fabricate(:user, username: "one", groups: [group1, group2])
|
|
user2 = Fabricate(:user, username: "two", groups: [group1], staged: true)
|
|
|
|
topic.allowed_users = [user, user1, user2]
|
|
topic.allowed_groups = [group1, group2]
|
|
|
|
mail =
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
expect(mail.body).to include(
|
|
"[group1 (2)](http://test.localhost/g/group1), [group2 (1)](http://test.localhost/g/group2), [one](http://test.localhost/u/one), [two](http://test.localhost/u/two)",
|
|
)
|
|
end
|
|
|
|
context "when SiteSetting.group_name_in_subject is true" do
|
|
before { SiteSetting.group_in_subject = true }
|
|
|
|
let(:group) { Fabricate(:group, name: "my_group") }
|
|
let(:mail) do
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
end
|
|
|
|
shared_examples "includes first group name" do
|
|
it "includes first group name in subject" do
|
|
expect(mail.subject).to include("[my_group] ")
|
|
end
|
|
|
|
context "when first group has full name" do
|
|
it "includes full name in subject" do
|
|
group.full_name = "My Group"
|
|
group.save
|
|
expect(mail.subject).to include("[My Group] ")
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with one group in pm" do
|
|
before { topic.allowed_groups = [group] }
|
|
|
|
include_examples "includes first group name"
|
|
end
|
|
|
|
context "with multiple groups in pm" do
|
|
let(:group2) { Fabricate(:group) }
|
|
|
|
before { topic.allowed_groups = [group, group2] }
|
|
|
|
include_examples "includes first group name"
|
|
end
|
|
|
|
context "with no groups in pm" do
|
|
it "includes %{optional_pm} in subject" do
|
|
expect(mail.subject).to include("[PM] ")
|
|
end
|
|
end
|
|
end
|
|
|
|
it "uses the original subject for staged users when topic was started via email" do
|
|
incoming_email =
|
|
Fabricate(
|
|
:incoming_email,
|
|
subject: "Original Subject",
|
|
post: post,
|
|
topic: topic,
|
|
user: user,
|
|
)
|
|
|
|
mail =
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
expect(mail.subject).to match(/Super cool topic/)
|
|
|
|
user.update!(staged: true)
|
|
mail =
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
expect(mail.subject).to eq("Re: Original Subject")
|
|
|
|
another_post = Fabricate(:post, topic: topic)
|
|
incoming_email.update!(post_id: another_post.id)
|
|
|
|
mail =
|
|
UserNotifications.user_private_message(
|
|
user,
|
|
post: response,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
expect(mail.subject).to match(/Super cool topic/)
|
|
end
|
|
end
|
|
|
|
it "adds a warning when mail limit is reached" do
|
|
SiteSetting.max_emails_per_day_per_user = 2
|
|
user = Fabricate(:user)
|
|
|
|
user.email_logs.create!(email_type: "blah", to_address: user.email, user_id: user.id)
|
|
|
|
post = Fabricate(:post)
|
|
reply = Fabricate(:post, topic_id: post.topic_id)
|
|
|
|
notification =
|
|
Fabricate(
|
|
:notification,
|
|
topic_id: post.topic_id,
|
|
post_number: reply.post_number,
|
|
user: post.user,
|
|
data: { original_username: "bob" }.to_json,
|
|
)
|
|
|
|
mail =
|
|
UserNotifications.user_replied(
|
|
user,
|
|
post: reply,
|
|
notification_type: notification.notification_type,
|
|
notification_data_hash: notification.data_hash,
|
|
)
|
|
|
|
# WARNING: you reached the limit of 100 email notifications per day. Further emails will be suppressed.
|
|
# Consider watching less topics or disabling mailing list mode.
|
|
expect(mail.html_part.body.to_s).to match(I18n.t("user_notifications.reached_limit", count: 2))
|
|
expect(mail.body.to_s).to match(I18n.t("user_notifications.reached_limit", count: 2))
|
|
end
|
|
|
|
def expects_build_with(condition)
|
|
UserNotifications.any_instance.expects(:build_email).with(user.email, condition)
|
|
mailer =
|
|
UserNotifications.public_send(
|
|
mail_type,
|
|
user,
|
|
notification_type: Notification.types[notification.notification_type],
|
|
notification_data_hash: notification.data_hash,
|
|
post: notification.post,
|
|
)
|
|
|
|
mailer.message
|
|
end
|
|
|
|
shared_examples "supports reply by email" do
|
|
context "with reply_by_email" do
|
|
it "should have allow_reply_by_email set when that feature is enabled" do
|
|
expects_build_with(has_entry(:allow_reply_by_email, true))
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "no reply by email" do
|
|
context "with reply_by_email" do
|
|
it "doesn't support reply by email" do
|
|
expects_build_with(Not(has_entry(:allow_reply_by_email, true)))
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "respect for private_email" do
|
|
context "with private_email" do
|
|
it "doesn't support reply by email" do
|
|
SiteSetting.private_email = true
|
|
|
|
mailer =
|
|
UserNotifications.public_send(
|
|
mail_type,
|
|
user,
|
|
notification_type: Notification.types[notification.notification_type],
|
|
notification_data_hash: notification.data_hash,
|
|
post: notification.post,
|
|
)
|
|
message = mailer.message
|
|
|
|
topic = notification.post.topic
|
|
expect(message.html_part.body.to_s).not_to include(topic.title)
|
|
expect(message.html_part.body.to_s).not_to include(topic.slug)
|
|
expect(message.text_part.body.to_s).not_to include(topic.title)
|
|
expect(message.text_part.body.to_s).not_to include(topic.slug)
|
|
end
|
|
end
|
|
end
|
|
|
|
# The parts of emails that are derived from templates are translated
|
|
shared_examples "sets user locale" do
|
|
context "with set locale for translating templates" do
|
|
it "sets the locale" do
|
|
expects_build_with(has_key(:locale))
|
|
end
|
|
end
|
|
end
|
|
|
|
shared_examples "notification email building" do
|
|
let(:post) { Fabricate(:post, user: user) }
|
|
let(:mail_type) { "user_#{notification_type}" }
|
|
let(:mail_template) { "user_notifications.#{mail_type}" }
|
|
let(:username) { "walterwhite" }
|
|
let(:notification) do
|
|
Fabricate(
|
|
:notification,
|
|
user: user,
|
|
topic: post.topic,
|
|
notification_type: Notification.types[notification_type],
|
|
post_number: post.post_number,
|
|
data: { original_username: username }.to_json,
|
|
)
|
|
end
|
|
|
|
describe "email building" do
|
|
it "has a username" do
|
|
expects_build_with(has_entry(:username, username))
|
|
end
|
|
|
|
it "has a url" do
|
|
expects_build_with(has_key(:url))
|
|
end
|
|
|
|
it "has a template" do
|
|
expects_build_with(has_entry(:template, mail_template))
|
|
end
|
|
|
|
it "overrides the html part" do
|
|
expects_build_with(has_key(:html_override))
|
|
end
|
|
|
|
it "has a message" do
|
|
expects_build_with(has_key(:message))
|
|
end
|
|
|
|
it "has a context" do
|
|
expects_build_with(has_key(:context))
|
|
end
|
|
|
|
it "has an unsubscribe link" do
|
|
expects_build_with(has_key(:add_unsubscribe_link))
|
|
end
|
|
|
|
it "has an post_id" do
|
|
expects_build_with(has_key(:post_id))
|
|
end
|
|
|
|
it "has an topic_id" do
|
|
expects_build_with(has_key(:topic_id))
|
|
end
|
|
|
|
it "should have user name as from_alias" do
|
|
SiteSetting.enable_names = true
|
|
SiteSetting.display_name_on_posts = true
|
|
expects_build_with(has_entry(:from_alias, "#{user.name} via Discourse"))
|
|
end
|
|
|
|
it "should not have user name as from_alias if display_name_on_posts is disabled" do
|
|
SiteSetting.enable_names = false
|
|
SiteSetting.display_name_on_posts = false
|
|
expects_build_with(has_entry(:from_alias, "walterwhite via Discourse"))
|
|
end
|
|
|
|
it "should explain how to respond" do
|
|
expects_build_with(Not(has_entry(:include_respond_instructions, false)))
|
|
end
|
|
|
|
it "should not explain how to respond if the user is suspended" do
|
|
User.any_instance.stubs(:suspended?).returns(true)
|
|
expects_build_with(has_entry(:include_respond_instructions, false))
|
|
end
|
|
|
|
context "when customized" do
|
|
let(:custom_body) do
|
|
body = +<<~BODY
|
|
You are now officially notified.
|
|
%{header_instructions}
|
|
%{message} %{respond_instructions}
|
|
%{topic_title_url_encoded}
|
|
%{site_title_url_encoded}
|
|
BODY
|
|
|
|
body << "%{context}" if notification_type != :invited_to_topic
|
|
body
|
|
end
|
|
|
|
before do
|
|
TranslationOverride.upsert!(
|
|
SiteSetting.default_locale,
|
|
"#{mail_template}.text_body_template",
|
|
custom_body,
|
|
)
|
|
end
|
|
|
|
it "shouldn't use the default html_override" do
|
|
expects_build_with(Not(has_key(:html_override)))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "user mentioned email" do
|
|
include_examples "notification email building" do
|
|
let(:notification_type) { :mentioned }
|
|
include_examples "respect for private_email"
|
|
include_examples "supports reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
end
|
|
|
|
describe "group mentioned email" do
|
|
include_examples "notification email building" do
|
|
let(:notification_type) { :group_mentioned }
|
|
let(:post) { Fabricate(:private_message_post) }
|
|
let(:user) { post.user }
|
|
let(:mail_type) { "group_mentioned" }
|
|
let(:mail_template) { "user_notifications.user_#{notification_type}_pm" }
|
|
|
|
include_examples "respect for private_email"
|
|
include_examples "supports reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
end
|
|
|
|
describe "user replied" do
|
|
include_examples "notification email building" do
|
|
let(:notification_type) { :replied }
|
|
include_examples "respect for private_email"
|
|
include_examples "supports reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
end
|
|
|
|
describe "user quoted" do
|
|
include_examples "notification email building" do
|
|
let(:notification_type) { :quoted }
|
|
include_examples "respect for private_email"
|
|
include_examples "supports reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
end
|
|
|
|
describe "user posted" do
|
|
include_examples "notification email building" do
|
|
let(:notification_type) { :posted }
|
|
include_examples "respect for private_email"
|
|
include_examples "supports reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
end
|
|
|
|
describe "user invited to a private message" do
|
|
include_examples "notification email building" do
|
|
let(:notification_type) { :invited_to_private_message }
|
|
let(:post) { Fabricate(:private_message_post) }
|
|
let(:user) { post.user }
|
|
let(:mail_template) { "user_notifications.user_#{notification_type}_pm" }
|
|
|
|
include_examples "respect for private_email"
|
|
include_examples "no reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
end
|
|
|
|
describe "group invited to a private message" do
|
|
include_examples "notification email building" do
|
|
let(:notification_type) { :invited_to_private_message }
|
|
let(:post) { Fabricate(:private_message_post) }
|
|
let(:user) { post.user }
|
|
let(:group) { Fabricate(:group) }
|
|
let(:mail_template) { "user_notifications.user_#{notification_type}_pm_group" }
|
|
|
|
before do
|
|
notification.data_hash[:group_id] = group.id
|
|
notification.save!
|
|
end
|
|
|
|
it "should include the group name" do
|
|
expects_build_with(has_entry(:group_name, group.name))
|
|
end
|
|
|
|
include_examples "respect for private_email"
|
|
include_examples "no reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
end
|
|
|
|
describe "user invited to a topic" do
|
|
let(:notification_type) { :invited_to_topic }
|
|
|
|
include_examples "notification email building" do
|
|
include_examples "respect for private_email"
|
|
include_examples "no reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
|
|
context "when showing the right name in 'From' field" do
|
|
let(:inviter) { Fabricate(:user) }
|
|
let(:invitee) { Fabricate(:user) }
|
|
|
|
let(:notification) do
|
|
Fabricate(
|
|
:notification,
|
|
notification_type: Notification.types[:invited_to_topic],
|
|
user: invitee,
|
|
topic: post.topic,
|
|
post_number: post.post_number,
|
|
data: {
|
|
topic_title: post.topic.title,
|
|
display_username: inviter.username,
|
|
original_user_id: inviter.id,
|
|
original_username: inviter.username,
|
|
}.to_json,
|
|
)
|
|
end
|
|
|
|
let(:mailer) do
|
|
UserNotifications.public_send(
|
|
"user_invited_to_topic",
|
|
invitee,
|
|
notification_type: Notification.types[notification.notification_type],
|
|
notification_data_hash: notification.data_hash,
|
|
post: notification.post,
|
|
)
|
|
end
|
|
|
|
it "sends the email as the inviter" do
|
|
SiteSetting.enable_names = false
|
|
|
|
expect(mailer.message.to_s).to include(
|
|
"From: #{inviter.username} via #{SiteSetting.title} <#{SiteSetting.notification_email}>",
|
|
)
|
|
end
|
|
|
|
it "sends the email as the inviter" do
|
|
expect(mailer.message.to_s).to include(
|
|
"From: #{inviter.name} via #{SiteSetting.title} <#{SiteSetting.notification_email}>",
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "watching first post" do
|
|
include_examples "notification email building" do
|
|
let(:notification_type) { :invited_to_topic }
|
|
include_examples "respect for private_email"
|
|
include_examples "no reply by email"
|
|
include_examples "sets user locale"
|
|
end
|
|
end
|
|
|
|
# notification emails derived from templates are translated into the user's locale
|
|
shared_context "with notification derived from template" do
|
|
let(:user) { Fabricate(:user, locale: locale) }
|
|
let(:mail_type) { mail_type }
|
|
let(:notification) { Fabricate(:notification, user: user) }
|
|
end
|
|
|
|
describe "notifications from template" do
|
|
context "when user locale is allowed" do
|
|
before { SiteSetting.allow_user_locale = true }
|
|
|
|
%w[
|
|
signup
|
|
signup_after_approval
|
|
confirm_old_email
|
|
notify_old_email
|
|
confirm_new_email
|
|
forgot_password
|
|
admin_login
|
|
account_created
|
|
].each do |mail_type|
|
|
include_examples "with notification derived from template" do
|
|
let(:locale) { "fr" }
|
|
let(:mail_type) { mail_type }
|
|
it "sets the locale" do
|
|
expects_build_with(has_entry(:locale, "fr"))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context "when user locale is not allowed" do
|
|
before { SiteSetting.allow_user_locale = false }
|
|
|
|
%w[
|
|
signup
|
|
signup_after_approval
|
|
notify_old_email
|
|
confirm_old_email
|
|
confirm_new_email
|
|
forgot_password
|
|
admin_login
|
|
account_created
|
|
].each do |mail_type|
|
|
include_examples "with notification derived from template" do
|
|
let(:locale) { "fr" }
|
|
let(:mail_type) { mail_type }
|
|
it "sets the locale" do
|
|
expects_build_with(has_entry(:locale, "en"))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#participants" do
|
|
fab!(:group1) { Fabricate(:group, name: "group1") }
|
|
fab!(:group2) { Fabricate(:group, name: "group2") }
|
|
fab!(:group3) { Fabricate(:group, name: "group3") }
|
|
fab!(:user1) { Fabricate(:user, username: "one", name: nil, groups: [group1, group2]) }
|
|
fab!(:user2) { Fabricate(:user, username: "two", name: nil, groups: [group1]) }
|
|
fab!(:user3) { Fabricate(:user, username: "three", name: nil, groups: [group3]) }
|
|
fab!(:user4) { Fabricate(:user, username: "four", name: nil, groups: [group1, group3]) }
|
|
fab!(:admin) { Fabricate(:admin, username: "admin", name: nil) }
|
|
|
|
fab!(:topic) do
|
|
t = Fabricate(:private_message_topic, title: "Super cool topic")
|
|
t.allowed_users = [user1, user2, user3, user4, admin]
|
|
t.allowed_groups = [group1]
|
|
t
|
|
end
|
|
fab!(:posts) do
|
|
[
|
|
Fabricate(:post, topic: topic, post_number: 1, user: user2),
|
|
Fabricate(:post, topic: topic, post_number: 2, user: user1),
|
|
Fabricate(:post, topic: topic, post_number: 3, user: user2),
|
|
Fabricate(:small_action, topic: topic, post_number: 4, user: admin),
|
|
Fabricate(:post, topic: topic, post_number: 5, user: user4),
|
|
Fabricate(:post, topic: topic, post_number: 6, user: user3),
|
|
Fabricate(:post, topic: topic, post_number: 7, user: user4),
|
|
]
|
|
end
|
|
|
|
it "returns a list of participants (except for the recipient), groups first, followed by users in order of their last reply" do
|
|
expect(UserNotifications.participants(posts.last, user3)).to eq(
|
|
"[group1 (3)](http://test.localhost/g/group1), " \
|
|
"[four](http://test.localhost/u/four), [two](http://test.localhost/u/two), [one](http://test.localhost/u/one), " \
|
|
"[admin](http://test.localhost/u/admin)",
|
|
)
|
|
end
|
|
|
|
it "caps the list according to site setting" do
|
|
SiteSetting.max_participant_names = 3
|
|
list =
|
|
"[group1 (3)](http://test.localhost/g/group1), [four](http://test.localhost/u/four), [two](http://test.localhost/u/two)"
|
|
expect(UserNotifications.participants(posts.last, user3)).to eq(
|
|
I18n.t("user_notifications.more_pm_participants", participants: list, count: 2),
|
|
)
|
|
end
|
|
|
|
it "orders groups by user count" do
|
|
SiteSetting.max_participant_names = 3
|
|
topic.allowed_groups = [group1, group2, group3]
|
|
|
|
list =
|
|
"[group1 (3)](http://test.localhost/g/group1), [group3 (2)](http://test.localhost/g/group3), [group2 (1)](http://test.localhost/g/group2)"
|
|
expect(UserNotifications.participants(posts.last, user3)).to eq(
|
|
I18n.t("user_notifications.more_pm_participants", participants: list, count: 4),
|
|
)
|
|
end
|
|
|
|
it "orders users by their last reply and user id" do
|
|
expect(UserNotifications.participants(posts[-3], user4)).to eq(
|
|
"[group1 (3)](http://test.localhost/g/group1), " \
|
|
"[two](http://test.localhost/u/two), [one](http://test.localhost/u/one), [three](http://test.localhost/u/three), " \
|
|
"[admin](http://test.localhost/u/admin)",
|
|
)
|
|
end
|
|
|
|
it "prefers full group names when available" do
|
|
SiteSetting.max_participant_names = 2
|
|
topic.allowed_groups = [group1, group2]
|
|
|
|
group2.update!(full_name: "Awesome Group")
|
|
|
|
list =
|
|
"[group1 (3)](http://test.localhost/g/group1), [Awesome Group (1)](http://test.localhost/g/group2)"
|
|
expect(UserNotifications.participants(posts.last, user3)).to eq(
|
|
I18n.t("user_notifications.more_pm_participants", participants: list, count: 4),
|
|
)
|
|
end
|
|
|
|
it "always uses usernames when prioritize_username_in_ux is enabled" do
|
|
user4.update!(name: "James Bond")
|
|
user1.update!(name: "Indiana Jones")
|
|
|
|
SiteSetting.prioritize_username_in_ux = true
|
|
expect(UserNotifications.participants(posts.last, user3)).to eq(
|
|
"[group1 (3)](http://test.localhost/g/group1), " \
|
|
"[four](http://test.localhost/u/four), [two](http://test.localhost/u/two), [one](http://test.localhost/u/one), " \
|
|
"[admin](http://test.localhost/u/admin)",
|
|
)
|
|
|
|
SiteSetting.prioritize_username_in_ux = false
|
|
expect(UserNotifications.participants(posts.last, user3)).to eq(
|
|
"[group1 (3)](http://test.localhost/g/group1), " \
|
|
"[James Bond](http://test.localhost/u/four), [two](http://test.localhost/u/two), [Indiana Jones](http://test.localhost/u/one), " \
|
|
"[admin](http://test.localhost/u/admin)",
|
|
)
|
|
end
|
|
|
|
it "reveals the email address of staged users if enabled" do
|
|
user4.update!(staged: true, email: "james.bond@mi6.invalid")
|
|
user1.update!(staged: true, email: "indiana.jones@example.com")
|
|
|
|
SiteSetting.prioritize_username_in_ux = true
|
|
expect(UserNotifications.participants(posts.last, user3, reveal_staged_email: true)).to eq(
|
|
"[group1 (3)](http://test.localhost/g/group1), james.bond@mi6.invalid, [two](http://test.localhost/u/two), " \
|
|
"indiana.jones@example.com, [admin](http://test.localhost/u/admin)",
|
|
)
|
|
end
|
|
|
|
it "does only include human users" do
|
|
topic.allowed_users << Discourse.system_user
|
|
|
|
expect(UserNotifications.participants(posts.last, user3)).to eq(
|
|
"[group1 (3)](http://test.localhost/g/group1), " \
|
|
"[four](http://test.localhost/u/four), [two](http://test.localhost/u/two), [one](http://test.localhost/u/one), " \
|
|
"[admin](http://test.localhost/u/admin)",
|
|
)
|
|
end
|
|
end
|
|
|
|
describe ".account_silenced" do
|
|
fab!(:user_history) { Fabricate(:user_history, action: UserHistory.actions[:silence_user]) }
|
|
|
|
it "adds the silenced_till date in user's timezone" do
|
|
user.user_option.timezone = "Asia/Tbilisi" # GMT+4
|
|
user.silenced_till = DateTime.parse("May 25, 2020, 12:00pm")
|
|
|
|
mail = UserNotifications.account_silenced(user, { user_history: user_history })
|
|
|
|
expect(mail.body).to include("May 25, 2020, 4:00pm")
|
|
end
|
|
|
|
context "when user doesn't have timezone set" do
|
|
before { user.user_option.timezone = nil }
|
|
|
|
it "doesn't raise error" do
|
|
expect { UserNotifications.account_silenced(user) }.not_to raise_error
|
|
end
|
|
|
|
it "adds the silenced_till date in UTC" do
|
|
date = "May 25, 2020, 12:00pm"
|
|
user.silenced_till = DateTime.parse(date)
|
|
|
|
mail = UserNotifications.account_silenced(user, { user_history: user_history })
|
|
|
|
expect(mail.body).to include(date)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe ".account_suspended" do
|
|
fab!(:user_history) { Fabricate(:user_history, action: UserHistory.actions[:suspend_user]) }
|
|
|
|
it "adds the suspended_till date in user's timezone" do
|
|
user.user_option.timezone = "Asia/Tbilisi" # GMT+4
|
|
user.suspended_till = DateTime.parse("May 25, 2020, 12:00pm")
|
|
|
|
mail = UserNotifications.account_suspended(user, { user_history: user_history })
|
|
|
|
expect(mail.body).to include("May 25, 2020, 4:00pm")
|
|
end
|
|
|
|
context "when user doesn't have timezone set" do
|
|
before { user.user_option.timezone = nil }
|
|
|
|
it "doesn't raise error" do
|
|
expect { UserNotifications.account_suspended(user) }.not_to raise_error
|
|
end
|
|
|
|
it "adds the suspended_till date in UTC" do
|
|
date = "May 25, 2020, 12:00pm"
|
|
user.suspended_till = DateTime.parse(date)
|
|
|
|
mail = UserNotifications.account_suspended(user, { user_history: user_history })
|
|
|
|
expect(mail.body).to include(date)
|
|
end
|
|
end
|
|
end
|
|
end
|