server-desktop-01/scripts/notify_backup_test.rb

139 lines
3.8 KiB
Ruby

#!/usr/bin/env ruby
# frozen_string_literal: true
require 'minitest/autorun'
require_relative 'notify_backup'
class ByteFormatterTest < Minitest::Test
def test_gigabytes
assert_equal '4.50 GB', ByteFormatter.format(4_831_838_208)
end
def test_megabytes
assert_equal '823.00 MB', ByteFormatter.format(862_978_048)
end
def test_kilobytes
assert_equal '12.00 KB', ByteFormatter.format(12_288)
end
def test_bytes_below_one_kb
assert_equal '512 B', ByteFormatter.format(512)
end
def test_nil_returns_nil
assert_nil ByteFormatter.format(nil)
end
def test_string_integer_is_coerced
assert_equal '1.00 GB', ByteFormatter.format('1073741824')
end
end
class PayloadBuilderTest < Minitest::Test
def base_options
{ machine: 'desktop', destination: 'synology', status: 'success' }
end
def test_builds_required_fields
payload = PayloadBuilder.new(base_options).build
assert_equal 'desktop', payload[:machine]
assert_equal 'synology', payload[:destination]
assert_equal 'success', payload[:status]
assert_match(/\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z\z/, payload[:timestamp])
end
def test_formats_bytes_to_human_readable
payload = PayloadBuilder.new(base_options.merge(bytes: 1_073_741_824)).build
assert_equal '1.00 GB', payload[:bytes_transferred]
end
def test_omits_nil_optional_fields
payload = PayloadBuilder.new(base_options).build
refute payload.key?(:bytes_transferred)
refute payload.key?(:snapshot_id)
refute payload.key?(:log_path)
refute payload.key?(:notes)
end
def test_includes_all_optional_fields_when_present
opts = base_options.merge(
bytes: 1_048_576,
snapshot: 'abc12345',
log_path: '/home/jared/.local/log/restic/2026-05-07.log',
notes: 'snapshot abc12345 saved'
)
payload = PayloadBuilder.new(opts).build
assert_equal '1.00 MB', payload[:bytes_transferred]
assert_equal 'abc12345', payload[:snapshot_id]
assert_equal '/home/jared/.local/log/restic/2026-05-07.log', payload[:log_path]
assert_equal 'snapshot abc12345 saved', payload[:notes]
end
def test_raises_on_invalid_status
assert_raises(ArgumentError) { PayloadBuilder.new(base_options.merge(status: 'unknown')).build }
end
def test_all_valid_statuses_accepted
%w[success failure skipped].each do |s|
assert PayloadBuilder.new(base_options.merge(status: s)).build
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