From e75c5b3bdcee111b3463c1fa91f99d74f21ba1a5 Mon Sep 17 00:00:00 2001 From: Min Zeya Phyo Date: Tue, 28 Jul 2026 02:13:51 +0800 Subject: [PATCH] feat(ntfy): add NtfyDispatchable concern for fanning out to admins --- app/models/concerns/ntfy_dispatchable.rb | 21 ++++++++ .../models/concerns/ntfy_dispatchable_test.rb | 49 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 app/models/concerns/ntfy_dispatchable.rb create mode 100644 test/models/concerns/ntfy_dispatchable_test.rb diff --git a/app/models/concerns/ntfy_dispatchable.rb b/app/models/concerns/ntfy_dispatchable.rb new file mode 100644 index 0000000..f8c9d04 --- /dev/null +++ b/app/models/concerns/ntfy_dispatchable.rb @@ -0,0 +1,21 @@ +module NtfyDispatchable + extend ActiveSupport::Concern + + class_methods do + def dispatch_ntfy(event_type, title:, message:, priority: 3, tags: [], click: nil) + AdminUser.where(ntfy_enabled: true).find_each do |admin| + next unless admin.ntfy_configured? + + SendNtfyNotificationJob.perform_later( + admin.id, + event_type, + title: title, + message: message, + priority: priority, + tags: tags, + click: click + ) + end + end + end +end diff --git a/test/models/concerns/ntfy_dispatchable_test.rb b/test/models/concerns/ntfy_dispatchable_test.rb new file mode 100644 index 0000000..42f3b70 --- /dev/null +++ b/test/models/concerns/ntfy_dispatchable_test.rb @@ -0,0 +1,49 @@ +require "test_helper" + +class NtfyDispatchableTest < ActiveJob::TestCase + setup do + ActiveJob::Base.queue_adapter = :test + @admin = AdminUser.create!( + name: "Dispatch Admin", email: "dispatch@example.com", + password: "password123", + ntfy_topic: "dispatch-topic", ntfy_token: "tk_dispatch", + ntfy_enabled: true, + ntfy_server_url: "https://ntfy.example.com" + ) + + stub_request(:post, "https://ntfy.example.com/dispatch-topic") + .to_return(status: 200, body: "", headers: {}) + end + + test "dispatch_ntfy enqueues a SendNtfyNotificationJob per configured admin" do + assert_enqueued_jobs 1 do + TestModel.dispatch_ntfy("sms_failed", + title: "SMS failed", + message: "msg_abc failed", + priority: 5, + tags: ["x"], + click: "https://app/admin/logs" + ) + end + end + + test "dispatch_ntfy skips admins without ntfy configured" do + AdminUser.create!(name: "No Ntfy", email: "none@example.com", password: "password123") + + assert_enqueued_jobs 1 do + TestModel.dispatch_ntfy("sms_failed", title: "T", message: "M", priority: 3, tags: []) + end + end + + test "dispatch_ntfy enqueues zero jobs if no admins configured" do + @admin.update!(ntfy_enabled: false) + + assert_enqueued_jobs 0 do + TestModel.dispatch_ntfy("sms_failed", title: "T", message: "M", priority: 3, tags: []) + end + end +end + +class TestModel + include NtfyDispatchable +end