feat(backup-monitor): implement PayloadBuilder with tests
This commit is contained in:
parent
3cbd04fe72
commit
c611b2e82a
|
|
@ -56,6 +56,33 @@ class ByteFormatter
|
|||
end
|
||||
|
||||
class PayloadBuilder
|
||||
VALID_STATUSES = %w[success failure skipped].freeze
|
||||
|
||||
def initialize(options)
|
||||
@options = options
|
||||
end
|
||||
|
||||
def build
|
||||
validate!
|
||||
{
|
||||
timestamp: Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ'),
|
||||
machine: @options[:machine],
|
||||
destination: @options[:destination],
|
||||
status: @options[:status],
|
||||
bytes_transferred: ByteFormatter.format(@options[:bytes]),
|
||||
snapshot_id: @options[:snapshot],
|
||||
log_path: @options[:log_path],
|
||||
notes: @options[:notes]
|
||||
}.compact
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate!
|
||||
return if VALID_STATUSES.include?(@options[:status])
|
||||
|
||||
raise ArgumentError, "status must be one of: #{VALID_STATUSES.join(', ')}"
|
||||
end
|
||||
end
|
||||
|
||||
class WebhookClient
|
||||
|
|
|
|||
|
|
@ -29,3 +29,54 @@ class ByteFormatterTest < Minitest::Test
|
|||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue