diff --git a/test/test_component.rb b/test/test_component.rb index 77e5bd504f751cdd3c5eee6a5f7eae0dae667f11..1eaf9452bddfc5480750f1eef7f242f628f4b88f 100644 --- a/test/test_component.rb +++ b/test/test_component.rb @@ -582,187 +582,6 @@ class ComponentTest < Minitest::Test end em :test_passthrough_message_emits_to_stream - def invoke_webhook(payload, extra_env: {}) - with_stubs([ - [ - SGXbwmsgsv2, - :write, - ->(data) { SGXbwmsgsv2.write_to_stream(data) } - ] - ]) do - handler = WebhookHandler.new - env = { - "REQUEST_URI" => "/", - "REQUEST_METHOD" => "POST", - "params" => {"_json" => [payload]} - }.merge(extra_env) - handler.instance_variable_set(:@env, env) - def handler.params - @env["params"] - end - - EMPromise.resolve(nil).then { - handler.response(env) - }.sync - end - end - - def test_inbound_sms_emits_to_stream - payload = { - "type" => "message-received", - "to" => "+15550000000", - "message" => { - "id" => "bw-in-123", - "direction" => "in", - "owner" => "+15550000000", - "from" => "+15551234567", - "to" => ["+15550000000"], - "time" => "2025-01-13T10:00:00Z", - "text" => "Hello from outside" - } - } - - invoke_webhook(payload) - - entries = REDIS.stream_entries("messages").sync - assert_equal 1, entries.length - - event = entries.first[:fields] - assert_equal "in", event["event"] - assert_equal "+15551234567", event["from"] - assert_equal JSON.dump(["+15550000000"]), event["to"] - assert_equal "bw-in-123", event["bandwidth_id"] - assert_equal "+15550000000", event["owner"] - assert_equal "Hello from outside", event["body"] - assert_equal JSON.dump([]), event["media_urls"] - end - em :test_inbound_sms_emits_to_stream - - def test_inbound_mms_emits_to_stream_and_filters_smil - payload = { - "type" => "message-received", - "to" => "+15550000000", - "message" => { - "id" => "bw-mms-456", - "direction" => "in", - "owner" => "+15550000000", - "from" => "+15551234567", - "to" => ["+15550000000"], - "time" => "2025-01-13T10:05:00Z", - "text" => "Check this out", - "media" => [ - "https://example.com/image.jpg", - "https://example.com/file.smil", - "https://example.com/data.txt", - "https://example.com/meta.xml" - ] - } - } - - invoke_webhook(payload) - - entries = REDIS.stream_entries("messages").sync - assert_equal 1, entries.length - - event = entries.first[:fields] - assert_equal "in", event["event"] - assert_equal JSON.dump(["https://example.com/image.jpg"]), event["media_urls"] - end - em :test_inbound_mms_emits_to_stream_and_filters_smil - - def test_message_delivered_emits_to_stream - payload = { - "type" => "message-delivered", - "to" => "+15550000000", - "message" => { - "id" => "bw-out-789", - "direction" => "out", - "owner" => "+15550000000", - "from" => "+15550000000", - "to" => ["+15551234567"], - "time" => "2025-01-13T10:10:00Z", - "tag" => "stanza-id-abc extra-data" - } - } - - invoke_webhook(payload) - - entries = REDIS.stream_entries("messages").sync - assert_equal 1, entries.length - - event = entries.first[:fields] - assert_equal "delivered", event["event"] - assert_equal "stanza-id-abc", event["stanza_id"] - assert_equal "bw-out-789", event["bandwidth_id"] - assert_equal "2025-01-13T10:10:00Z", event["timestamp"] - end - em :test_message_delivered_emits_to_stream - - def test_message_failed_emits_to_stream - payload = { - "type" => "message-failed", - "to" => "+15551234567", - "message" => { - "id" => "bw-out-999", - "direction" => "out", - "owner" => "+15550000000", - "from" => "+15550000000", - "to" => ["+15551234567"], - "time" => "2025-01-13T10:15:00Z", - "tag" => "failed-stanza-xyz extra", - "errorCode" => 4720, - "description" => "Carrier rejected message" - } - } - - invoke_webhook(payload) - - entries = REDIS.stream_entries("messages").sync - assert_equal 1, entries.length - - event = entries.first[:fields] - assert_equal "failed", event["event"] - assert_equal "failed-stanza-xyz", event["stanza_id"] - assert_equal "bw-out-999", event["bandwidth_id"] - assert_equal "4720", event["error_code"] - assert_equal "Carrier rejected message", event["error_description"] - assert_equal "2025-01-13T10:15:00Z", event["timestamp"] - end - em :test_message_failed_emits_to_stream - - def test_resend_emits_resend_event_instead_of_in - payload = { - "type" => "message-received", - "message" => { - "id" => "bw-in-resend-001", - "direction" => "in", - "owner" => "+15550000000", - "from" => "+15551234567", - "to" => ["+15550000000"], - "time" => "2025-01-13T10:00:00Z", - "text" => "Resent message" - } - } - - invoke_webhook( - payload, - extra_env: { "HTTP_X_JMP_RESEND_OF" => "1736762400000-0" } - ) - - entries = REDIS.stream_entries("messages").sync - assert_equal 1, entries.length - - event = entries.first[:fields] - assert_equal "resend", event["event"] - assert_equal "bwmsgsv2", event["source"] - assert_equal "+15550000000", event["owner"] - assert_equal "1736762400000-0", event["original_stream_id"] - assert_equal "bw-in-resend-001", event["original_bandwidth_id"] - refute event.key?("from"), "Resend events should not duplicate message fields" - refute event.key?("body"), "Resend events should not duplicate message fields" - end - em :test_resend_emits_resend_event_instead_of_in - def test_sentry_captures_handler_exception captured_exceptions = [] repo = SGXbwmsgsv2.instance_variable_get(:@registration_repo) diff --git a/test/test_webhook_handler.rb b/test/test_webhook_handler.rb new file mode 100644 index 0000000000000000000000000000000000000000..b5672db956fffff168e6d8df8ac0f8bccbde414d --- /dev/null +++ b/test/test_webhook_handler.rb @@ -0,0 +1,208 @@ +# frozen_string_literal: true + +require "test_helper" +require_relative "../sgx-bwmsgsv2" + +def panic(e) + $panic = e +end + +class WebhookHandlerTest < Minitest::Test + def setup + ARGV[0] = 'component' + SGXbwmsgsv2.instance_variable_set(:@written, []) + + def SGXbwmsgsv2.write_to_stream(s) + @written ||= [] + @written << s + end + + REDIS.reset! + REDIS.set("catapult_jid-", "HERE") + REDIS.set("catapult_jid-+15550000000", "test@example.com") + REDIS.set("catapult_cred-test@example.com", [ + 'account', 'user', 'password', '+15550000000' + ]) + end + + def invoke_webhook(payload, extra_env: {}) + with_stubs([ + [ + SGXbwmsgsv2, + :write, + ->(data) { SGXbwmsgsv2.write_to_stream(data) } + ] + ]) do + handler = WebhookHandler.new + env = { + "REQUEST_URI" => "/", + "REQUEST_METHOD" => "POST", + "params" => {"_json" => [payload]} + }.merge(extra_env) + handler.instance_variable_set(:@env, env) + def handler.params + @env["params"] + end + + EMPromise.resolve(nil).then { + handler.response(env) + }.sync + end + end + + def test_inbound_sms_emits_to_stream + payload = { + "type" => "message-received", + "to" => "+15550000000", + "message" => { + "id" => "bw-in-123", + "direction" => "in", + "owner" => "+15550000000", + "from" => "+15551234567", + "to" => ["+15550000000"], + "time" => "2025-01-13T10:00:00Z", + "text" => "Hello from outside" + } + } + + invoke_webhook(payload) + + entries = REDIS.stream_entries("messages").sync + assert_equal 1, entries.length + + event = entries.first[:fields] + assert_equal "in", event["event"] + assert_equal "+15551234567", event["from"] + assert_equal JSON.dump(["+15550000000"]), event["to"] + assert_equal "bw-in-123", event["bandwidth_id"] + assert_equal "+15550000000", event["owner"] + assert_equal "Hello from outside", event["body"] + assert_equal JSON.dump([]), event["media_urls"] + end + em :test_inbound_sms_emits_to_stream + + def test_inbound_mms_emits_to_stream_and_filters_smil + payload = { + "type" => "message-received", + "to" => "+15550000000", + "message" => { + "id" => "bw-mms-456", + "direction" => "in", + "owner" => "+15550000000", + "from" => "+15551234567", + "to" => ["+15550000000"], + "time" => "2025-01-13T10:05:00Z", + "text" => "Check this out", + "media" => [ + "https://example.com/image.jpg", + "https://example.com/file.smil", + "https://example.com/data.txt", + "https://example.com/meta.xml" + ] + } + } + + invoke_webhook(payload) + + entries = REDIS.stream_entries("messages").sync + assert_equal 1, entries.length + + event = entries.first[:fields] + assert_equal "in", event["event"] + assert_equal JSON.dump(["https://example.com/image.jpg"]), event["media_urls"] + end + em :test_inbound_mms_emits_to_stream_and_filters_smil + + def test_message_delivered_emits_to_stream + payload = { + "type" => "message-delivered", + "to" => "+15550000000", + "message" => { + "id" => "bw-out-789", + "direction" => "out", + "owner" => "+15550000000", + "from" => "+15550000000", + "to" => ["+15551234567"], + "time" => "2025-01-13T10:10:00Z", + "tag" => "stanza-id-abc extra-data" + } + } + + invoke_webhook(payload) + + entries = REDIS.stream_entries("messages").sync + assert_equal 1, entries.length + + event = entries.first[:fields] + assert_equal "delivered", event["event"] + assert_equal "stanza-id-abc", event["stanza_id"] + assert_equal "bw-out-789", event["bandwidth_id"] + assert_equal "2025-01-13T10:10:00Z", event["timestamp"] + end + em :test_message_delivered_emits_to_stream + + def test_message_failed_emits_to_stream + payload = { + "type" => "message-failed", + "to" => "+15551234567", + "message" => { + "id" => "bw-out-999", + "direction" => "out", + "owner" => "+15550000000", + "from" => "+15550000000", + "to" => ["+15551234567"], + "time" => "2025-01-13T10:15:00Z", + "tag" => "failed-stanza-xyz extra", + "errorCode" => 4720, + "description" => "Carrier rejected message" + } + } + + invoke_webhook(payload) + + entries = REDIS.stream_entries("messages").sync + assert_equal 1, entries.length + + event = entries.first[:fields] + assert_equal "failed", event["event"] + assert_equal "failed-stanza-xyz", event["stanza_id"] + assert_equal "bw-out-999", event["bandwidth_id"] + assert_equal "4720", event["error_code"] + assert_equal "Carrier rejected message", event["error_description"] + assert_equal "2025-01-13T10:15:00Z", event["timestamp"] + end + em :test_message_failed_emits_to_stream + + def test_resend_emits_resend_event_instead_of_in + payload = { + "type" => "message-received", + "message" => { + "id" => "bw-in-resend-001", + "direction" => "in", + "owner" => "+15550000000", + "from" => "+15551234567", + "to" => ["+15550000000"], + "time" => "2025-01-13T10:00:00Z", + "text" => "Resent message" + } + } + + invoke_webhook( + payload, + extra_env: { "HTTP_X_JMP_RESEND_OF" => "1736762400000-0" } + ) + + entries = REDIS.stream_entries("messages").sync + assert_equal 1, entries.length + + event = entries.first[:fields] + assert_equal "resend", event["event"] + assert_equal "bwmsgsv2", event["source"] + assert_equal "+15550000000", event["owner"] + assert_equal "1736762400000-0", event["original_stream_id"] + assert_equal "bw-in-resend-001", event["original_bandwidth_id"] + refute event.key?("from"), "Resend events should not duplicate message fields" + refute event.key?("body"), "Resend events should not duplicate message fields" + end + em :test_resend_emits_resend_event_instead_of_in +end