feat(backup-monitor): implement WebhookClient with injected HTTP adapter and tests
This commit is contained in:
parent
c611b2e82a
commit
3e49704bdb
|
|
@ -86,6 +86,32 @@ class PayloadBuilder
|
||||||
end
|
end
|
||||||
|
|
||||||
class WebhookClient
|
class WebhookClient
|
||||||
|
def initialize(base_url:, auth_token:, http_adapter: Net::HTTP)
|
||||||
|
@base_url = base_url
|
||||||
|
@auth_token = auth_token
|
||||||
|
@http_adapter = http_adapter
|
||||||
|
end
|
||||||
|
|
||||||
|
def post(payload)
|
||||||
|
uri = URI("#{@base_url}/webhook/backup-notify")
|
||||||
|
request = build_request(uri, payload)
|
||||||
|
|
||||||
|
response = @http_adapter.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
|
|
||||||
|
raise "HTTP #{response.code}: #{response.body}" unless response.is_a?(Net::HTTPSuccess)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def build_request(uri, payload)
|
||||||
|
req = Net::HTTP::Post.new(uri)
|
||||||
|
req['Content-Type'] = 'application/json'
|
||||||
|
req['Authorization'] = "Bearer #{@auth_token}"
|
||||||
|
req.body = JSON.generate(payload)
|
||||||
|
req
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class BackupNotifier
|
class BackupNotifier
|
||||||
|
|
|
||||||
|
|
@ -80,3 +80,59 @@ class PayloadBuilderTest < Minitest::Test
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Stub HTTP adapter for WebhookClient tests — replaces Net::HTTP entirely.
|
||||||
|
# Sandi Metz: test the interface, inject the dependency, don't touch globals.
|
||||||
|
class FakeHttpAdapter
|
||||||
|
def initialize(response)
|
||||||
|
@response = response
|
||||||
|
end
|
||||||
|
|
||||||
|
def start(_host, _port, use_ssl: false)
|
||||||
|
yield FakeHttpSession.new(@response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class FakeHttpSession
|
||||||
|
def initialize(response)
|
||||||
|
@response = response
|
||||||
|
end
|
||||||
|
|
||||||
|
def request(_req)
|
||||||
|
@response
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class WebhookClientTest < Minitest::Test
|
||||||
|
def make_success_response
|
||||||
|
res = Net::HTTPSuccess.new('1.1', '200', 'OK')
|
||||||
|
res.instance_variable_set(:@read, true)
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
def make_error_response
|
||||||
|
res = Net::HTTPServerError.new('1.1', '500', 'Internal Server Error')
|
||||||
|
res.instance_variable_set(:@body, 'something broke')
|
||||||
|
res.instance_variable_set(:@read, true)
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
def make_client(response)
|
||||||
|
WebhookClient.new(
|
||||||
|
base_url: 'https://n8n.example.com',
|
||||||
|
auth_token: 'test-token',
|
||||||
|
http_adapter: FakeHttpAdapter.new(response)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_post_succeeds_on_200
|
||||||
|
client = make_client(make_success_response)
|
||||||
|
client.post({ machine: 'desktop', status: 'success' }) # no error raised
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_post_raises_on_500
|
||||||
|
client = make_client(make_error_response)
|
||||||
|
err = assert_raises(RuntimeError) { client.post({}) }
|
||||||
|
assert_match(/HTTP 500/, err.message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue