From b93752dbb577448f0760699713eb0b1d638fda08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:10:37 +0100 Subject: [PATCH 01/10] Mention column name and creator in push event body when card is moved between columns --- app/models/notification/event_payload.rb | 6 ++++++ test/models/notification/push_target/web_test.rb | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/app/models/notification/event_payload.rb b/app/models/notification/event_payload.rb index fba3a6cb2..f43c2b0d5 100644 --- a/app/models/notification/event_payload.rb +++ b/app/models/notification/event_payload.rb @@ -22,6 +22,8 @@ class Notification::EventPayload < Notification::DefaultPayload card.closure ? "Moved to Done by #{event.creator.name}" : "Closed by #{event.creator.name}" when "card_reopened" "Reopened by #{event.creator.name}" + when "card_triaged" + "Moved to #{column_name} by #{event.creator.name}" else event.creator.name end @@ -57,6 +59,10 @@ class Notification::EventPayload < Notification::DefaultPayload card.title.presence || "Card #{card.number}" end + def column_name + event.particulars.dig("particulars", "column") + end + def card_url_with_comment_anchor(comment) Rails.application.routes.url_helpers.card_url( comment.card, diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index 94628fb82..3516c96ea 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -65,6 +65,18 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for triage includes column name" do + event = events(:logo_published) + event.update!(action: "card_triaged", particulars: { "particulars" => { "column" => "In Progress" } }) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved to In Progress by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for mention includes mentioner name" do @web_push_pool.expects(:queue).once.with do |payload, _| payload[:title].include?("mentioned you") From 9678bdbd246f4187145d6e036427acb0227a7423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:17:56 +0100 Subject: [PATCH 02/10] Add more specific messages to event push payload body --- app/models/notification/event_payload.rb | 18 ++++++ .../notification/push_target/web_test.rb | 60 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/app/models/notification/event_payload.rb b/app/models/notification/event_payload.rb index f43c2b0d5..e39cde9d4 100644 --- a/app/models/notification/event_payload.rb +++ b/app/models/notification/event_payload.rb @@ -24,6 +24,16 @@ class Notification::EventPayload < Notification::DefaultPayload "Reopened by #{event.creator.name}" when "card_triaged" "Moved to #{column_name} by #{event.creator.name}" + when "card_sent_back_to_triage" + "Moved back to Maybe? by #{event.creator.name}" + when "card_board_changed" + "Moved to #{new_board_name} by #{event.creator.name}" + when "card_title_changed" + "Renamed to #{new_title} by #{event.creator.name}" + when "card_postponed" + "Moved to Not Now by #{event.creator.name}" + when "card_auto_postponed" + "Moved to Not Now due to inactivity" else event.creator.name end @@ -63,6 +73,14 @@ class Notification::EventPayload < Notification::DefaultPayload event.particulars.dig("particulars", "column") end + def new_board_name + event.particulars.dig("particulars", "new_board") + end + + def new_title + event.particulars.dig("particulars", "new_title") + end + def card_url_with_comment_anchor(comment) Rails.application.routes.url_helpers.card_url( comment.card, diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index 3516c96ea..6892fb100 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -77,6 +77,66 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for sent back to triage includes Maybe?" do + event = events(:logo_published) + event.update!(action: "card_sent_back_to_triage") + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved back to Maybe? by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + + test "payload for board change includes new board name" do + event = events(:logo_published) + event.update!(action: "card_board_changed", particulars: { "particulars" => { "old_board" => "Old Board", "new_board" => "New Board" } }) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved to New Board by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + + test "payload for title change includes new title" do + event = events(:logo_published) + event.update!(action: "card_title_changed", particulars: { "particulars" => { "old_title" => "Old Title", "new_title" => "New Title" } }) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Renamed to New Title by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + + test "payload for postponed includes Not Now" do + event = events(:logo_published) + event.update!(action: "card_postponed") + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved to Not Now by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + + test "payload for auto postponed includes inactivity message" do + event = events(:logo_published) + event.update!(action: "card_auto_postponed") + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved to Not Now due to inactivity" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for mention includes mentioner name" do @web_push_pool.expects(:queue).once.with do |payload, _| payload[:title].include?("mentioned you") From 856d17c51062d0f672105582bc5fec5a6144c012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:26:50 +0100 Subject: [PATCH 03/10] Handle missing fields --- app/models/notification/event_payload.rb | 15 +++++++++--- .../notification/push_target/web_test.rb | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app/models/notification/event_payload.rb b/app/models/notification/event_payload.rb index e39cde9d4..b296f7252 100644 --- a/app/models/notification/event_payload.rb +++ b/app/models/notification/event_payload.rb @@ -27,9 +27,17 @@ class Notification::EventPayload < Notification::DefaultPayload when "card_sent_back_to_triage" "Moved back to Maybe? by #{event.creator.name}" when "card_board_changed" - "Moved to #{new_board_name} by #{event.creator.name}" + if new_board_name.present? + "Moved to #{new_board_name} by #{event.creator.name}" + else + "Moved by #{event.creator.name}" + end when "card_title_changed" - "Renamed to #{new_title} by #{event.creator.name}" + if new_title.present? + "Renamed to #{new_title} by #{event.creator.name}" + else + "Renamed by #{event.creator.name}" + end when "card_postponed" "Moved to Not Now by #{event.creator.name}" when "card_auto_postponed" @@ -74,7 +82,8 @@ class Notification::EventPayload < Notification::DefaultPayload end def new_board_name - event.particulars.dig("particulars", "new_board") + event.particulars.dig("particulars", "new_board") || + event.particulars.dig("particulars", "new_collection") end def new_title diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index 6892fb100..26ad80cc8 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -101,6 +101,18 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for board change falls back when board name is missing" do + event = events(:logo_published) + event.update!(action: "card_board_changed", particulars: {}) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for title change includes new title" do event = events(:logo_published) event.update!(action: "card_title_changed", particulars: { "particulars" => { "old_title" => "Old Title", "new_title" => "New Title" } }) @@ -113,6 +125,18 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for title change falls back when title is missing" do + event = events(:logo_published) + event.update!(action: "card_title_changed", particulars: {}) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Renamed by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for postponed includes Not Now" do event = events(:logo_published) event.update!(action: "card_postponed") From 566dd8ded2011f56681b4ff1d210473aa166b1b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:30:12 +0100 Subject: [PATCH 04/10] Update default message --- app/models/notification/event_payload.rb | 2 +- test/models/notification/push_target/web_test.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/models/notification/event_payload.rb b/app/models/notification/event_payload.rb index b296f7252..9fee43032 100644 --- a/app/models/notification/event_payload.rb +++ b/app/models/notification/event_payload.rb @@ -43,7 +43,7 @@ class Notification::EventPayload < Notification::DefaultPayload when "card_auto_postponed" "Moved to Not Now due to inactivity" else - event.creator.name + "Updated by #{event.creator.name}" end end diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index 26ad80cc8..4dd95ac40 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -161,6 +161,18 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for unhandled action uses updated fallback message" do + event = events(:logo_published) + event.update!(action: "card_unassigned") + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Updated by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for mention includes mentioner name" do @web_push_pool.expects(:queue).once.with do |payload, _| payload[:title].include?("mentioned you") From 7702e49afa567ece24675635272dede048aedbc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:42:49 +0100 Subject: [PATCH 05/10] Handle collection change the same as board change --- app/models/notification/event_payload.rb | 2 +- test/models/notification/push_target/web_test.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/models/notification/event_payload.rb b/app/models/notification/event_payload.rb index 9fee43032..a936c3e5c 100644 --- a/app/models/notification/event_payload.rb +++ b/app/models/notification/event_payload.rb @@ -26,7 +26,7 @@ class Notification::EventPayload < Notification::DefaultPayload "Moved to #{column_name} by #{event.creator.name}" when "card_sent_back_to_triage" "Moved back to Maybe? by #{event.creator.name}" - when "card_board_changed" + when "card_board_changed", "card_collection_changed" if new_board_name.present? "Moved to #{new_board_name} by #{event.creator.name}" else diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index 4dd95ac40..8f3e6eb9b 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -113,6 +113,18 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for collection change includes new collection name" do + event = events(:logo_published) + event.update!(action: "card_collection_changed", particulars: { "particulars" => { "new_collection" => "New Collection" } }) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved to New Collection by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for title change includes new title" do event = events(:logo_published) event.update!(action: "card_title_changed", particulars: { "particulars" => { "old_title" => "Old Title", "new_title" => "New Title" } }) From 44235da9c1efe7304cb57cca565dc29444633409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:47:41 +0100 Subject: [PATCH 06/10] Add fallback message for card triage when column name is missing --- app/models/notification/event_payload.rb | 6 +++++- test/models/notification/push_target/web_test.rb | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/models/notification/event_payload.rb b/app/models/notification/event_payload.rb index a936c3e5c..27a859793 100644 --- a/app/models/notification/event_payload.rb +++ b/app/models/notification/event_payload.rb @@ -23,7 +23,11 @@ class Notification::EventPayload < Notification::DefaultPayload when "card_reopened" "Reopened by #{event.creator.name}" when "card_triaged" - "Moved to #{column_name} by #{event.creator.name}" + if column_name.present? + "Moved to #{column_name} by #{event.creator.name}" + else + "Moved by #{event.creator.name}" + end when "card_sent_back_to_triage" "Moved back to Maybe? by #{event.creator.name}" when "card_board_changed", "card_collection_changed" diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index 8f3e6eb9b..b11ca8f7f 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -77,6 +77,18 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for triage falls back when column name is missing" do + event = events(:logo_published) + event.update!(action: "card_triaged", particulars: {}) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for sent back to triage includes Maybe?" do event = events(:logo_published) event.update!(action: "card_sent_back_to_triage") From 7ae3bbc6a59d470656ac0169e4c32fd665a13727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:49:08 +0100 Subject: [PATCH 07/10] Add test for fallback payload when column name is blank in triage event --- test/models/notification/push_target/web_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index b11ca8f7f..e5aec4bc8 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -89,6 +89,18 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for triage falls back when column name is blank" do + event = events(:logo_published) + event.update!(action: "card_triaged", particulars: { "particulars" => { "column" => "" } }) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for sent back to triage includes Maybe?" do event = events(:logo_published) event.update!(action: "card_sent_back_to_triage") From fd0df9d8b474a3dc6fc6e68666df906841817733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:52:21 +0100 Subject: [PATCH 08/10] Add tests for fallback payload when collection name is missing or blank, reformat --- .../notification/push_target/web_test.rb | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index e5aec4bc8..c2e265e28 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -115,7 +115,10 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase test "payload for board change includes new board name" do event = events(:logo_published) - event.update!(action: "card_board_changed", particulars: { "particulars" => { "old_board" => "Old Board", "new_board" => "New Board" } }) + event.update!( + action: "card_board_changed", + particulars: { "particulars" => { "old_board" => "Old Board", "new_board" => "New Board" } } + ) @notification.update!(source: event) @web_push_pool.expects(:queue).once.with do |payload, _| @@ -139,7 +142,10 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase test "payload for collection change includes new collection name" do event = events(:logo_published) - event.update!(action: "card_collection_changed", particulars: { "particulars" => { "new_collection" => "New Collection" } }) + event.update!( + action: "card_collection_changed", + particulars: { "particulars" => { "new_collection" => "New Collection" } } + ) @notification.update!(source: event) @web_push_pool.expects(:queue).once.with do |payload, _| @@ -149,9 +155,36 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for collection change falls back when collection name is missing" do + event = events(:logo_published) + event.update!(action: "card_collection_changed", particulars: {}) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + + test "payload for collection change falls back when collection name is blank" do + event = events(:logo_published) + event.update!(action: "card_collection_changed", particulars: { "particulars" => { "new_collection" => "" } }) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for title change includes new title" do event = events(:logo_published) - event.update!(action: "card_title_changed", particulars: { "particulars" => { "old_title" => "Old Title", "new_title" => "New Title" } }) + event.update!( + action: "card_title_changed", + particulars: { "particulars" => { "old_title" => "Old Title", "new_title" => "New Title" } } + ) @notification.update!(source: event) @web_push_pool.expects(:queue).once.with do |payload, _| From 97d188fae4b82cbe866dbb4c4c7763962bc523a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 18:54:15 +0100 Subject: [PATCH 09/10] Rename new_board_name to new_location_name for clarity in event payload handling --- app/models/notification/event_payload.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/notification/event_payload.rb b/app/models/notification/event_payload.rb index 27a859793..f760ba40c 100644 --- a/app/models/notification/event_payload.rb +++ b/app/models/notification/event_payload.rb @@ -31,8 +31,8 @@ class Notification::EventPayload < Notification::DefaultPayload when "card_sent_back_to_triage" "Moved back to Maybe? by #{event.creator.name}" when "card_board_changed", "card_collection_changed" - if new_board_name.present? - "Moved to #{new_board_name} by #{event.creator.name}" + if new_location_name.present? + "Moved to #{new_location_name} by #{event.creator.name}" else "Moved by #{event.creator.name}" end @@ -85,7 +85,7 @@ class Notification::EventPayload < Notification::DefaultPayload event.particulars.dig("particulars", "column") end - def new_board_name + def new_location_name event.particulars.dig("particulars", "new_board") || event.particulars.dig("particulars", "new_collection") end From ad45eabfdcac86989b2b0f9d9643e17a3cb0bd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jirka=20Hut=C3=A1rek?= Date: Fri, 27 Feb 2026 19:00:14 +0100 Subject: [PATCH 10/10] Add fallback handling for blank board and title names in event payloads --- .../notification/push_target/web_test.rb | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/models/notification/push_target/web_test.rb b/test/models/notification/push_target/web_test.rb index c2e265e28..37f23b557 100644 --- a/test/models/notification/push_target/web_test.rb +++ b/test/models/notification/push_target/web_test.rb @@ -140,6 +140,21 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for board change falls back when board name is blank" do + event = events(:logo_published) + event.update!( + action: "card_board_changed", + particulars: { "particulars" => { "new_board" => "" } } + ) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Moved by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for collection change includes new collection name" do event = events(:logo_published) event.update!( @@ -206,6 +221,18 @@ class Notification::PushTarget::WebTest < ActiveSupport::TestCase Notification::PushTarget::Web.new(@notification).process end + test "payload for title change falls back when title is blank" do + event = events(:logo_published) + event.update!(action: "card_title_changed", particulars: { "particulars" => { "new_title" => "" } }) + @notification.update!(source: event) + + @web_push_pool.expects(:queue).once.with do |payload, _| + payload[:body] == "Renamed by #{event.creator.name}" + end + + Notification::PushTarget::Web.new(@notification).process + end + test "payload for postponed includes Not Now" do event = events(:logo_published) event.update!(action: "card_postponed")