diff --git a/spec/deep_hash_accessor_spec.rb b/spec/deep_hash_accessor_spec.rb index b066e18..3f45f16 100644 --- a/spec/deep_hash_accessor_spec.rb +++ b/spec/deep_hash_accessor_spec.rb @@ -12,7 +12,8 @@ city: "San Francisco", country: "USA" }, - hobbies: %w[reading cycling] + hobbies: %w[reading cycling], + pets: [{name: "Rex", species: "dog"}] } end @@ -36,6 +37,11 @@ it "returns arrays as is for simple types" do expect(accessor.hobbies).to eq(%w[reading cycling]) end + + it "wraps hashes inside arrays" do + expect(accessor.pets.first).to be_a(described_class) + expect(accessor.pets.first.name).to eq("Rex") + end end describe "non-existent keys" do diff --git a/spec/resources/resource_errors_spec.rb b/spec/resources/resource_errors_spec.rb new file mode 100644 index 0000000..47f47f1 --- /dev/null +++ b/spec/resources/resource_errors_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +RSpec.describe "resource errors and warnings" do + describe Seam::Resources::ResourceErrorsSupport do + it "converts error hashes into ResourceError objects" do + device = Seam::Resources::Device.load_from_response( + "device_id" => "device_id_1234", + "errors" => [ + { + "error_code" => "device_removed", + "message" => "Device was removed", + "created_at" => "2024-01-01T00:00:00Z" + } + ] + ) + + error = device.errors.first + expect(error).to be_a(Seam::Resources::ResourceError) + expect(error.error_code).to eq("device_removed") + expect(error.message).to eq("Device was removed") + expect(error.created_at).to be_a(Time) + end + + it "returns an empty array when the resource has no errors" do + device = Seam::Resources::Device.load_from_response("device_id" => "device_id_1234") + + expect(device.errors).to eq([]) + end + end + + describe Seam::Resources::ResourceWarningsSupport do + it "converts warning hashes into ResourceWarning objects" do + device = Seam::Resources::Device.load_from_response( + "device_id" => "device_id_1234", + "warnings" => [ + { + "warning_code" => "privacy_mode", + "message" => "Device is in privacy mode", + "created_at" => "2024-01-01T00:00:00Z" + } + ] + ) + + warning = device.warnings.first + expect(warning).to be_a(Seam::Resources::ResourceWarning) + expect(warning.warning_code).to eq("privacy_mode") + expect(warning.message).to eq("Device is in privacy mode") + expect(warning.created_at).to be_a(Time) + end + + it "returns an empty array when the resource has no warnings" do + device = Seam::Resources::Device.load_from_response("device_id" => "device_id_1234") + + expect(device.warnings).to eq([]) + end + end +end diff --git a/spec/seam_client/malformed_response_spec.rb b/spec/seam_client/malformed_response_spec.rb new file mode 100644 index 0000000..86f6987 --- /dev/null +++ b/spec/seam_client/malformed_response_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +# The fake cannot produce malformed error responses, so WebMock drives the +# bodies that must fall through seam_api_error_response? to Faraday's own +# error handling rather than being parsed into a Seam::Http::ApiError. +RSpec.describe Seam::Http::Request do + let(:seam) { Seam.new(api_key: "seam_some_api_key") } + let(:url) { "#{Seam::DEFAULT_ENDPOINT}/devices/list" } + + describe "non-Seam error responses" do + it "raises a Faraday error for a plain text response" do + stub_request(:post, url).to_return( + status: 500, + body: "Internal Server Error", + headers: {"Content-Type" => "text/plain"} + ) + + expect { seam.devices.list }.to raise_error(Faraday::ServerError) + end + + it "raises a Faraday error for malformed JSON" do + stub_request(:post, url).to_return( + status: 500, + body: "{invalid json", + headers: {"Content-Type" => "application/json"} + ) + + expect { seam.devices.list }.to raise_error(Faraday::ServerError) + end + + it "raises a Faraday error for JSON without an error object" do + stub_request(:post, url).to_return( + status: 500, + body: {message: "Some error"}.to_json, + headers: {"Content-Type" => "application/json"} + ) + + expect { seam.devices.list }.to raise_error(Faraday::ServerError) + end + + it "raises a Faraday error for an error object without a type and message" do + stub_request(:post, url).to_return( + status: 500, + body: {error: {code: 500}}.to_json, + headers: {"Content-Type" => "application/json"} + ) + + expect { seam.devices.list }.to raise_error(Faraday::ServerError) + end + end +end