xpost 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1528ac526307947878501064a5b31c5c128883cf
4
+ data.tar.gz: a3a71ecaa5c1e6d786ae24e84cef98793b0ffb2a
5
+ SHA512:
6
+ metadata.gz: 380cd7435dd8e02ef74e2a3de907b6260d3a8c3731903fe9524c6b1909f5f40a0f04225ee55e11769460c224d4c1b1722a5bb5c94ac0b04f42cf849d18326e76
7
+ data.tar.gz: 49323931c9acd75d1f258dfa6f6f54f46b512991316b0c7c2fc88754e916ba5875c1fcec8b99efe6cedae5e6aade8dd1793e7156f850491ab58ac822d8cc4e37
Binary file
@@ -0,0 +1,10 @@
1
+ *.gem
2
+ .bundle
3
+ *.lock
4
+ pkg/*
5
+ .ruby-version
6
+ gemfiles/vendor/*
7
+ tmp/
8
+ spec/reports/
9
+
10
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 xpanse-ph
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,64 @@
1
+
2
+
3
+ # xpost
4
+
5
+ A ruby gem for accessing the xpost API created by xpanse.
6
+
7
+ # Configuration
8
+
9
+ ```ruby
10
+ # config/initializers/xpost.rb
11
+
12
+ Xpost.configure do |config|
13
+ config.api_key = 'your_api_key'
14
+ config.secret_key = 'your_secret_key'
15
+ end
16
+ ```
17
+
18
+ # Authentication
19
+
20
+ ```ruby
21
+ api_key = "1234"
22
+ secret_key = "ABCD"
23
+
24
+ Xpost::Authentication.authenticate(api_key, secret_key)
25
+
26
+ # "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0IiwiaWF0IjoxNTI2MzgzMzE0LCJqdGkiOjE1MjYzODMzMTR9.iXbnbn7XRmrq2msAMEGyv8cTl2PWkpfP7EbztKNo00A"
27
+ ```
28
+
29
+ # Order
30
+
31
+
32
+ ### Order.find
33
+
34
+ Returns all order data.
35
+
36
+ ```ruby
37
+ auth_token = "..."
38
+ tracking_number = "0076-1174-PSAT"
39
+
40
+ Xpost::Order.find(auth_token, tracking_number)
41
+ ```
42
+
43
+ ### Order.track
44
+
45
+ Returns the order events of a specific order.
46
+
47
+ ```ruby
48
+ auth_token = "..."
49
+ tracking_number = "0076-1174-PSAT"
50
+
51
+ Xpost::Order.find(auth_token, tracking_number)
52
+ ```
53
+
54
+ ### Order Flow
55
+
56
+ ```ruby
57
+ Order.create(auth_token, options: order_options)
58
+ Order.confirm(auth_token, options/payment_reference_id)
59
+ Order.for_pickup(auth_token, pickup_address)
60
+ ```
61
+
62
+ # Testing
63
+
64
+ Disclaimer: Most of the API calls still try to connect to an external HTTP connection.
@@ -0,0 +1,23 @@
1
+ module Xpost
2
+ autoload :Configuration, 'xpost/configuration'
3
+ autoload :Authentication, 'xpost/authentication'
4
+ autoload :Orders, 'xpost/orders'
5
+
6
+ module Models
7
+ autoload :Address, 'xpost/models/address'
8
+ autoload :Item, 'xpost/models/item'
9
+ autoload :Order, 'xpost/models/order'
10
+ end
11
+
12
+ class << self
13
+ attr_accessor :configuration
14
+ end
15
+
16
+ def self.configuration
17
+ @configuration ||= Configuration.new
18
+ end
19
+
20
+ def self.configure
21
+ yield configuration
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ require 'base64'
2
+ require 'openssl'
3
+ require 'json'
4
+
5
+ module Xpost
6
+ module Authentication
7
+ def self.authenticate(api_key, secret_key)
8
+ payload = payload(api_key)
9
+ signature = signature(header, payload, secret_key)
10
+ token = "#{header}.#{payload}.#{signature}"
11
+ end
12
+
13
+ private
14
+
15
+ def self.header
16
+ url_safe({ "alg" => "HS256", "typ" => "JWT"}.to_json)
17
+ end
18
+
19
+ def self.payload(api_key)
20
+ iat = jti = Time.now.to_i
21
+ url_safe({"sub": api_key, "iat": iat, "jti": jti }.to_json)
22
+ end
23
+
24
+ def self.signature(header, payload, secret_key, alg = 'HS256')
25
+ data = "#{header}.#{payload}"
26
+ url_safe(OpenSSL::HMAC.digest('SHA256', secret_key, data))
27
+ end
28
+
29
+ def self.url_safe(data)
30
+ Base64.urlsafe_encode64(data).delete('=')
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ module Xpost
2
+ class Configuration
3
+ attr_accessor :api_key, :secret_key, :staging_url, :production_url
4
+
5
+ def initialize
6
+ @api_key
7
+ @secret_key
8
+ @staging_url
9
+ @production_url
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ module Xpost
2
+ module Models
3
+
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_model'
2
+ require 'set'
3
+
4
+ module Xpost
5
+ module Models
6
+ class Address
7
+ include ActiveModel::Model
8
+
9
+ REQUIRED_ADDRESS_PARAMETERS = Set[:name, :shipment, :line_1, :city, :state, :postal_code, :country]
10
+ OPTIONAL_ADDRESS_PARAMETERS = Set[:company, :title, :email, :phone_number, :mobile_number, :fax_number,
11
+ :district, :line_2, :remarks]
12
+
13
+ attr_accessor :name, :shipment, :line_1, :city, :state, :postal_code, :country
14
+ attr_accessor :company, :title, :email, :phone_number, :mobile_number, :fax_number, :district, :line_2, :remarks
15
+
16
+ validates_presence_of :name, :shipment, :line_1, :city, :state, :postal_code, :country
17
+
18
+ def initialize(options = {})
19
+ @shipment = options[:shipment]
20
+ @name = options[:name]
21
+ @email = options[:email]
22
+ @phone_number = options[:phone_number]
23
+ @mobile_number = options[:mobile_number]
24
+ @fax_number = options[:fax_number]
25
+ @company = options[:company]
26
+ @title = options[:title]
27
+ @line_1 = options[:line_1]
28
+ @line_2 = options[:line_2]
29
+ @city = options[:city]
30
+ @district = options[:district]
31
+ @state = options[:state]
32
+ @postal_code = options[:postal_code]
33
+ @country = options[:country]
34
+ @remarks = options[:remarks]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_model'
2
+ require 'set'
3
+
4
+ module Xpost
5
+ module Models
6
+ class Item
7
+ include ActiveModel::Model
8
+
9
+ ITEM_TYPES = Set[:product, :shipping, :tax, :fee, :insurance, :discount]
10
+
11
+ attr_accessor :type, :description, :amount, :quantity, :metadata
12
+
13
+ validates_presence_of :type, :description, :amount
14
+ validate :check_item_type
15
+
16
+ def initialize(options = {})
17
+ @type = options[:type]
18
+ @description = options[:description]
19
+ @amount = options[:amount]
20
+ @quantity = options[:quantity]
21
+ @metadata = options[:metadata]
22
+ end
23
+
24
+ def check_item_type
25
+ if self.type.present? && !ITEM_TYPES.include?(self.type.to_sym)
26
+ errors.add(:type, "wrong item type")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,54 @@
1
+ require 'active_model'
2
+ require 'set'
3
+
4
+ module Xpost
5
+ module Models
6
+ class Order
7
+ include ActiveModel::Model
8
+
9
+ CONFIRMABLE_PARAMETERS = Set[:status, :email, :buyer_name, :contact_number, :delivery_address, :items,
10
+ :shipment, :total, :currency, :payment_method, :payment_provider]
11
+ FOR_PICKUP_PARAMETERS = Set[:pickup_address, :pickup_at]
12
+
13
+ attr_accessor :email, :buyer_name, :contact_number
14
+ attr_accessor :total, :currency, :payment_method, :payment_provider
15
+ attr_accessor :delivery_address, :pickup_address
16
+ attr_accessor :status, :items, :shipment
17
+
18
+ validates_presence_of :email, :buyer_name, :contact_number
19
+ validates_presence_of :delivery_address
20
+
21
+ def initialize(options = {})
22
+ @status = options[:status]
23
+ @email = options[:email]
24
+ @buyer_name = options[:buyer_name]
25
+ @contact_number = options[:contact_number]
26
+ @delivery_address = options[:delivery_address]
27
+ @items = options[:items]
28
+ @shipment = options[:shipment]
29
+ @total = options[:total]
30
+ @currency = options[:currency]
31
+ @payment_method = options[:payment_method]
32
+ @payment_provider = options[:payment_provider]
33
+ @pickup_address = options[:pickup_address]
34
+ @pickup_at = options[:pickup_at]
35
+ end
36
+
37
+ def confirmable?
38
+ self.valid? && self.delivery_address.present?
39
+ end
40
+
41
+ # https://docs.quadx.xyz/#5f38afd0-66bb-468f-ab4e-993d4745a257
42
+ # Sets the order status to canceled. An order can be canceled provided they have not passed the cutoff date and time as specified in the contract.
43
+ def cancellable?
44
+ true
45
+ end
46
+
47
+ # https://docs.quadx.xyz/#c831dc25-2de4-36c5-c321-8e9db0fc2105
48
+ # The following fields can be updated provided they have not passed the cutoff date and time as specified in the contract.
49
+ def updatable?
50
+ true
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,96 @@
1
+ require 'json'
2
+ require 'set'
3
+ require 'typhoeus'
4
+
5
+ # Ideal Order.create flow
6
+ # order = Order.create({...})
7
+ # order.confirm / order.cancel
8
+ # order.for_pickup(pickup_address, pickup_date)
9
+ # order.update({...})
10
+
11
+ module Xpost
12
+ class Orders
13
+ # cant actually get all orders since its paginated
14
+ def self.all(auth_token)
15
+ all_orders_url = "orders"
16
+
17
+ get_url(all_orders_url, headers: auth_header(auth_token))
18
+ end
19
+
20
+ def self.find(auth_token, tracking_number)
21
+ find_order_url = "orders/#{tracking_number}"
22
+
23
+ res = get_url(find_order_url, headers: auth_header(auth_token))
24
+ res = res[:message] == "Not Found" ? "Not Found" : res
25
+ end
26
+
27
+ def self.track(auth_token, tracking_number)
28
+ track_order_url = "orders/#{tracking_number}"
29
+
30
+ res = get_url(track_order_url, headers: auth_header(auth_token))
31
+ res = res[:message] == "Not Found" ? "Not Found" : { timeline: res[:tat], events: res[:events] }
32
+ end
33
+
34
+ def self.create(auth_token, options = {})
35
+ raise "Missing order data" if options[:order_data].empty?
36
+
37
+ create_order_url = "orders"
38
+ order_data = options[:order_data]
39
+
40
+ res = post_url(create_order_url, data: order_data, headers: auth_header(auth_token))
41
+ end
42
+
43
+ def self.confirm(auth_token, tracking_number, payment_reference_id)
44
+ confirm_order_url = "orders/#{tracking_number}/confirm"
45
+
46
+ res = put_url(confirm_order_url, data: payment_reference_id, headers: auth_header(auth_token))
47
+ res = res[:message] == "Not Found" ? "Not Found" : res
48
+ end
49
+
50
+ def self.for_pickup(auth_token, tracking_number, pickup_address)
51
+ pickup_address = Xpost::Models::Address.new(pickup_address)
52
+ for_pickup_url = "orders/#{tracking_number}/for-pickup"
53
+
54
+ raise "Invalid address" unless pickup_address.valid?
55
+
56
+ res = put_url(for_pickup_url, data: pickup_address, headers: auth_header(auth_token))
57
+ res = res[:message] == "Not Found" ? "Not Found" : res
58
+ end
59
+
60
+ private
61
+
62
+ def self.base_url
63
+ Xpost.configuration.production_url
64
+ end
65
+
66
+ def self.auth_header(auth_token)
67
+ {"Authorization" => "Bearer #{auth_token}"}
68
+ end
69
+
70
+ def self.get_url(url, options = {})
71
+ req_url = "#{base_url}/#{url}"
72
+ req_options = {headers: options[:headers]}
73
+
74
+ res = Typhoeus::Request.get(req_url, req_options).body
75
+ res = JSON.parse(res, symbolize_names: true)
76
+ end
77
+
78
+ def self.post_url(url, options = {})
79
+ headers = { 'Content-Type': 'application/json' }.merge options[:headers]
80
+ req_url = "#{base_url}/#{url}"
81
+ req_options = { headers: headers, body: options[:data].to_json }
82
+
83
+ res = Typhoeus::Request.post(req_url, req_options).body
84
+ res = JSON.parse(res, symbolize_names: true)
85
+ end
86
+
87
+ def self.put_url(url, options = {})
88
+ headers = { 'Content-Type': 'application/json' }.merge options[:headers]
89
+ req_url = "#{base_url}/#{url}"
90
+ req_options = { headers: headers, body: options[:data].to_json }
91
+
92
+ res = Typhoeus::Request.put(req_url, req_options).body
93
+ res = JSON.parse(res, symbolize_names: true)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,3 @@
1
+ module Xpost
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Address' do
4
+ it 'works' do
5
+ address = build(:address)
6
+
7
+ expect(address.name).to eq 'Bobby Axelrod'
8
+ expect(address.line_1).to eq 'Axe Capital'
9
+ end
10
+
11
+ describe 'with required parameters' do
12
+ it 'is valid' do
13
+ address = build(:required_address)
14
+ expect(address).to be_valid
15
+ end
16
+
17
+ it 'is invalid with missing parameters' do
18
+ address = build(:required_address, name: nil)
19
+ expect(address).not_to be_valid
20
+ expect(address.errors.messages).to eq(name: ["can't be blank"])
21
+ end
22
+ end
23
+
24
+ describe 'with complete parameters' do
25
+ it 'is valid' do
26
+ address = build(:complete_address)
27
+ expect(address.valid?).to be true
28
+ end
29
+
30
+ it 'is invalid without the required parameters' do
31
+ address = build(:complete_address, name: nil)
32
+ expect(address.valid?).to be false
33
+ expect(address.errors.messages).to eq(name: ["can't be blank"])
34
+ end
35
+
36
+ it 'is valid without the optional parameters' do
37
+ address = build(:complete_address, company: nil)
38
+ expect(address.valid?).to be true
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,39 @@
1
+ FactoryBot.define do
2
+ factory :address, class: Xpost::Models::Address do
3
+ name "Bobby Axelrod"
4
+ line_1 "Axe Capital"
5
+ end
6
+
7
+ factory :required_address, class: Xpost::Models::Address do
8
+ name "Bobby Axelrod"
9
+ shipment "small-pouch"
10
+ line_1 "855 Sixth Avenue"
11
+ city "New York"
12
+ state "NY"
13
+ postal_code 10001
14
+ country "US"
15
+
16
+ initialize_with { new(attributes) }
17
+ end
18
+
19
+ factory :complete_address, class: Xpost::Models::Address do
20
+ name "Bobby Axelrod"
21
+ shipment "small-pouch"
22
+ line_1 "855 Sixth Avenue"
23
+ city "New York"
24
+ state "NY"
25
+ postal_code 10001
26
+ country "US"
27
+ company "Axe Capital"
28
+ title "CEO"
29
+ email "bobby@axe.com"
30
+ phone_number "12345678"
31
+ mobile_number "091712345678"
32
+ fax_number "12345678"
33
+ district "Manhattan"
34
+ line_2 "5th floor"
35
+ remarks "Send ASAP"
36
+
37
+ initialize_with { new(attributes) }
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ FactoryBot.define do
2
+ factory :product_item, class: Xpost::Models::Item do
3
+ type "product"
4
+ description "orange shirt"
5
+ amount 1200
6
+ initialize_with { new(attributes) }
7
+ end
8
+
9
+ factory :complete_product_item, class: Xpost::Models::Item do
10
+ type "product"
11
+ description "red shirt"
12
+ amount 1000
13
+ quantity 1
14
+ metadata "Small"
15
+ initialize_with { new(attributes) }
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ FactoryBot.define do
2
+ factory :order, class: Xpost::Models::Order do
3
+ email "john@me.com"
4
+ buyer_name "John Doe"
5
+ contact_number "+6391712345678"
6
+
7
+ total 1500
8
+ currency "PHP"
9
+ payment_method "cod"
10
+ payment_provider "lbcx"
11
+
12
+ items { [build(:complete_product_item)] }
13
+ delivery_address { build(:complete_address) }
14
+ end
15
+
16
+ factory :cod_order, class: Xpost::Models::Order do
17
+ email "john@me.com"
18
+ buyer_name "John Doe"
19
+ contact_number "+6391712345678"
20
+
21
+ total 1500
22
+ currency "PHP"
23
+ payment_method "cod"
24
+ payment_provider "lbcx"
25
+
26
+ items { [build(:complete_product_item)] }
27
+ delivery_address { build(:complete_address) }
28
+ end
29
+
30
+ # factory :confirmable_order, class: Xpost::Models::Order do
31
+ # end
32
+
33
+ # factory :for_pickup_order, class: Xpost::Models::Order do
34
+ # end
35
+
36
+ end
@@ -0,0 +1,12 @@
1
+ module Helpers
2
+ def auth_token
3
+ Xpost.configure do |config|
4
+ config.api_key = 'api_key'
5
+ config.secret_key = 'secret_key'
6
+ config.staging_url = "https://api.staging.lbcx.ph/v1"
7
+ config.production_url = "https://api.staging.lbcx.ph/v1"
8
+ end
9
+
10
+ auth_token = Xpost::Authentication.authenticate(Xpost.configuration.api_key, Xpost.configuration.secret_key)
11
+ end
12
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Item' do
4
+ it 'works' do
5
+ item = build(:product_item)
6
+
7
+ expect(item).to be_valid
8
+ expect(item.type).to eq "product"
9
+ expect(item.description).to eq "orange shirt"
10
+ expect(item.amount).to eq 1200
11
+ end
12
+
13
+ it 'requires a valid item_type' do
14
+ expect(build(:product_item, type: "product")).to be_valid
15
+ expect(build(:product_item, type: "productz")).not_to be_valid
16
+ end
17
+
18
+ describe 'with required parameters' do
19
+ it 'is valid' do
20
+ item = build(:product_item)
21
+ expect(item).to be_valid
22
+ end
23
+
24
+ it 'is invalid with missing parameters' do
25
+ item = build(:product_item, amount: nil)
26
+ expect(item.valid?).to eq false
27
+ end
28
+ end
29
+
30
+ describe 'with complete parameters' do
31
+ it 'is valid' do
32
+ item = build(:complete_product_item)
33
+ expect(item).to be_valid
34
+ end
35
+
36
+ it 'is invalid without the required parameters' do
37
+ item = build(:complete_product_item, type: nil)
38
+ expect(item).not_to be_valid
39
+ end
40
+
41
+ it 'is valid without the optional parameters' do
42
+ item = build(:complete_product_item, quantity: nil)
43
+ expect(item).to be_valid
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'LineItem' do
4
+
5
+ describe 'with require parameters' do
6
+ # it 'is valid' do
7
+ # line_item = build(:line_item)
8
+ # expect(line_item).to be_valid
9
+ # end
10
+
11
+ # it 'is invalid with missing parameters' do
12
+ # line_item = build(:line_item, type: nil)
13
+ # expect(line_item).not_to be_valid
14
+ # end
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ require 'set'
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe "Orders.create" do
5
+ before(:each) do
6
+ @order = build(:order)
7
+ end
8
+
9
+ it 'requires a delivery address' do
10
+ order_without_delivery_address = build(:order, delivery_address: nil)
11
+ order_with_delivery_address = build(:order)
12
+ expect(order_without_delivery_address).not_to be_valid
13
+ expect(order_with_delivery_address).to be_valid
14
+ end
15
+
16
+ it 'requires a payment method' do
17
+ expect(@order.payment_method).to be_present
18
+ expect(@order.payment_provider).to be_present
19
+ end
20
+
21
+ it 'requires at least one product in line items' do
22
+ expect(@order.items.count).to eq 1
23
+ expect(@order.items.first.description).to eq "red shirt"
24
+ end
25
+
26
+ # TODO: Skipping calls for now to prevent multiple
27
+ # orders from being added to the staging site.
28
+
29
+
30
+ # it 'creates an order' do
31
+ # auth_token = Xpost::Authentication.local_auth
32
+ # @res = Xpost::Orders.create(auth_token, @order)
33
+ # expect(@res[:tracking_number]).to eq 200
34
+ # end
35
+
36
+ # describe 'returning a valid order object' do
37
+ # before(:each) do
38
+ # auth_token = Xpost::Authentication.local_auth
39
+ # @res = Xpost::Orders.create(auth_token, @order)
40
+ # end
41
+
42
+ # it 'has a tracking number'
43
+ # it 'has a status of confirming'
44
+ # end
45
+
46
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "@order.for_pickup" do
4
+ before do
5
+ Xpost.configure do |config|
6
+ config.api_key = 'api_key'
7
+ config.secret_key = 'secret_key'
8
+ config.staging_url = "https://api.staging.lbcx.ph/v1"
9
+ config.production_url = "https://api.staging.lbcx.ph/v1"
10
+ end
11
+ @auth_token = Xpost::Authentication.authenticate(Xpost.configuration.api_key, Xpost.configuration.secret_key)
12
+ end
13
+
14
+ it 'already has a delivery address'
15
+ it 'requires a pickup address'
16
+
17
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Orders.find" do
4
+ before do
5
+ Xpost.configure do |config|
6
+ config.api_key = 'api_key'
7
+ config.secret_key = 'secret_key'
8
+ config.staging_url = "https://api.staging.lbcx.ph/v1"
9
+ config.production_url = "https://api.staging.lbcx.ph/v1"
10
+ end
11
+ @auth_token = Xpost::Authentication.authenticate(Xpost.configuration.api_key, Xpost.configuration.secret_key)
12
+ end
13
+
14
+ it 'returns a valid order' do
15
+ tracking_number = "0076-1174-PSAT"
16
+ order = Xpost::Orders.find(@auth_token, tracking_number)
17
+
18
+ expect(order[:id]).to eq 761174
19
+ end
20
+
21
+ it 'fails on an invalid order' do
22
+ tracking_number = "0076-1174-PSAZ"
23
+ order = Xpost::Orders.find(@auth_token, tracking_number)
24
+
25
+ expect(order).to eq "Not Found"
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "Orders.track" do
4
+ before do
5
+ Xpost.configure do |config|
6
+ config.api_key = 'api_key'
7
+ config.secret_key = 'secret_key'
8
+ config.staging_url = "https://api.staging.lbcx.ph/v1"
9
+ config.production_url = "https://api.staging.lbcx.ph/v1"
10
+ end
11
+ @auth_token = Xpost::Authentication.authenticate(Xpost.configuration.api_key, Xpost.configuration.secret_key)
12
+ end
13
+
14
+ it 'returns a valid order' do
15
+ tracking_number = "0076-1174-PSAT"
16
+ order_events = Xpost::Orders.track(@auth_token, tracking_number)
17
+
18
+ expect(order_events[:timeline].count).to eq 5
19
+ end
20
+
21
+ it 'fails on an invalid order' do
22
+ tracking_number = "0076-1174-PSAZ"
23
+ order_events = Xpost::Orders.track(@auth_token, tracking_number)
24
+
25
+ expect(order_events).to eq "Not Found"
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ require 'bundler/setup'
2
+ require 'factory_bot'
3
+ require 'xpost'
4
+
5
+ require 'helpers'
6
+
7
+ RSpec.configure do |config|
8
+ # Enable flags like --only-failures and --next-failure
9
+ config.example_status_persistence_file_path = ".rspec_status"
10
+
11
+ # Disable RSpec exposing methods globally on `Module` and `main`
12
+ config.disable_monkey_patching!
13
+
14
+ config.expect_with :rspec do |c|
15
+ c.syntax = :expect
16
+ end
17
+
18
+ config.include Helpers
19
+
20
+ # factory_bot
21
+ config.include FactoryBot::Syntax::Methods
22
+ config.before(:suite) do
23
+ FactoryBot.find_definitions
24
+ end
25
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Xpost do
4
+ before do
5
+ @auth_token = auth_token
6
+ end
7
+
8
+ describe 'Configuration' do
9
+ it 'has keys' do
10
+ expect(Xpost.configuration.api_key).to eq 'api_key'
11
+ expect(Xpost.configuration.secret_key).to eq 'secret_key'
12
+ end
13
+
14
+ it 'has a staging url' do
15
+ expect(Xpost.configuration.staging_url).to eq "https://api.staging.lbcx.ph/v1"
16
+ end
17
+
18
+ it 'has a production url' do
19
+ expect(Xpost.configuration.production_url).to eq "https://api.staging.lbcx.ph/v1"
20
+ end
21
+ end
22
+
23
+ # TODO: need a better way to verify validity of the auth_token
24
+ describe 'Authentication' do
25
+ describe '.authenticate' do
26
+ it 'returns an auth_token' do
27
+ api_key = Xpost.configuration.api_key
28
+ secret_key = Xpost.configuration.secret_key
29
+ auth_token = Xpost::Authentication.authenticate(api_key, secret_key)
30
+
31
+ expect(auth_token).to_not be nil
32
+ expect(@auth_token).to_not be nil
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'xpost/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'xpost'
7
+ s.version = Xpost::VERSION
8
+ s.authors = ["David Marquez"]
9
+ s.email = 'david@xpanse.ph'
10
+
11
+ s.summary = "xpost Ruby API"
12
+ s.date = '2018-04-27'
13
+ s.description = "A quick wrapped of the xpost API written by xpanse."
14
+ s.homepage = 'http://rubygems.org/gems/xpost'
15
+ s.license = 'MIT'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency 'activemodel', '~> 5.2'
21
+ s.add_dependency 'typhoeus', '~> 1.3'
22
+ s.add_dependency 'factory_bot', '~> 4.8'
23
+ # s.add_dependency 'vcr', '~> 4.0'
24
+
25
+ s.add_development_dependency 'bundler', "~> 1.16"
26
+ s.add_development_dependency 'rake', "~> 12.3"
27
+ s.add_development_dependency 'rspec', '~> 3.2'
28
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xpost
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - David Marquez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemodel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: typhoeus
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: factory_bot
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.8'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.16'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.16'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '12.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '12.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.2'
97
+ description: A quick wrapped of the xpost API written by xpanse.
98
+ email: david@xpanse.ph
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - ".DS_Store"
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - Gemfile
107
+ - LICENSE
108
+ - README.md
109
+ - lib/xpost.rb
110
+ - lib/xpost/authentication.rb
111
+ - lib/xpost/configuration.rb
112
+ - lib/xpost/models.rb
113
+ - lib/xpost/models/address.rb
114
+ - lib/xpost/models/item.rb
115
+ - lib/xpost/models/order.rb
116
+ - lib/xpost/orders.rb
117
+ - lib/xpost/version.rb
118
+ - spec/address_spec.rb
119
+ - spec/factories/addresses.rb
120
+ - spec/factories/items.rb
121
+ - spec/factories/orders.rb
122
+ - spec/helpers.rb
123
+ - spec/item_spec.rb
124
+ - spec/line_item_spec.rb
125
+ - spec/orders/order_create_spec.rb
126
+ - spec/orders/order_for_pickup_spec.rb
127
+ - spec/orders/orders_find_spec.rb
128
+ - spec/orders/orders_track_spec.rb
129
+ - spec/spec_helper.rb
130
+ - spec/xpost_spec.rb
131
+ - xpost.gemspec
132
+ homepage: http://rubygems.org/gems/xpost
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.6.14
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: xpost Ruby API
156
+ test_files: []