Add JSON API for webhook deliveries (#2785)

* Add JSON API for webhook deliveries

* Extract sanitized_request method on Webhook::Delivery

* Extract response_summary method on Webhook::Delivery
This commit is contained in:
Rob Zolkos
2026-04-07 15:08:27 -04:00
committed by GitHub
parent f3bacffe2b
commit 21981898d2
9 changed files with 231 additions and 0 deletions
@@ -0,0 +1,90 @@
require "test_helper"
class Webhooks::DeliveriesControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in_as :kevin
end
test "index as JSON" do
webhook = webhooks(:active)
delivery = webhook_deliveries(:successfully_completed)
webhook_timestamp = delivery.event.created_at.utc.iso8601
delivery.update!(
request: {
headers: {
"User-Agent" => "fizzy/1.0.0 Webhook",
"Content-Type" => "application/json",
"X-Webhook-Signature" => "super-secret-signature",
"X-Webhook-Timestamp" => webhook_timestamp
}
},
response: { code: 200 }
)
get board_webhook_deliveries_path(webhook.board, webhook), as: :json
assert_response :success
assert_kind_of Array, @response.parsed_body
assert_equal webhook.deliveries.count, @response.parsed_body.count
assert_equal webhook.deliveries.ordered.pluck(:id), @response.parsed_body.pluck("id")
completed_delivery = @response.parsed_body.find { |record| record["id"] == delivery.id }
assert_equal "completed", completed_delivery["state"]
assert_equal delivery.created_at.utc.iso8601(3), completed_delivery["created_at"]
assert_equal delivery.updated_at.utc.iso8601(3), completed_delivery["updated_at"]
assert_equal "fizzy/1.0.0 Webhook", completed_delivery.dig("request", "headers", "User-Agent")
assert_equal "application/json", completed_delivery.dig("request", "headers", "Content-Type")
assert_equal webhook_timestamp, completed_delivery.dig("request", "headers", "X-Webhook-Timestamp")
assert_not completed_delivery.dig("request", "headers").key?("X-Webhook-Signature")
assert_equal 200, completed_delivery.dig("response", "code")
assert_nil completed_delivery.dig("response", "error")
assert_equal delivery.event.id, completed_delivery.dig("event", "id")
assert_equal delivery.event.action, completed_delivery.dig("event", "action")
assert_equal delivery.event.created_at.utc.iso8601(3), completed_delivery.dig("event", "created_at")
assert_equal delivery.event.creator_id, completed_delivery.dig("event", "creator", "id")
assert_equal delivery.event.creator.name, completed_delivery.dig("event", "creator", "name")
assert_equal delivery.event.eventable_type, completed_delivery.dig("event", "eventable", "type")
assert_equal delivery.event.eventable_id, completed_delivery.dig("event", "eventable", "id")
assert_equal polymorphic_url(delivery.event.eventable), completed_delivery.dig("event", "eventable", "url")
pending_delivery = @response.parsed_body.find { |record| record["id"] == webhook_deliveries(:pending).id }
assert_nil pending_delivery["request"]
assert_nil pending_delivery["response"]
end
test "index defaults to JSON" do
webhook = webhooks(:active)
get board_webhook_deliveries_path(webhook.board, webhook)
assert_response :success
assert_equal "application/json; charset=utf-8", @response.headers["Content-Type"]
end
test "index rejects HTML" do
webhook = webhooks(:active)
get board_webhook_deliveries_path(webhook.board, webhook, format: :html)
assert_response :not_acceptable
end
test "non-admin cannot access deliveries as JSON" do
logout_and_sign_in_as :jz
webhook = webhooks(:active)
get board_webhook_deliveries_path(webhook.board, webhook), as: :json
assert_response :forbidden
end
test "cannot access deliveries on board without access as JSON" do
logout_and_sign_in_as :jason
webhook = webhooks(:inactive)
get board_webhook_deliveries_path(webhook.board, webhook), as: :json
assert_response :not_found
end
end
+39
View File
@@ -45,6 +45,45 @@ class Webhook::DeliveryTest < ActiveSupport::TestCase
assert_not delivery.succeeded?, "the response can't have an error"
end
test "sanitized_request strips signature header" do
delivery = webhook_deliveries(:successfully_completed)
delivery.update!(request: {
headers: {
"User-Agent" => "fizzy/1.0.0 Webhook",
"Content-Type" => "application/json",
"X-Webhook-Signature" => "super-secret-signature",
"X-Webhook-Timestamp" => "2025-12-05T19:36:35.401Z"
}
})
result = delivery.sanitized_request
assert_equal %w[ User-Agent Content-Type X-Webhook-Timestamp ], result[:headers].keys
assert_not result[:headers].key?("X-Webhook-Signature")
end
test "sanitized_request returns nil when request is blank" do
delivery = webhook_deliveries(:pending)
delivery.update_columns(request: nil)
assert_nil delivery.sanitized_request
end
test "response_summary returns code and error" do
delivery = webhook_deliveries(:successfully_completed)
delivery.update!(response: { code: 200, error: nil })
result = delivery.response_summary
assert_equal 200, result[:code]
assert_nil result[:error]
end
test "response_summary returns nil when response is blank" do
delivery = webhook_deliveries(:pending)
delivery.update_columns(response: nil)
assert_nil delivery.response_summary
end
test "deliver_later" do
delivery = webhook_deliveries(:pending)