From dbbf99a7eb2bf8d0c4c2ddfa1d1562920ab632ed Mon Sep 17 00:00:00 2001 From: Kevin Soltysiak Date: Sun, 11 Feb 2024 16:59:37 +0100 Subject: [PATCH] refactor: remove custom Response object --- lib/scalingo/api/endpoint.rb | 7 - lib/scalingo/api/response.rb | 69 ------- spec/scalingo/api/endpoint_spec.rb | 23 --- spec/scalingo/api/response_spec.rb | 301 ----------------------------- 4 files changed, 400 deletions(-) delete mode 100644 lib/scalingo/api/response.rb delete mode 100644 spec/scalingo/api/response_spec.rb diff --git a/lib/scalingo/api/endpoint.rb b/lib/scalingo/api/endpoint.rb index 7f534e2..5698a23 100644 --- a/lib/scalingo/api/endpoint.rb +++ b/lib/scalingo/api/endpoint.rb @@ -1,5 +1,4 @@ require "forwardable" -require "scalingo/api/response" module Scalingo module API @@ -23,12 +22,6 @@ def inspect str << ">" str end - - private - - def unpack(*keys, &block) - Response.unpack(client, keys: keys, &block) - end end end end diff --git a/lib/scalingo/api/response.rb b/lib/scalingo/api/response.rb deleted file mode 100644 index f145663..0000000 --- a/lib/scalingo/api/response.rb +++ /dev/null @@ -1,69 +0,0 @@ -module Scalingo - module API - class Response - def self.unpack(client, key: nil, keys: nil) - response = yield - - body = response.body - has_hash_body = body.present? && body.respond_to?(:key) - - data = body - meta = nil - - if has_hash_body - keys = [key] if key.present? - - data = body.dig(*keys) if response.success? && keys.present? - - meta = body[:meta] - end - - new( - client: client, - status: response.status, - headers: response.headers, - data: data, - meta: meta, - full_body: body - ) - end - - attr_reader :client, :status, :headers, :data, :full_body, :meta - - def initialize(client:, status:, headers:, data:, full_body:, meta: nil) - @client = client - @status = status - @headers = headers - @data = data - @full_body = full_body - @meta = meta - end - - def inspect - %(<#{self.class}:0x#{object_id.to_s(16)} status:#{@status} data:#{@data} meta:#{@meta}>) - end - - def successful? - status >= 200 && status < 300 - end - - def paginated? - meta&.dig(:pagination).present? - end - - def operation - if operation? && client.respond_to?(:operations) - client.operations.get(operation_url) - end - end - - def operation_url - headers[:location] - end - - def operation? - operation_url.present? - end - end - end -end diff --git a/spec/scalingo/api/endpoint_spec.rb b/spec/scalingo/api/endpoint_spec.rb index 971d1b1..72fc111 100644 --- a/spec/scalingo/api/endpoint_spec.rb +++ b/spec/scalingo/api/endpoint_spec.rb @@ -19,27 +19,4 @@ expect(subject.connection).to eq :value end end - - describe "unpack" do - it "forwards unpack to Response without keys" do - mock = proc { 1 } - - expect(Scalingo::API::Response).to receive(:unpack).with(client, keys: [], &mock).and_return(:d).once - expect(subject.send(:unpack, &mock)).to eq :d - end - - it "forwards unpack to Response with a single key" do - mock = proc { 1 } - - expect(Scalingo::API::Response).to receive(:unpack).with(client, keys: [:a], &mock).and_return(:d).once - expect(subject.send(:unpack, :a, &mock)).to eq :d - end - - it "forwards unpack to Response with many keys" do - mock = proc { 1 } - - expect(Scalingo::API::Response).to receive(:unpack).with(client, keys: [:a, :b], &mock).and_return(:d).once - expect(subject.send(:unpack, :a, :b, &mock)).to eq :d - end - end end diff --git a/spec/scalingo/api/response_spec.rb b/spec/scalingo/api/response_spec.rb deleted file mode 100644 index 3a6318f..0000000 --- a/spec/scalingo/api/response_spec.rb +++ /dev/null @@ -1,301 +0,0 @@ -require "spec_helper" - -RSpec.describe Scalingo::API::Response do - let(:client) { regional } - let(:status) { 200 } - let(:headers) { {} } - let(:data) { "" } - let(:full_body) { "" } - let(:meta_object) { nil } - - subject { - described_class.new( - client: client, - status: status, - headers: headers, - data: data, - full_body: full_body, - meta: meta_object - ) - } - - describe "self.unpack" do - let(:body) { "" } - let(:success) { true } - - let(:response) { - OpenStruct.new( - body: body, - status: status, - headers: headers, - success?: success - ) - } - - it "passes the client supplied" do - object = described_class.unpack(:some_client) { response } - - expect(object.client).to eq :some_client - end - - it "passes the response status" do - object = described_class.unpack(:client) { response } - - expect(object.status).to eq status - end - - it "passes the response headers" do - object = described_class.unpack(:client) { response } - - expect(object.headers).to eq headers - end - - context "with an empty body" do - let(:body) { "" } - - it "without key" do - object = described_class.unpack(client) { response } - - expect(object.data).to eq "" - expect(object.full_body).to eq "" - expect(object.meta).to eq nil - end - - it "ignores key if supplied" do - object = described_class.unpack(client, key: :key) { response } - - expect(object.data).to eq "" - expect(object.full_body).to eq "" - expect(object.meta).to eq nil - end - end - - context "with a nil body" do - let(:body) { nil } - - it "without key" do - object = described_class.unpack(client) { response } - - expect(object.data).to eq nil - expect(object.full_body).to eq nil - expect(object.meta).to eq nil - end - - it "ignores key if supplied" do - object = described_class.unpack(client, key: :key) { response } - - expect(object.data).to eq nil - expect(object.full_body).to eq nil - expect(object.meta).to eq nil - end - end - - context "with a string body" do - let(:body) { "this is a string body, probably due to an error" } - - it "without key" do - object = described_class.unpack(client) { response } - - expect(object.data).to eq body - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - - it "ignores key if supplied" do - object = described_class.unpack(client, key: :key) { response } - - expect(object.data).to eq body - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - end - - context "with an json (array) body" do - let(:body) { - [{key: :value}] - } - - it "without key" do - object = described_class.unpack(client) { response } - - expect(object.data).to eq body - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - - it "ignores key if supplied" do - object = described_class.unpack(client, key: :root) { response } - - expect(object.data).to eq body - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - end - - context "with a json (hash) body" do - let(:body) { - {root: {key: :value}} - } - - it "without key" do - object = described_class.unpack(client) { response } - - expect(object.data).to eq body - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - - it "with valid key" do - object = described_class.unpack(client, key: :root) { response } - - expect(object.data).to eq({key: :value}) - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - - it "with invalid key" do - object = described_class.unpack(client, key: :other) { response } - - expect(object.data).to eq nil - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - - it "with valid keys" do - object = described_class.unpack(client, keys: [:root, :key]) { response } - - expect(object.data).to eq(:value) - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - - it "with invalid keys" do - object = described_class.unpack(client, keys: [:root, :other]) { response } - - expect(object.data).to eq nil - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - - context "with meta" do - let(:body) { - {root: {key: :value}, meta: {meta1: :value}} - } - - it "extracts the meta object" do - object = described_class.unpack(client) { response } - - expect(object.meta).to eq({meta1: :value}) - end - end - end - - context "with an error response" do - let(:success) { false } - let(:body) { {root: {key: :value}} } - - it "does not dig in the response hash, even with a valid key" do - object = described_class.unpack(client, key: :root) { response } - - expect(object.data).to eq body - expect(object.full_body).to eq body - expect(object.meta).to eq nil - end - end - end - - describe "successful?" do - context "is true when 2XX" do - let(:status) { 200 } - it { expect(subject.successful?).to be true } - end - - context "is false when 3XX" do - let(:status) { 300 } - it { expect(subject.successful?).to be false } - end - - context "is false when 4XX" do - let(:status) { 400 } - it { expect(subject.successful?).to be false } - end - - context "is false when 5XX" do - let(:status) { 500 } - it { expect(subject.successful?).to be false } - end - end - - describe "paginated?" do - context "with pagination metadata" do - let(:meta_object) { - {pagination: {page: 1}} - } - - it { expect(subject.paginated?).to be true } - end - - context "without pagination metadata" do - let(:meta_object) { - {messages: []} - } - - it { expect(subject.paginated?).to be false } - end - end - - describe "operation" do - context "with an operation url" do - before do - load_meta!(api: :regional, folder: :operations) - register_stubs!("find-200", api: :regional, folder: :operations) - end - - let(:url) { - path = "/apps/#{meta[:app_id]}/operations/#{meta[:id]}" - File.join(Scalingo::ENDPOINTS[:regional], path) - } - - let(:headers) { - {location: url} - } - - it { expect(subject.operation?).to be true } - it { expect(subject.operation_url).to eq url } - - it "can request the operation" do - response = subject.operation - - expect(response).to be_successful - expect(response.data[:id]).to be_present - expect(response.data[:status]).to be_present - expect(response.data[:type]).to be_present - end - - it "delegates the operation to the given client" do - mock = double - - expect(subject.client).to receive(:operations).and_return(mock) - expect(mock).to receive(:get).with(url).and_return(:response) - - expect(subject.operation).to eq :response - end - - context "when the client doesn't know about operations" do - let(:client) { auth } - - it "fails silently" do - expect(subject.operation).to eq nil - end - end - end - - context "without an operation url" do - let(:meta_object) { {} } - - it { expect(subject.operation?).to be false } - it { expect(subject.operation_url).to eq nil } - it { expect(subject.operation).to eq nil } - end - end -end