From 332d5f85cff1ebd654946fb253b793b48ae70d2c Mon Sep 17 00:00:00 2001 From: Vignesh Rajendran Date: Sun, 3 Jul 2022 01:19:33 +0530 Subject: [PATCH] Adds webhook delivery method --- README.md | 2 ++ docs/delivery_methods/webhook.md | 17 +++++++++ lib/noticed.rb | 1 + lib/noticed/delivery_methods/webhook.rb | 27 ++++++++++++++ test/delivery_methods/webhook_test.rb | 47 +++++++++++++++++++++++++ test/fixtures/files/webhook/failure.txt | 10 ++++++ test/fixtures/files/webhook/success.txt | 12 +++++++ 7 files changed, 116 insertions(+) create mode 100644 docs/delivery_methods/webhook.md create mode 100644 lib/noticed/delivery_methods/webhook.rb create mode 100644 test/delivery_methods/webhook_test.rb create mode 100644 test/fixtures/files/webhook/failure.txt create mode 100644 test/fixtures/files/webhook/success.txt diff --git a/README.md b/README.md index 78e5bdf5..99c1755a 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Currently, we support these notification delivery methods out of the box: * Vonage / Nexmo (SMS) * iOS Apple Push Notifications * Firebase Cloud Messaging (Android and more) +* Webhook And you can easily add new notification types for any other delivery methods. @@ -252,6 +253,7 @@ For example, emails will require a subject, body, and email address while an SMS * [Twilio](docs/delivery_methods/twilio.md) * [Vonage](docs/delivery_methods/vonage.md) * [Firebase Cloud Messaging](docs/delivery_methods/fcm.md) +* [Webhook](docs/delivery_methods/webhook.md) ### Fallback Notifications diff --git a/docs/delivery_methods/webhook.md b/docs/delivery_methods/webhook.md new file mode 100644 index 00000000..dbe59ff5 --- /dev/null +++ b/docs/delivery_methods/webhook.md @@ -0,0 +1,17 @@ +### Webhook Delivery Method + +Sends a notification via webhook. + +`deliver_by :webhook, url: "https://webhook.site/0090u9-989238u-23898u-1823"` + +##### Options + +* `format: :format_for_webhook` - *Optional* + + Use a custom method to define the payload sent to webhook URL. Method should return a Hash. + +* `url: :url_for_webhook` - **Required** + + Use a custom method to retrieve the Webhook URL. Method should return a String. + + diff --git a/lib/noticed.rb b/lib/noticed.rb index 921598eb..15f5cc87 100644 --- a/lib/noticed.rb +++ b/lib/noticed.rb @@ -23,6 +23,7 @@ module DeliveryMethods autoload :Test, "noticed/delivery_methods/test" autoload :Twilio, "noticed/delivery_methods/twilio" autoload :Vonage, "noticed/delivery_methods/vonage" + autoload :Webhook, "noticed/delivery_methods/webhook" end mattr_accessor :parent_class diff --git a/lib/noticed/delivery_methods/webhook.rb b/lib/noticed/delivery_methods/webhook.rb new file mode 100644 index 00000000..31894451 --- /dev/null +++ b/lib/noticed/delivery_methods/webhook.rb @@ -0,0 +1,27 @@ +module Noticed + module DeliveryMethods + class Webhook < Base + option :url + + def deliver + post(url, json: format) + end + + private + + def format + if (method = options[:format]) + notification.send(method) + else + notification.params + end + end + + def url + if (method = options[:url]) + notification.send(method) + end + end + end + end +end diff --git a/test/delivery_methods/webhook_test.rb b/test/delivery_methods/webhook_test.rb new file mode 100644 index 00000000..120a7d31 --- /dev/null +++ b/test/delivery_methods/webhook_test.rb @@ -0,0 +1,47 @@ +require "test_helper" + +class WebhookTest < ActiveSupport::TestCase + class WebhookExampleWithoutWebhookUrl < Noticed::Base + deliver_by :webhook, debug: true + end + + class WebhookExample < Noticed::Base + deliver_by :webhook, debug: true, url: :webhook_url + + def webhook_url + "https://webhook.site/8c6ed375-d871-41b9-9536-e01b47d6b20b" + end + end + + test "sends a POST to Webhook link" do + stub_delivery_method_request(delivery_method: :webhook, matcher: /webhook.site/) + WebhookExample.new.deliver(user) + end + + test "raises an error when http request fails" do + stub_delivery_method_request(delivery_method: :webhook, matcher: /webhook.site/, type: :failure) + e = assert_raises(::Noticed::ResponseUnsuccessful) { + WebhookExample.new.deliver(user) + } + assert_equal HTTP::Response, e.response.class + end + + test "deliver returns an http response" do + stub_delivery_method_request(delivery_method: :webhook, matcher: /webhook.site/) + + args = { + notification_class: "::WebhookTest::WebhookExample", + recipient: user, + options: {url: :webhook_url} + } + response = Noticed::DeliveryMethods::Webhook.new.perform(args) + + assert_kind_of HTTP::Response, response + end + + test "validates webhook url is specified for webhook delivery method" do + assert_raises Noticed::ValidationError do + WebhookExampleWithoutWebhookUrl.new.deliver(user) + end + end +end diff --git a/test/fixtures/files/webhook/failure.txt b/test/fixtures/files/webhook/failure.txt new file mode 100644 index 00000000..88c93377 --- /dev/null +++ b/test/fixtures/files/webhook/failure.txt @@ -0,0 +1,10 @@ +HTTP/1.1 403 +date: Mon, 09 Nov 2020 12:14:30 GMT +server: Apache +strict-transport-security: max-age=31536000; includeSubDomains; preload +access-control-allow-origin: * +x-frame-options: SAMEORIGIN +referrer-policy: no-referrer +vary: Accept-Encoding +content-type: text/html +x-via: haproxy-www-2n6w,haproxy-edge-fra-9k3b diff --git a/test/fixtures/files/webhook/success.txt b/test/fixtures/files/webhook/success.txt new file mode 100644 index 00000000..a9ea2681 --- /dev/null +++ b/test/fixtures/files/webhook/success.txt @@ -0,0 +1,12 @@ +HTTP/1.1 200 +date: Mon, 09 Nov 2020 12:14:30 GMT +server: Apache +strict-transport-security: max-age=31536000; includeSubDomains; preload +access-control-allow-origin: * +x-frame-options: SAMEORIGIN +referrer-policy: no-referrer +vary: Accept-Encoding +content-type: text/html +x-via: haproxy-www-2n6w,haproxy-edge-fra-9k3b + +ok