jirafe 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,38 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://api.jirafe.dev/v1/applications/1/resources?token=secret_token
6
+ body:
7
+ encoding: US-ASCII
8
+ string: sites[0][description]=Test%20Site&sites[0][url]=http%3A%2F%2Fjirafe.com&sites[0][currency]=EUR&sites[0][timezone]=Europe%2FParis&sites[0][external_id]=1&sites[0][site_id]=1&users[0][email]=user%40example.com&users[0][first_name]=Test&users[0][last_name]=User
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Server:
16
+ - nginx/1.2.2
17
+ Content-Type:
18
+ - application/json
19
+ Transfer-Encoding:
20
+ - chunked
21
+ Connection:
22
+ - keep-alive
23
+ Keep-Alive:
24
+ - timeout=10
25
+ X-Powered-By:
26
+ - PHP/5.3.15
27
+ Cache-Control:
28
+ - no-cache
29
+ Date:
30
+ - Wed, 12 Sep 2012 20:41:37 GMT
31
+ X-Debug-Token:
32
+ - 5050f3815203d
33
+ body:
34
+ encoding: US-ASCII
35
+ string: ! '{"sites":[{"site_id":1,"app_id":1,"description":"Test Site","url":"http:\/\/jirafe.com","timezone":"Europe\/Paris","currency":"EUR","external_id":"1","store_api_url":null,"store_cart_url":null}],"users":[{"email":"user@example.com","username":null,"first_name":"Test","last_name":"User","mobile_phone":null,"token":"c2785280dffad7835195b7a44829a103"}]}'
36
+ http_version:
37
+ recorded_at: Wed, 12 Sep 2012 20:41:37 GMT
38
+ recorded_with: VCR 2.2.4
@@ -16,6 +16,7 @@ module Jirafe
16
16
  autoload :VERSION, "jirafe/version.rb"
17
17
  autoload :Configuration, "jirafe/configuration.rb"
18
18
  autoload :Error, "jirafe/error.rb"
19
+ autoload :ResponseParser, "jirafe/response_parser.rb"
19
20
  autoload :Asset, "jirafe/asset.rb"
20
21
  autoload :Tracker, "jirafe/tracker.rb"
21
22
  module Resource
@@ -58,6 +59,8 @@ module Jirafe
58
59
  autoload :JirafeCallback, "jirafe/callback/jirafe_callback.rb"
59
60
  autoload :Event, "jirafe/callback/event.rb"
60
61
  module Events
62
+ autoload :DataHelper, "jirafe/callback/events/data_helper.rb"
63
+ autoload :Item, "jirafe/callback/events/item.rb"
61
64
  autoload :Order, "jirafe/callback/events/order.rb"
62
65
  autoload :Refund, "jirafe/callback/events/refund.rb"
63
66
  end
@@ -23,6 +23,10 @@ module Jirafe
23
23
  check_response_for_exception(response)
24
24
  true
25
25
  end
26
+
27
+ def trust_callback?(token, confirmation_token, confirmation_hash)
28
+ Digest::SHA1.hexdigest(confirmation_token.to_s + token.to_s) == confirmation_hash
29
+ end
26
30
  end
27
31
 
28
32
  def action_map
@@ -45,11 +49,6 @@ module Jirafe
45
49
  }.to_json(*args)
46
50
  end
47
51
 
48
- def initialize(attributes = {})
49
- attributes.each do |attr, value|
50
- self.send("#{attr}=", value) if self.respond_to?("#{attr}=")
51
- end
52
- end
53
52
  end
54
53
  end
55
54
  end
@@ -0,0 +1,25 @@
1
+ module Jirafe
2
+ module Callback
3
+ module Events
4
+ module DataHelper
5
+ def initialize(attributes = {})
6
+ attributes.each do |attr, value|
7
+ self.send("#{attr}=", value) if self.respond_to?("#{attr}=")
8
+ end
9
+ end
10
+
11
+ def format_amount(amount)
12
+ return nil if amount.nil?
13
+ "%01.4f" % amount
14
+ end
15
+
16
+ def format_discount_amount(amount)
17
+ return nil if amount.nil?
18
+ format_amount(amount.abs)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+
@@ -0,0 +1,21 @@
1
+ module Jirafe
2
+ module Callback
3
+ module Events
4
+ class Item
5
+ include DataHelper
6
+ attr_accessor :sku, :name, :price, :quantity, :category
7
+
8
+ def data
9
+ {
10
+ "sku" => sku,
11
+ "name" => name,
12
+ "price" => format_amount(price),
13
+ "quantity" => quantity,
14
+ "category" => category
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -2,6 +2,7 @@ module Jirafe
2
2
  module Callback
3
3
  module Events
4
4
  class Order < Jirafe::Callback::Event
5
+ include DataHelper
5
6
  attr_accessor :identifier, :status, :customer, :visitor_identifier, :created_at,
6
7
  :grand_total, :sub_total, :tax_amount, :shipping_amount, :discount_amount, :items
7
8
 
@@ -34,12 +35,12 @@ module Jirafe
34
35
  "customerHash" => customer,
35
36
  "vistorId" => visitor_identifier,
36
37
  "time" => created_at || Time.now.to_i,
37
- "grandTotal" => grand_total,
38
- "subTotal" => sub_total,
39
- "taxAmount" => tax_amount,
40
- "shippingAmount" => shipping_amount,
41
- "discountAmount" => discount_amount,
42
- "items" => items
38
+ "grandTotal" => format_amount(grand_total),
39
+ "subTotal" => format_amount(sub_total),
40
+ "taxAmount" => format_amount(tax_amount),
41
+ "shippingAmount" => format_amount(shipping_amount),
42
+ "discountAmount" => format_discount_amount(discount_amount),
43
+ "items" => items.map { |item| item.data }
43
44
  }
44
45
  end
45
46
  end
@@ -2,6 +2,7 @@ module Jirafe
2
2
  module Callback
3
3
  module Events
4
4
  class Refund < Jirafe::Callback::Event
5
+ include DataHelper
5
6
  attr_accessor :identifier, :order_identifier, :created_at,
6
7
  :grand_total, :sub_total, :tax_amount, :shipping_amount,
7
8
  :discount_amount, :items
@@ -18,12 +19,12 @@ module Jirafe
18
19
  "refundId" => identifier,
19
20
  "orderId" => order_identifier,
20
21
  "time" => created_at || Time.now.to_i,
21
- "grandTotal" => grand_total,
22
- "subTotal" => sub_total,
23
- "taxAmount" => tax_amount
24
- "shippingAmount" => shipping_amount,
25
- "discountAmount" => discount_amount,
26
- "items" => items
22
+ "grandTotal" => format_amount(grand_total),
23
+ "subTotal" => format_amount(sub_total),
24
+ "taxAmount" => format_amount(tax_amount),
25
+ "shippingAmount" => format_amount(shipping_amount),
26
+ "discountAmount" => format_discount_amount(discount_amount),
27
+ "items" => items.map { |item| item.data }
27
28
  }
28
29
  end
29
30
  end
@@ -2,6 +2,8 @@ module Jirafe
2
2
  module Callback
3
3
  class JirafeCallback
4
4
  include HTTParty
5
+ include Jirafe::ResponseParser
6
+
5
7
  base_uri Jirafe.config.callback_url
6
8
  format :html
7
9
  debug_output Jirafe.config.logger if ENV["DEBUG_JIRAFE"]
@@ -21,29 +23,6 @@ module Jirafe
21
23
  check_response_for_exception(response)
22
24
  true
23
25
  end
24
-
25
- private
26
-
27
- def check_response_for_exception(response)
28
- return if (200..399).include?(response.code) # Allow any 2xx or 3xx
29
- exception = case response.code.to_i
30
- when 400 # NOTE: Being thrown for what should be 422's
31
- Jirafe::Error::BadRequest
32
- when 401
33
- Jirafe::Error::Unauthorized
34
- when 403
35
- Jirafe::Error::Forbidden
36
- when 404
37
- Jirafe::Error::ResourceNotFound
38
- when 405
39
- Jirafe::Error::NotAllowed
40
- when 500
41
- Jirafe::Error::ServerError
42
- else
43
- Jirafe::Error::UnknownError
44
- end
45
- raise exception.new(response)
46
- end
47
26
  end
48
27
  end
49
28
  end
@@ -2,6 +2,8 @@ module Jirafe
2
2
  module Resource
3
3
  class JirafeResource
4
4
  include HTTParty
5
+ include Jirafe::ResponseParser
6
+
5
7
  base_uri Jirafe.config.url
6
8
  format :json
7
9
  default_params :token => Jirafe.config.token
@@ -95,27 +97,6 @@ module Jirafe
95
97
  query_options = options.delete(:query) || {}
96
98
  {:query => { :token => Jirafe.config.token }.merge(query_options) }.merge(options)
97
99
  end
98
-
99
- def check_response_for_exception(response)
100
- return if (200..399).include?(response.code) # Allow any 2xx or 3xx
101
- exception = case response.code.to_i
102
- when 400 # NOTE: Being thrown for what should be 422's
103
- Jirafe::Error::BadRequest
104
- when 401
105
- Jirafe::Error::Unauthorized
106
- when 403
107
- Jirafe::Error::Forbidden
108
- when 404
109
- Jirafe::Error::ResourceNotFound
110
- when 405
111
- Jirafe::Error::NotAllowed
112
- when 500
113
- Jirafe::Error::ServerError
114
- else
115
- Jirafe::Error::UnknownError
116
- end
117
- raise exception.new(response)
118
- end
119
100
  end
120
101
 
121
102
  def initialize(attributes = {})
@@ -0,0 +1,30 @@
1
+ module Jirafe
2
+ module ResponseParser
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def check_response_for_exception(response)
9
+ return if (200..399).include?(response.code) # Allow any 2xx or 3xx
10
+ exception = case response.code.to_i
11
+ when 400 # NOTE: Being thrown for what should be 422's
12
+ Jirafe::Error::BadRequest
13
+ when 401
14
+ Jirafe::Error::Unauthorized
15
+ when 403
16
+ Jirafe::Error::Forbidden
17
+ when 404
18
+ Jirafe::Error::ResourceNotFound
19
+ when 405
20
+ Jirafe::Error::NotAllowed
21
+ when 500
22
+ Jirafe::Error::ServerError
23
+ else
24
+ Jirafe::Error::UnknownError
25
+ end
26
+ raise exception.new(response)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Jirafe
2
- VERSION = "0.3.0"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -7,9 +7,8 @@ describe Jirafe::Callback::Event do
7
7
 
8
8
  let(:cassette) { "#{resource_prefix}_post_event" }
9
9
 
10
- before do
10
+ before :all do
11
11
  use_master_token
12
- @query_capture = ENV['CALLTHROUGH'] ? [] : ["confirmToken=#{'a' * 16}"]
13
12
  @server = CallbackServer.run(@query_capture, 3333)
14
13
  end
15
14
 
@@ -17,29 +16,60 @@ describe Jirafe::Callback::Event do
17
16
  @server.shutdown
18
17
  end
19
18
 
20
- describe ".send" do
21
- before do
22
- make_request("#{cassette}_fetch_token") do
23
- use_master_token
24
- app = Jirafe::Resource::Application.new(:name => "test app cmb")
25
- app.create
26
- @site = Jirafe::Resource::Site.new(:app_id => app.identifier,
27
- :description => "test site cmb",
28
- :url => "http://testsitecmb.example.com",
29
- :store_api_url =>"http://127.0.0.1:3333") # SF2 validator doesn't like 'localhost'
30
- @site.parent = app
31
-
32
- use_app_token(app)
33
- @site.create
34
- Jirafe::Callback::Event.notify(@site.identifier)
35
- while @query_capture.empty?
36
- sleep 0.1
37
- end
38
- @token = @query_capture.last.split("&").detect {|param| param.match(/confirmToken/) }.split("=").last
19
+ before do
20
+ static_hash = "af5f436b948804627dc5641e309f54dc87a0f1c7"
21
+ @query_capture = ENV['CALLTHROUGH'] ? [] : ["confirmToken=#{'a' * 16}&hash=#{static_hash}"]
22
+ make_request("#{cassette}_fetch_token") do
23
+ use_master_token
24
+ app = Jirafe::Resource::Application.new(:name => "test app cmb")
25
+ created_app = app.create
26
+ @app_token = created_app.token
27
+ @site = Jirafe::Resource::Site.new(:app_id => app.identifier,
28
+ :description => "test site cmb",
29
+ :url => "http://testsitecmb.example.com",
30
+ :store_api_url =>"http://127.0.0.1:3333") # SF2 validator doesn't like 'localhost'
31
+ @site.parent = app
32
+
33
+ use_app_token(app)
34
+ @site.create
35
+ Jirafe::Callback::Event.notify(@site.identifier)
36
+ while @query_capture.empty?
37
+ sleep 0.1
39
38
  end
39
+ @confirm_token = @query_capture.last.split("&").detect {|param| param.match(/confirmToken/) }.split("=").last
40
+ @hash = @query_capture.last.split("&").detect {|param| param.match(/hash/) }.split("=").last
41
+ end
42
+ end
43
+
44
+ describe ".trust_callback?" do
45
+ subject { Jirafe::Callback::Event.trust_callback?(app_token, confirm_token, hash) }
46
+ let(:app_token) { @app_token }
47
+ let(:confirm_token) { @confirm_token }
48
+ let(:hash) { @hash }
49
+
50
+ context "given valid values" do
51
+
52
+ it { should be_true }
40
53
  end
54
+
55
+ context "given something that doesn't match" do
56
+ let(:app_token) { tokens[:invalid_token] }
57
+
58
+ it { should be_false }
59
+ end
60
+ end
61
+
62
+ describe ".send" do
41
63
  let(:version) { 1 }
42
64
 
65
+ let(:item) do
66
+ Jirafe::Callback::Events::Item.new(:sku => "1234",
67
+ :name => "Widget",
68
+ :price => 40,
69
+ :quantity => 2,
70
+ :category => "Things")
71
+ end
72
+
43
73
  let(:newly_created_order) do
44
74
  Jirafe::Callback::Events::Order.new(:version => version,
45
75
  :action => :create,
@@ -48,7 +78,8 @@ describe Jirafe::Callback::Event do
48
78
  :sub_total => 80.00,
49
79
  :tax_amount => 20.00,
50
80
  :discount_amount => 0.00,
51
- :status => :pending)
81
+ :status => :pending,
82
+ :items => [item])
52
83
  end
53
84
 
54
85
  let(:completed_order) do
@@ -59,7 +90,8 @@ describe Jirafe::Callback::Event do
59
90
  :sub_total => 80.00,
60
91
  :tax_amount => 20.00,
61
92
  :discount_amount => 10.00,
62
- :status => :complete)
93
+ :status => :complete,
94
+ :items => [item])
63
95
  end
64
96
 
65
97
  let(:refund) do
@@ -76,7 +108,7 @@ describe Jirafe::Callback::Event do
76
108
  it "sends events for processing" do
77
109
  events = [newly_created_order, completed_order]
78
110
  make_request(cassette) do
79
- Jirafe::Callback::Event.send(@site.identifier, @token, events)
111
+ Jirafe::Callback::Event.send(@site.identifier, @confirm_token, events)
80
112
  end
81
113
  end
82
114
  end
@@ -0,0 +1,49 @@
1
+ require "spec_helper"
2
+
3
+ describe Jirafe::Callback::Events::DataHelper do
4
+ before do
5
+ class DataHelperTestClass
6
+ include Jirafe::Callback::Events::DataHelper
7
+ end
8
+ end
9
+
10
+ let(:instance) { DataHelperTestClass.new }
11
+
12
+ describe "#format_amount" do
13
+ subject { instance.format_amount(amount) }
14
+
15
+ context "given nil" do
16
+ let(:amount) { nil }
17
+
18
+ it { should be_nil }
19
+ end
20
+
21
+ context "given a whole number" do
22
+ let(:amount) { 23 }
23
+
24
+ it { should == "23.0000" }
25
+ end
26
+
27
+ context "given a float" do
28
+ let(:amount) { 12.34 }
29
+
30
+ it { should == "12.3400" }
31
+ end
32
+ end
33
+
34
+ describe "#format_discount_amount" do
35
+ subject { instance.format_discount_amount(amount) }
36
+
37
+ context "given nil" do
38
+ let(:amount) { nil }
39
+
40
+ it { should be_nil }
41
+ end
42
+
43
+ context "given a negative number" do
44
+ let(:amount) { -12.34 }
45
+
46
+ it { should == "12.3400" }
47
+ end
48
+ end
49
+ end