drip-ruby 3.2.0 → 3.3.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -1
  3. data/.rubocop_todo.yml +17 -9
  4. data/.travis.yml +1 -1
  5. data/CHANGELOG.md +20 -1
  6. data/Gemfile +10 -0
  7. data/drip-ruby.gemspec +3 -11
  8. data/lib/drip/client.rb +44 -66
  9. data/lib/drip/client/accounts.rb +2 -2
  10. data/lib/drip/client/broadcasts.rb +2 -2
  11. data/lib/drip/client/campaign_subscriptions.rb +1 -1
  12. data/lib/drip/client/campaigns.rb +5 -5
  13. data/lib/drip/client/configuration.rb +28 -0
  14. data/lib/drip/client/conversions.rb +2 -2
  15. data/lib/drip/client/custom_fields.rb +1 -1
  16. data/lib/drip/client/events.rb +4 -4
  17. data/lib/drip/client/forms.rb +2 -2
  18. data/lib/drip/client/http_client.rb +64 -0
  19. data/lib/drip/client/orders.rb +3 -3
  20. data/lib/drip/client/shopper_activity.rb +78 -0
  21. data/lib/drip/client/subscribers.rb +13 -13
  22. data/lib/drip/client/tags.rb +3 -3
  23. data/lib/drip/client/webhooks.rb +5 -5
  24. data/lib/drip/client/workflow_triggers.rb +3 -3
  25. data/lib/drip/client/workflows.rb +6 -6
  26. data/lib/drip/request.rb +31 -0
  27. data/lib/drip/response.rb +13 -13
  28. data/lib/drip/version.rb +1 -1
  29. data/test/drip/client/configuration_test.rb +122 -0
  30. data/test/drip/client/http_client_test.rb +96 -0
  31. data/test/drip/client/shopper_activity_test.rb +175 -0
  32. data/test/drip/client_test.rb +32 -97
  33. data/test/drip/collection_test.rb +14 -0
  34. data/test/drip/collections/account_test.rb +8 -0
  35. data/test/drip/collections/broadcasts_test.rb +8 -0
  36. data/test/drip/collections/campaign_subscriptions_test.rb +8 -0
  37. data/test/drip/collections/campaigns_test.rb +8 -0
  38. data/test/drip/collections/errors_test.rb +8 -0
  39. data/test/drip/collections/orders_test.rb +8 -0
  40. data/test/drip/collections/purchases_test.rb +8 -0
  41. data/test/drip/collections/tags_test.rb +8 -0
  42. data/test/drip/collections/webhooks_test.rb +8 -0
  43. data/test/drip/collections/workflow_triggers_test.rb +8 -0
  44. data/test/drip/collections/workflows_test.rb +8 -0
  45. data/test/drip/request_test.rb +58 -0
  46. data/test/drip/resource_test.rb +12 -0
  47. data/test/drip/resources/tag_test.rb +13 -0
  48. data/test/drip/response_test.rb +33 -0
  49. data/test/test_helper.rb +3 -0
  50. metadata +42 -104
@@ -0,0 +1,31 @@
1
+ require "net/http"
2
+
3
+ module Drip
4
+ class Request
5
+ attr_reader :http_verb, :url, :options, :content_type
6
+
7
+ VERB_CLASS_MAPPING = {
8
+ get: Net::HTTP::Get,
9
+ post: Net::HTTP::Post,
10
+ put: Net::HTTP::Put,
11
+ delete: Net::HTTP::Delete
12
+ }.freeze
13
+
14
+ def initialize(http_verb, url, options = {}, content_type = nil)
15
+ @http_verb = http_verb
16
+ @url = url
17
+ @options = options
18
+ @content_type = content_type
19
+ end
20
+
21
+ def verb_klass
22
+ VERB_CLASS_MAPPING[http_verb]
23
+ end
24
+
25
+ def body
26
+ return if http_verb == :get
27
+
28
+ options.to_json
29
+ end
30
+ end
31
+ end
@@ -44,20 +44,20 @@ module Drip
44
44
  end
45
45
 
46
46
  def parse_members
47
- if status == 429
48
- body
49
- else
50
- {}.tap do |members|
51
- if body.is_a?(Hash)
52
- body.each do |key, value|
53
- klass = if value.is_a?(Array)
54
- Drip::Collections.find_class(key)
55
- else
56
- Drip::Resources.find_class(key)
57
- end
47
+ return body unless success?
48
+ {}.tap do |members|
49
+ if body.is_a?(Hash)
50
+ body.each do |key, value|
51
+ klass = case value
52
+ when Array
53
+ Drip::Collections.find_class(key)
54
+ when String
55
+ String
56
+ else
57
+ Drip::Resources.find_class(key)
58
+ end
58
59
 
59
- members[key] = klass.new(value)
60
- end
60
+ members[key] = klass.new(value)
61
61
  end
62
62
  end
63
63
  end
@@ -1,3 +1,3 @@
1
1
  module Drip
2
- VERSION = "3.2.0".freeze
2
+ VERSION = "3.3.0".freeze
3
3
  end
@@ -0,0 +1,122 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+ require "drip/client/configuration"
3
+
4
+ class Drip::Client::ConfigurationTest < Drip::TestCase
5
+ context "#initializer" do
6
+ context "with reasonable parameters" do
7
+ should "accept parameters" do
8
+ config = Drip::Client::Configuration.new(access_token: "123")
9
+ assert_equal "123", config.access_token
10
+ end
11
+ end
12
+
13
+ context "with one additional parameter" do
14
+ should "raise singular error" do
15
+ err = assert_raises(ArgumentError) { Drip::Client::Configuration.new(blahdeblah: "123") }
16
+ assert_equal "unknown keyword: blahdeblah", err.message
17
+ end
18
+
19
+ should "match core ruby behavior" do
20
+ def test_method(hello: "test"); end
21
+ err = assert_raises(ArgumentError) { test_method(blahdeblah: "123") }
22
+ assert_equal "unknown keyword: blahdeblah", err.message
23
+ end
24
+ end
25
+
26
+ context "with multiple additional parameters" do
27
+ should "raise plural error" do
28
+ err = assert_raises(ArgumentError) { Drip::Client::Configuration.new(blahdeblah: "123", blahdeblah1: "123") }
29
+ assert_equal "unknown keywords: blahdeblah, blahdeblah1", err.message
30
+ end
31
+
32
+ should "match core ruby behavior" do
33
+ def test_method(hello: "test"); end
34
+ err = assert_raises(ArgumentError) { test_method(blahdeblah: "123", blahdeblah1: "123") }
35
+ assert_equal "unknown keywords: blahdeblah, blahdeblah1", err.message
36
+ end
37
+ end
38
+ end
39
+
40
+ context "#url_prefix" do
41
+ should "have default url prefix" do
42
+ config = Drip::Client::Configuration.new
43
+ assert_equal "https://api.getdrip.com/", config.url_prefix
44
+ end
45
+
46
+ should "accept passed parameter" do
47
+ config = Drip::Client::Configuration.new(url_prefix: "https://www.example.com/")
48
+ assert_equal "https://www.example.com/", config.url_prefix
49
+ end
50
+
51
+ should "allow setter" do
52
+ config = Drip::Client::Configuration.new
53
+ config.url_prefix = "https://www.example.com/"
54
+ assert_equal "https://www.example.com/", config.url_prefix
55
+ end
56
+ end
57
+
58
+ context "#access_token" do
59
+ should "accept passed parameter" do
60
+ config = Drip::Client::Configuration.new(access_token: "blah")
61
+ assert_equal "blah", config.access_token
62
+ end
63
+
64
+ should "allow setter" do
65
+ config = Drip::Client::Configuration.new
66
+ config.access_token = "blah"
67
+ assert_equal "blah", config.access_token
68
+ end
69
+ end
70
+
71
+ context "#api_key" do
72
+ should "accept passed parameter" do
73
+ config = Drip::Client::Configuration.new(api_key: "blah")
74
+ assert_equal "blah", config.api_key
75
+ end
76
+
77
+ should "allow setter" do
78
+ config = Drip::Client::Configuration.new
79
+ config.api_key = "blah"
80
+ assert_equal "blah", config.api_key
81
+ end
82
+ end
83
+
84
+ context "#account_id" do
85
+ should "accept passed parameter" do
86
+ config = Drip::Client::Configuration.new(account_id: "1234567")
87
+ assert_equal "1234567", config.account_id
88
+ end
89
+
90
+ should "allow setter" do
91
+ config = Drip::Client::Configuration.new
92
+ config.account_id = "1234567"
93
+ assert_equal "1234567", config.account_id
94
+ end
95
+ end
96
+
97
+ context "#http_open_timeout" do
98
+ should "accept passed parameter" do
99
+ config = Drip::Client::Configuration.new(http_open_timeout: 12)
100
+ assert_equal 12, config.http_open_timeout
101
+ end
102
+
103
+ should "allow setter" do
104
+ config = Drip::Client::Configuration.new
105
+ config.http_open_timeout = 12
106
+ assert_equal 12, config.http_open_timeout
107
+ end
108
+ end
109
+
110
+ context "#http_timeout" do
111
+ should "accept passed parameter" do
112
+ config = Drip::Client::Configuration.new(http_timeout: 42)
113
+ assert_equal 42, config.http_timeout
114
+ end
115
+
116
+ should "allow setter" do
117
+ config = Drip::Client::Configuration.new
118
+ config.http_timeout = 42
119
+ assert_equal 42, config.http_timeout
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,96 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+ require "drip/client/configuration"
3
+ require "drip/client/http_client"
4
+ require "drip/request"
5
+
6
+ class Drip::Client::HTTPClientTest < Drip::TestCase
7
+ context "given a personal api key" do
8
+ setup do
9
+ @key = "aaaa"
10
+ @config = Drip::Client::Configuration.new(api_key: @key)
11
+ @client = Drip::Client::HTTPClient.new(@config)
12
+ end
13
+
14
+ should "use Basic authentication" do
15
+ stub_request(:get, "https://api.getdrip.com/v2/testpath").
16
+ to_return(status: 200, body: "", headers: {})
17
+
18
+ @client.make_request(Drip::Request.new(:get, URI("https://api.getdrip.com/v2/testpath")))
19
+
20
+ header = "Basic #{Base64.encode64(@key + ':')}".strip
21
+ assert_requested :get, "https://api.getdrip.com/v2/testpath", headers: { 'Authorization' => header }
22
+ end
23
+ end
24
+
25
+ context "given a OAuth access token" do
26
+ setup do
27
+ @key = "aaaa"
28
+ @config = Drip::Client::Configuration.new(access_token: @key)
29
+ @client = Drip::Client::HTTPClient.new(@config)
30
+ end
31
+
32
+ should "use Bearer token authentication" do
33
+ stub_request(:get, "https://api.getdrip.com/v2/testpath").
34
+ to_return(status: 200, body: "", headers: {})
35
+ @client.make_request(Drip::Request.new(:get, URI("https://api.getdrip.com/v2/testpath")))
36
+ header = "Bearer #{@key}"
37
+ assert_requested :get, "https://api.getdrip.com/v2/testpath", headers: { 'Authorization' => header }
38
+ end
39
+ end
40
+
41
+ context "given a redirecting url" do
42
+ setup do
43
+ @config = Drip::Client::Configuration.new
44
+ @client = Drip::Client::HTTPClient.new(@config)
45
+ end
46
+
47
+ should "follow redirect" do
48
+ stub_request(:get, "https://api.getdrip.com/v2/testpath").
49
+ to_return(status: 301, body: "", headers: { "Location" => "https://api.example.com/mytestpath" })
50
+ stub_request(:get, "https://api.example.com/mytestpath").
51
+ to_return(status: 200, body: "{}")
52
+ response = @client.make_request(Drip::Request.new(:get, URI("https://api.getdrip.com/v2/testpath")))
53
+ assert_requested :get, "https://api.getdrip.com/v2/testpath"
54
+ assert_requested :get, "https://api.example.com/mytestpath"
55
+ assert_equal("{}", response.body)
56
+ end
57
+
58
+ should "not follow too many redirects" do
59
+ stub_request(:get, "https://api.getdrip.com/v2/accounts").
60
+ to_return(status: 301, body: "", headers: { "Location" => "https://api.example.com/mytestpath" })
61
+ stub_request(:get, "https://api.example.com/mytestpath").
62
+ to_return(status: 302, body: "", headers: { "Location" => "https://api.getdrip.com/v2/accounts" })
63
+ assert_raises(Drip::TooManyRedirectsError) { @client.make_request(Drip::Request.new(:get, URI("https://api.getdrip.com/v2/accounts"))) }
64
+ assert_requested :get, "https://api.getdrip.com/v2/accounts", times: 5
65
+ assert_requested :get, "https://api.example.com/mytestpath", times: 5
66
+ end
67
+ end
68
+
69
+ context "given a get request" do
70
+ setup do
71
+ @config = Drip::Client::Configuration.new(http_open_timeout: 20)
72
+ @client = Drip::Client::HTTPClient.new(@config)
73
+ @response = mock
74
+ @response.stubs(:code).returns('200')
75
+ @response.stubs(:body).returns('{}')
76
+
77
+ @http = mock
78
+ @http.expects(:request).returns(@response)
79
+
80
+ @request = mock
81
+ @request.stubs(:[]=)
82
+ @request.stubs(:basic_auth)
83
+ end
84
+
85
+ should "encode query and not set body" do
86
+ Net::HTTP::Get.expects(:new).returns(@request)
87
+ Net::HTTP.expects(:start).yields(@http).returns(@response)
88
+
89
+ @request.expects(:body=).with(nil)
90
+ URI.expects(:encode_www_form).once
91
+
92
+ response = @client.make_request(Drip::Request.new(:get, URI("https://api.getdrip.com/v2/testpath")))
93
+ assert_equal("{}", response.body)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,175 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+
3
+ class Drip::Client::ShopperActivityTest < Drip::TestCase
4
+ def setup
5
+ @client = Drip::Client.new { |c| c.account_id = "12345" }
6
+ end
7
+
8
+ context "#create_cart_activity_event" do
9
+ setup do
10
+ @email = "drippy@drip.com"
11
+ @options = {
12
+ email: @email,
13
+ action: "created",
14
+ provider: "shopify",
15
+ cart_id: "abcdef",
16
+ cart_url: "https://www.example.com/mythingy",
17
+ amount: 4900,
18
+ tax: 100,
19
+ fees: 0,
20
+ discount: 0,
21
+ currency_code: "USD",
22
+ properties: {
23
+ "size" => "medium",
24
+ "color" => "red"
25
+ }
26
+ }
27
+ @response_status = 202
28
+ @response_body = "{}"
29
+
30
+ stub_request(:post, "https://api.getdrip.com/v3/12345/shopper_activity/cart").
31
+ with(headers: { "Content-Type" => "application/json" }).
32
+ to_return(status: @response_status, body: @response_body, headers: {})
33
+ end
34
+
35
+ should "send the right request" do
36
+ expected = Drip::Response.new(@response_status, JSON.parse(@response_body))
37
+ assert_equal expected, @client.create_cart_activity_event(@options)
38
+ end
39
+
40
+ should "return error when missing fields" do
41
+ @options.delete(:cart_id)
42
+ assert_raises(ArgumentError) { @client.create_cart_activity_event(@options) }
43
+ end
44
+ end
45
+
46
+ context "#create_order_activity_event" do
47
+ setup do
48
+ @email = "drippy@drip.com"
49
+ @options = {
50
+ email: @email,
51
+ action: "created",
52
+ provider: "shopify",
53
+ order_id: "abcdef",
54
+ amount: 4900,
55
+ tax: 100,
56
+ fees: 0,
57
+ discount: 0,
58
+ currency_code: "USD",
59
+ properties: {
60
+ "size" => "medium",
61
+ "color" => "red"
62
+ }
63
+ }
64
+ @response_status = 202
65
+ @response_body = "{}"
66
+
67
+ stub_request(:post, "https://api.getdrip.com/v3/12345/shopper_activity/order").
68
+ with(headers: { "Content-Type" => "application/json" }).
69
+ to_return(status: @response_status, body: @response_body, headers: {})
70
+ end
71
+
72
+ should "send the right request" do
73
+ expected = Drip::Response.new(@response_status, JSON.parse(@response_body))
74
+ assert_equal expected, @client.create_order_activity_event(@options)
75
+ end
76
+
77
+ should "return error when missing fields" do
78
+ @options.delete(:order_id)
79
+ assert_raises(ArgumentError) { @client.create_order_activity_event(@options) }
80
+ end
81
+ end
82
+
83
+ context "#create_order_activity_events" do
84
+ setup do
85
+ @records = [
86
+ {
87
+ email: "drippy@example.com",
88
+ action: "created",
89
+ provider: "shopify",
90
+ order_id: "abcdef",
91
+ amount: 4900,
92
+ tax: 100,
93
+ fees: 0,
94
+ discount: 0,
95
+ currency_code: "USD",
96
+ properties: {
97
+ "size" => "medium",
98
+ "color" => "red"
99
+ }
100
+ },
101
+ {
102
+ email: "drippy1@example.com",
103
+ action: "created",
104
+ provider: "shopify",
105
+ order_id: "fdsgs",
106
+ amount: 4900,
107
+ tax: 100,
108
+ fees: 0,
109
+ discount: 0,
110
+ currency_code: "USD",
111
+ properties: {
112
+ "size" => "medium",
113
+ "color" => "red"
114
+ }
115
+ }
116
+ ]
117
+ @response_status = 202
118
+ @response_body = "{}"
119
+
120
+ stub_request(:post, "https://api.getdrip.com/v3/12345/shopper_activity/order/batch").
121
+ with(headers: { "Content-Type" => "application/json" }).
122
+ to_return(status: @response_status, body: @response_body, headers: {})
123
+ end
124
+
125
+ should "send the right request" do
126
+ expected = Drip::Response.new(@response_status, JSON.parse(@response_body))
127
+ assert_equal expected, @client.create_order_activity_events(@records)
128
+ end
129
+
130
+ should "return error when missing fields" do
131
+ @records[1].delete(:order_id)
132
+ err = assert_raises(ArgumentError) { @client.create_order_activity_events(@records) }
133
+ assert_equal "order_id: parameter required in record 1", err.message
134
+ end
135
+ end
136
+
137
+ context "#create_product_activity_event" do
138
+ setup do
139
+ @email = "drippy@drip.com"
140
+ @options = {
141
+ provider: "my_custom_platform",
142
+ action: "created",
143
+ occurred_at: "2019-01-28T12:15:23Z",
144
+ product_id: "B01J4SWO1G",
145
+ product_variant_id: "B01J4SWO1G-CW-BOTT",
146
+ sku: "XHB-1234",
147
+ name: "The Coolest Water Bottle",
148
+ brand: "Drip",
149
+ categories: [
150
+ "Accessories"
151
+ ],
152
+ price: 11.16,
153
+ inventory: 42,
154
+ product_url: "https://mysuperstore.example.com/dp/B01J4SWO1G",
155
+ image_url: "https://www.getdrip.com/images/example_products/water_bottle.png"
156
+ }
157
+ @response_status = 202
158
+ @response_body = "{}"
159
+
160
+ stub_request(:post, "https://api.getdrip.com/v3/12345/shopper_activity/product").
161
+ with(headers: { "Content-Type" => "application/json" }).
162
+ to_return(status: @response_status, body: @response_body, headers: {})
163
+ end
164
+
165
+ should "send the right request" do
166
+ expected = Drip::Response.new(@response_status, JSON.parse(@response_body))
167
+ assert_equal expected, @client.create_product_activity_event(@options)
168
+ end
169
+
170
+ should "return error when missing fields" do
171
+ @options.delete(:product_id)
172
+ assert_raises(ArgumentError) { @client.create_product_activity_event(@options) }
173
+ end
174
+ end
175
+ end