Skip to content

Commit

Permalink
add specs for mime encode/decode operations
Browse files Browse the repository at this point in the history
  • Loading branch information
raghuramg committed Dec 30, 2024
1 parent 4f0a9ed commit 598a7a7
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 26 deletions.
34 changes: 20 additions & 14 deletions lib/event_source/operations/mime_decode.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ module Operations
class MimeDecode
include Dry::Monads[:result, :do]

MIME_TYPES = %w[application/zlib application/json].freeze

# Compresses the payload into a compressed string using Zlib.
#
# @return [Dry::Monads::Success<String>] if compression is successful
# @return [Dry::Monads::Failure<String>] if an error occurs
def call
payload = yield validate_payload(payload)
compressed_data = yield decode(json_payload)
def call(mime_type, payload)
valid_payload = yield validate_payload(payload, mime_type)
decoded_data = yield decode(valid_payload, mime_type)

Success(compressed_data)
rescue StandardError => e
Failure("Compression failed: #{e.message}")
Success(decoded_data)
end

private
Expand All @@ -28,24 +28,30 @@ def call
#
# @return [Dry::Monads::Success<String>] if the payload is valid
# @return [Dry::Monads::Failure<String>] if the payload is invalid
def validate_payload
# return Failure('Payload must be a Hash or String') unless payload.is_a?(Hash) || payload.is_a?(String)
def validate_payload(payload, mime_type)
unless MIME_TYPES.include?(mime_type.to_s)
return Failure("Invalid mime type '#{mime_type}'. Supported types are: #{MIME_TYPES.join(', ')}.")
end

return Failure('Payload must be a binary') unless binary_payload?(payload)
if mime_type.to_s == 'application/zlib' && !binary_payload?(payload)
return Failure("Payload must be binary-encoded for mime type 'application/zlib'.")
end

Success(payload.is_a?(Hash) ? payload.to_json : payload)
Success(payload)
end

def decode(payload)
compressed_data = Zlib.inflate(payload)
def decode(payload, mime_type)
decoded_data = Zlib.inflate(payload) if mime_type.to_s == 'application/zlib'

Success(compressed_data)
Success(decoded_data || payload)
rescue Zlib::Error => e
Failure("Failed to decode payload using Zlib: #{e.message}")
end

# Checks if the payload is in binary encoding.
#
# @return [Boolean] true if the payload is binary, false otherwise
def binary_payload?
def binary_payload?(payload)
return false unless payload.respond_to?(:encoding)

payload.encoding == Encoding::BINARY
Expand Down
32 changes: 20 additions & 12 deletions lib/event_source/operations/mime_encode.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ module Operations
# A class for handling payload compression.
class MimeEncode
include Dry::Monads[:result, :do]

MIME_TYPES = %w[application/zlib application/json].freeze

# Compresses the payload into a compressed string using Zlib.
#
# @return [Dry::Monads::Success<String>] if compression is successful
# @return [Dry::Monads::Failure<String>] if an error occurs
def call
json_payload = yield validate_payload
compressed_data = yield encode(json_payload)
def call(mime_type, payload)
json_payload = yield validate_payload(payload, mime_type)
encoded_data = yield encode(json_payload, mime_type)

Success(compressed_data)
rescue StandardError => e
Failure("Compression failed: #{e.message}")
Success(encoded_data)
end

private
Expand All @@ -28,16 +28,24 @@ def call
#
# @return [Dry::Monads::Success<String>] if the payload is valid
# @return [Dry::Monads::Failure<String>] if the payload is invalid
def validate_payload
return Failure('Payload must be a Hash or String') unless payload.is_a?(Hash) || payload.is_a?(String)
def validate_payload(payload, mime_type)
unless MIME_TYPES.include?(mime_type.to_s)
return Failure("Invalid mime type '#{mime_type}'. Supported types are: #{MIME_TYPES.join(', ')}.")
end

unless payload.is_a?(Hash) || payload.is_a?(String)
return Failure("Invalid payload type. Expected a Hash or String, but received #{payload.class}.")
end

Success(payload.is_a?(Hash) ? payload.to_json : payload)
end

def encode(json_payload)
compressed_data = Zlib.deflate(json_payload)

Success(compressed_data)
def encode(json_payload, mime_type)
encoded_data = Zlib.deflate(json_payload) if mime_type.to_s == 'application/zlib'

Success(encoded_data || json_payload)
rescue Zlib::Error => e
Failure("Failed to compress payload using Zlib: #{e.message}")
end
end
end
Expand Down
56 changes: 56 additions & 0 deletions spec/event_source/operations/mime_decode_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

RSpec.describe EventSource::Operations::MimeDecode do
subject { described_class.new }

describe "#call" do
context "when the payload and mime type are valid" do
let(:payload) { { message: "Hello, World!" } }
let(:compressed_payload) { Zlib.deflate(payload.to_json) }
let(:mime_type) { "application/zlib" }

it "successfully decodes the payload" do
result = subject.call(mime_type, compressed_payload)

expect(result).to be_success
expect(result.value!).to eq(payload.to_json)
end
end

context "when the payload is not binary for application/zlib" do
let(:invalid_payload) { "Not binary data" }
let(:mime_type) { "application/zlib" }

it "returns a failure" do
result = subject.call(mime_type, invalid_payload)

expect(result).to be_failure
expect(result.failure).to eq("Payload must be binary-encoded for mime type 'application/zlib'.")
end
end

context "when the mime type is invalid" do
let(:payload) { { message: "Hello, World!" }.to_json }
let(:mime_type) { "text/plain" }

it "returns a failure" do
result = subject.call(mime_type, payload)

expect(result).to be_failure
expect(result.failure).to eq("Invalid mime type 'text/plain'. Supported types are: application/zlib, application/json.")
end
end

context "when decoding fails" do
let(:invalid_compressed_payload) { "Invalid compressed data" }
let(:mime_type) { "application/zlib" }

it "returns a failure with an error message" do
result = subject.call(mime_type, invalid_compressed_payload)

expect(result).to be_failure
expect(result.failure).to eq("Payload must be binary-encoded for mime type 'application/zlib'.")
end
end
end
end
55 changes: 55 additions & 0 deletions spec/event_source/operations/mime_encode_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

RSpec.describe EventSource::Operations::MimeEncode do
subject { described_class.new }

describe "#call" do
context "when the payload and mime type are valid" do
let(:payload) { { message: "Hello, World!" } }
let(:mime_type) { "application/zlib" }

it "successfully encodes the payload" do
result = subject.call(mime_type, payload)

expect(result).to be_success
expect(Zlib.inflate(result.value!)).to eq(payload.to_json)
end
end

context "when the payload is a string and mime type is valid" do
let(:payload) { "Hello, World!" }
let(:mime_type) { "application/json" }

it "returns the payload as JSON" do
result = subject.call(mime_type, payload)

expect(result).to be_success
expect(result.value!).to eq(payload)
end
end

context "when the mime type is invalid" do
let(:payload) { { message: "Hello, World!" } }
let(:mime_type) { "text/plain" }

it "returns a failure" do
result = subject.call(mime_type, payload)

expect(result).to be_failure
expect(result.failure).to eq("Invalid mime type 'text/plain'. Supported types are: application/zlib, application/json.")
end
end

context "when the payload is invalid" do
let(:payload) { 1000 }
let(:mime_type) { "application/json" }

it "returns a failure" do
result = subject.call(mime_type, payload)

expect(result).to be_failure
expect(result.failure).to eq("Invalid payload type. Expected a Hash or String, but received Integer.")
end
end
end
end

0 comments on commit 598a7a7

Please sign in to comment.