Group notification emails by board (#2506)
* Group notification emails by board Notification bundle emails now group items by board instead of showing the board name redundantly for each card. Each board section has a linked header and an <hr> separator. * Adjust board title styles and remove rem units * Sort board groups alphabetically Sort notification email board sections alphabetically by name (case-insensitive). Also, rewrite mailer tests to use Nokogiri::HTML5 for precise DOM assertions instead of regex matching. --------- Co-authored-by: Andy Smith <andy@37signals.com>
This commit is contained in:
@@ -14,11 +14,12 @@ class Notification::BundleMailerTest < ActionMailer::TestCase
|
||||
test "renders avatar with initials in span when avatar is not attached" do
|
||||
create_notification(@user)
|
||||
|
||||
email = Notification::BundleMailer.notification(@bundle)
|
||||
html = Nokogiri::HTML5(Notification::BundleMailer.notification(@bundle).html_part.body.to_s)
|
||||
|
||||
assert_match /<span[^>]*class="avatar"[^>]*>/, email.html_part.body.to_s
|
||||
assert_match /#{@user.initials}/, email.html_part.body.to_s
|
||||
assert_match /style="background-color: #[A-F0-9]{6};?"/, email.html_part.body.to_s
|
||||
avatar = html.at_css("span.avatar")
|
||||
assert avatar, "Expected a span.avatar element"
|
||||
assert_equal @user.initials, avatar.text.strip
|
||||
assert_match /background-color: #[A-F0-9]{6}/, avatar["style"]
|
||||
end
|
||||
|
||||
test "renders avatar with external image URL when avatar is attached" do
|
||||
@@ -30,15 +31,63 @@ class Notification::BundleMailerTest < ActionMailer::TestCase
|
||||
|
||||
create_notification(@user)
|
||||
|
||||
email = Notification::BundleMailer.notification(@bundle)
|
||||
html = Nokogiri::HTML5(Notification::BundleMailer.notification(@bundle).html_part.body.to_s)
|
||||
|
||||
assert_match /<img[^>]*class="avatar"[^>]*>/, email.html_part.body.to_s
|
||||
assert_match /<img[^>]*class="avatar"[^>]*src="[^"]*"/, email.html_part.body.to_s
|
||||
assert_match /alt="#{@user.name}"/, email.html_part.body.to_s
|
||||
avatar = html.at_css("img.avatar")
|
||||
assert avatar, "Expected an img.avatar element"
|
||||
assert avatar["src"].present?
|
||||
assert_equal @user.name, avatar["alt"]
|
||||
end
|
||||
|
||||
test "groups notifications by board, sorted alphabetically" do
|
||||
private_board = boards(:private)
|
||||
private_card = Current.with(user: @user) do
|
||||
private_board.cards.create!(
|
||||
title: "Private card", creator: @user, status: :published, account: @user.account
|
||||
)
|
||||
end
|
||||
private_event = Event.create!(
|
||||
creator: @user, board: private_board, eventable: private_card,
|
||||
action: :card_published, account: @user.account
|
||||
)
|
||||
|
||||
create_notification(@user, source: events(:logo_published))
|
||||
create_notification(@user, source: private_event)
|
||||
create_notification(@user, source: events(:layout_published))
|
||||
|
||||
html = Nokogiri::HTML5(Notification::BundleMailer.notification(@bundle).html_part.body.to_s)
|
||||
|
||||
board_headers = html.css(".notification__board")
|
||||
assert_equal 2, board_headers.size, "Should have exactly two board headers"
|
||||
assert_equal [ "Private board", "Writebook" ], board_headers.map(&:text)
|
||||
end
|
||||
|
||||
test "board header links to the board" do
|
||||
create_notification(@user, source: events(:logo_published))
|
||||
|
||||
html = Nokogiri::HTML5(Notification::BundleMailer.notification(@bundle).html_part.body.to_s)
|
||||
board = boards(:writebook)
|
||||
|
||||
link = html.at_css(".notification__board a")
|
||||
assert_equal "Writebook", link.text
|
||||
assert_match %r{boards/#{board.id}}, link["href"]
|
||||
end
|
||||
|
||||
test "shows multiple cards under same board header" do
|
||||
create_notification(@user, source: events(:logo_published))
|
||||
create_notification(@user, source: events(:layout_published))
|
||||
|
||||
html = Nokogiri::HTML5(Notification::BundleMailer.notification(@bundle).html_part.body.to_s)
|
||||
|
||||
assert_equal 1, html.css(".notification__board").size, "Same board should only have one header"
|
||||
|
||||
card_titles = html.css(".card__title").map(&:text)
|
||||
assert_includes card_titles, "#1 The logo isn't big enough"
|
||||
assert_includes card_titles, "#2 Layout is broken"
|
||||
end
|
||||
|
||||
private
|
||||
def create_notification(user)
|
||||
Notification.create!(user: user, creator: user, source: events(:logo_published), created_at: 30.minutes.ago)
|
||||
def create_notification(user, source: events(:logo_published))
|
||||
Notification.create!(user: user, creator: user, source: source, created_at: 30.minutes.ago)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user