diff --git a/lib/intelligent_foods/api_client.rb b/lib/intelligent_foods/api_client.rb index 5b8e625..f3841f0 100644 --- a/lib/intelligent_foods/api_client.rb +++ b/lib/intelligent_foods/api_client.rb @@ -24,6 +24,25 @@ def authenticate! self end + def build_patch_request(uri:, body: nil) + build_request_with_body(uri: uri, body: body, + http_method: Net::HTTP::Patch) + end + + def build_post_request(uri:, body: nil) + build_request_with_body(uri: uri, body: body, + http_method: Net::HTTP::Post) + end + + def build_request_with_body(uri:, body:, http_method:) + request = http_method.new(uri) + request["content-type"] = "application/json" + unless body.nil? + request.body = body.to_json + end + request + end + def execute_request(request:, uri:, body: nil, authorization: default_authorization) Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http| @@ -34,13 +53,6 @@ def execute_request(request:, uri:, body: nil, end end - def build_request_with_body(uri:, body:) - request = Net::HTTP::Post.new(uri) - request.body = body.to_json - request["content-type"] = "application/json" - request - end - def authenticated? access_token.present? end diff --git a/lib/intelligent_foods/errors.rb b/lib/intelligent_foods/errors.rb index 7648540..8511dcb 100644 --- a/lib/intelligent_foods/errors.rb +++ b/lib/intelligent_foods/errors.rb @@ -8,4 +8,6 @@ class OrderNotCancelledError < ApiError; end class OrderNotCreatedError < ApiError; end class AuthenticationError < ApiError; end + + class OrderNotUpdatedError < ApiError; end end diff --git a/lib/intelligent_foods/resources/order.rb b/lib/intelligent_foods/resources/order.rb index f3ff679..24fd8a1 100644 --- a/lib/intelligent_foods/resources/order.rb +++ b/lib/intelligent_foods/resources/order.rb @@ -22,7 +22,7 @@ def self.build_from_response(data) def create! uri = URI("#{IntelligentFoods.base_url}/order") - request = client.build_request_with_body(uri: uri, body: request_body) + request = client.build_post_request(uri: uri, body: request_body) response = client.execute_request(request: request, uri: uri) if response.success? Order::build_from_response(response.data) @@ -45,6 +45,18 @@ def cancel! end end + def update! + uri = URI("#{IntelligentFoods.base_url}/order/#{id}") + request = client.build_patch_request(uri: uri, body: update_request_body) + response = client.execute_request(request: request, uri: uri) + if response.success? + Order::build_from_response(response.data) + else + mark_as_invalid + raise OrderNotUpdatedError.build(response) + end + end + def request_body @request_body ||= { menu_id: menu.id, @@ -55,6 +67,12 @@ def request_body } end + def update_request_body + { + ship_to: ship_to, + } + end + def cancelled? status.downcase == CANCELLED end diff --git a/spec/factories.rb b/spec/factories.rb index 7cfeae7..2b6cd0d 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1,4 +1,15 @@ FactoryBot.define do + factory :order, class: "IntelligentFoods::Order" do + menu + recipient + delivery_date { Date.today.to_s } + items { [build(:order_item)] } + sequence :external_id do |n| + "d89397e1bad49c3b855df4406e5bf0#{n}" + end + callback_url { "http://test.com/api/callback" } + end + factory :recipient, class: "IntelligentFoods::Recipient" do name { "First Name" } street1 { "123 Main Street" } diff --git a/spec/intelligent_foods/api_client_spec.rb b/spec/intelligent_foods/api_client_spec.rb index 6bf86aa..ff88fda 100644 --- a/spec/intelligent_foods/api_client_spec.rb +++ b/spec/intelligent_foods/api_client_spec.rb @@ -165,6 +165,26 @@ end end + describe "#build_patch_request" do + it "builds a request using the Patch HTTP method" do + client = IntelligentFoods::ApiClient.new(id: "id", secret: "secret") + + result = client.build_patch_request(uri: "test.com", body: {}) + + expect(result.method).to eq("PATCH") + end + end + + describe "#build_post_request" do + it "builds a request using the Post HTTP method" do + client = IntelligentFoods::ApiClient.new(id: "id", secret: "secret") + + result = client.build_post_request(uri: "test.com", body: {}) + + expect(result.method).to eq("POST") + end + end + describe "#authenticated?" do it "is not authenticated" do client = IntelligentFoods::ApiClient.new(id: "id", secret: "secret") diff --git a/spec/intelligent_foods/resources/order_spec.rb b/spec/intelligent_foods/resources/order_spec.rb index 64d4e50..603411a 100644 --- a/spec/intelligent_foods/resources/order_spec.rb +++ b/spec/intelligent_foods/resources/order_spec.rb @@ -142,4 +142,45 @@ end end end + + describe "#update!" do + it "updates the order" do + order = build(:order) + body = build_order_response + response = build_response(body: body) + stub_api_response response: response + + result = order.update! + + expect(result).to be_accepted + end + + context "the response code is not 200" do + it "raises a OrderNotUpdatedError" do + order = build(:order) + response = error_response(message: "Order Not Found", + http_status_code: 404) + stub_api_response response: response + + expect { + order.update! + }.to raise_error(IntelligentFoods::OrderNotUpdatedError) + end + + it "marks the order as not valid" do + order = build(:order) + response = error_response(message: "Order Not Found", + http_status_code: 404) + stub_api_response response: response + + begin + order.update! + rescue IntelligentFoods::OrderNotUpdatedError + # noop + end + + expect(order).not_to be_valid + end + end + end end